<?php

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

class Accounting_model extends App_Model
{
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * get account types
     * @param  integer $id    member group id
     * @param  array  $where
     * @return object
     */
    public function get_account_types()
    {
        $account_types = hooks()->apply_filters('before_get_account_types', [
            [
                'id'             => 1,
                'name'           => _l('acc_accounts_receivable'),
                'order'          => 1,
                ],
            [
                'id'             => 2,
                'name'           => _l('acc_current_assets'),
                'order'          => 2,
                ],
            [
                'id'             => 3,
                'name'           => _l('acc_cash_and_cash_equivalents'),
                'order'          => 3,
                ],
            [
                'id'             => 4,
                'name'           => _l('acc_fixed_assets'),
                'order'          => 4,
                ],
            [
                'id'             => 5,
                'name'           => _l('acc_non_current_assets'),
                'order'          => 5,
                ],
            [
                'id'             => 6,
                'name'           => _l('acc_accounts_payable'),
                'order'          => 6,
                ],
            [
                'id'             => 7,
                'name'           => _l('acc_credit_card'),
                'order'          => 7,
                ],
            [
                'id'             => 8,
                'name'           => _l('acc_current_liabilities'),
                'order'          => 8,
                ],
            [
                'id'             => 9,
                'name'           => _l('acc_non_current_liabilities'),
                'order'          => 9,
                ],
            [
                'id'             => 10,
                'name'           => _l('acc_owner_equity'),
                'order'          => 10,
                ],
            [
                'id'             => 11,
                'name'           => _l('acc_income'),
                'order'          => 11,
                ],
            [
                'id'             => 12,
                'name'           => _l('acc_other_income'),
                'order'          => 12,
                ],
            [
                'id'             => 13,
                'name'           => _l('acc_cost_of_sales'),
                'order'          => 13,
                ],
            [
                'id'             => 14,
                'name'           => _l('acc_expenses'),
                'order'          => 14,
                ],
            [
                'id'             => 15,
                'name'           => _l('acc_other_expense'),
                'order'          => 15,
                ],
            [
                'id'             => 16,
                'name'           => _l('acc_bank'),
                'order'          => 16,
                ],
            ]);

        usort($account_types, function ($a, $b) {
            return $a['order'] - $b['order'];
        });

        return $account_types;
    }

    /**
     * get account type details
     * @param  integer $id    member group id
     * @param  array  $where
     * @return object
     */
    public function get_account_type_details()
    {
        $account_type_details = hooks()->apply_filters('before_get_account_type_details', [
            [
                'id'                => 1,
                'account_type_id'   => 1,
                'name'              => _l('acc_accounts_receivable'),
                'note'              => _l('acc_accounts_receivable_note'),
                'order'             => 1,
                ],
            [
                'id'                => 2,
                'account_type_id'   => 2,
                'name'              => _l('acc_allowance_for_bad_debts'),
                'note'              => _l('acc_allowance_for_bad_debts_note'),
                'order'             => 2,
                ],
            [
                'id'                => 3,
                'account_type_id'   => 2,
                'name'              => _l('acc_assets_available_for_sale'),
                'note'              => _l('acc_assets_available_for_sale_note'),
                'order'             => 3,
                ],
            [
                'id'                => 4,
                'account_type_id'   => 2,
                'name'              => _l('acc_development_costs'),
                'note'              => _l('acc_development_costs_note'),
                'order'             => 4,
                ],
            [
                'id'                => 141,
                'account_type_id'   => 2,
                'name'              => _l('acc_employee_cash_advances'),
                'note'              => _l('acc_employee_cash_advances_note'),
                'order'             => 5,
                ],
            [
                'id'                => 5,
                'account_type_id'   => 2,
                'name'              => _l('acc_inventory'),
                'note'              => _l('acc_inventory_note'),
                'order'             => 5,
                ],
            [
                'id'                => 6,
                'account_type_id'   => 2,
                'name'              => _l('acc_investments_other'),
                'note'              => _l('acc_investments_other_note'),
                'order'             => 6,
                ],
            [
                'id'                => 7,
                'account_type_id'   => 2,
                'name'              => _l('acc_loans_to_officers'),
                'note'              => _l('acc_loans_to_officers_note'),
                'order'             => 7,
                ],
            [
                'id'                => 8,
                'account_type_id'   => 2,
                'name'              => _l('acc_loans_to_others'),
                'note'              => _l('acc_loans_to_others_note'),
                'order'             => 8,
                ],
            [
                'id'                => 9,
                'account_type_id'   => 2,
                'name'              => _l('acc_loans_to_shareholders'),
                'note'              => _l('acc_loans_to_shareholders_note'),
                'order'             => 9,
                ],
            [
                'id'                => 10,
                'account_type_id'   => 2,
                'name'              => _l('acc_other_current_assets'),
                'note'              => _l('acc_other_current_assets_note'),
                'order'             => 10,
                ],
            [
                'id'                => 11,
                'account_type_id'   => 2,
                'name'              => _l('acc_prepaid_expenses'),
                'note'              => _l('acc_prepaid_expenses_note'),
                'order'             => 11,
                ],
            [
                'id'                => 12,
                'account_type_id'   => 2,
                'name'              => _l('acc_retainage'),
                'note'              => _l('acc_retainage_note'),
                'order'             => 12,
                ],
            [
                'id'                => 13,
                'account_type_id'   => 2,
                'name'              => _l('acc_undeposited_funds'),
                'note'              => _l('acc_undeposited_funds_note'),
                'order'             => 13,
                ],
            [
                'id'                => 14,
                'account_type_id'   => 16,
                'name'              => _l('acc_bank'),
                'note'              => _l('acc_bank_note'),
                'order'             => 14,
                ],
            [
                'id'                => 15,
                'account_type_id'   => 3,
                'name'              => _l('acc_cash_and_cash_equivalents'),
                'note'              => _l('acc_cash_and_cash_equivalents_note'),
                'order'             => 15,
                ],
            [
                'id'                => 16,
                'account_type_id'   => 3,
                'name'              => _l('acc_cash_on_hand'),
                'note'              => _l('acc_cash_on_hand_note'),
                'order'             => 16,
                ],
            [
                'id'                => 17,
                'account_type_id'   => 3,
                'name'              => _l('acc_client_trust_account'),
                'note'              => _l('acc_client_trust_account_note'),
                'order'             => 17,
                ],
            [
                'id'                => 18,
                'account_type_id'   => 3,
                'name'              => _l('acc_money_market'),
                'note'              => _l('acc_money_market_note'),
                'order'             => 18,
                ],
            [
                'id'                => 19,
                'account_type_id'   => 3,
                'name'              => _l('acc_rents_held_in_trust'),
                'note'              => _l('acc_rents_held_in_trust_note'),
                'order'             => 19,
                ],
            [
                'id'                => 20,
                'account_type_id'   => 3,
                'name'              => _l('acc_savings'),
                'note'              => _l('acc_savings_note'),
                'order'             => 20,
                ],
            [
                'id'                => 21,
                'account_type_id'   => 4,
                'name'              => _l('acc_accumulated_depletion'),
                'note'              => _l('acc_accumulated_depletion_note'),
                'order'             => 21,
                ],
            [
                'id'                => 22,
                'account_type_id'   => 4,
                'name'              => _l('acc_accumulated_depreciation_on_property_plant_and_equipment'),
                'note'              => _l('acc_accumulated_depreciation_on_property_plant_and_equipment_note'),
                'order'             => 22,
                ],
            [
                'id'                => 23,
                'account_type_id'   => 4,
                'name'              => _l('acc_buildings'),
                'note'              => _l('acc_buildings_note'),
                'order'             => 23,
                ],
            [
                'id'                => 24,
                'account_type_id'   => 4,
                'name'              => _l('acc_depletable_assets'),
                'note'              => _l('acc_depletable_assets_note'),
                'order'             => 24,
                ],
            [
                'id'                => 25,
                'account_type_id'   => 4,
                'name'              => _l('acc_furniture_and_fixtures'),
                'note'              => _l('acc_furniture_and_fixtures_note'),
                'order'             => 25,
                ],
            [
                'id'                => 26,
                'account_type_id'   => 4,
                'name'              => _l('acc_land'),
                'note'              => _l('acc_land_note'),
                'order'             => 26,
                ],
            [
                'id'                => 27,
                'account_type_id'   => 4,
                'name'              => _l('acc_leasehold_improvements'),
                'note'              => _l('acc_leasehold_improvements_note'),
                'order'             => 27,
                ],
            [
                'id'                => 28,
                'account_type_id'   => 4,
                'name'              => _l('acc_machinery_and_equipment'),
                'note'              => _l('acc_machinery_and_equipment_note'),
                'order'             => 28,
                ],
            [
                'id'                => 29,
                'account_type_id'   => 4,
                'name'              => _l('acc_other_fixed_assets'),
                'note'              => _l('acc_other_fixed_assets_note'),
                'order'             => 29,
                ],
            [
                'id'                => 30,
                'account_type_id'   => 4,
                'name'              => _l('acc_vehicles'),
                'note'              => _l('acc_vehicles_note'),
                'order'             => 30,
                ],
            [
                'id'                => 31,
                'account_type_id'   => 5,
                'name'              => _l('acc_accumulated_amortisation_of_non_current_assets'),
                'note'              => _l('acc_accumulated_amortisation_of_non_current_assets_note'),
                'order'             => 31,
                ],
            [
                'id'                => 32,
                'account_type_id'   => 5,
                'name'              => _l('acc_assets_held_for_sale'),
                'note'              => _l('acc_assets_held_for_sale_note'),
                'order'             => 32,
                ],
            [
                'id'                => 33,
                'account_type_id'   => 5,
                'name'              => _l('acc_deferred_tax'),
                'note'              => _l('acc_deferred_tax_note'),
                'order'             => 33,
                ],
            [
                'id'                => 34,
                'account_type_id'   => 5,
                'name'              => _l('acc_goodwill'),
                'note'              => _l('acc_goodwill_note'),
                'order'             => 34,
                ],
            [
                'id'                => 35,
                'account_type_id'   => 5,
                'name'              => _l('acc_intangible_assets'),
                'note'              => _l('acc_intangible_assets_note'),
                'order'             => 35,
                ],
            [
                'id'                => 36,
                'account_type_id'   => 5,
                'name'              => _l('acc_lease_buyout'),
                'note'              => _l('acc_lease_buyout_note'),
                'order'             => 36,
                ],
            [
                'id'                => 37,
                'account_type_id'   => 5,
                'name'              => _l('acc_licences'),
                'note'              => _l('acc_licences_note'),
                'order'             => 37,
                ],
            [
                'id'                => 38,
                'account_type_id'   => 5,
                'name'              => _l('acc_long_term_investments'),
                'note'              => _l('acc_long_term_investments_note'),
                'order'             => 38,
                ],
            [
                'id'                => 39,
                'account_type_id'   => 5,
                'name'              => _l('acc_organisational_costs'),
                'note'              => _l('acc_organisational_costs_note'),
                'order'             => 39,
                ],
            [
                'id'                => 40,
                'account_type_id'   => 5,
                'name'              => _l('acc_other_non_current_assets'),
                'note'              => _l('acc_other_non_current_assets_note'),
                'order'             => 40,
                ],
            [
                'id'                => 41,
                'account_type_id'   => 5,
                'name'              => _l('acc_security_deposits'),
                'note'              => _l('acc_security_deposits_note'),
                'order'             => 41,
                ],
            [
                'id'                => 42,
                'account_type_id'   => 6,
                'name'              => _l('acc_accounts_payable'),
                'note'              => _l('acc_accounts_payable_note'),
                'order'             => 42,
                ],
            [
                'id'                => 43,
                'account_type_id'   => 7,
                'name'              => _l('acc_credit_card'),
                'note'              => _l('acc_credit_card_note'),
                'order'             => 43,
                ],
            [
                'id'                => 44,
                'account_type_id'   => 8,
                'name'              => _l('acc_accrued_liabilities'),
                'note'              => _l('acc_accrued_liabilities_note'),
                'order'             => 44,
                ],
            [
                'id'                => 45,
                'account_type_id'   => 8,
                'name'              => _l('acc_client_trust_accounts_liabilities'),
                'note'              => _l('acc_client_trust_accounts_liabilities_note'),
                'order'             => 45,
                ],
            [
                'id'                => 46,
                'account_type_id'   => 8,
                'name'              => _l('acc_current_tax_liability'),
                'note'              => _l('acc_current_tax_liability_note'),
                'order'             => 46,
                ],
            [
                'id'                => 47,
                'account_type_id'   => 8,
                'name'              => _l('acc_current_portion_of_obligations_under_finance_leases'),
                'note'              => _l('acc_current_portion_of_obligations_under_finance_leases_note'),
                'order'             => 47,
                ],
            [
                'id'                => 48,
                'account_type_id'   => 8,
                'name'              => _l('acc_dividends_payable'),
                'note'              => _l('acc_dividends_payable_note'),
                'order'             => 48,
                ],
            [
                'id'                => 50,
                'account_type_id'   => 8,
                'name'              => _l('acc_income_tax_payable'),
                'note'              => _l('acc_income_tax_payable_note'),
                'order'             => 50,
                ],
            [
                'id'                => 51,
                'account_type_id'   => 8,
                'name'              => _l('acc_insurance_payable'),
                'note'              => _l('acc_insurance_payable_note'),
                'order'             => 51,
                ],
            [
                'id'                => 52,
                'account_type_id'   => 8,
                'name'              => _l('acc_line_of_credit'),
                'note'              => _l('acc_line_of_credit_note'),
                'order'             => 52,
                ],
            [
                'id'                => 53,
                'account_type_id'   => 8,
                'name'              => _l('acc_loan_payable'),
                'note'              => _l('acc_loan_payable_note'),
                'order'             => 53,
                ],
            [
                'id'                => 54,
                'account_type_id'   => 8,
                'name'              => _l('acc_other_current_liabilities'),
                'note'              => _l('acc_other_current_liabilities_note'),
                'order'             => 54,
                ],
            [
                'id'                => 55,
                'account_type_id'   => 8,
                'name'              => _l('acc_payroll_clearing'),
                'note'              => _l('acc_payroll_clearing_note'),
                'order'             => 55,
                ],
            [
                'id'                => 56,
                'account_type_id'   => 8,
                'name'              => _l('acc_payroll_liabilities'),
                'note'              => _l('acc_payroll_liabilities_note'),
                'order'             => 56,
                ],
            [
                'id'                => 58,
                'account_type_id'   => 8,
                'name'              => _l('acc_prepaid_expenses_payable'),
                'note'              => _l('acc_prepaid_expenses_payable_note'),
                'order'             => 58,
                ],
            [
                'id'                => 59,
                'account_type_id'   => 8,
                'name'              => _l('acc_rents_in_trust_liability'),
                'note'              => _l('acc_rents_in_trust_liability_note'),
                'order'             => 59,
                ],
            [
                'id'                => 60,
                'account_type_id'   => 8,
                'name'              => _l('acc_sales_and_service_tax_payable'),
                'note'              => _l('acc_sales_and_service_tax_payable_note'),
                'order'             => 60,
                ],
            [
                'id'                => 61,
                'account_type_id'   => 9,
                'name'              => _l('acc_accrued_holiday_payable'),
                'note'              => _l('acc_accrued_holiday_payable_note'),
                'order'             => 61,
                ],
            [
                'id'                => 62,
                'account_type_id'   => 9,
                'name'              => _l('acc_accrued_non_current_liabilities'),
                'note'              => _l('acc_accrued_non_current_liabilities_note'),
                'order'             => 62,
                ],
            [
                'id'                => 63,
                'account_type_id'   => 9,
                'name'              => _l('acc_liabilities_related_to_assets_held_for_sale'),
                'note'              => _l('acc_liabilities_related_to_assets_held_for_sale_note'),
                'order'             => 63,
                ],
            [
                'id'                => 64,
                'account_type_id'   => 9,
                'name'              => _l('acc_long_term_debt'),
                'note'              => _l('acc_long_term_debt_note'),
                'order'             => 64,
                ],
            [
                'id'                => 65,
                'account_type_id'   => 9,
                'name'              => _l('acc_notes_payable'),
                'note'              => _l('acc_notes_payable_note'),
                'order'             => 65,
                ],
            [
                'id'                => 66,
                'account_type_id'   => 9,
                'name'              => _l('acc_other_non_current_liabilities'),
                'note'              => _l('acc_other_non_current_liabilities_note'),
                'order'             => 66,
                ],
            [
                'id'                => 67,
                'account_type_id'   => 9,
                'name'              => _l('acc_shareholder_potes_payable'),
                'note'              => _l('acc_shareholder_potes_payable_note'),
                'order'             => 67,
                ],
            [
                'id'                => 68,
                'account_type_id'   => 10,
                'name'              => _l('acc_accumulated_adjustment'),
                'note'              => _l('acc_accumulated_adjustment_note'),
                'order'             => 68,
                ],
            [
                'id'                => 69,
                'account_type_id'   => 10,
                'name'              => _l('acc_dividend_disbursed'),
                'note'              => _l('acc_dividend_disbursed_note'),
                'order'             => 69,
                ],
            [
                'id'                => 70,
                'account_type_id'   => 10,
                'name'              => _l('acc_equity_in_earnings_of_subsidiaries'),
                'note'              => _l('acc_equity_in_earnings_of_subsidiaries_note'),
                'order'             => 70,
                ],
            [
                'id'                => 71,
                'account_type_id'   => 10,
                'name'              => _l('acc_opening_balance_equity'),
                'note'              => _l('acc_opening_balance_equity_note'),
                'order'             => 71,
                ],
            [
                'id'                => 72,
                'account_type_id'   => 10,
                'name'              => _l('acc_ordinary_shares'),
                'note'              => _l('acc_ordinary_shares_note'),
                'order'             => 72,
                ],
            [
                'id'                => 73,
                'account_type_id'   => 10,
                'name'              => _l('acc_other_comprehensive_income'),
                'note'              => _l('acc_other_comprehensive_income_note'),
                'order'             => 73,
                ],
            [
                'id'                => 74,
                'account_type_id'   => 10,
                'name'              => _l('acc_owner_equity'),
                'note'              => _l('acc_owner_equity_note'),
                'order'             => 74,
                ],
            [
                'id'                => 75,
                'account_type_id'   => 10,
                'name'              => _l('acc_paid_in_capital_or_surplus'),
                'note'              => _l('acc_paid_in_capital_or_surplus_note'),
                'order'             => 75,
                ],
            [
                'id'                => 76,
                'account_type_id'   => 10,
                'name'              => _l('acc_partner_contributions'),
                'note'              => _l('acc_partner_contributions_note'),
                'order'             => 76,
                ],
            [
                'id'                => 77,
                'account_type_id'   => 10,
                'name'              => _l('acc_partner_distributions'),
                'note'              => _l('acc_partner_distributions_note'),
                'order'             => 77,
                ],
            [
                'id'                => 78,
                'account_type_id'   => 10,
                'name'              => _l('acc_partner_equity'),
                'note'              => _l('acc_partner_equity_note'),
                'order'             => 78,
                ],
            [
                'id'                => 79,
                'account_type_id'   => 10,
                'name'              => _l('acc_preferred_shares'),
                'note'              => _l('acc_preferred_shares_note'),
                'order'             => 79,
                ],
            [
                'id'                => 80,
                'account_type_id'   => 10,
                'name'              => _l('acc_retained_earnings'),
                'note'              => _l('acc_retained_earnings_note'),
                'order'             => 80,
                ],
            [
                'id'                => 81,
                'account_type_id'   => 10,
                'name'              => _l('acc_share_capital'),
                'note'              => _l('acc_share_capital_note'),
                'order'             => 81,
                ],
            [
                'id'                => 82,
                'account_type_id'   => 10,
                'name'              => _l('acc_treasury_shares'),
                'note'              => _l('acc_treasury_shares_note'),
                'order'             => 82,
                ],
            [
                'id'                => 83,
                'account_type_id'   => 11,
                'name'              => _l('acc_discounts_refunds_given'),
                'note'              => _l('acc_discounts_refunds_given_note'),
                'order'             => 83,
                ],
            [
                'id'                => 84,
                'account_type_id'   => 11,
                'name'              => _l('acc_non_profit_income'),
                'note'              => _l('acc_non_profit_income_note'),
                'order'             => 84,
                ],
            [
                'id'                => 85,
                'account_type_id'   => 11,
                'name'              => _l('acc_other_primary_income'),
                'note'              => _l('acc_other_primary_income_note'),
                'order'             => 85,
                ],
            [
                'id'                => 86,
                'account_type_id'   => 11,
                'name'              => _l('acc_revenue_general'),
                'note'              => _l('acc_revenue_general_note'),
                'order'             => 86,
                ],
            [
                'id'                => 87,
                'account_type_id'   => 11,
                'name'              => _l('acc_sales_retail'),
                'note'              => _l('acc_sales_retail_note'),
                'order'             => 87,
                ],
            [
                'id'                => 88,
                'account_type_id'   => 11,
                'name'              => _l('acc_sales_wholesale'),
                'note'              => _l('acc_sales_wholesale_note'),
                'order'             => 88,
                ],
            [
                'id'                => 89,
                'account_type_id'   => 11,
                'name'              => _l('acc_sales_of_product_income'),
                'note'              => _l('acc_sales_of_product_income_note'),
                'order'             => 89,
                ],
            [
                'id'                => 90,
                'account_type_id'   => 11,
                'name'              => _l('acc_service_fee_income'),
                'note'              => _l('acc_service_fee_income_note'),
                'order'             => 90,
                ],
            [
                'id'                => 91,
                'account_type_id'   => 11,
                'name'              => _l('acc_unapplied_cash_payment_income'),
                'note'              => _l('acc_unapplied_cash_payment_income_note'),
                'order'             => 91,
                ],
            [
                'id'                => 92,
                'account_type_id'   => 12,
                'name'              => _l('acc_dividend_income'),
                'note'              => _l('acc_dividend_income_note'),
                'order'             => 92,
                ],
            [
                'id'                => 93,
                'account_type_id'   => 12,
                'name'              => _l('acc_interest_earned'),
                'note'              => _l('acc_interest_earned_note'),
                'order'             => 93,
                ],
            [
                'id'                => 94,
                'account_type_id'   => 12,
                'name'              => _l('acc_loss_on_disposal_of_assets'),
                'note'              => _l('acc_loss_on_disposal_of_assets_note'),
                'order'             => 94,
                ],
            [
                'id'                => 95,
                'account_type_id'   => 12,
                'name'              => _l('acc_other_investment_income'),
                'note'              => _l('acc_other_investment_income_note'),
                'order'             => 95,
                ],
            [
                'id'                => 96,
                'account_type_id'   => 12,
                'name'              => _l('acc_other_miscellaneous_income'),
                'note'              => _l('acc_other_miscellaneous_income_note'),
                'order'             => 96,
                ],
            [
                'id'                => 97,
                'account_type_id'   => 12,
                'name'              => _l('acc_other_operating_income'),
                'note'              => _l('acc_other_operating_income_note'),
                'order'             => 97,
                ],
            [
                'id'                => 98,
                'account_type_id'   => 12,
                'name'              => _l('acc_tax_exempt_interest'),
                'note'              => _l('acc_tax_exempt_interest_note'),
                'order'             => 98,
                ],
            [
                'id'                => 99,
                'account_type_id'   => 12,
                'name'              => _l('acc_unrealised_loss_on_securities_net_of_tax'),
                'note'              => _l('acc_unrealised_loss_on_securities_net_of_tax_note'),
                'order'             => 99,
                ],
            [
                'id'                => 100,
                'account_type_id'   => 13,
                'name'              => _l('acc_cost_of_labour_cos'),
                'note'              => _l('acc_cost_of_labour_cos_note'),
                'order'             => 100,
                ],
            [
                'id'                => 101,
                'account_type_id'   => 13,
                'name'              => _l('acc_equipment_rental_cos'),
                'note'              => _l('acc_equipment_rental_cos_note'),
                'order'             => 101,
                ],
            [
                'id'                => 102,
                'account_type_id'   => 13,
                'name'              => _l('acc_freight_and_delivery_cos'),
                'note'              => _l('acc_freight_and_delivery_cos_note'),
                'order'             => 102,
                ],
            [
                'id'                => 103,
                'account_type_id'   => 13,
                'name'              => _l('acc_other_costs_of_sales_cos'),
                'note'              => _l('acc_other_costs_of_sales_cos_note'),
                'order'             => 103,
                ],
            [
                'id'                => 104,
                'account_type_id'   => 13,
                'name'              => _l('acc_supplies_and_materials_cos'),
                'note'              => _l('acc_supplies_and_materials_cos_note'),
                'order'             => 104,
                ],
            [
                'id'                => 105,
                'account_type_id'   => 14,
                'name'              => _l('acc_advertising_promotional'),
                'note'              => _l('acc_advertising_promotional_note'),
                'order'             => 105,
                ],
            [
                'id'                => 106,
                'account_type_id'   => 14,
                'name'              => _l('acc_amortisation_expense'),
                'note'              => _l('acc_amortisation_expense_note'),
                'order'             => 106,
                ],
            [
                'id'                => 107,
                'account_type_id'   => 14,
                'name'              => _l('acc_auto'),
                'note'              => _l('acc_auto_note'),
                'order'             => 107,
                ],
            [
                'id'                => 108,
                'account_type_id'   => 14,
                'name'              => _l('acc_bad_debts'),
                'note'              => _l('acc_bad_debts_note'),
                'order'             => 108,
                ],
            [
                'id'                => 109,
                'account_type_id'   => 14,
                'name'              => _l('acc_bank_charges'),
                'note'              => _l('acc_bank_charges_note'),
                'order'             => 109,
                ],
            [
                'id'                => 110,
                'account_type_id'   => 14,
                'name'              => _l('acc_charitable_contributions'),
                'note'              => _l('acc_charitable_contributions_note'),
                'order'             => 110,
                ],
            [
                'id'                => 111,
                'account_type_id'   => 14,
                'name'              => _l('acc_commissions_and_fees'),
                'note'              => _l('acc_commissions_and_fees_note'),
                'order'             => 111,
                ],
            [
                'id'                => 112,
                'account_type_id'   => 14,
                'name'              => _l('acc_cost_of_labour'),
                'note'              => _l('acc_cost_of_labour_note'),
                'order'             => 112,
                ],
            [
                'id'                => 113,
                'account_type_id'   => 14,
                'name'              => _l('acc_dues_and_subscriptions'),
                'note'              => _l('acc_dues_and_subscriptions_note'),
                'order'             => 113,
                ],
            [
                'id'                => 114,
                'account_type_id'   => 14,
                'name'              => _l('acc_equipment_rental'),
                'note'              => _l('acc_equipment_rental_note'),
                'order'             => 114,
                ],
            [
                'id'                => 115,
                'account_type_id'   => 14,
                'name'              => _l('acc_finance_costs'),
                'note'              => _l('acc_finance_costs_note'),
                'order'             => 115,
                ],
            [
                'id'                => 116,
                'account_type_id'   => 14,
                'name'              => _l('acc_income_tax_expense'),
                'note'              => _l('acc_income_tax_expense_note'),
                'order'             => 116,
                ],
            [
                'id'                => 117,
                'account_type_id'   => 14,
                'name'              => _l('acc_insurance'),
                'note'              => _l('acc_insurance_note'),
                'order'             => 117,
                ],
            [
                'id'                => 118,
                'account_type_id'   => 14,
                'name'              => _l('acc_interest_paid'),
                'note'              => _l('acc_interest_paid_note'),
                'order'             => 118,
                ],
            [
                'id'                => 119,
                'account_type_id'   => 14,
                'name'              => _l('acc_legal_and_professional_fees'),
                'note'              => _l('acc_legal_and_professional_fees_note'),
                'order'             => 119,
                ],
            [
                'id'                => 120,
                'account_type_id'   => 14,
                'name'              => _l('acc_loss_on_discontinued_operations_net_of_tax'),
                'note'              => _l('acc_loss_on_discontinued_operations_net_of_tax_note'),
                'order'             => 120,
                ],
            [
                'id'                => 121,
                'account_type_id'   => 14,
                'name'              => _l('acc_management_compensation'),
                'note'              => _l('acc_management_compensation_note'),
                'order'             => 121,
                ],
            [
                'id'                => 122,
                'account_type_id'   => 14,
                'name'              => _l('acc_meals_and_entertainment'),
                'note'              => _l('acc_meals_and_entertainment_note'),
                'order'             => 122,
                ],
            [
                'id'                => 123,
                'account_type_id'   => 14,
                'name'              => _l('acc_office_general_administrative_expenses'),
                'note'              => _l('acc_office_general_administrative_expenses_note'),
                'order'             => 123,
                ],
            [
                'id'                => 124,
                'account_type_id'   => 14,
                'name'              => _l('acc_other_miscellaneous_service_cost'),
                'note'              => _l('acc_other_miscellaneous_service_cost_note'),
                'order'             => 124,
                ],
            [
                'id'                => 125,
                'account_type_id'   => 14,
                'name'              => _l('acc_other_selling_expenses'),
                'note'              => _l('acc_other_selling_expenses_note'),
                'order'             => 125,
                ],
            [
                'id'                => 126,
                'account_type_id'   => 14,
                'name'              => _l('acc_payroll_expenses'),
                'note'              => _l('acc_payroll_expenses_note'),
                'order'             => 126,
                ],
            [
                'id'                => 127,
                'account_type_id'   => 14,
                'name'              => _l('acc_rent_or_lease_of_buildings'),
                'note'              => _l('acc_rent_or_lease_of_buildings_note'),
                'order'             => 127,
                ],
            [
                'id'                => 128,
                'account_type_id'   => 14,
                'name'              => _l('acc_repair_and_maintenance'),
                'note'              => _l('acc_repair_and_maintenance_note'),
                'order'             => 128,
                ],
            [
                'id'                => 129,
                'account_type_id'   => 14,
                'name'              => _l('acc_shipping_and_delivery_expense'),
                'note'              => _l('acc_shipping_and_delivery_expense_note'),
                'order'             => 129,
                ],
            [
                'id'                => 130,
                'account_type_id'   => 14,
                'name'              => _l('acc_supplies_and_materials'),
                'note'              => _l('acc_supplies_and_materials_note'),
                'order'             => 130,
                ],
            [
                'id'                => 131,
                'account_type_id'   => 14,
                'name'              => _l('acc_taxes_paid'),
                'note'              => _l('acc_taxes_paid_note'),
                'order'             => 131,
                ],
            [
                'id'                => 132,
                'account_type_id'   => 14,
                'name'              => _l('acc_travel_expenses_general_and_admin_expenses'),
                'note'              => _l('acc_travel_expenses_general_and_admin_expenses_note'),
                'order'             => 132,
                ],
            [
                'id'                => 133,
                'account_type_id'   => 14,
                'name'              => _l('acc_travel_expenses_selling_expense'),
                'note'              => _l('acc_travel_expenses_selling_expense_note'),
                'order'             => 133,
                ],
            [
                'id'                => 134,
                'account_type_id'   => 14,
                'name'              => _l('acc_unapplied_cash_bill_payment_expense'),
                'note'              => _l('acc_unapplied_cash_bill_payment_expense_note'),
                'order'             => 134,
                ],
            [
                'id'                => 135,
                'account_type_id'   => 14,
                'name'              => _l('acc_utilities'),
                'note'              => _l('acc_utilities_note'),
                'order'             => 135,
                ],
            [
                'id'                => 136,
                'account_type_id'   => 15,
                'name'              => _l('acc_amortisation'),
                'note'              => _l('acc_amortisation_note'),
                'order'             => 136,
                ],
            [
                'id'                => 137,
                'account_type_id'   => 15,
                'name'              => _l('acc_depreciation'),
                'note'              => _l('acc_depreciation_note'),
                'order'             => 137,
                ],
            [
                'id'                => 138,
                'account_type_id'   => 15,
                'name'              => _l('acc_exchange_gain_or_loss'),
                'note'              => _l('acc_exchange_gain_or_loss_note'),
                'order'             => 138,
                ],
            [
                'id'                => 139,
                'account_type_id'   => 15,
                'name'              => _l('acc_other_expense'),
                'note'              => _l('acc_other_expense_note'),
                'order'             => 139,
                ],
            [
                'id'                => 140,
                'account_type_id'   => 15,
                'name'              => _l('acc_penalties_and_settlements'),
                'note'              => _l('acc_penalties_and_settlements_note'),
                'order'             => 140,
                ],
            ]);

        usort($account_type_details, function ($a, $b) {
            return $a['order'] - $b['order'];
        });

        $account_type_details_2 = $this->db->get(db_prefix().'acc_account_type_details')->result_array();

        return array_merge($account_type_details, $account_type_details_2);
    }

    /**
     * add default account
     */
    public function add_default_account(){

        if($this->db->count_all_results(db_prefix().'acc_accounts') > 1){
            return false;
        }

        $accounts = [
            [
                'name' => '',
                'key_name' => 'acc_accounts_receivable',
                'account_type_id' => 1,
                'account_detail_type_id' => 1,
            ],
            [
                'name' => '',
                'key_name' => 'acc_accrued_holiday_payable',
                'account_type_id' => 9,
                'account_detail_type_id' => 61,
            ],
            [
                'name' => '',
                'key_name' => 'acc_accrued_liabilities',
                'account_type_id' => 8,
                'account_detail_type_id' => 44,
            ],
            [
                'name' => '',
                'key_name' => 'acc_accrued_non_current_liabilities',
                'account_type_id' => 9,
                'account_detail_type_id' => 62,
            ],
            [
                'name' => '',
                'key_name' => 'acc_accumulated_depreciation_on_property_plant_and_equipment',
                'account_type_id' => 4,
                'account_detail_type_id' => 22,
            ],
            [
                'name' => '',
                'key_name' => 'acc_allowance_for_bad_debts',
                'account_type_id' => 2,
                'account_detail_type_id' => 2,
            ],
            [
                'name' => '',
                'key_name' => 'acc_amortisation_expense',
                'account_type_id' => 14,
                'account_detail_type_id' => 106,
            ],
            [
                'name' => '',
                'key_name' => 'acc_assets_held_for_sale',
                'account_type_id' => 5,
                'account_detail_type_id' => 32,
            ],
            [
                'name' => '',
                'key_name' => 'acc_available_for_sale_assets_short_term',
                'account_type_id' => 2,
                'account_detail_type_id' => 3,
            ],
            [
                'name' => '',
                'key_name' => 'acc_bad_debts',
                'account_type_id' => 14,
                'account_detail_type_id' => 108,
            ],
            [
                'name' => '',
                'key_name' => 'acc_bank_charges',
                'account_type_id' => 14,
                'account_detail_type_id' => 109,
            ],
            [
                'name' => '',
                'key_name' => 'acc_billable_expense_income',
                'account_type_id' => 11,
                'account_detail_type_id' => 89,
            ],
            [
                'name' => '',
                'key_name' => 'acc_cash_and_cash_equivalents',
                'account_type_id' => 3,
                'account_detail_type_id' => 15,
            ],
            [
                'name' => '',
                'key_name' => 'acc_change_in_inventory_cos',
                'account_type_id' => 13,
                'account_detail_type_id' => 100,
            ],
            [
                'name' => '',
                'key_name' => 'acc_commissions_and_fees',
                'account_type_id' => 14,
                'account_detail_type_id' => 111,
            ],
            [
                'name' => '',
                'key_name' => 'acc_cost_of_sales',
                'account_type_id' => 13,
                'account_detail_type_id' => 104,
            ],
            [
                'name' => '',
                'key_name' => 'acc_deferred_tax_assets',
                'account_type_id' => 5,
                'account_detail_type_id' => 33,
            ],
            [
                'name' => '',
                'key_name' => 'acc_direct_labour_cos',
                'account_type_id' => 13,
                'account_detail_type_id' => 100,
            ],
            [
                'name' => '',
                'key_name' => 'acc_discounts_given_cos',
                'account_type_id' => 13,
                'account_detail_type_id' => 100,
            ],
            [
                'name' => '',
                'key_name' => 'acc_dividend_disbursed',
                'account_type_id' => 10,
                'account_detail_type_id' => 69,
            ],
            [
                'name' => '',
                'key_name' => 'acc_dividend_income',
                'account_type_id' => 12,
                'account_detail_type_id' => 92,
            ],
            [
                'name' => '',
                'key_name' => 'acc_dividends_payable',
                'account_type_id' => 8,
                'account_detail_type_id' => 48,
            ],
            [
                'name' => '',
                'key_name' => 'acc_dues_and_subscriptions',
                'account_type_id' => 14,
                'account_detail_type_id' => 113,
            ],
            [
                'name' => '',
                'key_name' => 'acc_equipment_rental',
                'account_type_id' => 14,
                'account_detail_type_id' => 114,
            ],
            [
                'name' => '',
                'key_name' => 'acc_equity_in_earnings_of_subsidiaries',
                'account_type_id' => 10,
                'account_detail_type_id' => 70,
            ],
            [
                'name' => '',
                'key_name' => 'acc_freight_and_delivery_cos',
                'account_type_id' => 13,
                'account_detail_type_id' => 100,
            ],
            [
                'name' => '',
                'key_name' => 'acc_goodwill',
                'account_type_id' => 5,
                'account_detail_type_id' => 34,
            ],
            [
                'name' => '',
                'key_name' => 'acc_income_tax_expense',
                'account_type_id' => 14,
                'account_detail_type_id' => 116,
            ],
            [
                'name' => '',
                'key_name' => 'acc_income_tax_payable',
                'account_type_id' => 8,
                'account_detail_type_id' => 50,
            ],
            [
                'name' => '',
                'key_name' => 'acc_insurance_disability',
                'account_type_id' => 14,
                'account_detail_type_id' => 117,
            ],
            [
                'name' => '',
                'key_name' => 'acc_insurance_general',
                'account_type_id' => 14,
                'account_detail_type_id' => 117,
            ],
            [
                'name' => '',
                'key_name' => 'acc_insurance_liability',
                'account_type_id' => 14,
                'account_detail_type_id' => 117,
            ],
            [
                'name' => '',
                'key_name' => 'acc_intangibles',
                'account_type_id' => 5,
                'account_detail_type_id' => 35,
            ],
            [
                'name' => '',
                'key_name' => 'acc_interest_expense',
                'account_type_id' => 14,
                'account_detail_type_id' => 118,
            ],
            [
                'name' => '',
                'key_name' => 'acc_interest_income',
                'account_type_id' => 12,
                'account_detail_type_id' => 93,
            ],
            [
                'name' => '',
                'key_name' => 'acc_inventory',
                'account_type_id' => 2,
                'account_detail_type_id' => 5,
            ],
            [
                'name' => '',
                'key_name' => 'acc_inventory_asset',
                'account_type_id' => 2,
                'account_detail_type_id' => 5,
            ],
            [
                'name' => '',
                'key_name' => 'acc_legal_and_professional_fees',
                'account_type_id' => 14,
                'account_detail_type_id' => 119,
            ],
            [
                'name' => '',
                'key_name' => 'acc_liabilities_related_to_assets_held_for_sale',
                'account_type_id' => 9,
                'account_detail_type_id' => 63,
            ],
            [
                'name' => '',
                'key_name' => 'acc_long_term_debt',
                'account_type_id' => 9,
                'account_detail_type_id' => 64,
            ],
            [
                'name' => '',
                'key_name' => 'acc_long_term_investments',
                'account_type_id' => 5,
                'account_detail_type_id' => 38,
            ],
            [
                'name' => '',
                'key_name' => 'acc_loss_on_discontinued_operations_net_of_tax',
                'account_type_id' => 14,
                'account_detail_type_id' => 120,
            ],
            [
                'name' => '',
                'key_name' => 'acc_loss_on_disposal_of_assets',
                'account_type_id' => 12,
                'account_detail_type_id' => 94,
            ],
            [
                'name' => '',
                'key_name' => 'acc_management_compensation',
                'account_type_id' => 14,
                'account_detail_type_id' => 121,
            ],
            [
                'name' => '',
                'key_name' => 'acc_materials_cos',
                'account_type_id' => 13,
                'account_detail_type_id' => 100,
            ],
            [
                'name' => '',
                'key_name' => 'acc_meals_and_entertainment',
                'account_type_id' => 14,
                'account_detail_type_id' => 122,
            ],
            [
                'name' => '',
                'key_name' => 'acc_office_expenses',
                'account_type_id' => 14,
                'account_detail_type_id' => 123,
            ],
            [
                'name' => '',
                'key_name' => 'acc_other_cos',
                'account_type_id' => 13,
                'account_detail_type_id' => 100,
            ],
            [
                'name' => '',
                'key_name' => 'acc_other_comprehensive_income',
                'account_type_id' => 10,
                'account_detail_type_id' => 73,
            ],
            [
                'name' => '',
                'key_name' => 'acc_other_general_and_administrative_expenses',
                'account_type_id' => 14,
                'account_detail_type_id' => 123,
            ],
            [
                'name' => '',
                'key_name' => 'acc_other_operating_income_expenses',
                'account_type_id' => 12,
                'account_detail_type_id' => 97,
            ],
            [
                'name' => '',
                'key_name' => 'acc_other_selling_expenses',
                'account_type_id' => 14,
                'account_detail_type_id' => 125,
            ],
            [
                'name' => '',
                'key_name' => 'acc_other_type_of_expenses_advertising_expenses',
                'account_type_id' => 14,
                'account_detail_type_id' => 105,
            ],
            [
                'name' => '',
                'key_name' => 'acc_overhead_cos',
                'account_type_id' => 13,
                'account_detail_type_id' => 100,
            ],
            [
                'name' => '',
                'key_name' => 'acc_payroll_clearing',
                'account_type_id' => 8,
                'account_detail_type_id' => 55,
            ],
            [
                'name' => '',
                'key_name' => 'acc_payroll_expenses',
                'account_type_id' => 14,
                'account_detail_type_id' => 126,
            ],
            [
                'name' => '',
                'key_name' => 'acc_payroll_liabilities',
                'account_type_id' => 8,
                'account_detail_type_id' => 56,
            ],
            [
                'name' => '',
                'key_name' => 'acc_prepaid_expenses',
                'account_type_id' => 2,
                'account_detail_type_id' => 11,
            ],
            [
                'name' => '',
                'key_name' => 'acc_property_plant_and_equipment',
                'account_type_id' => 4,
                'account_detail_type_id' => 26,
            ],
            [
                'name' => '',
                'key_name' => 'acc_purchases',
                'account_type_id' => 14,
                'account_detail_type_id' => 130,
            ],
            [
                'name' => '',
                'key_name' => 'acc_reconciliation_discrepancies',
                'account_type_id' => 15,
                'account_detail_type_id' => 139,
            ],
            [
                'name' => '',
                'key_name' => 'acc_rent_or_lease_payments',
                'account_type_id' => 14,
                'account_detail_type_id' => 127,
            ],
            [
                'name' => '',
                'key_name' => 'acc_repair_and_maintenance',
                'account_type_id' => 14,
                'account_detail_type_id' => 128,
            ],
            [
                'name' => '',
                'key_name' => 'acc_retained_earnings',
                'account_type_id' => 10,
                'account_detail_type_id' => 80,
            ],
            [
                'name' => '',
                'key_name' => 'acc_revenue_general',
                'account_type_id' => 11,
                'account_detail_type_id' => 86,
            ],
            [
                'name' => '',
                'key_name' => 'acc_sales',
                'account_type_id' => 11,
                'account_detail_type_id' => 89,
            ],
            [
                'name' => '',
                'key_name' => 'acc_sales_retail',
                'account_type_id' => 11,
                'account_detail_type_id' => 87,
            ],
            [
                'name' => '',
                'key_name' => 'acc_sales_wholesale',
                'account_type_id' => 11,
                'account_detail_type_id' => 88,
            ],
            [
                'name' => '',
                'key_name' => 'acc_sales_of_product_income',
                'account_type_id' => 11,
                'account_detail_type_id' => 89,
            ],
            [
                'name' => '',
                'key_name' => 'acc_share_capital',
                'account_type_id' => 10,
                'account_detail_type_id' => 81,
            ],
            [
                'name' => '',
                'key_name' => 'acc_shipping_and_delivery_expense',
                'account_type_id' => 14,
                'account_detail_type_id' => 129,
            ],
            [
                'name' => '',
                'key_name' => 'acc_short_term_debit',
                'account_type_id' => 8,
                'account_detail_type_id' => 54,
            ],
            [
                'name' => '',
                'key_name' => 'acc_stationery_and_printing',
                'account_type_id' => 14,
                'account_detail_type_id' => 123,
            ],
            [
                'name' => '',
                'key_name' => 'acc_subcontractors_cos',
                'account_type_id' => 13,
                'account_detail_type_id' => 100,
            ],
            [
                'name' => '',
                'key_name' => 'acc_supplies',
                'account_type_id' => 14,
                'account_detail_type_id' => 130,
            ],
            [
                'name' => '',
                'key_name' => 'acc_travel_expenses_general_and_admin_expenses',
                'account_type_id' => 14,
                'account_detail_type_id' => 132,
            ],
            [
                'name' => '',
                'key_name' => 'acc_travel_expenses_selling_expense',
                'account_type_id' => 14,
                'account_detail_type_id' => 133,
            ],
            [
                'name' => '',
                'key_name' => 'acc_unapplied_cash_payment_income',
                'account_type_id' => 11,
                'account_detail_type_id' => 91,
            ],
            [
                'name' => '',
                'key_name' => 'acc_uncategorised_asset',
                'account_type_id' => 2,
                'account_detail_type_id' => 10,
            ],
            [
                'name' => '',
                'key_name' => 'acc_uncategorised_expense',
                'account_type_id' => 14,
                'account_detail_type_id' => 124,
            ],
            [
                'name' => '',
                'key_name' => 'acc_uncategorised_income',
                'account_type_id' => 11,
                'account_detail_type_id' => 89,
            ],
            [
                'name' => '',
                'key_name' => 'acc_undeposited_funds',
                'account_type_id' => 2,
                'account_detail_type_id' => 13,
            ],
            [
                'name' => '',
                'key_name' => 'acc_unrealised_loss_on_securities_net_of_tax',
                'account_type_id' => 12,
                'account_detail_type_id' => 99,
            ],
            [
                'name' => '',
                'key_name' => 'acc_utilities',
                'account_type_id' => 14,
                'account_detail_type_id' => 135,
            ],
            [
                'name' => '',
                'key_name' => 'acc_wage_expenses',
                'account_type_id' => 14,
                'account_detail_type_id' => 126,
            ],
            [
                'name' => '',
                'key_name' => 'acc_credit_card',
                'account_type_id' => 7,
                'account_detail_type_id' => 43,
            ],
            [
                'name' => '',
                'key_name' => 'acc_accounts_payable',
                'account_type_id' => 6,
                'account_detail_type_id' => 42,
            ],
        ];

        $affectedRows = $this->db->insert_batch(db_prefix().'acc_accounts',  $accounts);

        if ($affectedRows > 0) {
            $this->db->where('name', 'acc_add_default_account');
            $this->db->update(db_prefix() . 'options', [
                    'value' => 1,
                ]);

            return true;
        }

        return false;
    }

    /**
     * add default account new
     */
    public function add_default_account_new(){
        $this->db->where('key_name != ""');
        $affectedRows = $this->db->update(db_prefix().'acc_accounts',  ['default_account' => 1]);

        if ($affectedRows > 0) {
            $this->db->where('name', 'add_default_account_new');
            $this->db->update(db_prefix() . 'options', [
                    'value' => 1,
                ]);

            return true;
        }

        return false;
    }

    /**
     * update general setting
     *
     * @param      array   $data   The data
     *
     * @return     boolean 
     */
    public function update_general_setting($data){
        $affectedRows = 0;
        if(!isset($data['acc_close_the_books'])){
            $data['acc_close_the_books'] = 0;
        }
        if(!isset($data['acc_enable_account_numbers'])){
            $data['acc_enable_account_numbers'] = 0;
        }
        if(!isset($data['acc_show_account_numbers'])){
            $data['acc_show_account_numbers'] = 0;
        }
       
        if($data['acc_closing_date'] != ''){
            $data['acc_closing_date'] = to_sql_date($data['acc_closing_date']);
        }

        foreach ($data as $key => $value) {
            $this->db->where('name', $key);
            $this->db->update(db_prefix() . 'options', [
                    'value' => $value,
                ]);
            if ($this->db->affected_rows() > 0) {
                $affectedRows++;
            }
        }

        if ($affectedRows > 0) {
            return true;
        }
        return false;
    }

    /**
     * update automatic conversion
     *
     * @param      array   $data   The data
     *
     * @return     boolean 
     */
    public function update_automatic_conversion($data){
        $affectedRows = 0;
        
        if(!isset($data['acc_invoice_automatic_conversion'])){
            $data['acc_invoice_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_payment_automatic_conversion'])){
            $data['acc_payment_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_credit_note_automatic_conversion'])){
            $data['acc_credit_note_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_credit_note_refund_automatic_conversion'])){
            $data['acc_credit_note_refund_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_expense_automatic_conversion'])){
            $data['acc_expense_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_tax_automatic_conversion'])){
            $data['acc_tax_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_payment_expense_automatic_conversion'])){
            $data['acc_payment_expense_automatic_conversion'] = 0;
        }

        foreach ($data as $key => $value) {
            $this->db->where('name', $key);
            $this->db->update(db_prefix() . 'options', [
                    'value' => $value,
                ]);
            if ($this->db->affected_rows() > 0) {
                $affectedRows++;
            }
        }

        if ($affectedRows > 0) {
            return true;
        }

        return false;
    }

    /**
     * get accounts
     * @param  integer $id    member group id
     * @param  array  $where
     * @return object
     */
    public function get_accounts($id = '', $where = [], $show_account_numbers = true)
    {
        if (is_numeric($id)) {
            $this->db->where('id', $id);
            return $this->db->get(db_prefix() . 'acc_accounts')->row();
        }

        $acc_show_account_numbers = 0;
        if ($show_account_numbers) {
            $acc_show_account_numbers = get_option('acc_show_account_numbers');
        }

        $this->db->where($where);
        $this->db->where('active', 1);
        $this->db->order_by('account_type_id,account_detail_type_id', 'desc');
        $accounts = $this->db->get(db_prefix() . 'acc_accounts')->result_array();

        $account_types = $this->get_account_types();
        $detail_types = $this->get_account_type_details();

        $account_type_name = [];
        $detail_type_name = [];

        foreach ($account_types as $key => $value) {
            $account_type_name[$value['id']] = $value['name'];
        }

        foreach ($detail_types as $key => $value) {
            $detail_type_name[$value['id']] = $value['name'];
        }

        foreach ($accounts as $key => $value) {

            if($acc_show_account_numbers == 1 && $value['number'] != ''){
                $accounts[$key]['name'] = $value['name'] != '' ? $value['number'].' - '.$value['name'] : $value['number'].' - '._l($value['key_name']);
            }else{
                $accounts[$key]['name'] = $value['name'] != '' ? $value['name'] : _l($value['key_name']);
            }
            
            $_account_type_name = isset($account_type_name[$value['account_type_id']]) ? $account_type_name[$value['account_type_id']] : '';
            $_detail_type_name = isset($detail_type_name[$value['account_detail_type_id']]) ? $detail_type_name[$value['account_detail_type_id']] : '';
            $accounts[$key]['account_type_name'] = $_account_type_name;
            $accounts[$key]['detail_type_name'] = $_detail_type_name;
        }

        return $accounts;
    }

    /**
     * add new account
     * @param array $data
     * @return integer
     */
    public function add_account($data)
    {
        if (isset($data['id'])) {
            unset($data['id']);
        }

        if (!isset($data['account_type_id'])) {
            $data['account_type_id'] = 16;
        }

        if (!isset($data['account_detail_type_id'])) {
            $data['account_detail_type_id'] = 14;
        }

        if($data['balance_as_of'] != ''){
            $data['balance_as_of'] = to_sql_date($data['balance_as_of']);
        }

        if(isset($data['update_balance'])){
            unset($data['update_balance']);
        }

        $data['balance'] = str_replace(',', '', $data['balance']);
        $this->db->insert(db_prefix() . 'acc_accounts', $data);

        $insert_id = $this->db->insert_id();

        if ($insert_id) {
            if($data['balance'] != 0 && $data['balance'] != ''){
                $node = [];
                $node['account'] = $insert_id;
                $node['ending_balance'] = $data['balance'];
                $node['beginning_balance'] = 0;
                $node['opening_balance'] = 0;
                $node['finish'] = 1;
                if($data['balance_as_of'] != ''){
                    $node['ending_date'] = $data['balance_as_of'];
                }else{
                    $node['ending_date'] = date('Y-m-d');
                }
            
                $this->db->insert(db_prefix().'acc_reconciles', $node);
                $reconcile_id = $this->db->insert_id();

                $this->db->where('account_type_id', 10);
                $this->db->where('account_detail_type_id', 71);
                $account = $this->db->get(db_prefix().'acc_accounts')->row();

                if($account){
                    $node = [];

                    if($data['account_type_id'] == 7 || $data['account_type_id'] == 15 || $data['account_type_id'] == 8 || $data['account_type_id'] == 9){
                        if($data['balance'] > 0){
                            $node['debit'] = $data['balance'];
                            $node['credit'] = 0;
                        }else{
                            $node['debit'] = 0;
                            $node['credit'] = abs($data['balance']);
                        }
                    }else{
                        if($data['balance'] > 0){
                            $node['debit'] = 0;
                            $node['credit'] = $data['balance'];
                        }else{
                            $node['debit'] = abs($data['balance']);
                            $node['credit'] = 0;
                        }
                    }

                    $node['split'] = $insert_id;
                    $node['account'] = $account->id;
                    $node['rel_id'] = 0;
                    $node['rel_type'] = 'deposit';
                    if($data['balance_as_of'] != ''){
                        $node['date'] = $data['balance_as_of'];
                    }else{
                        $node['date'] = date('Y-m-d');
                    }
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();

                    $this->db->insert(db_prefix().'acc_account_history', $node);

                    $node = [];
                    if($data['account_type_id'] == 7 || $data['account_type_id'] == 15 || $data['account_type_id'] == 8 || $data['account_type_id'] == 9){
                        if($data['balance'] > 0){
                            $node['debit'] = 0;
                            $node['credit'] = $data['balance'];
                        }else{
                            $node['debit'] = abs($data['balance']);
                            $node['credit'] = 0;
                        }
                    }else{
                        if($data['balance'] > 0){
                            $node['debit'] = $data['balance'];
                            $node['credit'] = 0;
                        }else{
                            $node['debit'] = 0;
                            $node['credit'] = abs($data['balance']);
                        }
                    }

                    $node['reconcile'] = $reconcile_id;
                    $node['split'] = $account->id;
                    $node['account'] = $insert_id;
                    $node['rel_id'] = 0;
                    $node['rel_type'] = 'deposit';
                    if($data['balance_as_of'] != ''){
                        $node['date'] = $data['balance_as_of'];
                    }else{
                        $node['date'] = date('Y-m-d');
                    }
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();

                    $this->db->insert(db_prefix().'acc_account_history', $node);
                }else{
                    $this->db->insert(db_prefix().'acc_accounts', [
                        'name' => '',
                        'key_name' => 'acc_opening_balance_equity',
                        'account_type_id' => 10,
                        'account_detail_type_id' => 71,
                    ]);

                    $account_id = $this->db->insert_id();

                    if ($account_id) {
                        $node = [];
                        if($data['account_type_id'] == 7 || $data['account_type_id'] == 15 || $data['account_type_id'] == 8 || $data['account_type_id'] == 9){
                            if($data['balance'] > 0){
                                $node['debit'] = $data['balance'];
                                $node['credit'] = 0;
                            }else{
                                $node['debit'] = 0;
                                $node['credit'] = abs($data['balance']);
                            }
                        }else{
                            if($data['balance'] > 0){
                                $node['debit'] = 0;
                                $node['credit'] = $data['balance'];
                            }else{
                                $node['debit'] = abs($data['balance']);
                                $node['credit'] = 0;
                            }
                        }
                        
                        $node['split'] = $insert_id;
                        $node['account'] = $account_id;
                        if($data['balance_as_of'] != ''){
                            $node['date'] = $data['balance_as_of'];
                        }else{
                            $node['date'] = date('Y-m-d');
                        }
                        $node['rel_id'] = 0;
                        $node['rel_type'] = 'deposit';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();

                        $this->db->insert(db_prefix().'acc_account_history', $node);

                        $node = [];
                        if($data['account_type_id'] == 7 || $data['account_type_id'] == 15 || $data['account_type_id'] == 8 || $data['account_type_id'] == 9){
                            if($data['balance'] > 0){
                                $node['debit'] = 0;
                                $node['credit'] = $data['balance'];
                            }else{
                                $node['debit'] = abs($data['balance']);
                                $node['credit'] = 0;
                            }
                        }else{
                            if($data['balance'] > 0){
                                $node['debit'] = $data['balance'];
                                $node['credit'] = 0;
                            }else{
                                $node['debit'] = 0;
                                $node['credit'] = abs($data['balance']);
                            }
                        }
                        
                        $node['reconcile'] = $reconcile_id;
                        $node['split'] = $account_id;
                        $node['account'] = $insert_id;
                        if($data['balance_as_of'] != ''){
                            $node['date'] = $data['balance_as_of'];
                        }else{
                            $node['date'] = date('Y-m-d');
                        }
                        $node['rel_id'] = 0;
                        $node['rel_type'] = 'deposit';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();

                        $this->db->insert(db_prefix().'acc_account_history', $node);
                    }
                }
            }

           
            return $insert_id;
        }

        return false;
    }

    /**
     * update account
     * @param array $data
     * @param integer $id
     * @return integer
     */
    public function update_account($data, $id)
    {
        if (isset($data['id'])) {
            unset($data['id']);
        }

        if (!isset($data['account_type_id'])) {
            $data['account_type_id'] = 16;
        }

        if (!isset($data['account_detail_type_id'])) {
            $data['account_detail_type_id'] = 14;
        }

        if($data['balance_as_of'] != ''){
            $data['balance_as_of'] = to_sql_date($data['balance_as_of']);
        }
        $update_balance = 0;
        if(isset($data['update_balance'])){
            $update_balance = $data['update_balance'];
            unset($data['update_balance']);
        }

        $data['balance'] = str_replace(',', '', $data['balance']);
        $this->db->where('id', $id);
        $this->db->update(db_prefix() . 'acc_accounts', $data);

        if ($this->db->affected_rows() > 0) {
            if($data['balance'] > 0 && $update_balance == 1){
                $node = [];
                $node['account'] = $id;
                $node['ending_balance'] = $data['balance'];
                $node['beginning_balance'] = 0;
                $node['opening_balance'] = 0;
                $node['finish'] = 1;
                if($data['balance_as_of'] != ''){
                    $node['ending_date'] = $data['balance_as_of'];
                }else{
                    $node['ending_date'] = date('Y-m-d');
                }
            
                $this->db->insert(db_prefix().'acc_reconciles', $node);
                $reconcile_id = $this->db->insert_id();

                $this->db->where('account_type_id', 10);
                $this->db->where('account_detail_type_id', 71);
                $account = $this->db->get(db_prefix().'acc_accounts')->row();

                if($account){
                    $node = [];

                    if($data['account_type_id'] == 7 || $data['account_type_id'] == 15 || $data['account_type_id'] == 8 || $data['account_type_id'] == 9){
                        $node['debit'] = $data['balance'];
                        $node['credit'] = 0;

                    }else{
                        $node['debit'] = 0;
                        $node['credit'] = $data['balance'];
                    }

                    $node['split'] = $id;
                    $node['account'] = $account->id;

                    if($data['balance_as_of'] != ''){
                        $node['date'] = $data['balance_as_of'];
                    }else{
                        $node['date'] = date('Y-m-d');
                    }

                    $node['rel_id'] = 0;
                    $node['rel_type'] = 'deposit';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $this->db->insert(db_prefix().'acc_account_history', $node);

                    $node = [];
                    if($data['account_type_id'] == 7 || $data['account_type_id'] == 15 || $data['account_type_id'] == 8 || $data['account_type_id'] == 9){
                        $node['debit'] = 0;
                        $node['credit'] = $data['balance'];
                    }else{
                        $node['debit'] = $data['balance'];
                        $node['credit'] = 0;
                    }

                    $node['reconcile'] = $reconcile_id;
                    $node['split'] = $account->id;
                    $node['account'] = $id;
                    $node['rel_id'] = 0;

                    if($data['balance_as_of'] != ''){
                        $node['date'] = $data['balance_as_of'];
                    }else{
                        $node['date'] = date('Y-m-d');
                    }
                    $node['rel_type'] = 'deposit';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();

                    $this->db->insert(db_prefix().'acc_account_history', $node);
                }else{
                    $this->db->insert(db_prefix().'acc_accounts', [
                        'name' => '',
                        'key_name' => 'acc_opening_balance_equity',
                        'account_type_id' => 10,
                        'account_detail_type_id' => 71,
                    ]);

                    $account_id = $this->db->insert_id();

                    if ($account_id) {
                        $node = [];
                        if($data['account_type_id'] == 7 || $data['account_type_id'] == 15 || $data['account_type_id'] == 8 || $data['account_type_id'] == 9){
                            $node['debit'] = $data['balance'];
                            $node['credit'] = 0;
                        }else{
                            $node['debit'] = 0;
                            $node['credit'] = $data['balance'];
                        }
                        
                        $node['split'] = $id;
                        $node['account'] = $account_id;
                        $node['rel_id'] = 0;
                        if($data['balance_as_of'] != ''){
                            $node['date'] = $data['balance_as_of'];
                        }else{
                            $node['date'] = date('Y-m-d');
                        }
                        $node['rel_type'] = 'deposit';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();

                        $this->db->insert(db_prefix().'acc_account_history', $node);

                        $node = [];
                        if($data['account_type_id'] == 7 || $data['account_type_id'] == 15 || $data['account_type_id'] == 8 || $data['account_type_id'] == 9){
                            $node['debit'] = 0;
                            $node['credit'] = $data['balance'];
                        }else{
                            $node['debit'] = $data['balance'];
                            $node['credit'] = 0;
                        }
                        
                        $node['reconcile'] = $reconcile_id;
                        $node['split'] = $account_id;
                        $node['account'] = $id;
                        $node['rel_id'] = 0;
                        if($data['balance_as_of'] != ''){
                            $node['date'] = $data['balance_as_of'];
                        }else{
                            $node['date'] = date('Y-m-d');
                        }
                        $node['rel_type'] = 'deposit';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();

                        $this->db->insert(db_prefix().'acc_account_history', $node);
                    }
                }
            }

            return true;
        }

        return false;
    }

    /**
     * Get the data account to choose from.
     *
     * @return     array  The product group select.
     */
    public function get_data_account_to_select() {

        $accounts = $this->get_accounts();
        $acc_enable_account_numbers = get_option('acc_enable_account_numbers');
        $acc_show_account_numbers = get_option('acc_show_account_numbers');
        $list_accounts = [];

        $account_types = $this->get_account_types();
        $account_type_name = [];

        foreach ($account_types as $key => $value) {
            $account_type_name[$value['id']] = $value['name'];
        }

        foreach ($accounts as $key => $account) {
            $note = [];
            $note['id'] = $account['id'];

            $_account_type_name = isset($account_type_name[$account['account_type_id']]) ? $account_type_name[$account['account_type_id']] : '';
           
            $note['label'] = $account['name'].' - '.$_account_type_name;

            $list_accounts[] = $note;
        }
        return $list_accounts;
    }

    /**
     * add account history
     * @param array $data
     * @return boolean
     */
    public function add_account_history($data){
        $this->db->where('rel_id', $data['id']);
        $this->db->where('rel_type', $data['type']);
        $this->db->delete(db_prefix().'acc_account_history');

        $data['amount'] = str_replace(',', '', $data['amount']);

        $data_insert = [];
        if($data['type'] == 'invoice'){
            $this->load->model('invoices_model');
            $invoice = $this->invoices_model->get($data['id']);

            $this->load->model('currencies_model');
            $currency = $this->currencies_model->get_base_currency();

            $currency_converter = 0;
            $currency_rate = 0;
            if($invoice->currency_name != $currency->name){
                $currency_converter = 1;

                if(isset($data['exchange_rate'])){
                    $currency_rate = $data['exchange_rate'];
                }else{
                    $currency_rate = acc_get_currency_rate($invoice->currency_name, $currency->name);
                }
            }

            $payment_account = $data['payment_account'];
            $deposit_to = $data['deposit_to'];
            $invoice_payment_account = get_option('acc_invoice_payment_account');
            $invoice_deposit_to = get_option('acc_invoice_deposit_to');
            $invoice_discount_payment_account = get_option('acc_invoice_discount_payment_account');
            $invoice_discount_deposit_to = get_option('acc_invoice_discount_deposit_to');

            $tax_payment_account = get_option('acc_tax_payment_account');
            $tax_deposit_to = get_option('acc_tax_deposit_to');
            $item_amount = $data['item_amount'];
            $paid = 0;
            if($invoice->status == 2){
                $paid = 1;
            }

            foreach ($invoice->items as $value) {
                $item = $this->get_item_by_name($value['description']);
                $item_id = 0;
                if(isset($item->id)){
                    $item_id = $item->id;
                }

                $item_total = $value['qty'] * $value['rate'];
                if(isset($data['exchange_rate'])){
                    $item_total = round(($value['qty'] * $value['rate']) * $data['exchange_rate'], 4);
                }elseif($currency_converter == 1){
                    $item_total = round($currency_rate * ($value['qty'] * $value['rate']), 4);
                }

                if(isset($payment_account[$value['id']])) {
                    $node = [];
                    $node['itemable_id'] = $value['id'];
                    $node['split'] = $payment_account[$value['id']];
                    $node['account'] = $deposit_to[$value['id']];
                    $node['debit'] = $item_total;
                    $node['paid'] = $paid;
                    $node['date'] = $invoice->date;
                    $node['item'] = $item_id;
                    $node['customer'] = $invoice->clientid;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['itemable_id'] = $value['id'];
                    $node['split'] = $deposit_to[$value['id']];
                    $node['paid'] = $paid;
                    $node['date'] = $invoice->date;
                    $node['item'] = $item_id;
                    $node['account'] = $payment_account[$value['id']];
                    $node['customer'] = $invoice->clientid;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }else{
                    $node = [];
                    $node['itemable_id'] = $value['id'];
                    $node['split'] = $invoice_payment_account;
                    $node['account'] = $invoice_deposit_to;
                    $node['date'] = $invoice->date;
                    $node['item'] = $item_id;
                    $node['debit'] = $item_total;
                    $node['customer'] = $invoice->clientid;
                    $node['paid'] = $paid;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['itemable_id'] = $value['id'];
                    $node['split'] = $invoice_deposit_to;
                    $node['customer'] = $invoice->clientid;
                    $node['account'] = $invoice_payment_account;
                    $node['date'] = $invoice->date;
                    $node['item'] = $item_id;
                    $node['paid'] = $paid;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }

                if(get_option('acc_tax_automatic_conversion') == 1){
                    $data_tax = $this->get_invoice_item_tax( $value, $invoice);
                    foreach ($data_tax['tax_id'] as $k => $tax_id) {
                        $tax_mapping = $this->get_tax_mapping($tax_id);

                        if($tax_mapping){
                            $tax_mapping_payment_account = $tax_mapping->payment_account;
                            $tax_mapping_deposit_to = $tax_mapping->deposit_to;
                        }else{
                            $tax_mapping_payment_account = $tax_payment_account;
                            $tax_mapping_deposit_to = $tax_deposit_to;
                        }

                        $total_tax = $data_tax['tax_amount'][$k];
                        if($currency_converter == 1){
                            $total_tax = round($currency_rate * $data_tax['tax_amount'][$k], 2);
                        }

                        $node = [];
                        $node['itemable_id'] = $value['id'];
                        $node['split'] = $tax_mapping_payment_account;
                        $node['account'] = $tax_mapping_deposit_to;
                        $node['tax'] = $tax_id;
                        $node['item'] = $item_id;
                        $node['paid'] = $paid;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['customer'] = $invoice->clientid;
                        $node['date'] = $invoice->date;
                        $node['description'] = '';
                        $node['rel_id'] = $invoice->id;
                        $node['rel_type'] = 'invoice';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;

                        $node = [];
                        $node['itemable_id'] = $value['id'];
                        $node['split'] = $tax_mapping_deposit_to;
                        $node['customer'] = $invoice->clientid;
                        $node['account'] = $tax_mapping_payment_account;
                        $node['tax'] = $tax_id;
                        $node['item'] = $item_id;
                        $node['paid'] = $paid;
                        $node['date'] = $invoice->date;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $invoice->id;
                        $node['rel_type'] = 'invoice';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;
                    }
                }
            }

            if($invoice->discount_total > 0){
                $discount_total = $invoice->discount_total;
                if($currency_converter == 1){
                    $discount_total = round($currency_rate * $invoice->discount_total, 2);
                }

                $node = [];
                $node['itemable_id'] = 0;
                $node['split'] = $invoice_discount_payment_account;
                $node['account'] = $invoice_discount_deposit_to;
                $node['tax'] = 0;
                $node['item'] = 0;
                $node['paid'] = $paid;
                $node['debit'] = $discount_total;
                $node['credit'] = 0;
                $node['customer'] = $invoice->clientid;
                $node['date'] = $invoice->date;
                $node['description'] = '';
                $node['rel_id'] = $invoice->id;
                $node['rel_type'] = 'invoice';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['currency_rate'] = $currency_rate;
                $data_insert[] = $node;

                $node = [];
                $node['itemable_id'] = 0;
                $node['split'] = $invoice_discount_deposit_to;
                $node['account'] = $invoice_discount_payment_account;
                $node['customer'] = $invoice->clientid;
                $node['tax'] = 0;
                $node['item'] = 0;
                $node['paid'] = $paid;
                $node['date'] = $invoice->date;
                $node['debit'] = 0;
                $node['credit'] = $discount_total;
                $node['description'] = '';
                $node['rel_id'] = $invoice->id;
                $node['rel_type'] = 'invoice';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['currency_rate'] = $currency_rate;
                $data_insert[] = $node;
            }
        }elseif($data['type'] == 'loss_adjustment'){

            $this->load->model('warehouse/warehouse_model');
            $loss_adjustment = $this->warehouse_model->get_loss_adjustment($data['id']);
            $loss_adjustment_detail = $this->warehouse_model->get_loss_adjustment_detailt_by_masterid($data['id']);

            $this->load->model('currencies_model');
            $currency = $this->currencies_model->get_base_currency();

            $payment_account = $data['payment_account'];
            $deposit_to = $data['deposit_to'];
            $item_amount = $data['item_amount'];

            $decrease_payment_account = get_option('acc_wh_decrease_payment_account');
            $decrease_deposit_to = get_option('acc_wh_decrease_deposit_to');
            $increase_payment_account = get_option('acc_wh_increase_payment_account');
            $increase_deposit_to = get_option('acc_wh_increase_deposit_to');


            foreach ($loss_adjustment_detail as $value) {
                if($value['current_number'] < $value['loss_adjustment']){
                    $loss_adjustment_payment_account = $increase_payment_account;
                    $loss_adjustment_deposit_to = $increase_deposit_to;
                }else{
                    $loss_adjustment_payment_account = $decrease_payment_account;
                    $loss_adjustment_deposit_to = $decrease_deposit_to;
                }

                $item_id = $value['items'];
                $item_total = $item_amount[$item_id];

                if(isset($payment_account[$item_id])) {
                    $node = [];
                    $node['split'] = $payment_account[$item_id];
                    $node['account'] = $deposit_to[$item_id];
                    $node['debit'] = $item_total;
                    $node['date'] = date('Y-m-d', strtotime($loss_adjustment->time));
                    $node['item'] = $item_id;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $deposit_to[$item_id];
                    $node['date'] = date('Y-m-d', strtotime($loss_adjustment->time));
                    $node['item'] = $item_id;
                    $node['account'] = $payment_account[$item_id];
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $data_insert[] = $node;
                }else{
                    $node = [];
                    $node['split'] = $loss_adjustment_payment_account;
                    $node['account'] = $loss_adjustment_deposit_to;
                    $node['date'] = date('Y-m-d', strtotime($loss_adjustment->time));
                    $node['item'] = $item_id;
                    $node['debit'] = $item_total;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $loss_adjustment_deposit_to;
                    $node['account'] = $loss_adjustment_payment_account;
                    $node['date'] = date('Y-m-d', strtotime($loss_adjustment->time));
                    $node['item'] = $item_id;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $data_insert[] = $node;
                }
            }
        }elseif($data['type'] == 'stock_export'){

            $this->load->model('warehouse/warehouse_model');
            $goods_delivery = $this->warehouse_model->get_goods_delivery($data['id']);
            $goods_delivery_detail = $this->warehouse_model->get_goods_delivery_detail($data['id']);

            $this->load->model('currencies_model');
            $currency = $this->currencies_model->get_base_currency();

            $profit_payment_account = $data['profit_payment_account'];
            $profit_deposit_to = $data['profit_deposit_to'];
            $payment_account = $data['payment_account'];
            $deposit_to = $data['deposit_to'];

            $profit_mapping = [];
            if(isset($data['profit_mapping'])){
                $profit_mapping = $data['profit_mapping'];
            }

            $stock_export_payment_account = get_option('acc_wh_stock_export_payment_account');
            $stock_export_deposit_to = get_option('acc_wh_stock_export_deposit_to');
            $stock_export_profit_payment_account = get_option('acc_wh_stock_export_profit_payment_account');
            $stock_export_profit_deposit_to = get_option('acc_wh_stock_export_profit_deposit_to');

            $item_amount = $data['item_amount'];
            $profit_item_amount = $data['profit_item_amount'];

            foreach ($goods_delivery_detail as $value) {
                $item_id = $value['commodity_code'];
                $_item_amount = $item_amount[$item_id];

                if($_item_amount > 0){
                    if(isset($payment_account[$item_id])) {
                        $node = [];
                        $node['split'] = $payment_account[$item_id];
                        $node['account'] = $deposit_to[$item_id];
                        $node['debit'] = $_item_amount;
                        $node['date'] = $goods_delivery->date_c;
                        $node['item'] = $item_id;
                        $node['sub_type'] = 'inventory';
                        $node['tax'] = 0;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $deposit_to[$item_id];
                        $node['date'] = $goods_delivery->date_c;
                        $node['item'] = $item_id;
                        $node['account'] = $payment_account[$item_id];
                        $node['sub_type'] = 'inventory';
                        $node['tax'] = 0;
                        $node['debit'] = 0;
                        $node['credit'] = $_item_amount;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }else{
                        $node = [];
                        $node['split'] = $stock_export_payment_account;
                        $node['account'] = $stock_export_deposit_to;
                        $node['date'] = $goods_delivery->date_c;
                        $node['item'] = $item_id;
                        $node['debit'] = $_item_amount;
                        $node['sub_type'] = 'inventory';
                        $node['tax'] = 0;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $stock_export_deposit_to;
                        $node['account'] = $stock_export_payment_account;
                        $node['date'] = $goods_delivery->date_c;
                        $node['item'] = $item_id;
                        $node['sub_type'] = 'inventory';
                        $node['tax'] = 0;
                        $node['debit'] = 0;
                        $node['credit'] = $_item_amount;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }
                }

                $_profit_item_amount = $profit_item_amount[$item_id];

                if($_profit_item_amount > 0 && isset($profit_mapping[$item_id])){
                    if(isset($profit_payment_account[$item_id])) {
                        $node = [];
                        $node['split'] = $profit_payment_account[$item_id];
                        $node['account'] = $profit_deposit_to[$item_id];
                        $node['debit'] = $_profit_item_amount;
                        $node['date'] = $goods_delivery->date_c;
                        $node['item'] = $item_id;
                        $node['sub_type'] = 'profit';
                        $node['tax'] = 0;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $profit_deposit_to[$item_id];
                        $node['date'] = $goods_delivery->date_c;
                        $node['item'] = $item_id;
                        $node['account'] = $profit_payment_account[$item_id];
                        $node['sub_type'] = 'profit';
                        $node['tax'] = 0;
                        $node['debit'] = 0;
                        $node['credit'] = $_profit_item_amount;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }else{
                        $node = [];
                        $node['split'] = $stock_export_profit_payment_account;
                        $node['account'] = $stock_export_profit_deposit_to;
                        $node['date'] = $goods_delivery->date_c;
                        $node['item'] = $item_id;
                        $node['debit'] = $_profit_item_amount;
                        $node['sub_type'] = 'profit';
                        $node['tax'] = 0;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $stock_export_profit_deposit_to;
                        $node['account'] = $stock_export_profit_payment_account;
                        $node['date'] = $goods_delivery->date_c;
                        $node['item'] = $item_id;
                        $node['sub_type'] = 'profit';
                        $node['tax'] = 0;
                        $node['debit'] = 0;
                        $node['credit'] = $_profit_item_amount;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }
                }

                $item_total = $_item_amount + $_profit_item_amount;

                if(get_option('acc_tax_automatic_conversion') == 1 && $value['tax_id'] != 0 && $value['tax_id'] != ''){
                    $tax_payment_account = get_option('acc_tax_payment_account');
                    $tax_deposit_to = get_option('acc_tax_deposit_to');

                    $total_tax = $value['total_money'] - $item_total;

                    $tax_mapping = $this->get_tax_mapping($value['tax_id']);

                    if($tax_mapping){
                        $node = [];
                        $node['split'] = $tax_mapping->payment_account;
                        $node['account'] = $tax_mapping->deposit_to;
                        $node['tax'] = $value['tax_id'];
                        $node['sub_type'] = '';
                        $node['item'] = $item_id;
                        $node['date'] = $goods_delivery->date_c;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_mapping->deposit_to;
                        $node['account'] = $tax_mapping->payment_account;
                        $node['tax'] = $value['tax_id'];
                        $node['sub_type'] = '';
                        $node['item'] = $item_id;
                        $node['date'] = $goods_delivery->date_c;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }else{
                        $node = [];
                        $node['split'] = $tax_payment_account;
                        $node['account'] = $tax_deposit_to;
                        $node['tax'] = $value['tax_id'];
                        $node['sub_type'] = '';
                        $node['item'] = $item_id;
                        $node['date'] = $goods_delivery->date_c;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_deposit_to;
                        $node['date'] = $goods_delivery->date_c;
                        $node['account'] = $tax_payment_account;
                        $node['tax'] = $value['tax_id'];
                        $node['sub_type'] = '';
                        $node['item'] = $item_id;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }
                }
            }
        }elseif($data['type'] == 'stock_import'){

            $this->load->model('warehouse/warehouse_model');
            $goods_receipt = $this->warehouse_model->get_goods_receipt($data['id']);
            $goods_receipt_detail = $this->warehouse_model->get_goods_receipt_detail($data['id']);

            $this->load->model('currencies_model');
            $currency = $this->currencies_model->get_base_currency();

            $payment_account = $data['payment_account'];
            $deposit_to = $data['deposit_to'];
            $stock_import_payment_account = get_option('acc_wh_stock_import_payment_account');
            $stock_import_deposit_to = get_option('acc_wh_stock_import_deposit_to');
            $item_amount = $data['item_amount'];
            $currency_rate = 1;
            if($goods_receipt->pr_order_id != 0 && $goods_receipt->currency != 0 && $goods_receipt->currency != $currency->id && (float)($goods_receipt->currency_exchange_rate) != 0){
                $currency_rate = $goods_receipt->currency_exchange_rate;
            }

            foreach ($goods_receipt_detail as $value) {
                $item_id = $value['commodity_code'];
                $item_total = $item_amount[$item_id];

                if(isset($payment_account[$item_id])) {
                    $node = [];
                    $node['split'] = $payment_account[$item_id];
                    $node['account'] = $deposit_to[$item_id];
                    $node['debit'] = $item_total;
                    $node['date'] = $goods_receipt->date_c;
                    $node['item'] = $item_id;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $deposit_to[$item_id];
                    $node['date'] = $goods_receipt->date_c;
                    $node['item'] = $item_id;
                    $node['account'] = $payment_account[$item_id];
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $data_insert[] = $node;
                }else{
                    $node = [];
                    $node['split'] = $stock_import_payment_account;
                    $node['account'] = $stock_import_deposit_to;
                    $node['date'] = $goods_receipt->date_c;
                    $node['item'] = $item_id;
                    $node['debit'] = $item_total;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $stock_import_deposit_to;
                    $node['account'] = $stock_import_payment_account;
                    $node['date'] = $goods_receipt->date_c;
                    $node['item'] = $item_id;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $data_insert[] = $node;
                }
                if(get_option('acc_tax_automatic_conversion') == 1 && $value['tax'] != 0){
                    $tax_payment_account = get_option('acc_expense_tax_payment_account');
                    $tax_deposit_to = get_option('acc_expense_tax_deposit_to');

                    $total_tax = $value['tax_money'] / $currency_rate;

                    $tax_mapping = $this->get_tax_mapping($value['tax']);

                    if($tax_mapping){
                        $node = [];
                        $node['split'] = $tax_mapping->expense_payment_account;
                        $node['account'] = $tax_mapping->expense_deposit_to;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $goods_receipt->date_c;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_mapping->expense_deposit_to;
                        $node['account'] = $tax_mapping->expense_payment_account;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $goods_receipt->date_c;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }else{
                        $node = [];
                        $node['split'] = $tax_payment_account;
                        $node['account'] = $tax_deposit_to;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $goods_receipt->date_c;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_deposit_to;
                        $node['date'] = $goods_receipt->date_c;
                        $node['account'] = $tax_payment_account;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }
                }
            }
        }elseif($data['type'] == 'purchase_order'){
            $this->load->model('currencies_model');
            $currency = $this->currencies_model->get_base_currency();

            $this->load->model('purchase/purchase_model');
            $purchase_order = $this->purchase_model->get_pur_order($data['id']);
            $purchase_order_detail = $this->purchase_model->get_pur_order_detail($data['id']);

            $base_currency = get_base_currency_pur();
            if($purchase_order->currency != 0){
                $base_currency = pur_get_currency_by_id($purchase_order->currency);
            }

            $currency_converter = 0;
            $currency_rate = 0;
            if($base_currency->name != $currency->name){
                $currency_converter = 1;
                $currency_rate = $purchase_order->currency_rate;

                // if(isset($data['exchange_rate'])){
                //     $currency_rate = $data['exchange_rate'];
                // }else{
                //     $currency_rate = acc_get_currency_rate($base_currency->name, $currency->name);
                // }
            }

            $item_discount = 0;
            foreach($purchase_order_detail as $row){
                $item_discount += $row['discount_money'];
            }


            $payment_account = $data['payment_account'];
            $deposit_to = $data['deposit_to'];
            
            $expense_payment_account = get_option('acc_pur_order_payment_account');
            $expense_deposit_to = get_option('acc_pur_order_deposit_to');

            $item_amount = $data['item_amount'];
            foreach ($purchase_order_detail as $value) {

                $item_id = $value['item_code'];
                $item_total = $item_amount[$item_id];

                // if(isset($data['exchange_rate'])){
                //     $item_total = round(($item_amount[$item_id]) * $data['exchange_rate'], 4);
                // }elseif($currency_converter == 1){
                //     $item_total = round($item_amount[$item_id], 4);
                // }

                if(isset($payment_account[$item_id])) {

                    $node = [];
                    $node['split'] = $payment_account[$item_id];
                    $node['account'] = $deposit_to[$item_id];
                    $node['debit'] = $item_total;
                    $node['date'] = $purchase_order->order_date;
                    $node['item'] = $item_id;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $deposit_to[$item_id];
                    $node['date'] = $purchase_order->order_date;
                    $node['item'] = $item_id;
                    $node['account'] = $payment_account[$item_id];
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }else{
                    $node = [];
                    $node['split'] = $expense_payment_account;
                    $node['account'] = $expense_deposit_to;
                    $node['date'] = $purchase_order->order_date;
                    $node['item'] = $item_id;
                    $node['debit'] = $item_total;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $expense_deposit_to;
                    $node['account'] = $expense_payment_account;
                    $node['date'] = $purchase_order->order_date;
                    $node['item'] = $item_id;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }
                if(get_option('acc_tax_automatic_conversion') == 1 && $value['tax'] > 0){
                    $tax_payment_account = get_option('acc_pur_tax_payment_account');
                    $tax_deposit_to = get_option('acc_pur_tax_deposit_to');

                    if($purchase_order->discount_type == 'before_tax'){
                        $total_tax = 0;
                        if($value['tax'] != ''){
                            $tax_arr = explode('|', $value['tax']);

                            $tax_rate_arr = [];
                            if($value['tax_rate'] != ''){
                                $tax_rate_arr = explode('|', $value['tax_rate']);
                            }

                            foreach($tax_arr as $k => $tax_it){
                                if(!isset($tax_rate_arr[$k]) ){
                                    $tax_rate_arr[$k] = $this->purchase_model->tax_rate_by_id($tax_it);
                                }

                                $total_tax += $tax_rate_arr[$k]*$value['into_money']/100;
                            }
                        }

                        $total_discount = $item_discount + $purchase_order->discount_total;

                        $t     = ($total_discount / $purchase_order->subtotal) * 100;
                        $total_tax = ($total_tax - $total_tax * $t / 100);
                    }else{
                        $total_tax = ($value['total'] - $value['into_money']);
                    }


                    if($currency_converter == 1){
                        $total_tax = round($total_tax/$currency_rate, 4);
                    }

                    $tax_mapping = $this->get_tax_mapping($value['tax']);

                    if($tax_mapping){
                        $node = [];
                        $node['split'] = $tax_mapping->purchase_payment_account;
                        $node['account'] = $tax_mapping->purchase_deposit_to;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $purchase_order->order_date;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_mapping->purchase_deposit_to;
                        $node['account'] = $tax_mapping->purchase_payment_account;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $purchase_order->order_date;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;
                    }else{
                        $node = [];
                        $node['split'] = $tax_payment_account;
                        $node['account'] = $tax_deposit_to;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $purchase_order->order_date;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_deposit_to;
                        $node['date'] = $purchase_order->order_date;
                        $node['account'] = $tax_payment_account;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;
                    }
                }
            }

        }elseif ($data['type'] == 'payslip') {
            $date = date('Y-m-d');

                $node = [];
                $node['split'] = $data['payment_account_insurance'];
                $node['account'] = $data['deposit_to_insurance'];
                $node['debit'] = $data['total_insurance'];
                $node['date'] = $date;
                $node['credit'] = 0;
                $node['tax'] = 0;
                $node['description'] = '';
                $node['rel_id'] = $data['id'];
                $node['rel_type'] = $data['type'];
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['payslip_type'] = 'total_insurance';
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $data['deposit_to_insurance'];
                $node['account'] = $data['payment_account_insurance'];
                $node['date'] = $date;
                $node['tax'] = 0;
                $node['debit'] = 0;
                $node['credit'] = $data['total_insurance'];
                $node['description'] = '';
                $node['rel_id'] = $data['id'];
                $node['rel_type'] = $data['type'];
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['payslip_type'] = 'total_insurance';
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $data['payment_account_tax_paye'];
                $node['account'] = $data['deposit_to_tax_paye'];
                $node['debit'] = $data['tax_paye'];
                $node['date'] = $date;
                $node['credit'] = 0;
                $node['tax'] = 0;
                $node['description'] = '';
                $node['rel_id'] = $data['id'];
                $node['rel_type'] = $data['type'];
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['payslip_type'] = 'tax_paye';
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $data['deposit_to_tax_paye'];
                $node['account'] = $data['payment_account_tax_paye'];
                $node['date'] = $date;
                $node['tax'] = 0;
                $node['debit'] = 0;
                $node['credit'] = $data['tax_paye'];
                $node['description'] = '';
                $node['rel_id'] = $data['id'];
                $node['rel_type'] = $data['type'];
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['payslip_type'] = 'tax_paye';
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $data['payment_account_net_pay'];
                $node['account'] = $data['deposit_to_net_pay'];
                $node['debit'] = $data['net_pay'];
                $node['date'] = $date;
                $node['credit'] = 0;
                $node['tax'] = 0;
                $node['description'] = '';
                $node['rel_id'] = $data['id'];
                $node['rel_type'] = $data['type'];
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['payslip_type'] = 'net_pay';
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $data['deposit_to_net_pay'];
                $node['account'] = $data['payment_account_net_pay'];
                $node['date'] = $date;
                $node['tax'] = 0;
                $node['debit'] = 0;
                $node['credit'] = $data['net_pay'];
                $node['description'] = '';
                $node['rel_id'] = $data['id'];
                $node['rel_type'] = $data['type'];
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['payslip_type'] = 'net_pay';
                $data_insert[] = $node;

        }elseif($data['type'] == 'opening_stock'){
            $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

            $date_financial_year = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.date('Y')));

            $node = [];
            $node['split'] = $data['payment_account'];
            $node['account'] = $data['deposit_to'];
            $node['debit'] = $data['amount'];
            $node['date'] = $date_financial_year;
            $node['credit'] = 0;
            $node['tax'] = 0;
            $node['description'] = '';
            $node['rel_id'] = $data['id'];
            $node['rel_type'] = $data['type'];
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $data['deposit_to'];
            $node['account'] = $data['payment_account'];
            $node['date'] = $date_financial_year;
            $node['tax'] = 0;
            $node['debit'] = 0;
            $node['credit'] = $data['amount'];
            $node['description'] = '';
            $node['rel_id'] = $data['id'];
            $node['rel_type'] = $data['type'];
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;
        }elseif($data['type'] == 'manufacturing_order'){
            $this->load->model('manufacturing/manufacturing_model');
            $_manufacturing_order = $this->manufacturing_model->get_manufacturing_order($data['id']);
            $manufacturing_order = $_manufacturing_order['manufacturing_order'];

            if(isset($data['material_cost'])){
                $payment_account_material_cost = $data['payment_account_material_cost'];
                $deposit_to_material_cost = $data['deposit_to_material_cost'];
                $material_cost = $data['material_cost'];

                $node = [];
                $node['split'] = $payment_account_material_cost;
                $node['account'] = $deposit_to_material_cost;
                $node['debit'] = $material_cost;
                $node['date'] = $manufacturing_order->date_plan_from;
                $node['tax'] = 0;
                $node['credit'] = 0;
                $node['description'] = '';
                $node['rel_id'] = $data['id'];
                $node['rel_type'] = $data['type'];
                $node['sub_type'] = 'material_cost';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $deposit_to_material_cost;
                $node['date'] = $manufacturing_order->date_plan_from;
                $node['account'] = $payment_account_material_cost;
                $node['tax'] = 0;
                $node['debit'] = 0;
                $node['credit'] = $material_cost;
                $node['description'] = '';
                $node['rel_id'] = $data['id'];
                $node['rel_type'] = $data['type'];
                $node['sub_type'] = 'material_cost';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;
            }
            
            if(isset($data['labour_cost'])){
                $payment_account_labour_cost = $data['payment_account_labour_cost'];
                $deposit_to_labour_cost = $data['deposit_to_labour_cost'];
                $labour_cost = $data['labour_cost'];

                $node = [];
                $node['split'] = $payment_account_labour_cost;
                $node['account'] = $deposit_to_labour_cost;
                $node['debit'] = $labour_cost;
                $node['date'] = $manufacturing_order->date_plan_from;
                $node['tax'] = 0;
                $node['credit'] = 0;
                $node['description'] = '';
                $node['rel_id'] = $data['id'];
                $node['rel_type'] = $data['type'];
                $node['sub_type'] = 'labour_cost';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $deposit_to_labour_cost;
                $node['date'] = $manufacturing_order->date_plan_from;
                $node['account'] = $payment_account_labour_cost;
                $node['tax'] = 0;
                $node['debit'] = 0;
                $node['credit'] = $labour_cost;
                $node['description'] = '';
                $node['rel_id'] = $data['id'];
                $node['rel_type'] = $data['type'];
                $node['sub_type'] = 'labour_cost';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;
            }
        }elseif($data['type'] == 'purchase_order_return'){
            $this->load->model('purchase/purchase_model');

            $order_return = $this->purchase_model->get_order_return($data['id']);
            $order_return_detail = $this->purchase_model->get_order_return_detail($data['id']);
            $purchase_order = $this->purchase_model->get_pur_order($order_return->rel_id);

            $base_currency = get_base_currency_pur();
            if($order_return->currency != 0){
                $base_currency = pur_get_currency_by_id($order_return->currency);
            }

            $this->load->model('currencies_model');
            $currency = $this->currencies_model->get_base_currency();

            $payment_account = $data['payment_account'];
            $deposit_to = $data['deposit_to'];
            
            $expense_payment_account = get_option('acc_pur_order_return_payment_account');
            $expense_deposit_to = get_option('acc_pur_order_return_deposit_to');

            $currency_converter = 0;
            $currency_rate = 1;
            if($base_currency->name != $currency->name){
                $currency_converter = 1;
                $currency_rate = $purchase_order->currency_rate;

                // if(isset($data['exchange_rate'])){
                //     $currency_rate = $data['exchange_rate'];
                // }else{
                //     $currency_rate = acc_get_currency_rate($base_currency->name, $currency->name);
                // }
            }

            $item_amount = $data['item_amount'];
            foreach ($order_return_detail as $value) {

                $item_id = $value['commodity_code'];
                $item_total = $item_amount[$item_id];
                // if(isset($data['exchange_rate'])){
                //     $item_total = round(($item_amount[$item_id]) * $data['exchange_rate'], 4);
                // }elseif($currency_converter == 1){
                //     $item_total = round($currency_rate * $item_amount[$item_id], 4);
                        
                // }

                if(isset($payment_account[$item_id])) {
                    $node = [];
                    $node['split'] = $payment_account[$item_id];
                    $node['account'] = $deposit_to[$item_id];
                    $node['debit'] = $item_total;
                    $node['date'] = $order_return->datecreated;
                    $node['item'] = $item_id;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $deposit_to[$item_id];
                    $node['date'] = $order_return->datecreated;
                    $node['item'] = $item_id;
                    $node['account'] = $payment_account[$item_id];
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }else{
                    $node = [];
                    $node['split'] = $expense_payment_account;
                    $node['account'] = $expense_deposit_to;
                    $node['date'] = $order_return->datecreated;
                    $node['item'] = $item_id;
                    $node['debit'] = $item_total;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $expense_deposit_to;
                    $node['account'] = $expense_payment_account;
                    $node['date'] = $order_return->datecreated;
                    $node['item'] = $item_id;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }

                // if(get_option('acc_tax_automatic_conversion') == 1 && $value['tax_id'] > 0){
                //     $tax_payment_account = get_option('acc_pur_tax_payment_account');
                //     $tax_deposit_to = get_option('acc_pur_tax_deposit_to');

                //     if($purchase_order->discount_type == 'before_tax'){
                //         $total_tax = 0;
                //         if($value['tax_id'] != ''){
                //             $tax_arr = explode('|', $value['tax_id']);

                //             $tax_rate_arr = [];
                //             if($value['tax_rate'] != ''){
                //                 $tax_rate_arr = explode('|', $value['tax_rate']);
                //             }

                //             foreach($tax_arr as $k => $tax_it){
                //                 if(!isset($tax_rate_arr[$k]) ){
                //                     $tax_rate_arr[$k] = $this->purchase_model->tax_rate_by_id($tax_it);
                //                 }

                //                 $total_tax += $tax_rate_arr[$k]*$value['sub_total']/100;
                //             }
                //         }

                //         $total_discount = $item_discount + $purchase_order->discount_total;

                //         $t     = ($total_discount / $purchase_order->subtotal) * 100;
                //         $total_tax = ($total_tax - $total_tax * $t / 100);
                //     }else{
                //         $total_tax = ($value['total_amount'] - $value['sub_total']);
                //     }


                //     if($currency_converter == 1){
                //         $total_tax = round($total_tax / $currency_rate, 4);
                //     }

                //     $tax_mapping = $this->get_tax_mapping($value['tax_id']);

                //     if($tax_mapping){
                //         $node = [];
                //         $node['split'] = $tax_mapping->purchase_deposit_to;
                //         $node['account'] = $tax_mapping->purchase_payment_account;
                //         $node['tax'] = $value['tax_id'];
                //         $node['item'] = $item_id;
                //         $node['date'] = $order_return->datecreated;
                //         $node['debit'] = $total_tax;
                //         $node['credit'] = 0;
                //         $node['description'] = '';
                //         $node['rel_id'] = $data['id'];
                //         $node['rel_type'] = $data['type'];
                //         $node['datecreated'] = date('Y-m-d H:i:s');
                //         $node['addedfrom'] = get_staff_user_id();
                //         $node['currency_rate'] = $currency_rate;
                //         $data_insert[] = $node;

                //         $node = [];
                //         $node['split'] = $tax_mapping->purchase_deposit_to;
                //         $node['account'] = $tax_mapping->purchase_payment_account;
                //         $node['tax'] = $value['tax_id'];
                //         $node['item'] = $item_id;
                //         $node['date'] = $order_return->datecreated;
                //         $node['debit'] = 0;
                //         $node['credit'] = $total_tax;
                //         $node['description'] = '';
                //         $node['rel_id'] = $data['id'];
                //         $node['rel_type'] = $data['type'];
                //         $node['datecreated'] = date('Y-m-d H:i:s');
                //         $node['addedfrom'] = get_staff_user_id();
                //         $node['currency_rate'] = $currency_rate;
                //         $data_insert[] = $node;
                //     }else{
                //         $node = [];
                //         $node['split'] = $tax_deposit_to;
                //         $node['account'] = $tax_payment_account;
                //         $node['tax'] = $value['tax_id'];
                //         $node['item'] = $item_id;
                //         $node['date'] = $order_return->datecreated;
                //         $node['debit'] = $total_tax;
                //         $node['credit'] = 0;
                //         $node['description'] = '';
                //         $node['rel_id'] = $data['id'];
                //         $node['rel_type'] = $data['type'];
                //         $node['datecreated'] = date('Y-m-d H:i:s');
                //         $node['addedfrom'] = get_staff_user_id();
                //         $node['currency_rate'] = $currency_rate;
                //         $data_insert[] = $node;

                //         $node = [];
                //         $node['split'] = $tax_payment_account;
                //         $node['date'] = $order_return->datecreated;
                //         $node['account'] = $tax_deposit_to;
                //         $node['tax'] = $value['tax_id'];
                //         $node['item'] = $item_id;
                //         $node['debit'] = 0;
                //         $node['credit'] = $total_tax;
                //         $node['description'] = '';
                //         $node['rel_id'] = $data['id'];
                //         $node['rel_type'] = $data['type'];
                //         $node['datecreated'] = date('Y-m-d H:i:s');
                //         $node['addedfrom'] = get_staff_user_id();
                //         $node['currency_rate'] = $currency_rate;
                //         $data_insert[] = $node;
                //     }
                // }
            }

        }elseif($data['type'] == 'purchase_invoice'){
            $this->load->model('purchase/purchase_model');
            $purchase_invoice = $this->purchase_model->get_pur_invoice($data['id']);
            $purchase_invoice_detail = $this->purchase_model->get_pur_invoice_detail($data['id']);

            $this->load->model('currencies_model');
            $currency = $this->currencies_model->get_base_currency();

            $base_currency = get_base_currency_pur();
            if($purchase_invoice->currency != 0){
                $base_currency = pur_get_currency_by_id($purchase_invoice->currency);
            }

            $currency_rate = 0;
            $currency_converter = 0;
            if($base_currency->name != $currency->name){
                $currency_converter = 1;

                if(isset($data['exchange_rate'])){
                    $currency_rate = $data['exchange_rate'];
                }else{
                    $currency_rate = acc_get_currency_rate($base_currency->name, $currency->name);
                }
            }

            $payment_account = $data['payment_account'];
            $deposit_to = $data['deposit_to'];
            
            $expense_payment_account = get_option('acc_pur_invoice_payment_account');
            $expense_deposit_to = get_option('acc_pur_invoice_deposit_to');

            $item_discount = 0;
            foreach($purchase_invoice_detail as $row){
                $item_discount += $row['discount_money'];
            }


            $item_amount = $data['item_amount'];
            foreach ($purchase_invoice_detail as $value) {
                $item_id = $value['item_code'];
                $item_total = $item_amount[$item_id];
                
                if(isset($data['exchange_rate'])){
                    $item_total = round(($item_amount[$item_id]) * $data['exchange_rate'], 4);
                }elseif($currency_converter == 1){
                    $item_total = round($currency_rate * $item_amount[$item_id], 4);
                }

                if(isset($payment_account[$item_id])) {

                    $node = [];
                    $node['split'] = $payment_account[$item_id];
                    $node['account'] = $deposit_to[$item_id];
                    $node['debit'] = $item_total;
                    $node['date'] = $purchase_invoice->invoice_date;
                    $node['item'] = $item_id;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $deposit_to[$item_id];
                    $node['date'] = $purchase_invoice->invoice_date;
                    $node['item'] = $item_id;
                    $node['account'] = $payment_account[$item_id];
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }else{
                    $node = [];
                    $node['split'] = $expense_payment_account;
                    $node['account'] = $expense_deposit_to;
                    $node['date'] = $purchase_invoice->invoice_date;
                    $node['item'] = $item_id;
                    $node['debit'] = $item_total;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $expense_deposit_to;
                    $node['account'] = $expense_payment_account;
                    $node['date'] = $purchase_invoice->invoice_date;
                    $node['item'] = $item_id;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }
                if(get_option('acc_tax_automatic_conversion') == 1 && $value['tax'] > 0){
                    $tax_payment_account = get_option('acc_pur_tax_payment_account');
                    $tax_deposit_to = get_option('acc_pur_tax_deposit_to');

                    if($purchase_invoice->discount_type == 'before_tax'){
                        $total_tax = 0;
                        if($value['tax'] != ''){
                            $tax_arr = explode('|', $value['tax']);

                            $tax_rate_arr = [];
                            if($value['tax_rate'] != ''){
                                $tax_rate_arr = explode('|', $value['tax_rate']);
                            }

                            foreach($tax_arr as $k => $tax_it){
                                if(!isset($tax_rate_arr[$k]) ){
                                    $tax_rate_arr[$k] = $this->purchase_model->tax_rate_by_id($tax_it);
                                }

                                $total_tax += $tax_rate_arr[$k]*$value['into_money']/100;
                            }
                        }

                        $total_discount = $item_discount + $purchase_invoice->discount_total;

                        $t     = ($total_discount / $purchase_invoice->subtotal) * 100;
                        $total_tax = ($total_tax - $total_tax * $t / 100);
                    }else{
                        $total_tax = $value['total'] - $value['into_money'];
                    }


                    if(isset($data['exchange_rate'])){
                        $total_tax = round(($total_tax) * $data['exchange_rate'], 4);
                    }elseif($currency_converter == 1){
                        $total_tax = round($currency_rate * $total_tax, 4);
                    }

                    $tax_mapping = $this->get_tax_mapping($value['tax']);

                    if($tax_mapping){
                        $node = [];
                        $node['split'] = $tax_mapping->purchase_payment_account;
                        $node['account'] = $tax_mapping->purchase_deposit_to;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $purchase_invoice->invoice_date;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_mapping->purchase_deposit_to;
                        $node['account'] = $tax_mapping->purchase_payment_account;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $purchase_invoice->invoice_date;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;
                    }else{
                        $node = [];
                        $node['split'] = $tax_payment_account;
                        $node['account'] = $tax_deposit_to;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $purchase_invoice->invoice_date;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_deposit_to;
                        $node['date'] = $purchase_invoice->invoice_date;
                        $node['account'] = $tax_payment_account;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $data['id'];
                        $node['rel_type'] = $data['type'];
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;
                    }
                }
            }

        }elseif($data['type'] == 'sales_return_order'){
            $this->load->model('omni_sales/omni_sales_model');
            $return_order = $this->omni_sales_model->get_cart($data['id']);
            $return_order_detail = $this->omni_sales_model->get_cart_detailt_by_cart_id($data['id']);

            $this->load->model('currencies_model');
            $currency = $this->currencies_model->get_base_currency();

            $base_currency = $currency;
            if($return_order->currency != 0){
                $base_currency = $this->currencies_model->get($return_order->currency);
            }

            $currency_converter = 0;
            $currency_rate = 0;
            if($base_currency->name != $currency->name){
                $currency_converter = 1;
                if(isset($data['exchange_rate'])){
                    $currency_rate = $data['exchange_rate'];
                }else{
                    $currency_rate = acc_get_currency_rate($base_currency->name, $currency->name);
                }
            }

            $payment_account = $data['payment_account'];
            $deposit_to = $data['deposit_to'];
            
            $expense_payment_account = get_option('acc_omni_sales_order_return_payment_account');
            $expense_deposit_to = get_option('acc_omni_sales_order_return_deposit_to');

            $item_amount = $data['item_amount'];
            foreach ($return_order_detail as $value) {
                $item_id = $value['product_id'];
                $item_total = $item_amount[$item_id];
                if(isset($data['exchange_rate'])){
                    $item_total = round($item_amount[$item_id] * $data['exchange_rate'], 4);
                }elseif($currency_converter == 1){
                    $item_total = round($currency_rate * $item_amount[$item_id], 4);
                }

                if(isset($payment_account[$item_id])) {

                    $node = [];
                    $node['split'] = $payment_account[$item_id];
                    $node['account'] = $deposit_to[$item_id];
                    $node['debit'] = $item_total;
                    $node['date'] = $return_order->datecreator;
                    $node['item'] = $item_id;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $deposit_to[$item_id];
                    $node['date'] = $return_order->datecreator;
                    $node['item'] = $item_id;
                    $node['account'] = $payment_account[$item_id];
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }else{
                    $node = [];
                    $node['split'] = $expense_payment_account;
                    $node['account'] = $expense_deposit_to;
                    $node['date'] = $return_order->datecreator;
                    $node['item'] = $item_id;
                    $node['debit'] = $item_total;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $expense_deposit_to;
                    $node['account'] = $expense_payment_account;
                    $node['date'] = $return_order->datecreator;
                    $node['item'] = $item_id;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $data['id'];
                    $node['rel_type'] = $data['type'];
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }
                // if(get_option('acc_tax_automatic_conversion') == 1 && $value['tax'] > 0){
                //     $tax_payment_account = get_option('acc_expense_tax_payment_account');
                //     $tax_deposit_to = get_option('acc_expense_tax_deposit_to');

                //     $total_tax = $value['total'] - $value['into_money'];

                //     $tax_mapping = $this->get_tax_mapping($value['tax']);

                //     if($tax_mapping){
                //         $node = [];
                //         $node['split'] = $tax_mapping->payment_account;
                //         $node['account'] = $tax_mapping->deposit_to;
                //         $node['tax'] = $value['tax'];
                //         $node['item'] = 0;
                //         $node['date'] = $return_order->datecreator;
                //         $node['debit'] = $total_tax;
                //         $node['credit'] = 0;
                //         $node['description'] = '';
                //         $node['rel_id'] = $data['id'];
                //         $node['rel_type'] = $data['type'];
                //         $node['datecreated'] = date('Y-m-d H:i:s');
                //         $node['addedfrom'] = get_staff_user_id();
                //         $data_insert[] = $node;

                //         $node = [];
                //         $node['split'] = $tax_mapping->deposit_to;
                //         $node['account'] = $tax_mapping->payment_account;
                //         $node['tax'] = $value['tax'];
                //         $node['item'] = 0;
                //         $node['date'] = $return_order->datecreator;
                //         $node['debit'] = 0;
                //         $node['credit'] = $total_tax;
                //         $node['description'] = '';
                //         $node['rel_id'] = $data['id'];
                //         $node['rel_type'] = $data['type'];
                //         $node['datecreated'] = date('Y-m-d H:i:s');
                //         $node['addedfrom'] = get_staff_user_id();
                //         $data_insert[] = $node;
                //     }else{
                //         $node = [];
                //         $node['split'] = $tax_payment_account;
                //         $node['account'] = $tax_deposit_to;
                //         $node['tax'] = $value['tax'];
                //         $node['item'] = 0;
                //         $node['date'] = $return_order->datecreator;
                //         $node['debit'] = $total_tax;
                //         $node['credit'] = 0;
                //         $node['description'] = '';
                //         $node['rel_id'] = $data['id'];
                //         $node['rel_type'] = $data['type'];
                //         $node['datecreated'] = date('Y-m-d H:i:s');
                //         $node['addedfrom'] = get_staff_user_id();
                //         $data_insert[] = $node;

                //         $node = [];
                //         $node['split'] = $tax_deposit_to;
                //         $node['date'] = $return_order->datecreator;
                //         $node['account'] = $tax_payment_account;
                //         $node['tax'] = $value['tax'];
                //         $node['item'] = 0;
                //         $node['debit'] = 0;
                //         $node['credit'] = $total_tax;
                //         $node['description'] = '';
                //         $node['rel_id'] = $data['id'];
                //         $node['rel_type'] = $data['type'];
                //         $node['datecreated'] = date('Y-m-d H:i:s');
                //         $node['addedfrom'] = get_staff_user_id();
                //         $data_insert[] = $node;
                //     }
                // }
            }

        }else{
            $currency_rate = 0;
            $customer = 0;
            $date = date('Y-m-d');
            $description = '';
            
            if($data['type'] == 'payment'){
                $this->load->model('payments_model');
                $this->load->model('invoices_model');
                $payment = $this->payments_model->get($data['id']);
                $date = $payment->date;
                $invoice = $this->invoices_model->get($payment->invoiceid);

                $this->automatic_invoice_conversion($payment->invoiceid);
                
                $customer = $invoice->clientid;
                $this->load->model('currencies_model');
                $currency = $this->currencies_model->get_base_currency();

                if(isset($data['exchange_rate'])){
                    $data['amount'] = round($data['amount'] * $data['exchange_rate'], 4);
                    $currency_rate = $data['exchange_rate'];
                }elseif($invoice->currency_name != $currency->name){
                    $currency_rate = acc_get_currency_rate($invoice->currency_name, $currency->name);
                    $data['amount'] = round($currency_rate * $data['amount'], 4);
                }
            }elseif ($data['type'] == 'expense') {
                $this->load->model('expenses_model');
                $expense = $this->expenses_model->get($data['id']);
                $date = $expense->date;
                $customer = $expense->clientid;

                $this->load->model('currencies_model');
                $currency = $this->currencies_model->get_base_currency();

                if(isset($data['exchange_rate'])){
                    $data['amount'] = round($data['amount'] * $data['exchange_rate'], 4);
                    $currency_rate = $data['exchange_rate'];
                }elseif($expense->currency_data->name != $currency->name){
                    $currency_rate = acc_get_currency_rate($expense->currency_data->name, $currency->name);
                    $data['amount'] = round($currency_rate * $data['amount'], 4);
                }

                if(get_option('acc_tax_automatic_conversion') == 1){
                    $tax_payment_account = get_option('acc_expense_tax_payment_account');
                    $tax_deposit_to = get_option('acc_expense_tax_deposit_to');

                    if($expense->tax > 0){
                        $this->db->where('id', $expense->tax);
                        $tax = $this->db->get(db_prefix().'taxes')->row();
                        $total_tax = 0;
                        if($tax){
                            $total_tax = ($tax->taxrate/100) * $data['amount'];
                        }

                        if(isset($data['exchange_rate'])){
                            $total_tax = round($total_tax * $data['exchange_rate'], 4);
                        }elseif($expense->currency_data->name != $currency->name){
                            $total_tax = round($currency_rate * $total_tax, 4);
                        }

                        $tax_mapping = $this->get_tax_mapping($expense->tax);
                        if($tax_mapping){
                            $node = [];
                            $node['split'] = $tax_mapping->expense_payment_account;
                            $node['account'] = $tax_mapping->expense_deposit_to;
                            $node['tax'] = $expense->tax;
                            $node['debit'] = $total_tax;
                            $node['credit'] = 0;
                            $node['customer'] = $expense->clientid;
                            $node['date'] = $expense->date;
                            $node['description'] = '';
                            $node['rel_id'] = $data['id'];
                            $node['rel_type'] = 'expense';
                            $node['datecreated'] = date('Y-m-d H:i:s');
                            $node['addedfrom'] = get_staff_user_id();
                            $node['currency_rate'] = $currency_rate;
                            $data_insert[] = $node;

                            $node = [];
                            $node['split'] = $tax_mapping->expense_deposit_to;
                            $node['customer'] = $expense->clientid;
                            $node['account'] = $tax_mapping->expense_payment_account;
                            $node['tax'] = $expense->tax;
                            $node['date'] = $expense->date;
                            $node['debit'] = 0;
                            $node['credit'] = $total_tax;
                            $node['description'] = '';
                            $node['rel_id'] = $data['id'];
                            $node['rel_type'] = 'expense';
                            $node['datecreated'] = date('Y-m-d H:i:s');
                            $node['addedfrom'] = get_staff_user_id();
                            $node['currency_rate'] = $currency_rate;
                            $data_insert[] = $node;
                        }else{
                            $node = [];
                            $node['split'] = $tax_payment_account;
                            $node['account'] = $tax_deposit_to;
                            $node['tax'] = $expense->tax;
                            $node['date'] = $expense->date;
                            $node['debit'] = $total_tax;
                            $node['customer'] = $expense->clientid;
                            $node['credit'] = 0;
                            $node['description'] = '';
                            $node['rel_id'] = $data['id'];
                            $node['rel_type'] = 'expense';
                            $node['datecreated'] = date('Y-m-d H:i:s');
                            $node['addedfrom'] = get_staff_user_id();
                            $node['currency_rate'] = $currency_rate;
                            $data_insert[] = $node;

                            $node = [];
                            $node['split'] = $tax_deposit_to;
                            $node['customer'] = $expense->clientid;
                            $node['account'] = $tax_payment_account;
                            $node['date'] = $expense->date;
                            $node['tax'] = $expense->tax;
                            $node['debit'] = 0;
                            $node['credit'] = $total_tax;
                            $node['description'] = '';
                            $node['rel_id'] = $data['id'];
                            $node['rel_type'] = 'expense';
                            $node['datecreated'] = date('Y-m-d H:i:s');
                            $node['addedfrom'] = get_staff_user_id();
                            $node['currency_rate'] = $currency_rate;
                            $data_insert[] = $node;
                        }
                    }

                    if($expense->tax2 > 0){
                        $this->db->where('id', $expense->tax2);
                        $tax = $this->db->get(db_prefix().'taxes')->row();
                        $total_tax = 0;
                        if($tax){
                            $total_tax = ($tax->taxrate/100) * $data['amount'];
                        }

                        if(isset($data['exchange_rate'])){
                            $total_tax = round($total_tax * $data['exchange_rate'], 4);
                        }elseif($expense->currency_data->name != $currency->name){
                            $total_tax = round($currency_rate * $total_tax, 4);
                        }

                        $tax_mapping = $this->get_tax_mapping($expense->tax2);
                        if($tax_mapping){
                            $node = [];
                            $node['split'] = $tax_mapping->expense_payment_account;
                            $node['account'] = $tax_mapping->expense_deposit_to;
                            $node['tax'] = $expense->tax2;
                            $node['debit'] = $total_tax;
                            $node['credit'] = 0;
                            $node['customer'] = $expense->clientid;
                            $node['date'] = $expense->date;
                            $node['description'] = '';
                            $node['rel_id'] = $expense_id;
                            $node['rel_type'] = 'expense';
                            $node['datecreated'] = date('Y-m-d H:i:s');
                            $node['addedfrom'] = get_staff_user_id();
                            $node['currency_rate'] = $currency_rate;
                            $data_insert[] = $node;

                            $node = [];
                            $node['split'] = $tax_mapping->expense_deposit_to;
                            $node['customer'] = $expense->clientid;
                            $node['account'] = $tax_mapping->expense_payment_account;
                            $node['tax'] = $expense->tax2;
                            $node['date'] = $expense->date;
                            $node['debit'] = 0;
                            $node['credit'] = $total_tax;
                            $node['description'] = '';
                            $node['rel_id'] = $expense_id;
                            $node['rel_type'] = 'expense';
                            $node['datecreated'] = date('Y-m-d H:i:s');
                            $node['addedfrom'] = get_staff_user_id();
                            $node['currency_rate'] = $currency_rate;
                            $data_insert[] = $node;
                        }else{
                            $node = [];
                            $node['split'] = $tax_payment_account;
                            $node['account'] = $tax_deposit_to;
                            $node['tax'] = $expense->tax2;
                            $node['date'] = $expense->date;
                            $node['debit'] = $total_tax;
                            $node['customer'] = $expense->clientid;
                            $node['credit'] = 0;
                            $node['description'] = '';
                            $node['rel_id'] = $expense_id;
                            $node['rel_type'] = 'expense';
                            $node['datecreated'] = date('Y-m-d H:i:s');
                            $node['addedfrom'] = get_staff_user_id();
                            $node['currency_rate'] = $currency_rate;
                            $data_insert[] = $node;

                            $node = [];
                            $node['split'] = $tax_deposit_to;
                            $node['customer'] = $expense->clientid;
                            $node['account'] = $tax_payment_account;
                            $node['date'] = $expense->date;
                            $node['tax'] = $expense->tax2;
                            $node['debit'] = 0;
                            $node['credit'] = $total_tax;
                            $node['description'] = '';
                            $node['rel_id'] = $expense_id;
                            $node['rel_type'] = 'expense';
                            $node['datecreated'] = date('Y-m-d H:i:s');
                            $node['addedfrom'] = get_staff_user_id();
                            $node['currency_rate'] = $currency_rate;
                            $data_insert[] = $node;
                        }
                    }
                }
            }elseif($data['type'] == 'banking'){
                $banking = $this->get_transaction_banking($data['id']);
                if($banking){
                    $date = $banking->date;
                    $description = $banking->description;
                }
            }elseif($data['type'] == 'purchase_payment'){
                $this->load->model('purchase/purchase_model');
                $payment = $this->purchase_model->get_payment_pur_invoice($data['id']);
                $purchase_invoice = $this->purchase_model->get_pur_invoice($payment->pur_invoice);

                $this->load->model('currencies_model');
                $currency = $this->currencies_model->get_base_currency();

                $base_currency = get_base_currency_pur();
                if($purchase_invoice->currency != 0){
                    $base_currency = pur_get_currency_by_id($purchase_invoice->currency);
                }

                $currency_converter = 0;
                if($base_currency->name != $currency->name){
                    $currency_converter = 1;
                }

                $data['amount'] = $payment->amount;
                if(isset($data['exchange_rate'])){
                    $data['amount'] = round(($payment->amount) * $data['exchange_rate'], 4);
                    $currency_rate = $data['exchange_rate'];
                }elseif($currency_converter == 1){
                    $currency_rate = acc_get_currency_rate($base_currency->name, $currency->name);
                    $data['amount'] = round($currency_rate * $payment->amount, 4);
                }

                $date = $payment->date;
            }elseif($data['type'] == 'purchase_refund'){
                $this->load->model('purchase/purchase_model');
                $refund = $this->purchase_model->get_order_return_refund($data['id']);
                $order_return = $this->purchase_model->get_order_return($refund->order_return_id);

                $this->load->model('currencies_model');
                $currency = $this->currencies_model->get_base_currency();

                $base_currency = get_base_currency_pur();
                if($order_return->currency != 0){
                    $base_currency = pur_get_currency_by_id($order_return->currency);
                }

                $currency_converter = 0;
                if($base_currency->name != $currency->name){
                    $currency_converter = 1;
                }

                $data['amount'] = $refund->amount;
                if(isset($data['exchange_rate'])){
                    $data['amount'] = round(($refund->amount) * $data['exchange_rate'], 4);
                    $currency_rate = $data['exchange_rate'];
                }elseif($currency_converter == 1){
                    $currency_rate = acc_get_currency_rate($base_currency->name, $currency->name);
                    $data['amount'] = round($currency_rate * $refund->amount, 4);
                }

                $date = $refund->refunded_on;
            }elseif($data['type'] == 'sales_refund'){
                $this->load->model('omni_sales/omni_sales_model');
                $refund = $this->omni_sales_model->get_refund($data['id']);
                $return_order = $this->omni_sales_model->get_cart($refund->order_id);

                $this->load->model('currencies_model');
                $currency = $this->currencies_model->get_base_currency();

                $base_currency = $currency;
                if($return_order->currency != 0){
                    $base_currency = $this->currencies_model->get($return_order->currency);
                }

                $currency_converter = 0;
                if($base_currency->name != $currency->name){
                    $currency_converter = 1;
                }

                $data['amount'] = $refund->amount;
                if(isset($data['exchange_rate'])){
                    $data['amount'] = round(($refund->amount) * $data['exchange_rate'], 4);
                    $currency_rate = $data['exchange_rate'];
                }elseif($currency_converter == 1){
                    $currency_rate = acc_get_currency_rate($base_currency->name, $currency->name);
                    $data['amount'] = round($currency_rate * $refund->amount, 4);
                }

                $date = $refund->refunded_on;
                
            }elseif($data['type'] == 'fe_asset'){
                $this->load->model('fixed_equipment/fixed_equipment_model');
                $asset = $this->fixed_equipment_model->get_assets($data['id']);
                $date = $asset->date_buy ?? date('Y-m-d');
            }elseif($data['type'] == 'fe_license'){
                $this->load->model('fixed_equipment/fixed_equipment_model');
                $asset = $this->fixed_equipment_model->get_assets($data['id']);
                $date = $asset->date_buy ?? date('Y-m-d');
            }elseif($data['type'] == 'fe_component'){
                $this->load->model('fixed_equipment/fixed_equipment_model');
                $asset = $this->fixed_equipment_model->get_assets($data['id']);
                $date = $asset->date_buy ?? date('Y-m-d');
            }elseif($data['type'] == 'fe_consumable'){
                $this->load->model('fixed_equipment/fixed_equipment_model');
                $asset = $this->fixed_equipment_model->get_assets($data['id']);
                $date = $asset->date_buy ?? date('Y-m-d');
            }elseif($data['type'] == 'fe_maintenance'){
                $this->load->model('fixed_equipment/fixed_equipment_model');
                $maintenance = $this->fixed_equipment_model->get_asset_maintenances($data['id']);

                $date = $maintenance->start_date ?? date('Y-m-d');
            }elseif($data['type'] == 'fe_depreciation'){
                $this->db->where('id', $data['id']);
                $depreciation = $this->db->get(db_prefix().'fe_depreciation_items')->row();

                $date = $depreciation->date ?? date('Y-m-d');
            }

            $node = [];
            $node['split'] = $data['payment_account'];
            $node['account'] = $data['deposit_to'];
            $node['debit'] = $data['amount'];
            $node['customer'] = $customer;
            $node['date'] = $date;
            $node['credit'] = 0;
            $node['tax'] = 0;
            $node['description'] = $description;
            $node['rel_id'] = $data['id'];
            $node['rel_type'] = $data['type'];
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $node['currency_rate'] = $currency_rate;
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $data['deposit_to'];
            $node['account'] = $data['payment_account'];
            $node['customer'] = $customer;
            $node['date'] = $date;
            $node['tax'] = 0;
            $node['debit'] = 0;
            $node['credit'] = $data['amount'];
            $node['description'] = $description;
            $node['rel_id'] = $data['id'];
            $node['rel_type'] = $data['type'];
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $node['currency_rate'] = $currency_rate;
            $data_insert[] = $node;
        }

        $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            
        if ($affectedRows > 0) {
            return true;
        }

        return false;
    }

    /**
     * add transfer
     * @param array $data
     * @return boolean
     */
    public function add_transfer($data){
        if(isset($data['id'])){
            unset($data['id']);
        }
        $data['date'] = to_sql_date($data['date']);
        if(get_option('acc_close_the_books') == 1){
            if(strtotime($data['date']) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                return 'close_the_book';
            }
        }
        $data['transfer_amount'] = str_replace(',', '', $data['transfer_amount']);
        $data['datecreated'] = date('Y-m-d H:i:s');
        $data['addedfrom'] = get_staff_user_id();

        $this->db->insert(db_prefix().'acc_transfers', $data);
        $insert_id = $this->db->insert_id();
        
        if($insert_id){
            $node = [];
            $node['split'] = $data['transfer_funds_to'];
            $node['account'] = $data['transfer_funds_from'];
            $node['debit'] = 0;
            $node['date'] = $data['date'];
            $node['credit'] = $data['transfer_amount'];
            $node['rel_id'] = $insert_id;
            $node['rel_type'] = 'transfer';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();

            $this->db->insert(db_prefix().'acc_account_history', $node);

            $node = [];
            $node['split'] = $data['transfer_funds_from'];
            $node['account'] = $data['transfer_funds_to'];
            $node['debit'] = $data['transfer_amount'];
            $node['date'] = $data['date'];
            $node['credit'] = 0;
            $node['rel_id'] = $insert_id;
            $node['rel_type'] = 'transfer';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();

            $this->db->insert(db_prefix().'acc_account_history', $node);

            return true;
        }

        return false;
    }

    /**
     * add journal entry
     * @param array $data 
     * @return boolean
     */
    public function add_journal_entry($data){

        if (isset($data['recurring'])) {
            if ($data['recurring'] == 'custom') {
                $data['recurring_type']   = $data['repeat_type_custom'];
                $data['custom_recurring'] = 1;
                $data['recurring']        = $data['repeat_every_custom'];
            }
        } else {
            $data['custom_recurring'] = 0;
            $data['recurring']        = 0;
        }

        if (isset($data['repeat_type_custom'])) {
            unset($data['repeat_type_custom']);
        }

        if (isset($data['repeat_every_custom'])) {
            unset($data['repeat_every_custom']);
        }

        $account = $data['account'];
        unset($data['account']);

        $debit_amount = $data['debit_amount'];
        unset($data['debit_amount']);

        $credit_amount = $data['credit_amount'];
        unset($data['credit_amount']);

        $description_detail = $data['description_detail'];
        unset($data['description_detail']);

        $data['journal_date'] = to_sql_date($data['journal_date']);

        if(get_option('acc_close_the_books') == 1){
            if(strtotime($data['journal_date']) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                return 'close_the_book';
            }
        }
        
        $data['datecreated'] = date('Y-m-d H:i:s');
        $data['addedfrom'] = get_staff_user_id();
        
        $this->db->insert(db_prefix().'acc_journal_entries', $data);
        $insert_id = $this->db->insert_id();
        
        if($insert_id){
            $data_insert = [];

            foreach ($account as $key => $value) {
                $node = [];
                $node['account'] = $value;
                $node['date'] = $data['journal_date'];
                $node['debit'] = str_replace(',', '', $debit_amount[$key]);
                $node['credit'] = str_replace(',', '', $credit_amount[$key]);
                $node['description'] = $description_detail[$key];
                $node['rel_id'] = $insert_id;
                $node['rel_type'] = 'journal_entry';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();

                $data_insert[] = $node;
            }
            
            $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);

            if($data['recurring'] != 0){
                $this->recurring_journal_entry_by_id($insert_id);
            }
            
            return true;
        }

        return false;
    }

    /**
     * get data balance sheet
     * @param  array $data_filter
     * @return array           
     */
    public function get_data_balance_sheet($data_filter){

        $from_date = date('1970-01-01');
        $to_date = date('Y-m-d');
        $date_filter_type = 'to_date';
        $accounting_method = 'cash';
        $acc_show_account_numbers = get_option('acc_show_account_numbers');
        $where_items = '';
        if(isset($data_filter['items'])){
            $where_items = '(item IN ('. implode(',', $data_filter['items']).'))';
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['date_filter_type'])){
            $date_filter_type = $data_filter['date_filter_type'];
        }

        if(isset($data_filter['from_date']) && $date_filter_type == 'from_and_to'){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 1){
                $data_accounts['accounts_receivable'][] = $value;
            }
            if($value['account_type_id'] == 2){
                $data_accounts['current_assets'][] = $value;
            }
            if($value['account_type_id'] == 3 || $value['account_type_id'] == 16){
                $data_accounts['cash_and_cash_equivalents'][] = $value;
            }
            if($value['account_type_id'] == 4){
                $data_accounts['fixed_assets'][] = $value;
            }
            if($value['account_type_id'] == 5){
                $data_accounts['non_current_assets'][] = $value;
            }
            if($value['account_type_id'] == 6){
                $data_accounts['accounts_payable'][] = $value;
            }
            if($value['account_type_id'] == 7){
                $data_accounts['credit_card'][] = $value;
            }
            if($value['account_type_id'] == 8){
                $data_accounts['current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 9){
                $data_accounts['non_current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 10){
                $data_accounts['owner_equity'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }


                    $child_account = $this->get_data_balance_sheet_recursive([], $val['id'], $value['account_type_id'], $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items);

                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                        $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $credits - $debits, 'child_account' => $child_account];
                        $total += $credits - $debits;
                    }else{
                        $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $debits - $credits, 'child_account' => $child_account];
                        $total += $debits - $credits;
                    }

                }
            }
            $data_total[$data_key] = $total;
        }

        
        $net_income = $this->get_net_income($data_filter);

        return ['data' => $data_report, 'total' => $data_total, 'from_date' => $from_date, 'to_date' => $to_date, 'date_filter_type' => $date_filter_type, 'net_income' => $net_income];
        
    }

    /**
     * get data balance sheet comparison
     * @param  array $data_filter 
     * @return array           
     */
    public function get_data_balance_sheet_comparison($data_filter){
        $from_date = date('1970-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $acc_show_account_numbers = get_option('acc_show_account_numbers');
        $where_items = '';
        if(isset($data_filter['items'])){
            $where_items = '(item IN ('. implode(',', $data_filter['items']).'))';
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        $date_filter_type = 'to_date';
        if(isset($data_filter['date_filter_type'])){
            $date_filter_type = $data_filter['date_filter_type'];
        }

        if(isset($data_filter['from_date']) && $date_filter_type == 'from_and_to'){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }


        $last_from_date = date('Y-m-d', strtotime($from_date.' - 1 year'));
        $last_to_date = date('Y-m-d', strtotime($to_date.' - 1 year'));
        $this_year = date('Y', strtotime($to_date));
        $last_year = date('Y', strtotime($last_to_date));

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 1){
                $data_accounts['accounts_receivable'][] = $value;
            }
            if($value['account_type_id'] == 2){
                $data_accounts['current_assets'][] = $value;
            }
            if($value['account_type_id'] == 3 || $value['account_type_id'] == 16){
                $data_accounts['cash_and_cash_equivalents'][] = $value;
            }
            if($value['account_type_id'] == 4){
                $data_accounts['fixed_assets'][] = $value;
            }
            if($value['account_type_id'] == 5){
                $data_accounts['non_current_assets'][] = $value;
            }
            if($value['account_type_id'] == 6){
                $data_accounts['accounts_payable'][] = $value;
            }
            if($value['account_type_id'] == 7){
                $data_accounts['credit_card'][] = $value;
            }
            if($value['account_type_id'] == 8){
                $data_accounts['current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 9){
                $data_accounts['non_current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 10){
                $data_accounts['owner_equity'][] = $value;
            }
        }
        
        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            $py_total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;

                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date_format(datecreated, \'%Y-%m-%d\') >= "' . $last_from_date . '" and date_format(datecreated, \'%Y-%m-%d\') <= "' . $last_to_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $py_account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $py_credits = $py_account_history->credit != '' ? $py_account_history->credit : 0;
                    $py_debits = $py_account_history->debit != '' ? $py_account_history->debit : 0;

                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }

                    $child_account = $this->get_data_balance_sheet_comparison_recursive([], $val['id'], $value['account_type_id'], $from_date, $to_date, $last_from_date, $last_to_date, $accounting_method, $acc_show_account_numbers, $where_items);
                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                        $data_report[$data_key][] = ['account_id' =>  $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => ($credits - $debits), 'py_amount' => ($py_credits - $py_debits), 'child_account' => $child_account];
                        $total += $credits - $debits;
                        $py_total += $py_credits - $py_debits;
                    }else{
                        $data_report[$data_key][] = ['account_id' =>  $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => ($debits - $credits), 'py_amount' => ($py_debits - $py_credits), 'child_account' => $child_account];
                        $total += $debits - $credits;
                        $py_total += $py_debits - $py_credits;
                    }
                }
            }
            $data_total[$data_key] = ['this_year' => $total, 'last_year' => $py_total];
        }

        $this_net_income = $this->get_net_income($data_filter);

        $data_filter['to_date'] = _d($last_to_date);
        $last_net_income = $this->get_net_income($data_filter);

        return ['data' => $data_report, 'total' => $data_total, 'this_year' => $this_year, 'last_year' => $last_year, 'from_date' => $from_date, 'to_date' => $to_date, 'this_net_income' => $this_net_income, 'last_net_income' => $last_net_income, 'date_filter_type' => $date_filter_type];
    }

    /**
     * get data balance sheet detail
     * @param  array $data_filter 
     * @return array           
     */
    public function get_data_balance_sheet_detail($data_filter){
        $from_date = date('Y-m-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $acc_show_account_numbers = get_option('acc_show_account_numbers');
        $where_items = '';
        if(isset($data_filter['items'])){
            $where_items = '(item IN ('. implode(',', $data_filter['items']).'))';
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }
        
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 1){
                $data_accounts['accounts_receivable'][] = $value;
            }
            if($value['account_type_id'] == 2){
                $data_accounts['current_assets'][] = $value;
            }
            if($value['account_type_id'] == 3 || $value['account_type_id'] == 16){
                $data_accounts['cash_and_cash_equivalents'][] = $value;
            }
            if($value['account_type_id'] == 4){
                $data_accounts['fixed_assets'][] = $value;
            }
            if($value['account_type_id'] == 5){
                $data_accounts['non_current_assets'][] = $value;
            }
            if($value['account_type_id'] == 6){
                $data_accounts['accounts_payable'][] = $value;
            }
            if($value['account_type_id'] == 7){
                $data_accounts['credit_card'][] = $value;
            }
            if($value['account_type_id'] == 8){
                $data_accounts['current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 9){
                $data_accounts['non_current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 10){
                $data_accounts['owner_equity'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            if($data_key != 'income' && $data_key != 'other_income' && $data_key != 'cost_of_sales' && $data_key != 'expenses' && $data_key != 'other_expenses'){
            $data_report[$data_key] = [];
            $total = 0;
            $balance_total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date < "' . $from_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $_account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $_account_history->credit != '' ? $_account_history->credit : 0;
                    $debits = $_account_history->debit != '' ? $_account_history->debit : 0;

                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 10 || $value['account_type_id'] == 9 || $value['account_type_id'] == 8 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                        $beginning_balance = $credits - $debits;
                    }else{
                        $beginning_balance = $debits - $credits;
                    }

                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }

                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $this->db->order_by('date', 'asc');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
                    $node = [];
                    $amount = 0;
                    $balance = $beginning_balance;

                    foreach ($account_history as $v) {
                        if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 10 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                            $am = $v['credit'] - $v['debit'];
                        }else{
                            $am = $v['debit'] - $v['credit'];
                        }

                        $node[] =   [
                                        'date' => date('Y-m-d', strtotime($v['date'])),
                                        'type' => _l($v['rel_type']),
                                        'description' => $v['description'],
                                        'debit' => $v['debit'],
                                        'credit' => $v['credit'],
                                        'amount' => $am,
                                        'balance' => $balance + $am,
                                        'rel_id' => $v['rel_id'],
                                        'rel_type' => $v['rel_type'],
                                    ];
                            $amount += $am;
                            $balance += $am;
                    }

                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }


                    $child_account = $this->get_data_balance_sheet_detail_recursive([], $val['id'], $value['account_type_id'], $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items);
                    
                    $data_report[$data_key][] = ['from_date' => $from_date, 'to_date' => $to_date, 'account' => $val['id'], 'name' => $name, 'amount' => $amount, 'balance' => $balance, 'beginning_balance' => $beginning_balance, 'details' => $node, 'child_account' => $child_account];


                    $total += $amount;
                    $balance_total += $balance;
                }
            }
            $data_total[$data_key] = ['amount' => $total, 'balance' => $balance_total];
            }
        }

        $data_filter['date_filter_type'] = 'from_and_to';
        $net_income = $this->get_net_income($data_filter);

        $data_filter['date_filter_type'] = 'to_date';
        $data_filter['to_date'] = $data_filter['from_date'];
        $net_income_beginning_balance = $this->get_net_income($data_filter);

        return ['data' => $data_report, 'total' => $data_total, 'from_date' => $from_date, 'to_date' => $to_date, 'net_income' => $net_income, 'net_income_beginning_balance' => $net_income_beginning_balance];
        
    }

    /**
     * get data balance sheet summary
     * @param  array $data_filter 
     * @return array           
     */
    public function get_data_balance_sheet_summary($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $from_date = date('1970-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $where_items = '';
        if(isset($data_filter['items'])){
            $where_items = '(item IN ('. implode(',', $data_filter['items']).'))';
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }
        
        $date_filter_type = 'to_date';
        if(isset($data_filter['date_filter_type'])){
            $date_filter_type = $data_filter['date_filter_type'];
        }

        if(isset($data_filter['from_date']) && $date_filter_type == 'from_and_to'){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 1){
                $data_accounts['accounts_receivable'][] = $value;
            }
            if($value['account_type_id'] == 2){
                $data_accounts['current_assets'][] = $value;
            }
            if($value['account_type_id'] == 3 || $value['account_type_id'] == 16){
                $data_accounts['cash_and_cash_equivalents'][] = $value;
            }
            if($value['account_type_id'] == 4){
                $data_accounts['fixed_assets'][] = $value;
            }
            if($value['account_type_id'] == 5){
                $data_accounts['non_current_assets'][] = $value;
            }
            if($value['account_type_id'] == 6){
                $data_accounts['accounts_payable'][] = $value;
            }
            if($value['account_type_id'] == 7){
                $data_accounts['credit_card'][] = $value;
            }
            if($value['account_type_id'] == 8){
                $data_accounts['current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 9){
                $data_accounts['non_current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 10){
                $data_accounts['owner_equity'][] = $value;
            }
        }
        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }


                    $child_account = $this->get_data_balance_sheet_summary_recursive([], $val['id'], $value['account_type_id'], $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items);
                    
                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                        $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $credits - $debits, 'child_account' => $child_account];
                        $total += $credits - $debits;
                    }else{
                        $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $debits - $credits, 'child_account' => $child_account];
                        $total += $debits - $credits;
                    }
                }
            }
            $data_total[$data_key] = $total;
        }

        $net_income = $this->get_net_income($data_filter);

        return ['data' => $data_report, 'total' => $data_total, 'from_date' => $from_date, 'to_date' => $to_date, 'net_income' => $net_income, 'date_filter_type' => $date_filter_type];
        
    }

    /**
     * get data custom summary report
     * @param  array $data_filter 
     * @return array           
     */
    public function get_data_custom_summary_report($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $display_rows_by = 'income_statement';
        $display_columns_by = 'total_only';

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        if(isset($data_filter['display_rows_by'])){
            $display_rows_by = $data_filter['display_rows_by'];
        }

        if(isset($data_filter['display_columns_by'])){
            $display_columns_by = $data_filter['display_columns_by'];
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_accounts = [];
        $headers = [];
        if($display_rows_by == 'total_only'){
            $headers[] = _l('total');
        }elseif ($display_rows_by == 'months') {
            $start = $month = strtotime($from_date);
            $end = strtotime($to_date);

            while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
            {
                $headers[] = date('', $month);
                $month = strtotime("+1 month", $month);
            }
        }

        if($display_rows_by == 'income_statement'){
            foreach ($account_type_details as $key => $value) {
                if($value['account_type_id'] == 11){
                    $data_accounts['income'][] = $value;
                }

                if($value['account_type_id'] == 12){
                    $data_accounts['other_income'][] = $value;
                }

                if($value['account_type_id'] == 13){
                    $data_accounts['cost_of_sales'][] = $value;
                }

                if($value['account_type_id'] == 14){
                    $data_accounts['expenses'][] = $value;
                }

                if($value['account_type_id'] == 15){
                    $data_accounts['other_expenses'][] = $value;
                }
            }

            foreach ($data_accounts as $data_key => $data_account) {
                $data_report[$data_key] = [];
                foreach ($data_account as $key => $value) {
                    $this->db->where('active', 1);
                    $this->db->where('(parent_account is null or parent_account = 0)');
                    $this->db->where('account_detail_type_id', $value['id']);
                    $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                    foreach ($accounts as $val) {
                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('account', $val['id']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;
                        if($acc_show_account_numbers == 1 && $val['number'] != ''){
                            $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                        }else{
                            $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                        }


                        $child_account = $this->get_data_custom_summary_recursive([
                            'child_account' => [],
                            'account_id' => $val['id'],
                            'account_type_id' => $value['account_type_id'],
                            'from_date' => $from_date,
                            'to_date' => $to_date,
                            'accounting_method' => $accounting_method,
                            'acc_show_account_numbers' => $acc_show_account_numbers,
                            'display_rows_by' => $display_rows_by,
                            'display_columns_by' => $display_columns_by,
                        ]);

                        if($display_columns_by == 'total_only'){
                            if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                                $data_report[$data_key][] = ['name' => $name, 'amount' => $credits - $debits, 'child_account' => $child_account];
                            }else{
                                $data_report[$data_key][] = ['name' => $name, 'amount' => $debits - $credits, 'child_account' => $child_account];
                            }
                        }
                    }
                }
            }
        }elseif ($display_rows_by == 'customers') {
            $clients = $this->clients_model->get();
            $headers = [];

            foreach ($clients as $key => $value) {
                $columns = [];
                if($display_columns_by == 'total_only'){
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('customer', $value['userid']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    $columns[] = $debits - $credits;
                }elseif ($display_columns_by == 'months') {
                    $start = $month = strtotime($from_date);
                    $end = strtotime($to_date);

                    while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
                    {
                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('customer', $value['userid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;
                        $columns[] = $debits - $credits;
                        $month = strtotime("+1 month", $month);
                    }
                }

                $data_report[] = ['name' => $value['company'], 'columns' => $columns];
            }
        }

        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date, 'display_rows_by' => $display_rows_by, 'display_columns_by' => $display_columns_by];
        
    }

    /**
     * get data profit and loss as of total income
     * @param  array $data_filter
     * @return array             
     */
    public function get_data_profit_and_loss_as_of_total_income($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');
        $acc_enable_income_statement_modifications = get_option('acc_enable_income_statement_modifications');

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';

        $where_items = '';
        if(isset($data_filter['items'])){
            $where_items = '(item IN ('. implode(',', $data_filter['items']).'))';
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_percent = [];

        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($acc_enable_income_statement_modifications != 1){
                if($value['account_type_id'] == 11){
                    $data_accounts['income'][] = $value;
                }
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        if($acc_enable_income_statement_modifications == 1){
            $total_income = $this->caculate_data_income_profit_and_loss($data_filter, 'total_amount');
            $data_total['income'] = $total_income['income'];
            $data_total['net_income'] = $total_income['net_income'];

            $data_income = $this->caculate_data_income_profit_and_loss($data_filter, 'profit_and_loss_as_of_total_income', $data_total['income']);

            $data_report['income'] = $data_income['income'];
            $data_report['net_income'] = $data_income['net_income'];

            if($data_total['income'] != 0){
                $data_percent['income'] = round(($data_total['income'] / $data_total['income']) * 100, 2);
                $data_percent['net_income'] = round(($data_total['net_income'] / $data_total['income']) * 100, 2);
            }else{
                $data_percent['income'] = 0;
                $data_percent['net_income'] = 0;
            }
        }else{
            $total = 0;
            foreach ($data_accounts['income'] as $value) {
                $this->db->where('active', 1);
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                        $total += $credits - $debits;
                    }else{
                        $total += $debits - $credits;
                    }
                }
            }
            $data_total['income'] = $total;
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            $percent = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;

                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }

                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                        $r_am = $credits - $debits;
                        $total += $credits - $debits;
                    }else{
                        $r_am = $debits - $credits;
                        $total += $debits - $credits;
                    }

                    $child_account = $this->get_data_profit_and_loss_as_of_total_income_recursive([], $data_total['income'], $val['id'], $value['account_type_id'], $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items);

                    if($data_total['income'] != 0){
                        $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $r_am, 'percent' => round((($r_am) / $data_total['income']) * 100, 2), 'child_account' => $child_account];
                    }else{
                        $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $r_am, 'percent' => 0, 'child_account' => $child_account];
                    }
                }
            }
            $data_total[$data_key] = $total;
            if($data_total['income'] != 0){
                $data_percent[$data_key] = round(($total / $data_total['income']) * 100, 2);
            }else{
                $data_percent[$data_key] = 0;
            }
        }

        return ['data' => $data_report, 'total' => $data_total, 'percent' => $data_percent, 'from_date' => $from_date, 'to_date' => $to_date];
        
    }

    /**
     * get data profit and loss comparison
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_profit_and_loss_comparison($data_filter){
        $this_year = date('Y');
        $last_year = $this_year - 1;
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');
        $acc_enable_income_statement_modifications = get_option('acc_enable_income_statement_modifications');

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';

        $where_items = '';
        if(isset($data_filter['items'])){
            $where_items = '(item IN ('. implode(',', $data_filter['items']).'))';
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $last_from_date = date('Y-m-d', strtotime($from_date.' - 1 year'));
        $last_to_date = date('Y-m-d', strtotime($to_date.' - 1 year'));
        $this_year = date('Y', strtotime($to_date));
        $last_year = date('Y', strtotime($last_to_date));

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_this_year = [];
        $data_last_year = [];
        $data_accounts = [];

        if($acc_enable_income_statement_modifications == 1){
            $data_income = $this->caculate_data_income_profit_and_loss_comparison($data_filter);
            $data_report['income'] = $data_income['income'];
            $data_report['net_income'] = $data_income['net_income'];
        }

        foreach ($account_type_details as $key => $value) {
            if($acc_enable_income_statement_modifications != 1){
                if($value['account_type_id'] == 11){
                    $data_accounts['income'][] = $value;
                }
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            $py_total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;

                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date_format(datecreated, \'%Y-%m-%d\') >= "' . $last_from_date . '" and date_format(datecreated, \'%Y-%m-%d\') <= "' . $last_to_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $py_account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $py_credits = $py_account_history->credit != '' ? $py_account_history->credit : 0;
                    $py_debits = $py_account_history->debit != '' ? $py_account_history->debit : 0;

                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }


                    $child_account = $this->get_data_profit_and_loss_comparison_recursive([], $val['id'], $value['account_type_id'], $from_date, $to_date, $last_from_date, $last_to_date, $accounting_method, $acc_show_account_numbers, $where_items);

                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                        $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'this_year' => $credits - $debits, 'last_year' => $py_credits - $py_debits, 'child_account' => $child_account];
                    }else{
                        $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'this_year' => $debits - $credits, 'last_year' => $py_debits - $py_credits, 'child_account' => $child_account];
                    }
                }
            }
        }

        return ['data' => $data_report, 'this_year_header' => $this_year, 'last_year_header' => $last_year, 'from_date' => $from_date, 'to_date' => $to_date];
        
    }

    /**
     * get data profit and loss detail
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_profit_and_loss_detail($data_filter){
        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $where_items = '';
        if(isset($data_filter['items'])){
            $where_items = '(item IN ('. implode(',', $data_filter['items']).'))';
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }
        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $accounts = $this->get_accounts();

        $account_name = [];

        foreach ($accounts as $key => $value) {
            $account_name[$value['id']] = $value['name'];
        }

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 11){
                $data_accounts['income'][] = $value;
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            $balance_total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $this->db->order_by('date', 'asc');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
                    $node = [];
                    $balance = 0;
                    $amount = 0;
                    foreach ($account_history as $v) {
                        if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                            $am = $v['credit'] - $v['debit'];
                        }else{
                            $am = $v['debit'] - $v['credit'];
                        }
                        $node[] =   [
                                        'date' => date('Y-m-d', strtotime($v['date'])),
                                        'type' => _l($v['rel_type']),
                                        'split' => $v['split'] != 0 ? (isset($account_name[$v['split']]) ? $account_name[$v['split']] : '') : '-Split-',
                                        'description' => $v['description'],
                                        'customer' => $v['customer'],
                                        'amount' => $am,
                                        'balance' => $balance + $am,
                                        'rel_type' => $v['rel_type'],
                                        'rel_id' => $v['rel_id'],
                                    ];
                        $amount += $am;
                        $balance += $am;
                    }

                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }

                    $child_account = $this->get_data_profit_and_loss_detail_recursive([], $val['id'], $value['account_type_id'], $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items);

                    $data_report[$data_key][] = ['from_date' => $from_date, 'to_date' => $to_date, 'account' => $val['id'], 'name' => $name, 'amount' => $amount, 'balance' => $balance, 'details' => $node, 'child_account' => $child_account];

                    $total += $amount;
                    $balance_total += $balance;
                }
            }
            $data_total[$data_key] = ['amount' => $total, 'balance' => $balance_total];
        }
        
        return ['data' => $data_report, 'total' => $data_total, 'from_date' => $from_date, 'to_date' => $to_date];
        
    }

    /**
     * get data profit and loss year to date comparison
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_profit_and_loss_year_to_date_comparison($data_filter){
        $from_date = date('Y-m-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $acc_show_account_numbers = get_option('acc_show_account_numbers');
        $acc_enable_income_statement_modifications = get_option('acc_enable_income_statement_modifications');

        $where_items = '';
        if(isset($data_filter['items'])){
            $where_items = '(item IN ('. implode(',', $data_filter['items']).'))';
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }
        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $last_from_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.date('Y')));
        $last_to_date = $to_date;

        if($last_from_date > $to_date){
            $last_from_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.(date('Y') - 1)));
        }

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_accounts = [];

        if($acc_enable_income_statement_modifications == 1){
            $data_income = $this->caculate_data_income_profit_and_loss_comparison($data_filter, 'year_to_date');
            $data_report['income'] = $data_income['income'];
            $data_report['net_income'] = $data_income['net_income'];
        }

        foreach ($account_type_details as $key => $value) {
            if($acc_enable_income_statement_modifications != 1){
                if($value['account_type_id'] == 11){
                    $data_accounts['income'][] = $value;
                }
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;

                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date_format(datecreated, \'%Y-%m-%d\') >= "' . $last_from_date . '" and date_format(datecreated, \'%Y-%m-%d\') <= "' . $last_to_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $py_account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $py_credits = $py_account_history->credit != '' ? $py_account_history->credit : 0;
                    $py_debits = $py_account_history->debit != '' ? $py_account_history->debit : 0;

                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }


                    $child_account = $this->get_data_profit_and_loss_year_to_date_comparison_recursive([], $val['id'], $value['account_type_id'], $from_date, $to_date, $last_from_date, $last_to_date, $accounting_method, $acc_show_account_numbers, $where_items);
                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                        $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'this_year' => $credits - $debits, 'last_year' => $py_credits - $py_debits, 'child_account' => $child_account];
                    }else{
                        $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'this_year' => $debits - $credits, 'last_year' => $py_debits - $py_credits, 'child_account' => $child_account];
                    }
                }
            }
        }
        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date, 'last_from_date' => $last_from_date, 'last_to_date' => $last_to_date];
        
    }

    /**
     * get data profit and loss
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_profit_and_loss($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');
        $acc_enable_income_statement_modifications = get_option('acc_enable_income_statement_modifications');

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        
        $where_items = '';
        if(isset($data_filter['items'])){
            $where_items = '(item IN ('. implode(',', $data_filter['items']).'))';
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }
        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_accounts = [];

        if($acc_enable_income_statement_modifications == 1){
            $data_income = $this->caculate_data_income_profit_and_loss($data_filter);
            $data_report['income'] = $data_income['income'];
            $data_report['net_income'] = $data_income['net_income'];
        }
        
        foreach ($account_type_details as $key => $value) {
            if($acc_enable_income_statement_modifications != 1){
                if($value['account_type_id'] == 11){
                    $data_accounts['income'][] = $value;
                }
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                   
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }


                    $child_account = $this->get_data_profit_and_loss_recursive([], $val['id'], $value['account_type_id'], $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items);

                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                        $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $credits - $debits, 'child_account' => $child_account];
                    }else{
                        $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $debits - $credits, 'child_account' => $child_account];
                    }
                }
            }
        }
        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date];
        
    }

    /**
     * get data statement of cash flows
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_statement_of_cash_flows($data_filter){
        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        $data_accounts['cash_flows_from_operating_activities'] = [];
        $data_accounts['cash_flows_from_financing_activities'] = [];
        $data_accounts['cash_flows_from_investing_activities'] = [];
        $data_accounts['cash_and_cash_equivalents_at_beginning_of_year'] = [];

        foreach ($account_type_details as $key => $value) {
            if(isset($value['statement_of_cash_flows'])){
                $data_accounts[$value['statement_of_cash_flows']][] = $value;
                continue;
            }

            if($value['account_type_id'] == 1){
                $data_accounts['accounts_receivable'][] = $value;
            }
            if($value['account_type_id'] == 2){
                if($value['id'] == 13){
                    $data_accounts['current_assets_3'][] = $value;
                }elseif($value['id'] == 3 || $value['id'] == 6){
                    $data_accounts['current_assets_2'][] = $value;
                }else{
                    $data_accounts['current_assets_1'][] = $value;
                }
            }
            if($value['account_type_id'] == 3 || $value['account_type_id'] == 16){
                $data_accounts['cash_and_cash_equivalents'][] = $value;
            }
            if($value['account_type_id'] == 4){
                if($value['id'] == 21 || $value['id'] == 26){
                    $data_accounts['fixed_assets_2'][] = $value;
                }else{
                    $data_accounts['fixed_assets_1'][] = $value;
                }
            }
            if($value['account_type_id'] == 5){
                if($value['id'] != 31){
                    $data_accounts['non_current_assets_2'][] = $value;
                }else{
                    $data_accounts['non_current_assets_1'][] = $value;
                }
            }
            if($value['account_type_id'] == 6){
                $data_accounts['accounts_payable'][] = $value;
            }
            if($value['account_type_id'] == 7){
                $data_accounts['credit_card'][] = $value;
            }
            if($value['account_type_id'] == 8){
                $data_accounts['current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 9){
                if($value['id'] != 63 && $value['id'] != 64){
                    $data_accounts['non_current_liabilities_2'][] = $value;
                }else{
                    $data_accounts['non_current_liabilities_1'][] = $value;
                }
            }
            if($value['account_type_id'] == 10){
                $data_accounts['owner_equity'][] = $value;
            }

            if($value['account_type_id'] == 11){
                $data_accounts['income'][] = $value;
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    if($val['id'] == 13){
                        $this->db->where('(rel_type != "invoice" and rel_type != "expense" and rel_type != "payment")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $this->db->where('account', $val['id']);
                    
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }


                    $child_account = $this->get_data_statement_of_cash_flows_recursive([], $val['id'], $value['account_type_id'], $value['id'], $from_date, $to_date, $acc_show_account_numbers);

                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 10 || $value['account_type_id'] == 8 || $value['account_type_id'] == 7 || $value['account_type_id'] == 4 || $value['account_type_id'] == 5 || $value['account_type_id'] == 6 || $value['account_type_id'] == 2 || $value['account_type_id'] == 9 || $value['account_type_id'] == 1){
                        $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'account_detail_type_id' => $value['id'], 'name' => $name, 'amount' => $credits - $debits, 'child_account' => $child_account];
                        $total += $credits - $debits;
                    }else{
                        $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'account_detail_type_id' => $value['id'], 'name' => $name, 'amount' => $debits - $credits, 'child_account' => $child_account];
                        $total += $debits - $credits;
                    }
                }
            }
            $data_total[$data_key] = $total;
        }


        $net_income = $this->get_net_income($data_filter);

        return ['data' => $data_report, 'total' => $data_total, 'net_income' => $net_income, 'from_date' => $from_date, 'to_date' => $to_date];
        
    }
    
    /**
     * get data statement of changes in equity
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_statement_of_changes_in_equity($data_filter){
        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }
        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 10){
                $data_accounts['owner_equity'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                            $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                        }else{
                            $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                        }

                    
                    $child_account = $this->get_data_statement_of_changes_in_equity_recursive([], $val['id'], $from_date, $to_date, $accounting_method, $acc_show_account_numbers);

                    $data_report[$data_key][] = ['account_detail_type_id' => $value['id'], 'name' => $name, 'amount' => $credits - $debits, 'child_account' => $child_account];
                    $total += $credits - $debits;

                }
            }
            $data_total[$data_key] = $total;
        }

        return ['data' => $data_report, 'total' => $data_total, 'from_date' => $from_date, 'to_date' => $to_date];
    }

    /**
     * get data deposit detail
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_deposit_detail($data_filter){
        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 1){
                $data_accounts['accounts_receivable'][] = $value;
            }
            if($value['account_type_id'] == 2){
                $data_accounts['current_assets'][] = $value;
            }
            if($value['account_type_id'] == 3 || $value['account_type_id'] == 16){
                $data_accounts['cash_and_cash_equivalents'][] = $value;
            }
            if($value['account_type_id'] == 4){
                $data_accounts['fixed_assets'][] = $value;
            }
            if($value['account_type_id'] == 5){
                $data_accounts['non_current_assets'][] = $value;
            }
            if($value['account_type_id'] == 6){
                $data_accounts['accounts_payable'][] = $value;
            }
            if($value['account_type_id'] == 7){
                $data_accounts['credit_card'][] = $value;
            }
            if($value['account_type_id'] == 8){
                $data_accounts['current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 9){
                $data_accounts['non_current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 10){
                $data_accounts['owner_equity'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            $balance_total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $this->db->where('account', $val['id']);
                    $this->db->where('((rel_type = "payment" and debit > 0) or (rel_type = "deposit"  and credit > 0))');
                    $this->db->order_by('date', 'asc');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
                    $node = [];
                    $balance = 0;
                    $amount = 0;
                    foreach ($account_history as $v) {
                        if($value['account_type_id'] == 10 || $value['account_type_id'] == 9 || $value['account_type_id'] == 8 || $value['account_type_id'] == 7){
                            $amount += $v['credit'] - $v['debit'];
                            $am = ($v['credit'] - $v['debit']);
                        }else{
                            $amount += $v['debit'] - $v['credit'];
                            $am = ($v['debit'] - $v['credit']);
                        }

                        $node[] =   [
                                        'date' => date('Y-m-d', strtotime($v['date'])),
                                        'type' => _l($v['rel_type']),
                                        'description' => $v['description'],
                                        'customer' => $v['customer'],
                                        'debit' => $v['debit'],
                                        'credit' => $v['credit'],
                                        'amount' =>  $am,
                                        'rel_type' => $v['rel_type'],
                                        'rel_id' => $v['rel_id'],
                                    ];
                    }

                    $child_account = $this->get_data_deposit_detail_recursive([], $val['id'], $value['account_type_id'], $from_date, $to_date, $acc_show_account_numbers);

                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }

                    $data_report[$data_key][] = ['account' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $amount, 'details' => $node, 'child_account' => $child_account];

                    $total += $amount;
                    $balance_total += $balance;
                }
            }
            $data_total[$data_key] = ['amount' => $total, 'balance' => $balance_total];
        }

        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date];
        
    }

    /**
     * get data income by customer summary
     * @return array
     */
    public function get_data_income_by_customer_summary($data_filter){
        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }
        
        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 11){
                $data_accounts['income'][] = $value;
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }
        $list_customer = [];
        foreach ($data_accounts as $data_key => $data_account) {
            $total = [];
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit, customer');
                    $this->db->group_by('customer');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $this->db->where('(customer != 0)');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }

                    $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();

                    foreach ($account_history as $v) {
                        if(get_company_name($v['customer']) == ''){
                            continue;
                        }

                        $credits = $v['credit'] != '' ? $v['credit'] : 0;
                        $debits = $v['debit'] != '' ? $v['debit'] : 0;

                        if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                            $amount = $credits - $debits;
                        }else{
                            $amount = $debits - $credits;
                        }

                        if(isset($total[$v['customer']])){
                            $total[$v['customer']] += $amount;
                        }else{
                            $total[$v['customer']] = $amount;
                        }

                        if(!in_array($v['customer'], $list_customer)){
                            $list_customer[] = $v['customer'];
                        }
                    }
                }
            }
            $data_total[$data_key] = $total;
        }

        return ['list_customer' => $list_customer, 'total' => $data_total, 'from_date' => $from_date, 'to_date' => $to_date];
    }

    /**
     * get data check detail
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_check_detail($data_filter){
        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 3 || $value['account_type_id'] == 16){
                $data_accounts['cash_and_cash_equivalents'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->where('account', $val['id']);
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $this->db->where('rel_type', 'expense');
                    $this->db->order_by('date', 'asc');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();

                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }

                    $data_report[$data_key][] = ['account_detail_type_id' => $value['id'], 'name' => $name, 'details' => $account_history];
                }
            }
        }
        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date];
        
    }

    /**
     * get data account list
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_account_list($data_filter){
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $account_types = $this->get_account_types();
        $detail_types = $this->get_account_type_details();

        $account_type_name = [];
        $detail_type_name = [];

        foreach ($account_types as $key => $value) {
            $account_type_name[$value['id']] = $value['name'];
        }

        foreach ($detail_types as $key => $value) {
            $detail_type_name[$value['id']] = $value['name'];
        }


        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 1){
                $data_accounts['accounts_receivable'][] = $value;
            }
            if($value['account_type_id'] == 2){
                $data_accounts['current_assets'][] = $value;
            }
            if($value['account_type_id'] == 3 || $value['account_type_id'] == 16){
                $data_accounts['cash_and_cash_equivalents'][] = $value;
            }
            if($value['account_type_id'] == 4){
                $data_accounts['fixed_assets'][] = $value;
            }
            if($value['account_type_id'] == 5){
                $data_accounts['non_current_assets'][] = $value;
            }
            if($value['account_type_id'] == 6){
                $data_accounts['accounts_payable'][] = $value;
            }
            if($value['account_type_id'] == 7){
                $data_accounts['credit_card'][] = $value;
            }
            if($value['account_type_id'] == 8){
                $data_accounts['current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 9){
                $data_accounts['non_current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 10){
                $data_accounts['owner_equity'][] = $value;
            }

            if($value['account_type_id'] == 11){
                $data_accounts['income'][] = $value;
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }


                    $child_account = $this->get_data_account_list_recursive([], $val['id'], $value['account_type_id'], $account_type_name, $detail_type_name, $acc_show_account_numbers);

                    $_account_type_name = isset($account_type_name[$val['account_type_id']]) ? $account_type_name[$val['account_type_id']] : '';
                    $_detail_type_name = isset($detail_type_name[$val['account_detail_type_id']]) ? $detail_type_name[$val['account_detail_type_id']] : '';
                    
                    $data_report[$data_key][] = ['description' => $val['description'], 'type' => $_account_type_name, 'detail_type' => $_detail_type_name, 'name' => $name, 'amount' => $debits - $credits, 'child_account' => $child_account];
                    $total += $debits - $credits;
                }
            }
            $data_total[$data_key] = $total;
        }

        return ['data' => $data_report, 'total' => $data_total];
    }
    
    /**
     * get data general ledger 
     * @return array
     */
    public function get_data_general_ledger($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }
        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $accounts = $this->get_accounts();

        $account_name = [];

        foreach ($accounts as $key => $value) {
            $account_name[$value['id']] = $value['name'];
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 1){
                $data_accounts['accounts_receivable'][] = $value;
            }
            if($value['account_type_id'] == 2){
                $data_accounts['current_assets'][] = $value;
            }
            if($value['account_type_id'] == 3 || $value['account_type_id'] == 16){
                $data_accounts['cash_and_cash_equivalents'][] = $value;
            }
            if($value['account_type_id'] == 4){
                $data_accounts['fixed_assets'][] = $value;
            }
            if($value['account_type_id'] == 5){
                $data_accounts['non_current_assets'][] = $value;
            }
            if($value['account_type_id'] == 6){
                $data_accounts['accounts_payable'][] = $value;
            }
            if($value['account_type_id'] == 7){
                $data_accounts['credit_card'][] = $value;
            }
            if($value['account_type_id'] == 8){
                $data_accounts['current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 9){
                $data_accounts['non_current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 10){
                $data_accounts['owner_equity'][] = $value;
            }
            if($value['account_type_id'] == 11){
                $data_accounts['income'][] = $value;
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        $data = [
            'from_date' => $from_date,
            'to_date' => $to_date,
            'accounting_method' => $accounting_method,
            'acc_show_account_numbers' => $acc_show_account_numbers,
        ];

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            $balance_total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('(date < "' . $from_date . '")');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $_account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $_account_history->credit != '' ? $_account_history->credit : 0;
                    $debits = $_account_history->debit != '' ? $_account_history->debit : 0;

                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 10 || $value['account_type_id'] == 9 || $value['account_type_id'] == 8 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                        $beginning_balance = $credits - $debits;
                    }else{
                        $beginning_balance = $debits - $credits;
                    }

                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }

                    $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
                    $node = [];
                    $balance = $beginning_balance;
                    $amount = 0;
                    foreach ($account_history as $v) {
                        if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 10 || $value['account_type_id'] == 9 || $value['account_type_id'] == 8 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                            $am = $v['credit'] - $v['debit'];
                        }else{
                            $am = $v['debit'] - $v['credit'];
                        }

                        $node[] =   [
                            'date' => date('Y-m-d', strtotime($v['date'])),
                            'type' => _l($v['rel_type']),
                            'split_id' => $v['split'] != 0 ? $v['split'] : '',
                            'split' => $v['split'] != 0 ? (isset($account_name[$v['split']]) ? $account_name[$v['split']] : '') : '-Split-',
                            'description' => $v['description'],
                            'number' => $v['number'],
                            'customer' => $v['customer'],
                            'vendor' => $v['vendor'],
                            'debit' => $v['debit'],
                            'credit' => $v['credit'],
                            'amount' => $am,
                            'balance' => $balance + $am,
                            'rel_type' => $v['rel_type'],
                            'rel_id' => $v['rel_id'],
                        ];

                        
                        $amount += $am;
                        $balance += $am;
                    }
                    $child_account = $this->get_data_general_ledger_recursive([], $val['id'], $value['account_type_id'], $data);

                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }

                    if($amount != 0 || $child_account != []){
                        $data_report[$data_key][] = ['from_date' => $from_date, 'to_date' => $to_date, 'account' => $val['id'], 'name' => $name, 'amount' => $amount, 'balance' => $balance, 'beginning_balance' => $beginning_balance, 'details' => $node, 'child_account' => $child_account];

                    }

                    $total += $amount;
                    $balance_total += $balance;
                }
            }

            $data_total[$data_key] = ['amount' => $total, 'balance' => $balance_total];
        }
        
        return ['data' => $data_report, 'total' => $data_total, 'from_date' => $from_date, 'to_date' => $to_date];
    }

    /**
     * get data journal
     * @return array 
     */
    public function get_data_journal($data_filter){
        $from_date = date('Y-m-01');
        $to_date = date('Y-m-d');

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $accounts = $this->get_accounts();

        $account_name = [];

        foreach ($accounts as $key => $value) {
            $account_name[$value['id']] = $value['name'];
        }

        $data_report = [];
        
        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
        $this->db->order_by('date', 'asc');
        
        $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
        $balance = 0;
        $amount = 0;
        foreach ($account_history as $v) {
            $data_report[] =   [
                            'date' => date('Y-m-d', strtotime($v['date'])),
                            'type' => _l($v['rel_type']),
                            'number' => $v['number'],
                            'name' => (isset($account_name[$v['account']]) ? $account_name[$v['account']] : ''),
                            'description' => $v['description'],
                            'customer' => $v['customer'],
                            'debit' => $v['debit'],
                            'credit' => $v['credit'],
                            'rel_type' => $v['rel_type'],
                            'rel_id' => $v['rel_id'],
                        ];
        }
                
        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date];
    }
    
    /**
     * get data recent transactions
     * @return array
     */
    public function get_data_recent_transactions($data_filter){
        $from_date = date('Y-m-01');
        $to_date = date('Y-m-d');

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $accounts = $this->get_accounts();

        $account_name = [];

        foreach ($accounts as $key => $value) {
            $account_name[$value['id']] = $value['name'];
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 1){
                $data_accounts['accounts_receivable'][] = $value;
            }
            if($value['account_type_id'] == 2){
                $data_accounts['current_assets'][] = $value;
            }
            if($value['account_type_id'] == 3 || $value['account_type_id'] == 16){
                $data_accounts['cash_and_cash_equivalents'][] = $value;
            }
            if($value['account_type_id'] == 4){
                $data_accounts['fixed_assets'][] = $value;
            }
            if($value['account_type_id'] == 5){
                $data_accounts['non_current_assets'][] = $value;
            }
            if($value['account_type_id'] == 6){
                $data_accounts['accounts_payable'][] = $value;
            }
            if($value['account_type_id'] == 7){
                $data_accounts['credit_card'][] = $value;
            }
            if($value['account_type_id'] == 8){
                $data_accounts['current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 9){
                $data_accounts['non_current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 10){
                $data_accounts['owner_equity'][] = $value;
            }
            if($value['account_type_id'] == 11){
                $data_accounts['income'][] = $value;
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();

                foreach ($accounts as $val) {
                    $this->db->where('account', $val['id']);
                    
                    $this->db->where('((debit > 0 and (rel_type != "expense" and rel_type != "transfer")) or (credit > 0 and (rel_type = "expense" or rel_type = "transfer")))');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $this->db->order_by('rel_type,date', 'asc');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();

                    foreach ($account_history as $v) {
                        if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 10 || $value['account_type_id'] == 9 || $value['account_type_id'] == 8 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                            $am = $v['credit'] - $v['debit'];
                        }else{
                            $am = $v['debit'] - $v['credit'];
                        }

                        $data_report[$v['rel_type']][] =   [
                                        'date' => date('Y-m-d', strtotime($v['date'])),
                                        'type' => _l($v['rel_type']),
                                        'name' => (isset($account_name[$v['account']]) ? $account_name[$v['account']] : ''),
                                        'description' => $v['description'],
                                        'customer' => $v['customer'],
                                        'amount' => $am,
                                        'rel_id' => $v['rel_id'],
                                        'rel_type' => $v['rel_type'],
                                    ];
                    }
                }
            }
        }

        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date];
    }

    /**
     * get data transaction detail by account
     * @return array
     */
    public function get_data_transaction_detail_by_account($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $from_date = date('Y-m-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }
        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $accounts = $this->get_accounts();

        $account_name = [];

        foreach ($accounts as $key => $value) {
            $account_name[$value['id']] = $value['name'];
        }
        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 1){
                $data_accounts['accounts_receivable'][] = $value;
            }
            if($value['account_type_id'] == 2){
                $data_accounts['current_assets'][] = $value;
            }
            if($value['account_type_id'] == 3 || $value['account_type_id'] == 16){
                $data_accounts['cash_and_cash_equivalents'][] = $value;
            }
            if($value['account_type_id'] == 4){
                $data_accounts['fixed_assets'][] = $value;
            }
            if($value['account_type_id'] == 5){
                $data_accounts['non_current_assets'][] = $value;
            }
            if($value['account_type_id'] == 6){
                $data_accounts['accounts_payable'][] = $value;
            }
            if($value['account_type_id'] == 7){
                $data_accounts['credit_card'][] = $value;
            }
            if($value['account_type_id'] == 8){
                $data_accounts['current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 9){
                $data_accounts['non_current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 10){
                $data_accounts['owner_equity'][] = $value;
            }
            if($value['account_type_id'] == 11){
                $data_accounts['income'][] = $value;
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            $balance_total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->order_by('date', 'asc');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
                    $node = [];
                    $balance = 0;
                    $amount = 0;
                    foreach ($account_history as $v) {
                        if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 10 || $value['account_type_id'] == 9 || $value['account_type_id'] == 8 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                            $am = $v['credit'] - $v['debit'];
                        }else{
                            $am = $v['debit'] - $v['credit'];
                        }
                        $node[] =   [
                                        'date' => date('Y-m-d', strtotime($v['date'])),
                                        'type' => _l($v['rel_type']),
                                        'description' => $v['description'],
                                        'customer' => $v['customer'],
                                        'split' => $v['split'] != 0 ? (isset($account_name[$v['split']]) ? $account_name[$v['split']] : '') : '-Split-',
                                        'debit' => $v['debit'],
                                        'credit' => $v['credit'],
                                        'amount' => $am,
                                        'balance' => $balance + ($am),
                                        'rel_type' => $v['rel_type'],
                                        'rel_id' => $v['rel_id'],

                                    ];
                        $amount += $am;
                        $balance += $am;
                    }

                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }

                    $child_account = $this->get_data_transaction_detail_by_account_recursive([], $val['id'], $value['account_type_id'], $from_date, $to_date, $accounting_method, $acc_show_account_numbers);

                    $data_report[$data_key][] = ['from_date' => $from_date, 'to_date' => $to_date, 'account' => $val['id'], 'name' => $name, 'amount' => $amount, 'balance' => $balance, 'details' => $node, 'child_account' => $child_account];

                    $total += $amount;
                    $balance_total += $balance;
                }
            }
            $data_total[$data_key] = ['amount' => $total, 'balance' => $balance_total];
        }
        
        return ['data' => $data_report, 'total' => $data_total, 'from_date' => $from_date, 'to_date' => $to_date];
    }

    /**
     * get data transaction list by date
     * @return array
     */
    public function get_data_transaction_list_by_date($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $from_date = date('Y-m-01');
        $to_date = date('Y-m-d');

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $accounts = $this->get_accounts();

        $account_name = [];
        $account_type = [];

        foreach ($accounts as $key => $value) {
            $account_name[$value['id']] = $value['name'];
            $account_type[$value['id']] = $value['account_type_id'];
        }


        $data_report = [];
        
        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
        $this->db->where('((debit > 0 and (rel_type != "expense" and rel_type != "transfer")) or (credit > 0 and (rel_type = "expense" or rel_type = "transfer")))');
        $this->db->order_by('date', 'asc');
        $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
        $balance = 0;
        $amount = 0;
        foreach ($account_history as $v) {
            $account_type_id = (isset($account_type[$v['account']]) ? $account_type[$v['account']] : '');
            if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                $am = $v['credit'] - $v['debit'];
            }else{
                $am = $v['debit'] - $v['credit'];
            }
            $data_report[] =   [
                            'date' => date('Y-m-d', strtotime($v['date'])),
                            'type' => _l($v['rel_type']),
                            'split' => $v['split'] != 0 ? (isset($account_name[$v['split']]) ? $account_name[$v['split']] : '') : '-Split-',
                            'name' => isset($account_name[$v['account']]) ? $account_name[$v['account']] : '',
                            'description' => $v['description'],
                            'customer' => $v['customer'],
                            'amount' => $am,
                            'debit' => $v['debit'],
                            'credit' => $v['credit'],
                            'rel_type' => $v['rel_type'],
                            'rel_id' => $v['rel_id'],
                        ];
        }
        
        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date];
    }

    /**
     * get data trial balance
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_trial_balance($data_filter){
        $from_date = date('Y-m-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }
        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 1){
                $data_accounts['accounts_receivable'][] = $value;
            }
            if($value['account_type_id'] == 2){
                $data_accounts['current_assets'][] = $value;
            }
            if($value['account_type_id'] == 3 || $value['account_type_id'] == 16){
                $data_accounts['cash_and_cash_equivalents'][] = $value;
            }
            if($value['account_type_id'] == 4){
                $data_accounts['fixed_assets'][] = $value;
            }
            if($value['account_type_id'] == 5){
                $data_accounts['non_current_assets'][] = $value;
            }
            if($value['account_type_id'] == 6){
                $data_accounts['accounts_payable'][] = $value;
            }
            if($value['account_type_id'] == 7){
                $data_accounts['credit_card'][] = $value;
            }
            if($value['account_type_id'] == 8){
                $data_accounts['current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 9){
                $data_accounts['non_current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 10){
                $data_accounts['owner_equity'][] = $value;
            }

            if($value['account_type_id'] == 11){
                $data_accounts['income'][] = $value;
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    if($credits > $debits){
                        $credits = $credits - $debits;
                        $debits = 0;
                    }else{
                        $debits = $debits - $credits;
                        $credits = 0;
                    }
                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }


                    $child_account = $this->get_data_trial_balance_recursive([], $val['id'], $value['account_type_id'], $from_date, $to_date, $accounting_method, $acc_show_account_numbers);

                    $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'debit' => $debits, 'credit' => $credits, 'child_account' => $child_account];
                }
            }
            $data_total[$data_key] = $total;
        }
        return ['data' => $data_report, 'total' => $data_total, 'from_date' => $from_date, 'to_date' => $to_date];
        
    }

    /**
     * import xlsx banking
     * @param  array $data
     * @return integer or boolean      
     */
    public function import_xlsx_banking($data){
        $data['datecreated'] = date('Y-m-d H:i:s');
        $data['addedfrom'] = get_staff_user_id();
        $data['date'] = str_replace('/', '-', $data['date']);
        $data['date'] = date("Y-m-d", strtotime($data['date']));
        $this->db->insert(db_prefix() . 'acc_transaction_bankings', $data);

        $insert_id = $this->db->insert_id();

        if ($insert_id) {
            return $insert_id;
        }

        return false;
    }

    /**
     * get transaction banking
     * @param  string $id
     * @param  array  $where
     * @return array or object
     */
    public function get_transaction_banking($id = '', $where = [])
    {
        if (is_numeric($id)) {
            $this->db->where('id', $id);
            return $this->db->get(db_prefix() . 'acc_transaction_bankings')->row();
        }

        $this->db->where($where);
        $this->db->order_by('id', 'desc');
        return $this->db->get(db_prefix() . 'acc_transaction_bankings')->result_array();
    }
    /**
     * get journal entry
     * @param  integer $id 
     * @return object     
     */
    public function get_journal_entry($id){
        $this->db->where('id', $id);
        $journal_entrie = $this->db->get(db_prefix() . 'acc_journal_entries')->row();

        if($journal_entrie){
            $this->db->where('rel_id', $id);
            $this->db->where('rel_type', 'journal_entry');
            $details = $this->db->get(db_prefix().'acc_account_history')->result_array();

            $data_details =[];
            foreach ($details as $key => $value) {
                $data_details[] = [
                    "account" => $value['account'],
                    "debit" => floatval($value['debit']),
                    "credit" => floatval($value['credit']),
                    "addedfrom" => floatval($value['addedfrom']),
                    "description" => $value['description']];
            }
            if(count($data_details) < 10){

            }
            $journal_entrie->details = $data_details;
        }

        return $journal_entrie;
    }

    /**
     * delete journal entry
     * @param integer $id
     * @return boolean
     */

    public function delete_journal_entry($id)
    {
        $this->db->where('id', $id);
        $this->db->delete(db_prefix() . 'acc_journal_entries');
        if ($this->db->affected_rows() > 0) {
            $this->db->where('rel_id', $id);
            $this->db->where('rel_type', 'journal_entry');
            $this->db->delete(db_prefix() . 'acc_account_history');

            return true;
        }
        return false;
    }

    /**
     * update journal entry
     * @param  array $data 
     * @param  integer $id 
     * @return boolean       
     */
    public function update_journal_entry($data, $id){
        $data['cycles']                   = !isset($data['cycles']) ? 0 : $data['cycles'];

        if (isset($data['recurring'])) {
            if ($data['recurring'] == 'custom') {
                $data['recurring_type']   = $data['repeat_type_custom'];
                $data['custom_recurring'] = 1;
                $data['recurring']        = $data['repeat_every_custom'];
            } else {
                $data['recurring_type']   = null;
                $data['custom_recurring'] = 0;
            }
        } else {
            $data['custom_recurring'] = 0;
            $data['recurring']        = 0;
            $data['recurring_type']   = null;
        }


        if (isset($data['repeat_type_custom'])) {
            unset($data['repeat_type_custom']);
        }

        if (isset($data['repeat_every_custom'])) {
            unset($data['repeat_every_custom']);
        }

        $account = $data['account'];
        unset($data['account']);

        $debit_amount = $data['debit_amount'];
        unset($data['debit_amount']);

        $credit_amount = $data['credit_amount'];
        unset($data['credit_amount']);

        $description_detail = $data['description_detail'];
        unset($data['description_detail']);

        $data['journal_date'] = to_sql_date($data['journal_date']);
        if(get_option('acc_close_the_books') == 1){
            if(strtotime($data['journal_date']) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                return 'close_the_book';
            }
        }

        $this->db->where('id', $id);
        $this->db->update(db_prefix().'acc_journal_entries', $data);

        $this->db->where('rel_id', $id);
        $this->db->where('rel_type', 'journal_entry');
        $this->db->delete(db_prefix() . 'acc_account_history');

        $data_insert = [];
        foreach ($account as $key => $value) {
            $node = [];
            $node['account'] = $value;
            $node['date'] = $data['journal_date'];
            $node['debit'] = str_replace(',', '', $debit_amount[$key]);
            $node['credit'] = str_replace(',', '', $credit_amount[$key]);
            $node['description'] = $description_detail[$key];
            $node['rel_id'] = $id;
            $node['rel_type'] = 'journal_entry';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();

            $data_insert[] = $node;
        }

        $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);

        return true;
    }

    /**
     * check format date Y-m-d
     *
     * @param      String   $date   The date
     *
     * @return     boolean
     */
    public function check_format_date($date)
    {
        if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/", $date)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * get transfer
     * @param  integer $id 
     * @return object    
     */
    public function get_transfer($id){
        $this->db->where('id', $id);
        return $this->db->get(db_prefix() . 'acc_transfers')->row();
    }

    /**
     * update transfer
     * @param array $data
     * @param  integer $id 
     * @return boolean
     */
    public function update_transfer($data, $id){
        if(isset($data['id'])){
            unset($data['id']);
        }
        $data['date'] = to_sql_date($data['date']);

        if(get_option('acc_close_the_books') == 1){
            if(strtotime($data['date']) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                return 'close_the_book';
            }
        }

        $data['transfer_amount'] = str_replace(',', '', $data['transfer_amount']);

        $this->db->where('id', $id);
        $this->db->update(db_prefix().'acc_transfers', $data);
        
        $this->db->where('rel_id', $id);
        $this->db->where('rel_type', 'transfer');
        $this->db->delete(db_prefix() . 'acc_account_history');

        $node = [];
        $node['account'] = $data['transfer_funds_from'];
        $node['debit'] = 0;
        $node['credit'] = $data['transfer_amount'];
        $node['date'] = $data['date'];
        $node['rel_id'] = $id;
        $node['rel_type'] = 'transfer';
        $node['datecreated'] = date('Y-m-d H:i:s');
        $node['addedfrom'] = get_staff_user_id();

        $this->db->insert(db_prefix().'acc_account_history', $node);

        $node = [];
        $node['account'] = $data['transfer_funds_to'];
        $node['debit'] = $data['transfer_amount'];
        $node['credit'] = 0;
        $node['date'] = $data['date'];
        $node['rel_id'] = $id;
        $node['rel_type'] = 'transfer';
        $node['datecreated'] = date('Y-m-d H:i:s');
        $node['addedfrom'] = get_staff_user_id();

        $this->db->insert(db_prefix().'acc_account_history', $node);

        return true;
    }

    /**
     * delete transfer
     * @param integer $id
     * @return boolean
     */

    public function delete_transfer($id)
    {
        $this->db->where('id', $id);
        $this->db->delete(db_prefix() . 'acc_transfers');
        if ($this->db->affected_rows() > 0) {
            $this->db->where('rel_id', $id);
            $this->db->where('rel_type', 'transfer');
            $this->db->delete(db_prefix() . 'acc_account_history');

            return true;
        }
        return false;
    }

    /**
     * delete account
     * @param integer $id
     * @return boolean
     */

    public function delete_account($id)
    {
        $this->db->where('(account = '. $id .' or split = '. $id.')');
        $count = $this->db->count_all_results(db_prefix() . 'acc_account_history');

        if($count > 0){
            return 'have_transaction';
        }

        $this->db->where('id', $id);
        $this->db->where('default_account', 0);
        $this->db->delete(db_prefix() . 'acc_accounts');
        if ($this->db->affected_rows() > 0) {
            $this->db->where('account', $id);
            $this->db->delete(db_prefix() . 'acc_account_history');

            return true;
        }
        return false;
    }

    /**
     * delete convert
     * @param integer $id
     * @return boolean
     */
    public function delete_convert($id, $type)
    {
        if($type == 'opening_stock'){
            $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

            $date_financial_year = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.date('Y')));

            $this->db->where('rel_id', $id);
            $this->db->where('rel_type', $type);
            $this->db->where('date >= "'.$date_financial_year.'"');
            $this->db->delete(db_prefix() . 'acc_account_history');
        }else{
            $this->db->where('rel_id', $id);
            $this->db->where('rel_type', $type);
            $this->db->delete(db_prefix() . 'acc_account_history');
        }
        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }
    
    /**
     * Gets the invoice without commission.
     * 
     * @param      bool        $old_invoice 
     * 
     * @return     array  The invoice without commission.
     */
    public function get_data_invoices_for_select($where = []){
        $this->db->where($where);
        $invoices = $this->db->get(db_prefix() . 'invoices')->result_array();

        $invoice_return = [];

        foreach ($invoices as $key => $value) {
            $payments_amount = sum_from_table(db_prefix() . 'invoicepaymentrecords', array('field' => 'amount', 'where' => array('invoiceid' => $value['id'])));

            if($payments_amount > 0){
                $node = [];
                $node['id'] = $value['id'];
                $node['name'] = format_invoice_number($value['id']);
                $invoice_return[] = $node;
            }
        }

        return $invoice_return;
    }

    /**
     * get reconcile by account
     * @param  integer $account 
     * @return object or boolean          
     */
    public function get_reconcile_by_account($account){
        $this->db->where('account', $account);
        $this->db->order_by('id', 'desc');
        $reconcile = $this->db->get(db_prefix() . 'acc_reconciles')->row();

        if($reconcile){
            return $reconcile;
        }

        return false;
    }

    /**
     * add reconcile
     * @param array $data 
     * @return  integer or boolean
     */
    public function add_reconcile($data){
        if($data['ending_date'] != ''){
            $data['ending_date'] = to_sql_date($data['ending_date']);
        }

        if($data['income_date'] != ''){
            $data['income_date'] = to_sql_date($data['income_date']);
        }

        if($data['expense_date'] != ''){
            $data['expense_date'] = to_sql_date($data['expense_date']);
        }

        $data['service_charge'] = str_replace(',', '', $data['service_charge']);
        $data['interest_earned'] = str_replace(',', '', $data['interest_earned']);
        $data['ending_balance'] = str_replace(',', '', $data['ending_balance']);
        $data['beginning_balance'] = str_replace(',', '', $data['beginning_balance']);
        
        $this->db->insert(db_prefix().'acc_reconciles', $data);
        $insert_id = $this->db->insert_id();
        
        if($insert_id){
            if($data['service_charge'] > 0){
                $node = [];
                $node['split'] = $data['account'];
                $node['reconcile'] = $insert_id;
                $node['account'] = $data['expense_account'];
                $node['debit'] = $data['service_charge'];
                $node['credit'] = 0;
                $node['rel_id'] = 0;
                $node['rel_type'] = 'cheque_expense';
                $node['description'] = _l('service_charge');
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();

                $this->db->insert(db_prefix().'acc_account_history', $node);

                $node = [];
                $node['split'] = $data['expense_account'];
                $node['reconcile'] = $insert_id;
                $node['account'] = $data['account'];
                
                $node['debit'] = 0;
                $node['credit'] = $data['service_charge'];
                $node['rel_id'] = 0;
                $node['rel_type'] = 'cheque_expense';
                $node['description'] = _l('service_charge');
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();

                $this->db->insert(db_prefix().'acc_account_history', $node);
            }
            if($data['interest_earned'] > 0){
                $node = [];
                $node['split'] = $data['account'];
                $node['reconcile'] = $insert_id;
                $node['account'] = $data['income_account'];
                $node['debit'] = 0;
                $node['credit'] = $data['interest_earned'];
                $node['rel_id'] = 0;
                $node['rel_type'] = 'deposit';
                $node['description'] = _l('interest_earned');
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();

                $this->db->insert(db_prefix().'acc_account_history', $node);

                $node = [];
                $node['split'] = $data['income_account'];
                $node['reconcile'] = $insert_id;
                $node['account'] = $data['account'];
                $node['debit'] = $data['interest_earned'];
                $node['credit'] = 0;
                $node['rel_id'] = 0;
                $node['rel_type'] = 'deposit';
                $node['description'] = _l('interest_earned');
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();

                $this->db->insert(db_prefix().'acc_account_history', $node);
            }

            return $insert_id;
        }

        return false;
    }

    /**
     * update reconcile
     * @param array $data 
     * @param integer $id 
     * @return  boolean
     */
    public function update_reconcile($data, $id){
        if($data['ending_date'] != ''){
            $data['ending_date'] = to_sql_date($data['ending_date']);
        }

        if($data['income_date'] != ''){
            $data['income_date'] = to_sql_date($data['income_date']);
        }

        if($data['expense_date'] != ''){
            $data['expense_date'] = to_sql_date($data['expense_date']);
        }

        $account = 0;
        if(isset($data['expense_date'])){
            $account = $data['account'];
            unset($data['account']);
        }

        $data['service_charge'] = str_replace(',', '', $data['service_charge']);
        $data['interest_earned'] = str_replace(',', '', $data['interest_earned']);
        $data['ending_balance'] = str_replace(',', '', $data['ending_balance']);
        $data['beginning_balance'] = str_replace(',', '', $data['beginning_balance']);

        $this->db->where('id', $id);
        $this->db->update(db_prefix().'acc_reconciles', $data);
        
        if ($this->db->affected_rows() > 0) {
            $this->db->where('rel_id', 0);
            $this->db->where('rel_type', 'cheque_expense');
            $this->db->where('reconcile', $id);
            $this->db->delete(db_prefix().'acc_account_history');

            $this->db->where('rel_id', 0);
            $this->db->where('rel_type', 'deposit');
            $this->db->where('reconcile', $id);
            $this->db->delete(db_prefix().'acc_account_history');

            if($data['service_charge'] > 0){
                $node = [];
                $node['split'] = $account;
                $node['reconcile'] = 0;
                $node['account'] = $data['expense_account'];
                $node['debit'] = $data['service_charge'];
                $node['credit'] = 0;
                $node['rel_id'] = 0;
                $node['rel_type'] = 'cheque_expense';
                $node['description'] = _l('service_charge');
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();

                $this->db->insert(db_prefix().'acc_account_history', $node);

                $node = [];
                $node['split'] = $data['expense_account'];
                $node['reconcile'] = $id;
                $node['account'] = $account;
                $node['debit'] = 0;
                $node['credit'] = $data['service_charge'];
                $node['rel_id'] = 0;
                $node['rel_type'] = 'cheque_expense';
                $node['description'] = _l('service_charge');
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();

                $this->db->insert(db_prefix().'acc_account_history', $node);
            }
            if($data['interest_earned'] > 0){
                $node = [];
                $node['split'] = $account;
                $node['reconcile'] = 0;
                $node['account'] = $data['income_account'];
                $node['debit'] = 0;
                $node['credit'] = $data['interest_earned'];
                $node['rel_id'] = 0;
                $node['rel_type'] = 'deposit';
                $node['description'] = _l('interest_earned');
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();

                $this->db->insert(db_prefix().'acc_account_history', $node);

                $node = [];
                $node['split'] = $data['income_account'];
                $node['reconcile'] = $id;
                $node['account'] = $account;
                $node['debit'] = $data['interest_earned'];
                $node['credit'] = 0;
                $node['rel_id'] = 0;
                $node['rel_type'] = 'deposit';
                $node['description'] = _l('interest_earned');
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();

                $this->db->insert(db_prefix().'acc_account_history', $node);
            }

            return true;
        }

        return false;
    }

    /**
     * add adjustment
     * @param array $data 
     * @return  integer or boolean
     */
    public function add_adjustment($data){
        $this->db->where('account_type_id', 15);
        $this->db->where('account_detail_type_id', 139);
        $account = $this->db->get(db_prefix().'acc_accounts')->row();
        $data['adjustment_date'] = to_sql_date($data['adjustment_date']);

        if(get_option('acc_close_the_books') == 1){
            if(strtotime($data['adjustment_date']) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                return 'close_the_book';
            }
        }
        if($account){
            $data['adjustment_amount'] = str_replace(',', '', $data['adjustment_amount']);

            $node = [];

            $node['account'] = $account->id;
            if($data['adjustment_amount'] > 0){
                $node['rel_id'] = 0;
                $node['rel_type'] = 'deposit';
                $node['debit'] = $data['adjustment_amount'];
                $node['credit'] = 0;
            }else{
                $node['rel_id'] = 0;
                $node['rel_type'] = 'cheque_expense';
                $node['debit'] = 0;
                $node['credit'] = $data['adjustment_amount'];
            }
            $node['split'] = $data['account'];
            $node['reconcile'] = $data['reconcile'];
            $node['description'] = _l('reconcile_adjustment');
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['date'] = $data['adjustment_date'];
            $node['addedfrom'] = get_staff_user_id();

            $this->db->insert(db_prefix().'acc_account_history', $node);

            $node = [];
            $node['account'] = $data['account'];
            if($data['adjustment_amount'] > 0){
                $node['rel_id'] = 0;
                $node['rel_type'] = 'deposit';
                $node['debit'] = 0;
                $node['credit'] = $data['adjustment_amount'];
            }else{
                $node['rel_id'] = 0;
                $node['rel_type'] = 'cheque_expense';
                $node['debit'] = $data['adjustment_amount'];
                $node['credit'] = 0;
            }

            $node['split'] = $account->id;
            $node['reconcile'] = $data['reconcile'];
            $node['description'] = _l('reconcile_adjustment');
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['date'] = $data['adjustment_date'];
            $node['addedfrom'] = get_staff_user_id();

            $this->db->insert(db_prefix().'acc_account_history', $node);

            $insert_id = $this->db->insert_id();
            if ($insert_id) {
                return $insert_id;
            }
        }else{
            $this->db->insert(db_prefix().'acc_accounts', [
                'name' => '',
                'key_name' => 'acc_reconciliation_discrepancies',
                'account_type_id' => 15,
                'account_detail_type_id' => 139,
            ]);

            $account_id = $this->db->insert_id();

            if ($account_id) {
                $node = [];
                $node['split'] = $data['account'];
                $node['account'] = $account_id;
                if($data['adjustment_amount'] > 0){
                    $node['rel_id'] = $id;
                    $node['rel_type'] = 'deposit';
                    $node['debit'] = $data['adjustment_amount'];
                    $node['credit'] = 0;
                }else{
                    $node['rel_id'] = $id;
                    $node['rel_type'] = 'cheque_expense';
                    $node['debit'] = 0;
                    $node['credit'] = $data['adjustment_amount'];
                }

                $node['reconcile'] = $data['reconcile'];
                $node['description'] = _l('reconcile_adjustment');
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['date'] = $data['adjustment_date'];
                $node['addedfrom'] = get_staff_user_id();

                $this->db->insert(db_prefix().'acc_account_history', $node);

                $node = [];
                $node['account'] = $data['account'];
                if($data['adjustment_amount'] > 0){
                    $node['rel_id'] = 0;
                    $node['rel_type'] = 'deposit';
                    $node['debit'] = 0;
                    $node['credit'] = $data['adjustment_amount'];
                }else{
                    $node['rel_id'] = 0;
                    $node['rel_type'] = 'cheque_expense';
                    $node['debit'] = $data['adjustment_amount'];
                    $node['credit'] = 0;
                }

                $node['split'] = $account_id;
                $node['reconcile'] = $data['reconcile'];
                $node['description'] = _l('reconcile_adjustment');
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['date'] = $data['adjustment_date'];
                $node['addedfrom'] = get_staff_user_id();

                $this->db->insert(db_prefix().'acc_account_history', $node);

                $insert_id = $this->db->insert_id();

                if ($insert_id) {
                    return $insert_id;
                }
            }
        }

        return false;
    }

    /**
     * finish reconcile account
     * @param  array $data 
     * @return boolean       
     */
    public function finish_reconcile_account($data){
        $affectedRows = 0;

        if($data['history_ids'] != ''){
            $history_ids = explode(', ', $data['history_ids']);

            foreach ($history_ids as $key => $value) {
                $this->db->where('id', $value);
                $this->db->update(db_prefix().'acc_account_history', ['reconcile' => $data['reconcile']]);

                if ($this->db->affected_rows() > 0) {
                    $affectedRows++;
                }
            }
        }

        if($data['finish'] == 1){
            $this->db->where('id', $data['reconcile']);
            $this->db->update(db_prefix().'acc_reconciles', ['finish' => 1]);

            if ($this->db->affected_rows() > 0) {
                $affectedRows++;
            }

        }

        if ($affectedRows > 0) {
            return true;
        }

        return true;
    }



    /**
     * reconcile save for later
     * @param  array $data 
     * @return boolean       
     */
    
    public function reconcile_save_for_later($data){
        $affectedRows = 0;
        if($data['history_ids'] != ''){
            $history_ids = explode(', ', $data['history_ids']);

            foreach ($history_ids as $key => $value) {
                $this->db->where('id', $value);
                $this->db->update(db_prefix().'acc_account_history', ['reconcile' => $data['reconcile']]);

                if ($this->db->affected_rows() > 0) {
                    $affectedRows++;
                }
            }
        }

        if ($affectedRows > 0) {
            return true;
        }
        return true;
    }

    /**
     * get data bank accounts dashboard
     * @param  array $data_filter 
     * @return array 
     */
    public function get_data_bank_accounts_dashboard($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $where = $this->get_where_report_period();

        $account_type_details = $this->get_account_type_details();
        $data_return = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 3 || $value['account_type_id'] == 16){
                $data_accounts['cash_and_cash_equivalents'][] = $value;
            }
            if($value['account_type_id'] == 7){
                $data_accounts['credit_card'][] = $value;
            }
        }
        $html = '<ul class="list-group">
            <li class="list-group-item bold">'. _l('bank_accounts_uppercase').'<span class="badge">'. _l('balance').'</span></li>';
        foreach ($data_accounts as $data_key => $data_account) {
            $total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    if($where != ''){
                        $this->db->where($where);
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }


                    if($value['account_type_id'] == 10 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 7){
                        $html .= '<li class="list-group-item">'.$name.'<span class="badge">'.app_format_money($credits - $debits, $currency->name).'</span></li>';
                    }else{
                        $html .= '<li class="list-group-item">'.$name.'<span class="badge">'.app_format_money($debits - $credits, $currency->name).'</span></li>';
                    }

                    $data_return[] = ['name' => $name, 'balance' => $debits - $credits];
                }
            }
        }
        $html .= '</ul>';
        
        return $html;
    }

    /**
     * get data convert status dashboard
     * @param  array $data_filter 
     * @return array 
     */
    public function get_data_convert_status_dashboard($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $where = $this->get_where_report_period();

        $data_currency = $currency->id;
        if($this->input->get('currency')){
            $data_currency = $this->input->get('currency');
            $currency = $this->currencies_model->get($data_currency);
        }

        $this->db->select_sum('total');
        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'invoices.id and ' . db_prefix() . 'acc_account_history.rel_type = "invoice") = 0) and currency = '.$data_currency);
        $invoice = $this->db->get(db_prefix().'invoices')->row();

        $this->db->select_sum('amount');
        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'expenses.id and ' . db_prefix() . 'acc_account_history.rel_type = "expense") = 0) and currency = '.$data_currency);
        $this->db->join(db_prefix().'expenses_categories', db_prefix() . 'expenses_categories.id = ' . db_prefix() . 'expenses.category');
        $expense = $this->db->get(db_prefix().'expenses')->row();

        $where_payment = $this->get_where_report_period(db_prefix() . 'invoicepaymentrecords.date');
        $this->db->select_sum('amount');
        if($where_payment != ''){
            $this->db->where($where_payment);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'invoicepaymentrecords.id and ' . db_prefix() . 'acc_account_history.rel_type = "payment") = 0) and currency = '.$data_currency);
        $this->db->join(db_prefix() . 'invoices', db_prefix() . 'invoices.id=' . db_prefix() . 'invoicepaymentrecords.invoiceid', 'left');
        $payment = $this->db->get(db_prefix().'invoicepaymentrecords')->row();


        $html = '<table class="table border table-striped no-margin">
                      <tbody>
                        <tr class="project-overview">
                            <td colspan="3" class="text-center"><h4>'. _l('transaction_not_yet_converted').'</h4></td>
                        </tr>
                        <tr class="project-overview">
                            <td class="bold" width="30%">'. _l('transaction').'</td>
                            <td class="bold" width="30%">'. _l('invoice_table_quantity_heading').'</td>
                            <td class="bold">'. _l('acc_amount').'</td>
                        </tr>
                        <tr class="project-overview '. ($invoice->total > 0 ? 'text-danger' : '').'">
                            <td class="bold" width="30%"><a href="'.admin_url('accounting/transaction?group=sales&tab=invoice&status=has_not_been_converted').'">'. _l('invoice').'</a></td>
                            <td width="30%">'. $this->count_invoice_not_convert_yet($data_currency, $where) .'</td>
                            <td>'. app_format_money($invoice->total, $currency->name)  .'</td>
                        </tr>
                        <tr class="project-overview '. ($payment->amount > 0 ? 'text-danger' : '').'">
                            <td class="bold" width="30%"><a href="'.admin_url('accounting/transaction?group=sales&tab=payment&status=has_not_been_converted').'">'. _l('payment').'</a></td>
                            <td width="30%">'. $this->count_payment_not_convert_yet($data_currency, $where_payment)  .'</td>
                            <td>'. app_format_money($payment->amount, $currency->name)  .'</td>
                         </tr>
                         <tr class="project-overview '. ($expense->amount > 0 ? 'text-danger' : '').'">
                            <td class="bold" width="30%"><a href="'.admin_url('accounting/transaction?group=expenses&status=has_not_been_converted').'">'. _l('expense').'</a></td>
                            <td width="30%">'. $this->count_expense_not_convert_yet($data_currency, $where)  .'</td>
                            <td>'. app_format_money($expense->amount, $currency->name)  .'</td>
                         </tr>
                        </tbody>
                  </table>';
        return $html;
    }

    /**
     * get data profit and loss chart
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_profit_and_loss_chart(){
        $accounting_method = get_option('acc_accounting_method');

        $where = $this->get_where_report_period();
        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 11){
                $data_accounts['income'][] = $value;
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }
        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    if($where != ''){
                        $this->db->where($where);
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;

                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                        $total += $credits - $debits;
                    }else{
                        $total += $debits - $credits;
                    }
                }
            }
            $data_total[$data_key] = $total;
        }

        $income = $data_total['income'] + $data_total['other_income'];
        $expenses = $data_total['expenses'] + $data_total['other_expenses'] + $data_total['cost_of_sales'];
        $net_income = $income - $expenses;

        return [$net_income, $income, $expenses];
    }

    /**
     * get data expenses chart
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_expenses_chart($data_filter){
        $where = $this->get_where_report_period();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }
        $total = 0;

        if($where != ''){
            $this->db->select('*, (SELECT (sum(debit) - sum(credit)) as balance FROM '.db_prefix().'acc_account_history where account = '.db_prefix().'acc_accounts.id and '.$where.') as amount');
        }else{
            $this->db->select('*, (SELECT (sum(debit) - sum(credit)) as balance FROM '.db_prefix().'acc_account_history where account = '.db_prefix().'acc_accounts.id) as amount');
        }

        $this->db->where('(account_type_id = 13 or account_type_id = 14 or account_type_id = 15)');
        $this->db->where('active', 1);

        $this->db->order_by('amount', 'desc');
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        foreach ($accounts as $k => $val) {
            if($k > 2){
                $total += $val['amount'];
            }else{
                if($acc_show_account_numbers == 1 && $val['number'] != ''){
                            $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                        }else{
                            $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                        }

                if($val['amount'] < 0){
                    $data_return[] = ['name' => $name, 'y' => floatval(-$val['amount']), 'amount' => ''.floatval($val['amount'])];
                }else{
                    $data_return[] = ['name' => $name, 'y' => floatval($val['amount']), 'amount' => ''.floatval($val['amount'])];
                }
            }
        }
        if($total < 0){
            $data_return[] = ['name' => _l('everything_else'), 'y' => floatval(-$total), 'amount' => ''.$total];
        }else{
            $data_return[] = ['name' => _l('everything_else'), 'y' => floatval($total), 'amount' => ''.$total];
        }
        return $data_return;
    }

    /**
     * get data income chart
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_income_chart($data_filter){
        $accounting_method = get_option('acc_accounting_method');
        $where = $this->get_where_report_period('date');

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        if(isset($data_filter['currency'])){
            $data_currency = $data_filter['currency'];
        }else{
            $data_currency = $currency->id;
        }

        $last_30_days = date('Y-m-d', strtotime('today - 30 days'));

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->select('*, (SELECT sum(amount) as amount FROM '.db_prefix().'invoicepaymentrecords where invoiceid = '.db_prefix().'invoices.id and date >= "'.$last_30_days.'") as amount');
        $this->db->where('currency', $data_currency);
        $invoices = $this->db->get(db_prefix().'invoices')->result_array();
        $mapped = 0;
        $open_invoice = 0;
        $overdue_invoices = 0;
        $paid_last_30_days = 0;
        $list_invoice = '0';

        foreach ($invoices as $key => $value) {
            $list_invoice .= ','.$value['id'];

            $this->db->select('sum(credit) as credit');
            $this->db->where('rel_id', $value['id']);
            $this->db->where('rel_type', 'invoice');
            $this->db->where('tax < 1');
            $this->db->where('paid', 1);
            $count = $this->db->get(db_prefix().'acc_account_history')->row();
            if(isset($count->credit) && $count->credit > 0){
                $mapped += $count->credit;
            }else{
                if($value['status'] == 1){
                    $open_invoice += $value['subtotal'];
                }elseif ($value['status'] == 2 && $value['amount'] > 0) {
                    $paid_last_30_days += $value['amount'];
                }elseif ($value['status'] == 4) {
                    $overdue_invoices += $value['subtotal'];
                }
            }
        }

        $data_return = [];
        $data_return[] = ['name' => _l('open_invoice'), 'data' => [floatval($open_invoice)]];
        $data_return[] = ['name' => _l('overdue_invoices'), 'data' => [floatval($overdue_invoices)]];
        $data_return[] = ['name' => _l('paid_last_30_days'), 'data' => [floatval($paid_last_30_days)]];

        $where = $this->get_where_report_period();
        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_total = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 11){
                $data_accounts['income'][] = $value;
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            $total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->where('account', $val['id']);
                    if($where != ''){
                        $this->db->where($where);
                    }
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    if($currency->id != $data_currency){
                        $this->db->where('1=0');
                    }
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    if($where != ''){
                        $this->db->where($where);
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;

                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                        $total += $credits - $debits;
                    }else{
                        $total += $debits - $credits;
                    }
                }
            }
            $data_total[$data_key] = $total;
        }

        $income = $data_total['income'] + $data_total['other_income'];
        $data_return[] = ['name' => _l('has_been_mapping'), 'data' => [floatval($data_total['income'] + $data_total['other_income'])]];
        return $data_return;
    }

    /**
     * get data sales chart
     * @param  array $data_filter
     * @return array
     */
    public function get_data_sales_chart($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        if(isset($data_filter['currency'])){
            $data_currency = $data_filter['currency'];
        }else{
            $data_currency = $currency->id;
        }


        $where = $this->get_where_report_period('date');

        if($where != ''){
            $this->db->where($where);
        }

        $this->db->where('currency', $data_currency);
        $invoices = $this->db->get(db_prefix().'invoices')->result_array();

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('currency', $data_currency);
        $expenses = $this->db->get(db_prefix().'expenses')->result_array();

        $data_return = [];
        $data_date = [];

        $list_invoice = '0';
        foreach ($invoices as $key => $value) {
            $list_invoice .= ','.$value['id'];
            $this->db->where('rel_id', $value['id']);
            $this->db->where('rel_type', 'invoice');
            $this->db->where('paid', 1);
            $count = $this->db->count_all_results(db_prefix().'acc_account_history');

            if($count == 0){
                if(isset($data_date[$value['date']])){
                    $data_date[$value['date']]['payment'] += floatval($value['subtotal']);
                }else{
                    $data_date[$value['date']] = [];
                    $data_date[$value['date']]['payment'] = floatval($value['subtotal']);
                    $data_date[$value['date']]['expense'] = 0;
                    $data_date[$value['date']]['invoice_have_been_mapping'] = 0;
                    $data_date[$value['date']]['expense_have_been_mapping'] = 0;
                }
            }
        }

        $list_expense = '0';

        foreach ($expenses as $key => $value) {
            $list_expense .= ','.$value['id'];

            $this->db->where('rel_id', $value['id']);
            $this->db->where('rel_type', 'expense');
            $count = $this->db->count_all_results(db_prefix().'acc_account_history');
            if($count == 0){
                if(isset($data_date[$value['date']])){
                    $data_date[$value['date']]['expense'] += floatval($value['amount']);
                }else{
                    $data_date[$value['date']] = [];
                    $data_date[$value['date']]['expense'] = floatval($value['amount']);
                    $data_date[$value['date']]['payment'] = 0;
                    $data_date[$value['date']]['invoice_have_been_mapping'] = 0;
                    $data_date[$value['date']]['expense_have_been_mapping'] = 0;
                }
            }
        }

        $account_type_details = $this->get_account_type_details();

        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 11){
                $data_accounts['income'][] = $value;
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->where('account', $val['id']);
                    $this->db->select('credit, debit, date, datecreated');
                    if($currency->id != $data_currency){
                        $this->db->where('1=0');
                    }
                    if($where != ''){
                        $this->db->where($where);
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();

                    foreach ($account_history as $val) {
                        $credits = $val['credit'] != '' ? $val['credit'] : 0;
                        $debits = $val['debit'] != '' ? $val['debit'] : 0;
                        $date = $val['date'] != '' ? $val['date'] : date('Y-m-d', strtotime($val['datecreated']));

                        if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                            $total = $credits - $debits;
                            if(isset($data_date[$date])){
                                $data_date[$date]['invoice_have_been_mapping'] += floatval($total);

                            }else{
                                $data_date[$date] = [];
                                $data_date[$date]['invoice_have_been_mapping'] = floatval($total);
                                $data_date[$date]['expense_have_been_mapping'] = 0;
                                $data_date[$date]['payment'] = 0;
                                $data_date[$date]['expense'] = 0;
                            }
                        }else{
                            $total = $debits - $credits;
                            if(isset($data_date[$date])){
                                $data_date[$date]['expense_have_been_mapping'] += floatval($total);
                            }else{
                                $data_date[$date] = [];
                                $data_date[$date]['expense_have_been_mapping'] = floatval($total);
                                $data_date[$date]['invoice_have_been_mapping'] = 0;
                                $data_date[$date]['payment'] = 0;
                                $data_date[$date]['expense'] = 0;
                            }
                        }
                    }

                }
            }
        }

        $sales = [];
        $invoice_have_been_mapping = [];
        $expense_have_been_mapping = [];
        $expenses = [];
        $categories = [];
        $date_array = [];

        foreach ($data_date as $d => $val) {
            $_date = $d;
            foreach ($data_date as $date => $value) {
                if(strtotime($_date) > (strtotime($date)) && !in_array($date,$date_array)){
                    $_date = $date;
                }elseif(!in_array($date,$date_array) && in_array($_date,$date_array)){
                    $_date = $date;
                }
            }

            $date_array[] = $_date;

        }

        foreach ($date_array as $date) {
            if(isset($data_date[$date])){
                $sales[] = $data_date[$date]['payment'];
                $expenses[] = $data_date[$date]['expense'];
                $invoice_have_been_mapping[] = $data_date[$date]['invoice_have_been_mapping'];
                $expense_have_been_mapping[] = $data_date[$date]['expense_have_been_mapping'];
                $categories[] = _d($date);
            }
        }

        $data_return = [
            'data' => [
                ['name' => _l('sales'), 'data' => $sales],
                ['name' => _l('sales_have_been_mapping'), 'data' => $invoice_have_been_mapping],
                ['name' => _l('expenses'), 'data' => $expenses],
                ['name' => _l('expenses_have_been_mapping'), 'data' => $expense_have_been_mapping],
            ],
            'categories' => $categories
        ];
        return $data_return;
    }

    /**
     * add rule
     * @param array $data 
     */
    public function add_rule($data){

        if(isset($data['type'])){
            $type = $data['type'];
            unset($data['type']);
        }

        if(isset($data['subtype'])){
            $subtype = $data['subtype'];
            unset($data['subtype']);
        }

        if(isset($data['text'])){
            $text = $data['text'];
            unset($data['text']);
        }

        if(isset($data['subtype_amount'])){
            $subtype_amount = $data['subtype_amount'];
            unset($data['subtype_amount']);
        }

        if(!isset($data['auto_add'])){
            $data['auto_add'] = 0;
        }

        $percentage = '';
        if(isset($data['percentage'])){
            $percentage = $data['percentage'];
            unset($data['percentage']);
        }

        $account_split = '';
        if(isset($data['account_split'])){
            $account_split = $data['account_split'];
            unset($data['account_split']);
        }

        $fixed_amount = '';
        if(isset($data['fixed_amount'])){
            $fixed_amount = $data['fixed_amount'];
            unset($data['fixed_amount']);
        }

        $account_split_fixed = '';
        if(isset($data['account_split_fixed'])){
            $account_split_fixed = $data['account_split_fixed'];
            unset($data['account_split_fixed']);
        }

        $data['split_percentage'] = json_encode(['percentage' => $percentage, 'account_split' => $account_split]);
        $data['split_amount'] = json_encode(['fixed_amount' => $fixed_amount, 'account_split_fixed' => $account_split_fixed]);

        $this->db->insert(db_prefix().'acc_banking_rules', $data);

        $insert_id = $this->db->insert_id();

        if ($insert_id) {
            if(isset($type)){
                foreach ($type as $key => $value) {
                    $this->db->insert(db_prefix().'acc_banking_rule_details', [
                        'rule_id' => $insert_id,
                        'type' => $value,
                        'subtype' => $subtype[$key],
                        'subtype_amount' => $subtype_amount[$key],
                        'text' => $text[$key],
                    ]);
                }
            }

            return $insert_id;
        }

        return false;
    }

    /**
     * update rule
     * @param array $data 
     */
    public function update_rule($data, $id){
        $affectedRows = 0;

        if(isset($data['type'])){
            $type = $data['type'];
            unset($data['type']);
        }

        if(isset($data['subtype'])){
            $subtype = $data['subtype'];
            unset($data['subtype']);
        }

        if(isset($data['text'])){
            $text = $data['text'];
            unset($data['text']);
        }

        if(isset($data['subtype_amount'])){
            $subtype_amount = $data['subtype_amount'];
            unset($data['subtype_amount']);
        }

        $percentage = '';
        if(isset($data['percentage'])){
            $percentage = $data['percentage'];
            unset($data['percentage']);
        }

        $account_split = '';
        if(isset($data['account_split'])){
            $account_split = $data['account_split'];
            unset($data['account_split']);
        }

        $fixed_amount = '';
        if(isset($data['fixed_amount'])){
            $fixed_amount = $data['fixed_amount'];
            unset($data['fixed_amount']);
        }

        $account_split_fixed = '';
        if(isset($data['account_split_fixed'])){
            $account_split_fixed = $data['account_split_fixed'];
            unset($data['account_split_fixed']);
        }

        $data['split_percentage'] = json_encode(['percentage' => $percentage, 'account_split' => $account_split]);
        $data['split_amount'] = json_encode(['fixed_amount' => $fixed_amount, 'account_split_fixed' => $account_split_fixed]);


        $this->db->where('id', $id);
        $this->db->update(db_prefix().'acc_banking_rules', $data);

        if ($this->db->affected_rows() > 0) {
            $affectedRows++;
        }

        $this->db->where('rule_id', $id);
        $this->db->delete(db_prefix() . 'acc_banking_rule_details');

        if(isset($type)){
            foreach ($type as $key => $value) {
                $this->db->insert(db_prefix().'acc_banking_rule_details', [
                    'rule_id' => $id,
                    'type' => $value,
                    'subtype_amount' => $subtype_amount[$key],
                    'subtype' => $subtype[$key],
                    'text' => $text[$key],
                ]);
            }
        }

        if ($affectedRows > 0) {
            return $insert_id;
        }

        return false;
    }

    /**
     * get rule
     * @param  integer $id 
     * @param  array $where 
     * @return object     
     */
    public function get_rule($id = '', $where = []){
        if($id != ''){
            $this->db->where('id', $id);
            $rule = $this->db->get(db_prefix() . 'acc_banking_rules')->row();

            if($rule){
                $this->db->where('rule_id', $id);
                $rule->details = $this->db->get(db_prefix() . 'acc_banking_rule_details')->result_array();
            }
            return $rule;
        }

        $this->db->where($where);
        $rule = $this->db->get(db_prefix() . 'acc_banking_rules')->result_array();
        if($rule){
            foreach ($rule as $key => $value) {
                $this->db->where('rule_id', $value['id']);
                $rule[$key]['details'] = $this->db->get(db_prefix() . 'acc_banking_rule_details')->result_array();
            }
        }
            
        return $rule;
    }

    /**
     * delete journal entry
     * @param integer $id
     * @return boolean
     */

    public function delete_rule($id)
    {
        $this->db->where('id', $id);
        $this->db->delete(db_prefix() . 'acc_banking_rules');
        if ($this->db->affected_rows() > 0) {
            $this->db->where('rule_id', $id);
            $this->db->delete(db_prefix() . 'acc_banking_rule_details');

            return true;
        }
        return false;
    }

    /**
     * insert batch banking
     * @param  array $data_insert 
     * @return boolean              
     */
    public function insert_batch_banking($data_insert){
        $rule = $this->get_rule();
        

        foreach ($data_insert as $value) {
            $value['date'] = str_replace('/', '-', $value['date']);
            $value['date'] = date('Y-m-d', strtotime($value['date']));
            $this->db->insert(db_prefix().'acc_transaction_bankings', $value);

            $insert_id = $this->db->insert_id();

            if (!$insert_id) {
                continue;
            }

            if(get_option('acc_close_the_books') == 1){
                if(strtotime($value['date']) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    continue;
                }
            }

            foreach ($rule as $val) {
                if($this->check_rule($val, $value)){
                    if($val['then'] == 'exclude'){
                        break;
                    }elseif($val['auto_add'] == 0){
                        continue;
                    }

                    $data = [];

                    if ($val['mapping_type'] == 'full_amount' || $val['mapping_type'] == '') {
                        $amount = $value['deposits'];
                        $payment_account = $val['account'];
                        $deposit_to = $value['bank_id'];

                        if($value['withdrawals'] > 0){
                            $amount = $value['withdrawals'];
                            $payment_account = $value['bank_id'];
                            $deposit_to = $val['account'];
                        }

                        $node = [];
                        $node['split'] = $payment_account;
                        $node['account'] = $deposit_to;
                        $node['debit'] = $amount;
                        $node['date'] = $value['date'];
                        $node['credit'] = 0;
                        $node['description'] = _l('banking_rule');
                        $node['rel_id'] = $insert_id;
                        $node['rel_type'] = 'banking';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['cleared'] = 1;
                        $node['reconcile'] = -1;
                        $this->db->insert(db_prefix().'acc_account_history', $node);
                        $account_history_id = $this->db->insert_id();

                        $this->db->insert(db_prefix().'acc_matched_transactions', [
                            'account_history_id' => $account_history_id,
                            'history_amount' => 0,
                            'rel_id' => $insert_id,
                            'rel_type' => 'banking',
                            'amount' => 0,
                            'reconcile' => -1,
                        ]);

                        $node = [];
                        $node['split'] = $deposit_to;
                        $node['account'] = $payment_account;
                        $node['date'] = $value['date'];
                        $node['debit'] = 0;
                        $node['credit'] = $amount;
                        $node['description'] = _l('banking_rule');
                        $node['rel_id'] = $insert_id;
                        $node['rel_type'] = 'banking';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['cleared'] = 1;
                        $node['reconcile'] = -1;
                        $this->db->insert(db_prefix().'acc_account_history', $node);
                        $account_history_id = $this->db->insert_id();

                        $this->db->insert(db_prefix().'acc_matched_transactions', [
                            'account_history_id' => $account_history_id,
                            'history_amount' => 0,
                            'rel_id' => $insert_id,
                            'rel_type' => 'banking',
                            'amount' => 0,
                            'reconcile' => -1,
                        ]);

                    }elseif($val['mapping_type'] == 'split_percentage'){
                        $split_percentage = json_decode($val['split_percentage'], true);
                        $percentage = $split_percentage['percentage'];
                        $account_split = $split_percentage['account_split'];

                        foreach ($percentage as $key => $percent) {

                            $amount = $value['deposits'];
                            $payment_account = $account_split[$key];
                            $deposit_to = $value['bank_id'];

                            if($value['withdrawals'] > 0){
                                $amount = $value['withdrawals'];
                                $payment_account = $value['bank_id'];
                                $deposit_to = $account_split[$key];
                            }

                            $sub_amount = (($percent*$amount) / 100);

                            $node = [];
                            $node['split'] = $payment_account;
                            $node['account'] = $deposit_to;
                            $node['debit'] = $sub_amount;
                            $node['date'] = $value['date'];
                            $node['credit'] = 0;
                            $node['description'] = _l('banking_rule');
                            $node['rel_id'] = $insert_id;
                            $node['rel_type'] = 'banking';
                            $node['datecreated'] = date('Y-m-d H:i:s');
                            $node['addedfrom'] = get_staff_user_id();
                            $node['cleared'] = 1;
                            $node['reconcile'] = -1;
                            $this->db->insert(db_prefix().'acc_account_history', $node);
                            $account_history_id = $this->db->insert_id();

                            $this->db->insert(db_prefix().'acc_matched_transactions', [
                                'account_history_id' => $account_history_id,
                                'history_amount' => 0,
                                'rel_id' => $insert_id,
                                'rel_type' => 'banking',
                                'amount' => 0,
                                'reconcile' => -1,
                            ]);

                            $node = [];
                            $node['split'] = $deposit_to;
                            $node['account'] = $payment_account;
                            $node['date'] = $value['date'];
                            $node['debit'] = 0;
                            $node['credit'] = $sub_amount;
                            $node['description'] = _l('banking_rule');
                            $node['rel_id'] = $insert_id;
                            $node['rel_type'] = 'banking';
                            $node['datecreated'] = date('Y-m-d H:i:s');
                            $node['addedfrom'] = get_staff_user_id();
                            $node['cleared'] = 1;
                            $node['reconcile'] = -1;
                            $this->db->insert(db_prefix().'acc_account_history', $node);
                            $account_history_id = $this->db->insert_id();

                            $this->db->insert(db_prefix().'acc_matched_transactions', [
                                'account_history_id' => $account_history_id,
                                'history_amount' => 0,
                                'rel_id' => $insert_id,
                                'rel_type' => 'banking',
                                'amount' => 0,
                                'reconcile' => -1,
                            ]);
                        }

                    }else{
                        $split_amount = json_decode($val['split_amount'], true);
                        $fixed_amount = $split_amount['fixed_amount'];
                        $account_split_fixed = $split_amount['account_split_fixed'];
                        $total_fixed_amount = 0;
                        foreach ($fixed_amount as $key => $fixed) {
                            $total_fixed_amount += $fixed;

                            $payment_account = $account_split_fixed[$key];
                            $deposit_to = $value['bank_id'];

                            if($value['withdrawals'] > 0){
                                $payment_account = $value['bank_id'];
                                $deposit_to = $account_split_fixed[$key];
                            }

                            $node = [];
                            $node['split'] = $payment_account;
                            $node['account'] = $deposit_to;
                            $node['debit'] = $fixed;
                            $node['date'] = $value['date'];
                            $node['credit'] = 0;
                            $node['description'] = _l('banking_rule');
                            $node['rel_id'] = $insert_id;
                            $node['rel_type'] = 'banking';
                            $node['datecreated'] = date('Y-m-d H:i:s');
                            $node['addedfrom'] = get_staff_user_id();
                            $node['cleared'] = 1;
                            $node['reconcile'] = -1;
                            $this->db->insert(db_prefix().'acc_account_history', $node);
                            $account_history_id = $this->db->insert_id();

                            $this->db->insert(db_prefix().'acc_matched_transactions', [
                                'account_history_id' => $account_history_id,
                                'history_amount' => 0,
                                'rel_id' => $insert_id,
                                'rel_type' => 'banking',
                                'amount' => 0,
                                'reconcile' => -1,
                            ]);

                            $node = [];
                            $node['split'] = $deposit_to;
                            $node['account'] = $payment_account;
                            $node['date'] = $value['date'];
                            $node['debit'] = 0;
                            $node['credit'] = $fixed;
                            $node['description'] = _l('banking_rule');
                            $node['rel_id'] = $insert_id;
                            $node['rel_type'] = 'banking';
                            $node['datecreated'] = date('Y-m-d H:i:s');
                            $node['addedfrom'] = get_staff_user_id();
                            $node['cleared'] = 1;
                            $node['reconcile'] = -1;
                            $this->db->insert(db_prefix().'acc_account_history', $node);
                            $account_history_id = $this->db->insert_id();

                            $this->db->insert(db_prefix().'acc_matched_transactions', [
                                'account_history_id' => $account_history_id,
                                'history_amount' => 0,
                                'rel_id' => $insert_id,
                                'rel_type' => 'banking',
                                'amount' => 0,
                                'reconcile' => -1,
                            ]);
                        }

                        $amount = $value['deposits'];
                        $payment_account = $account_split_fixed[10000];
                        $deposit_to = $value['bank_id'];

                        if($value['withdrawals'] > 0){
                            $amount = $value['withdrawals'];
                            $payment_account = $value['bank_id'];
                            $deposit_to = $account_split_fixed[10000];
                        }

                        $remainder = $amount - $total_fixed_amount;
                        if($remainder > 0){
                            $node = [];
                            $node['split'] = $payment_account;
                            $node['account'] = $deposit_to;
                            $node['debit'] = $remainder;
                            $node['date'] = $value['date'];
                            $node['credit'] = 0;
                            $node['description'] = _l('banking_rule');
                            $node['rel_id'] = $insert_id;
                            $node['rel_type'] = 'banking';
                            $node['datecreated'] = date('Y-m-d H:i:s');
                            $node['addedfrom'] = get_staff_user_id();
                            $node['cleared'] = 1;
                            $node['reconcile'] = -1;
                            $this->db->insert(db_prefix().'acc_account_history', $node);
                            $account_history_id = $this->db->insert_id();

                            $this->db->insert(db_prefix().'acc_matched_transactions', [
                                'account_history_id' => $account_history_id,
                                'history_amount' => 0,
                                'rel_id' => $insert_id,
                                'rel_type' => 'banking',
                                'amount' => 0,
                                'reconcile' => -1,
                            ]);

                            $node = [];
                            $node['split'] = $deposit_to;
                            $node['account'] = $payment_account;
                            $node['date'] = $value['date'];
                            $node['debit'] = 0;
                            $node['credit'] = $remainder;
                            $node['description'] = _l('banking_rule');
                            $node['rel_id'] = $insert_id;
                            $node['rel_type'] = 'banking';
                            $node['datecreated'] = date('Y-m-d H:i:s');
                            $node['addedfrom'] = get_staff_user_id();
                            $node['cleared'] = 1;
                            $node['reconcile'] = -1;
                            $this->db->insert(db_prefix().'acc_account_history', $node);
                            $account_history_id = $this->db->insert_id();

                            $this->db->insert(db_prefix().'acc_matched_transactions', [
                                'account_history_id' => $account_history_id,
                                'history_amount' => 0,
                                'rel_id' => $insert_id,
                                'rel_type' => 'banking',
                                'amount' => 0,
                                'reconcile' => -1,
                            ]);
                        }
                    }

                    $this->db->where('id', $insert_id);
                    $this->db->update(db_prefix().'acc_transaction_bankings', [
                            'banking_rule' => $val['id'],
                            'matched' => 1,
                            'reconcile' => -1
                        ]);

                    break;
                }
            }
        }

        return true;
    }

    /**
     * check rule
     * @param  array $rule 
     * @param  array $data 
     * @return boolean       
     */
    public function check_rule($rule, $data){
        $check = false;
        $amount = $data['deposits'];
        if($data['withdrawals'] > 0){
            $amount = $data['withdrawals'];
        }
        if(($rule['transaction'] == 'money_out' && $data['withdrawals'] > 0) || ($rule['transaction'] == 'money_in' && $data['deposits'] > 0)){
            if($rule['following'] == 'any'){
                foreach ($rule['details'] as $v) {
                    if ($v['type'] == 'amount') {
                        switch ($v['subtype_amount']) {
                            case 'does_not_equal':
                                if(floatval($v['text']) != $amount){
                                    return true;
                                }
                                break;
                            case 'equals':
                                if(floatval($v['text']) == $amount){
                                    return true;
                                }
                                break;
                            case 'is_greater_than':
                                if(floatval($v['text']) < $amount){
                                    return true;
                                }
                                break;
                            case 'is_loss_than':
                                if(floatval($v['text']) > $amount){
                                    return true;
                                }
                                break;
                            default:
                                break;
                        }
                    }elseif($v['type'] == 'description'){
                        switch ($v['subtype']) {
                            case 'contains':
                                if (str_contains($data['description'], $v['text'])) { 
                                    return true;
                                }
                                break;
                            case 'does_not_contain':
                                if (!str_contains($data['description'], $v['text'])) { 
                                    return true;
                                }
                                break;
                            case 'is_exactly':
                                if ($data['description'] == $v['text']) { 
                                    return true;
                                }
                                break;
                            default:
                                break;
                        }
                    }                      
                }
            }else{
                foreach ($rule['details'] as $v) {
                    if ($v['type'] == 'amount') {
                        switch ($v['subtype_amount']) {
                            case 'does_not_equal':
                                if(floatval($v['text']) == $amount){
                                    return false;
                                }
                                break;
                            case 'equals':
                                if(floatval($v['text']) != $amount){
                                    return false;
                                }
                                break;
                            case 'is_greater_than':
                                if(floatval($v['text']) > $amount){
                                    return false;
                                }
                                break;
                            case 'is_loss_than':
                                if(floatval($v['text']) < $amount){
                                    return false;
                                }
                                break;
                            default:
                                break;
                        }
                    }elseif($v['type'] == 'description'){
                        switch ($v['subtype']) {
                            case 'contains':
                                if (!str_contains($data['description'], $v['text'])) { 
                                    return false;
                                }
                                break;
                            case 'does_not_contain':
                                if (str_contains($data['description'], $v['text'])) { 
                                    return false;
                                }
                                break;
                            case 'is_exactly':
                                if ($data['description'] != $v['text']) { 
                                    return false;
                                }
                                break;
                            default:
                                break;
                        }
                    } 
                    $check = true;                     
                }

                return true;
            }
        }

        return $check;
    }

    /**
     * get data journal
     * @return array 
     */
    public function get_data_account_history($data_filter){
        $from_date = date('Y-m-01');
        $to_date = date('Y-m-d');
        $account = 0;

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        if(isset($data_filter['account'])){
            $account = $data_filter['account'];
        }

        $info_account = $this->get_accounts($account);

        $accounts = $this->get_accounts();

        $account_name = [];

        foreach ($accounts as $key => $value) {
            $account_name[$value['id']] = $value['name'];
        }

        $data_report = [];
        
        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
        if($account != ''){
            $this->db->where('account', $account);
        }
        $this->db->order_by('date', 'asc');
        
        $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
        $balance = 0;
        $amount = 0;
        foreach ($account_history as $v) {
            $decrease = 0;
            $increase = 0;
            if($info_account->account_type_id == 7 || $info_account->account_type_id == 8){
                $increase = $v['credit'];
                $decrease = $v['debit'];
                $balance += ($v['credit'] - $v['debit']);
            }elseif($info_account->account_type_id == 1){
                $increase = $v['credit'];
                $decrease = $v['debit'];
                $balance += ($v['debit'] - $v['credit']);
            }else{
                $increase = $v['debit'];
                $decrease = $v['credit'];
                $balance += ($v['debit'] - $v['credit']);
            }
            $data_report[] =   [
                            'date' => date('Y-m-d', strtotime($v['date'])),
                            'split' => $v['split'] != 0 ? (isset($account_name[$v['split']]) ? $account_name[$v['split']] : '') : '-Split-',
                            'type' => _l($v['rel_type']),
                            'name' => (isset($account_name[$v['account']]) ? $account_name[$v['account']] : ''),
                            'description' => $v['description'],
                            'customer' => $v['customer'],
                            'decrease' => $decrease,
                            'increase' => $increase,
                            'balance' => $balance,
                            'rel_id' => $v['rel_id'],
                            'rel_type' => $v['rel_type'],

                        ];
        }
                
        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date, 'account_type' => $info_account->account_type_id];
    }

    /**
     * Gets the where report period.
     *
     * @param      string  $field  The field
     *
     * @return     string  The where report period.
     */
    private function get_where_report_period($field = 'date')
    {
        $months_report      = $this->input->get('date_filter');
        
        $custom_date_select = '';
        if ($months_report != '') {
            if (is_numeric($months_report)) {
                // Last month
                if ($months_report == '1') {
                    $beginMonth = date('Y-m-01', strtotime('first day of last month'));
                    $endMonth   = date('Y-m-t', strtotime('last day of last month'));
                } else {
                    $months_report = (int) $months_report;
                    $months_report--;
                    $beginMonth = date('Y-m-01', strtotime("-$months_report MONTH"));
                    $endMonth   = date('Y-m-t');
                }

                $custom_date_select = '(' . $field . ' BETWEEN "' . $beginMonth . '" AND "' . $endMonth . '")';
            } elseif ($months_report == 'last_30_days') {
                $custom_date_select = '(' . $field . ' BETWEEN "' . date('Y-m-d', strtotime('today - 30 days')) . '" AND "' . date('Y-m-d') . '")';
            } elseif ($months_report == 'this_month') {
                $custom_date_select = '(' . $field . ' BETWEEN "' . date('Y-m-01') . '" AND "' . date('Y-m-t') . '")';
            } elseif ($months_report == 'last_month') {
                $this_month = date('m') - 1;
                $custom_date_select = '(' . $field . ' BETWEEN "' . date("Y-m-d", strtotime("first day of previous month")) . '" AND "' . date("Y-m-d", strtotime("last day of previous month")) . '")';
            }elseif ($months_report == 'this_quarter') {
                $current_month = date('m');
                  $current_year = date('Y');
                  if($current_month>=1 && $current_month<=3)
                  {
                    $start_date = date('Y-m-d', strtotime('1-January-'.$current_year));  // timestamp or 1-Januray 12:00:00 AM
                    $end_date = date('Y-m-d', strtotime('1-April-'.$current_year));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                  }
                  else  if($current_month>=4 && $current_month<=6)
                  {
                    $start_date = date('Y-m-d', strtotime('1-April-'.$current_year));  // timestamp or 1-April 12:00:00 AM
                    $end_date = date('Y-m-d', strtotime('1-July-'.$current_year));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                  }
                  else  if($current_month>=7 && $current_month<=9)
                  {
                    $start_date = date('Y-m-d', strtotime('1-July-'.$current_year));  // timestamp or 1-July 12:00:00 AM
                    $end_date = date('Y-m-d', strtotime('1-October-'.$current_year));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                  }
                  else  if($current_month>=10 && $current_month<=12)
                  {
                    $start_date = date('Y-m-d', strtotime('1-October-'.$current_year));  // timestamp or 1-October 12:00:00 AM
                    $end_date = date('Y-m-d', strtotime('1-January-'.($current_year+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                  }
                $custom_date_select = '(' . $field . ' BETWEEN "' .
                $start_date .
                '" AND "' .
                $end_date . '")';

            }elseif ($months_report == 'last_quarter') {
                $current_month = date('m');
                    $current_year = date('Y');

                  if($current_month>=1 && $current_month<=3)
                  {
                    $start_date = date('Y-m-d', strtotime('1-October-'.($current_year-1)));  // timestamp or 1-October Last Year 12:00:00 AM
                    $end_date = date('Y-m-d', strtotime('1-January-'.$current_year));  // // timestamp or 1-January  12:00:00 AM means end of 31 December Last year
                  } 
                  else if($current_month>=4 && $current_month<=6)
                  {
                    $start_date = date('Y-m-d', strtotime('1-January-'.$current_year));  // timestamp or 1-Januray 12:00:00 AM
                    $end_date = date('Y-m-d', strtotime('1-April-'.$current_year));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                  }
                  else  if($current_month>=7 && $current_month<=9)
                  {
                    $start_date = date('Y-m-d', strtotime('1-April-'.$current_year));  // timestamp or 1-April 12:00:00 AM
                    $end_date = date('Y-m-d', strtotime('1-July-'.$current_year));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                  }
                  else  if($current_month>=10 && $current_month<=12)
                  {
                    $start_date = date('Y-m-d', strtotime('1-July-'.$current_year));  // timestamp or 1-July 12:00:00 AM
                    $end_date = date('Y-m-d', strtotime('1-October-'.$current_year));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                  }
                $custom_date_select = '(' . $field . ' BETWEEN "' .
                $start_date .
                '" AND "' .
                $end_date . '")';

            }elseif ($months_report == 'this_year') {
                $custom_date_select = '(' . $field . ' BETWEEN "' .
                date('Y-m-d', strtotime(date('Y-01-01'))) .
                '" AND "' .
                date('Y-m-d', strtotime(date('Y-12-31'))) . '")';
            } elseif ($months_report == 'last_year') {
                $custom_date_select = '(' . $field . ' BETWEEN "' .
                date('Y-m-d', strtotime(date(date('Y', strtotime('last year')) . '-01-01'))) .
                '" AND "' .
                date('Y-m-d', strtotime(date(date('Y', strtotime('last year')) . '-12-31'))) . '")';
            } elseif ($months_report == 'custom') {
                $from_date = to_sql_date($this->input->post('report_from'));
                $to_date   = to_sql_date($this->input->post('report_to'));
                if ($from_date == $to_date) {
                    $custom_date_select = '' . $field . ' = "' . $from_date . '"';
                } else {
                    $custom_date_select = '(' . $field . ' BETWEEN "' . $from_date . '" AND "' . $to_date . '")';
                }
            } elseif(!(strpos($months_report, 'financial_year') === false)){
                $year = explode('financial_year_', $months_report);

                $first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

                $month = date('m', strtotime($first_month_of_financial_year));
                $custom_date_select = '(' . $field . ' BETWEEN "' . date($year[1].'-'.$month.'-01') . '" AND "' . date(($year[1]+1).'-'.$month.'-01') . '")';
            }else if($months_report == 'all_time'){
                $custom_date_select = '';
            }
        }

        return $custom_date_select;
    }

    /**
     * delete all data the accounting module
     *
     * @param      int   $id     The identifier
     *
     * @return     boolean
     */
    public function reset_data()
    {

        update_option('acc_add_default_account', 0);
        update_option('acc_add_default_account_new', 0);

        $affectedRows = 0;
        if ($this->db->table_exists(db_prefix() . 'acc_accounts')) {
            $this->db->query('DROP TABLE `'.db_prefix() .'acc_accounts`;');
            $this->db->query('CREATE TABLE ' . db_prefix() . "acc_accounts (
              `id` INT(11) NOT NULL AUTO_INCREMENT,
              `name` VARCHAR(255) NOT NULL,
              `key_name` VARCHAR(255) NULL,
              `number` VARCHAR(45) NULL,
              `parent_account` INT(11) NULL,
              `account_type_id` INT(11) NOT NULL,
              `account_detail_type_id` INT(11) NOT NULL,
              `balance` DECIMAL(15,2) NULL,
              `balance_as_of` DATE NULL,
              `description` TEXT NULL,
              `default_account` INT(11) NOT NULL DEFAULT 0,
              `active` INT(11) NOT NULL DEFAULT 1,
              `access_token` TEXT NULL,
                `account_id` VARCHAR(255) NULL,
                `plaid_status` TINYINT(5) NOT NULL DEFAULT 0 COMMENT \"1=>verified, 0=>not verified\",
                `plaid_account_name` VARCHAR(255) NULL,
                `bank_account` TEXT NULL,
                `bank_routing` TEXT NULL,
                `address_line_1` TEXT NULL,
                `address_line_2` TEXT NULL,
                `bank_name` varchar(255) NULL,
              PRIMARY KEY (`id`)
            ) ENGINE=InnoDB DEFAULT CHARSET=" . $this->db->char_set . ';');
            $this->add_default_account();
            $this->add_default_account_new();
            $affectedRows++;
        }

        update_option('acc_first_month_of_financial_year', 'January');
        update_option('acc_first_month_of_tax_year', 'same_as_financial_year');
        update_option('acc_accounting_method', 'accrual');
        update_option('acc_close_the_books', 0);
        update_option('acc_allow_changes_after_viewing', 'allow_changes_after_viewing_a_warning');
        update_option('acc_enable_account_numbers', 0);
        update_option('acc_show_account_numbers', 0);

        update_option('acc_add_default_account', 0);
        update_option('acc_add_default_account_new', 0);
        update_option('acc_invoice_automatic_conversion', 1);
        update_option('acc_payment_automatic_conversion', 1);
        update_option('acc_expense_automatic_conversion', 1);
        update_option('acc_tax_automatic_conversion', 1);

        update_option('acc_invoice_payment_account', 66);
        update_option('acc_invoice_deposit_to', 1);
        update_option('acc_payment_payment_account', 1);
        update_option('acc_payment_deposit_to', 13);
        update_option('acc_expense_payment_account', 13);
        update_option('acc_expense_deposit_to', 80);
        update_option('acc_tax_payment_account', 29);
        update_option('acc_tax_deposit_to', 1);

        $this->db->where('id > 0');
        $this->db->delete(db_prefix() . 'acc_account_history');
        if ($this->db->affected_rows() > 0) {
            $affectedRows++;
        }

        $this->db->where('id > 0');
        $this->db->delete(db_prefix() . 'acc_banking_rules');
        if ($this->db->affected_rows() > 0) {
            $affectedRows++;
        }
        $this->db->where('id > 0');
        $this->db->delete(db_prefix() . 'acc_banking_rule_details');
        if ($this->db->affected_rows() > 0) {
            $affectedRows++;
        }
        $this->db->where('id > 0');
        $this->db->delete(db_prefix() . 'acc_journal_entries');
        if ($this->db->affected_rows() > 0) {
            $affectedRows++;
        }
        $this->db->where('id > 0');
        $this->db->delete(db_prefix() . 'acc_reconciles');
        if ($this->db->affected_rows() > 0) {
            $affectedRows++;
        }
        $this->db->where('id > 0');
        $this->db->delete(db_prefix() . 'acc_transaction_bankings');
        if ($this->db->affected_rows() > 0) {
            $affectedRows++;
        }

        $this->db->where('id > 0');
        $this->db->delete(db_prefix() . 'acc_transfers');
        if ($this->db->affected_rows() > 0) {
            $affectedRows++;
        }

        $this->db->where('id > 0');
        $this->db->delete(db_prefix() . 'acc_item_automatics');
        if ($this->db->affected_rows() > 0) {
            $affectedRows++;
        }

        $this->db->where('id > 0');
        $this->db->delete(db_prefix() . 'acc_tax_mappings');
        if ($this->db->affected_rows() > 0) {
            $affectedRows++;
        }

        $this->reset_account_detail_types();

        if ($affectedRows > 0) {
            return true;
        }
        return false;
    }

    /**
     * Change account status / active / inactive
     * @param  mixed $id     staff id
     * @param  mixed $status status(0/1)
     */
    public function change_account_status($id, $status)
    {
        $this->db->where('id', $id);
        $this->db->update(db_prefix() . 'acc_accounts', [
            'active' => $status,
        ]);

        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }

    /**
     * Automatic invoice conversion
     * @param  integer $invoice_id 
     * @return boolean
     */
    public function automatic_invoice_conversion($invoice_id){
        if(get_option('acc_invoice_automatic_conversion') == 0){
            return false;
        }

        $this->delete_convert($invoice_id, 'invoice');

        $affectedRows = 0;

        $this->load->model('invoices_model');
        $invoice = $this->invoices_model->get($invoice_id);

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $currency_converter = 0;
        $currency_rate = 0;
        if($invoice->currency_name != $currency->name){
            $currency_converter = 1;
            $currency_rate = acc_get_currency_rate($invoice->currency_name, $currency->name);
        }

        $payment_account = get_option('acc_invoice_payment_account');
        $deposit_to = get_option('acc_invoice_deposit_to');

        $invoice_discount_payment_account = get_option('acc_invoice_discount_payment_account');
        $invoice_discount_deposit_to = get_option('acc_invoice_discount_deposit_to');

        
        $tax_payment_account = get_option('acc_tax_payment_account');
        $tax_deposit_to = get_option('acc_tax_deposit_to');

        if($invoice){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($invoice->date) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }
            $paid = 0;
            if($invoice->status == 2){
                $paid = 1;
            }
            $data_insert = [];

            foreach ($invoice->items as $item) {
                $item_detail = $this->get_item_by_name($item['description']);
                $item_id = 0;
                if(isset($item_detail->id)){
                    $item_id = $item_detail->id;
                }

                $item_total = $item['qty'] * $item['rate'];
                if($currency_converter == 1){
                    $item_total = round($currency_rate * ($item['qty'] * $item['rate']), 2);
                }

                $item_automatic = $this->get_item_automatic($item_id);

                if($item_automatic){
                    $node = [];
                    $node['itemable_id'] = $item['id'];
                    $node['split'] = $payment_account;
                    $node['account'] = $deposit_to;
                    $node['item'] = $item_id;
                    $node['date'] = $invoice->date;
                    $node['paid'] = $paid;
                    $node['debit'] = $item_total;
                    $node['customer'] = $invoice->clientid;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $invoice_id;
                    $node['rel_type'] = 'invoice';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['itemable_id'] = $item['id'];
                    $node['split'] = $deposit_to;
                    $node['customer'] = $invoice->clientid;
                    $node['account'] = $item_automatic->income_account;
                    $node['item'] = $item_id;
                    $node['paid'] = $paid;
                    $node['date'] = $invoice->date;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $invoice_id;
                    $node['rel_type'] = 'invoice';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }else{
                    $node = [];
                    $node['itemable_id'] = $item['id'];
                    $node['split'] = $payment_account;
                    $node['account'] = $deposit_to;
                    $node['item'] = $item_id;
                    $node['debit'] = $item_total;
                    $node['customer'] = $invoice->clientid;
                    $node['paid'] = $paid;
                    $node['date'] = $invoice->date;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $invoice_id;
                    $node['rel_type'] = 'invoice';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['itemable_id'] = $item['id'];
                    $node['split'] = $deposit_to;
                    $node['customer'] = $invoice->clientid;
                    $node['account'] = $payment_account;
                    $node['item'] = $item_id;
                    $node['date'] = $invoice->date;
                    $node['paid'] = $paid;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $invoice_id;
                    $node['rel_type'] = 'invoice';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }

                if(get_option('acc_tax_automatic_conversion') == 1){
                    $data_tax = $this->get_invoice_item_tax($item, $invoice);

                    foreach ($data_tax['tax_id'] as $k => $tax_id) {
                        $tax_mapping = $this->get_tax_mapping($tax_id);

                        if($tax_mapping){
                            $tax_mapping_payment_account = $tax_mapping->payment_account;
                            $tax_mapping_deposit_to = $tax_mapping->deposit_to;
                        }else{
                            $tax_mapping_payment_account = $tax_payment_account;
                            $tax_mapping_deposit_to = $tax_deposit_to;
                        }

                        $total_tax = $data_tax['tax_amount'][$k];
                        if($currency_converter == 1){
                            $total_tax = round($currency_rate * $data_tax['tax_amount'][$k], 2);
                        }

                        $node = [];
                        $node['itemable_id'] = $item['id'];
                        $node['split'] = $tax_mapping_payment_account;
                        $node['account'] = $tax_mapping_deposit_to;
                        $node['tax'] = $tax_id;
                        $node['item'] = $item_id;
                        $node['paid'] = $paid;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['customer'] = $invoice->clientid;
                        $node['date'] = $invoice->date;
                        $node['description'] = '';
                        $node['rel_id'] = $invoice_id;
                        $node['rel_type'] = 'invoice';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;

                        $node = [];
                        $node['itemable_id'] = $item['id'];
                        $node['split'] = $tax_mapping_deposit_to;
                        $node['customer'] = $invoice->clientid;
                        $node['account'] = $tax_mapping_payment_account;
                        $node['tax'] = $tax_id;
                        $node['item'] = $item_id;
                        $node['paid'] = $paid;
                        $node['date'] = $invoice->date;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $invoice_id;
                        $node['rel_type'] = 'invoice';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;
                    }
                }
            }

            if($invoice->discount_total > 0){
                $discount_total = $invoice->discount_total;
                if($currency_converter == 1){
                    $discount_total = round($currency_rate * $invoice->discount_total, 2);
                }

                $node = [];
                $node['itemable_id'] = 0;
                $node['split'] = $invoice_discount_payment_account;
                $node['account'] = $invoice_discount_deposit_to;
                $node['tax'] = 0;
                $node['item'] = 0;
                $node['paid'] = $paid;
                $node['debit'] = $discount_total;
                $node['credit'] = 0;
                $node['customer'] = $invoice->clientid;
                $node['date'] = $invoice->date;
                $node['description'] = '';
                $node['rel_id'] = $invoice_id;
                $node['rel_type'] = 'invoice';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['currency_rate'] = $currency_rate;
                $data_insert[] = $node;

                $node = [];
                $node['itemable_id'] = 0;
                $node['split'] = $invoice_discount_deposit_to;
                $node['account'] = $invoice_discount_payment_account;
                $node['customer'] = $invoice->clientid;
                $node['tax'] = 0;
                $node['item'] = 0;
                $node['paid'] = $paid;
                $node['date'] = $invoice->date;
                $node['debit'] = 0;
                $node['credit'] = $discount_total;
                $node['description'] = '';
                $node['rel_id'] = $invoice_id;
                $node['rel_type'] = 'invoice';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['currency_rate'] = $currency_rate;
                $data_insert[] = $node;
            }

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Automatic payment conversion
     * @param  integer $payment_id 
     * @return boolean
     */
    public function automatic_payment_conversion($payment_id){
        $this->delete_convert($payment_id, 'payment');

        $this->load->model('payments_model');
        $payment = $this->payments_model->get($payment_id);
        $payment_account = get_option('acc_payment_payment_account');
        $deposit_to = get_option('acc_payment_deposit_to');
        $affectedRows = 0;


        if($payment){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($payment->date) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }
            $this->load->model('invoices_model');
            $invoice = $this->invoices_model->get($payment->invoiceid);
            if(!$invoice){
                return false;
            }

            $this->automatic_invoice_conversion($payment->invoiceid);

            $this->load->model('currencies_model');
            $currency = $this->currencies_model->get_base_currency();

            $payment_total = $payment->amount;
            $currency_rate = 0;
            if($invoice->currency_name != $currency->name){
                $currency_rate = acc_get_currency_rate($invoice->currency_name, $currency->name);
                $payment_total = round($currency_rate * $payment->amount, 2);
            }

            if(get_option('acc_active_payment_mode_mapping') == 1){
                $payment_mode_mapping = $this->get_payment_mode_mapping($payment->paymentmode);
                $data_insert = [];
                if($payment_mode_mapping){
                    $node = [];
                    $node['split'] = $payment_mode_mapping->payment_account;
                    $node['account'] = $payment_mode_mapping->deposit_to;
                    $node['date'] = $payment->date;
                    $node['debit'] = $payment_total;
                    $node['customer'] = $invoice->clientid;
                    $node['credit'] = 0;
                    $node['tax'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $payment_id;
                    $node['rel_type'] = 'payment';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $payment_mode_mapping->deposit_to;
                    $node['customer'] = $invoice->clientid;
                    $node['account'] = $payment_mode_mapping->payment_account;
                    $node['date'] = $payment->date;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $payment_total;
                    $node['description'] = '';
                    $node['rel_id'] = $payment_id;
                    $node['rel_type'] = 'payment';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }

                if(count($data_insert) == 0){   
                    if(get_option('acc_payment_automatic_conversion') == 1){
                        $node = [];
                        $node['split'] = $payment_account;
                        $node['account'] = $deposit_to;
                        $node['customer'] = $invoice->clientid;
                        $node['debit'] = $payment_total;
                        $node['credit'] = 0;
                        $node['date'] = $payment->date;
                        $node['description'] = '';
                        $node['rel_id'] = $payment_id;
                        $node['rel_type'] = 'payment';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $deposit_to;
                        $node['customer'] = $invoice->clientid;
                        $node['account'] = $payment_account;
                        $node['date'] = $payment->date;
                        $node['debit'] = 0;
                        $node['credit'] = $payment_total;
                        $node['description'] = '';
                        $node['rel_id'] = $payment_id;
                        $node['rel_type'] = 'payment';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;
                    }
                }
            }else{
                if(get_option('acc_payment_automatic_conversion') == 1){
                    $node = [];
                    $node['split'] = $payment_account;
                    $node['account'] = $deposit_to;
                    $node['customer'] = $invoice->clientid;
                    $node['debit'] = $payment_total;
                    $node['credit'] = 0;
                    $node['date'] = $payment->date;
                    $node['description'] = '';
                    $node['rel_id'] = $payment_id;
                    $node['rel_type'] = 'payment';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $deposit_to;
                    $node['customer'] = $invoice->clientid;
                    $node['account'] = $payment_account;
                    $node['date'] = $payment->date;
                    $node['debit'] = 0;
                    $node['credit'] = $payment_total;
                    $node['description'] = '';
                    $node['rel_id'] = $payment_id;
                    $node['rel_type'] = 'payment';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }
            }

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Automatic expense conversion
     * @param  integer $expense_id 
     * @return boolean
     */
    public function automatic_expense_conversion($expense_id){
        if(get_option('acc_expense_automatic_conversion') == 0){
            return false;
        }

        $this->delete_convert($expense_id, 'expense');

        $this->load->model('expenses_model');
        $expense = $this->expenses_model->get($expense_id);
        
        if(acc_get_status_modules('purchase')){
            $this->db->where('expense_convert', $expense_id);
            $count_purchase_order = $this->db->count_all_results(db_prefix() . 'pur_orders');
            
            if($count_purchase_order > 0){
                return false;
            }
        }

        $payment_account = get_option('acc_expense_payment_account');
        $deposit_to = get_option('acc_expense_deposit_to');
        $tax_payment_account = get_option('acc_expense_tax_payment_account');
        $tax_deposit_to = get_option('acc_expense_tax_deposit_to');
        $payment_mode_payment_account = get_option('acc_expense_payment_payment_account');
        $payment_mode_deposit_to = get_option('acc_expense_payment_deposit_to');
        $affectedRows = 0;

        if($expense){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($expense->date) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }

            $this->load->model('currencies_model');
            $currency = $this->currencies_model->get_base_currency();

            $expense_total = $expense->amount;
            $currency_rate = 0;
            if($expense->currency_data->name != $currency->name){
                $currency_rate = acc_get_currency_rate($expense->currency_data->name, $currency->name);
                $expense_total = round($currency_rate * $expense->amount, 2);
            }

            $data_insert = [];

            if(get_option('acc_active_expense_category_mapping') == 1){
                $expense_category_mapping = $this->get_expense_category_mapping($expense->category);
                if($expense_category_mapping){
                    $expense_payment_account = $expense_category_mapping->payment_account;
                    $expense_deposit_to = $expense_category_mapping->deposit_to;

                    if($expense_category_mapping->preferred_payment_method == 1 && $expense->paymentmode != ''){
                        $payment_account = '';
                        $deposit_to = '';
                        foreach ($expense_category_mapping->payment_method_mapping as $key => $value) {
                            if($expense->paymentmode == $value['payment_mode_id']){
                                $expense_payment_account = $value['payment_account'];
                                $expense_deposit_to = $value['deposit_to'];
                            }
                        }
                    }

                    $node = [];
                    $node['split'] = $expense_payment_account;
                    $node['account'] = $expense_deposit_to;
                    $node['tax'] = 0;
                    $node['debit'] = $expense_total;
                    $node['credit'] = 0;
                    $node['customer'] = $expense->clientid;
                    $node['date'] = $expense->date;
                    $node['description'] = '';
                    $node['rel_id'] = $expense_id;
                    $node['rel_type'] = 'expense';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $expense_deposit_to;
                    $node['customer'] = $expense->clientid;
                    $node['account'] = $expense_payment_account;
                    $node['tax'] = 0;
                    $node['date'] = $expense->date;
                    $node['debit'] = 0;
                    $node['credit'] = $expense_total;
                    $node['description'] = '';
                    $node['rel_id'] = $expense_id;
                    $node['rel_type'] = 'expense';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }
            }

            if(count($data_insert) == 0 && $expense->paymentmode != ''){
                $payment_mode_mapping = $this->get_payment_mode_mapping($expense->paymentmode);

                if($payment_mode_mapping && get_option('acc_active_payment_mode_mapping') == 1){
                    $node = [];
                    $node['split'] = $payment_mode_mapping->expense_payment_account;
                    $node['account'] = $payment_mode_mapping->expense_deposit_to;
                    $node['tax'] = 0;
                    $node['debit'] = $expense_total;
                    $node['credit'] = 0;
                    $node['customer'] = $expense->clientid;
                    $node['date'] = $expense->date;
                    $node['description'] = '';
                    $node['rel_id'] = $expense_id;
                    $node['rel_type'] = 'expense';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $payment_mode_mapping->expense_deposit_to;
                    $node['customer'] = $expense->clientid;
                    $node['account'] = $payment_mode_mapping->expense_payment_account;
                    $node['tax'] = 0;
                    $node['date'] = $expense->date;
                    $node['debit'] = 0;
                    $node['credit'] = $expense_total;
                    $node['description'] = '';
                    $node['rel_id'] = $expense_id;
                    $node['rel_type'] = 'expense';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }elseif(get_option('acc_payment_expense_automatic_conversion') == 1){
                    $node = [];
                    $node['split'] = $payment_mode_payment_account;
                    $node['account'] = $payment_mode_deposit_to;
                    $node['tax'] = 0;
                    $node['date'] = $expense->date;
                    $node['debit'] = $expense_total;
                    $node['customer'] = $expense->clientid;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $expense_id;
                    $node['rel_type'] = 'expense';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $payment_mode_deposit_to;
                    $node['customer'] = $expense->clientid;
                    $node['account'] = $payment_mode_payment_account;
                    $node['date'] = $expense->date;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $expense_total;
                    $node['description'] = '';
                    $node['rel_id'] = $expense_id;
                    $node['rel_type'] = 'expense';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }
            }

            if(count($data_insert) == 0 && get_option('acc_expense_automatic_conversion') == 1){   
                $node = [];
                $node['split'] = $payment_account;
                $node['account'] = $deposit_to;
                $node['debit'] = $expense_total;
                $node['customer'] = $expense->clientid;
                $node['date'] = $expense->date;
                $node['tax'] = 0;
                $node['credit'] = 0;
                $node['description'] = '';
                $node['rel_id'] = $expense_id;
                $node['rel_type'] = 'expense';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['currency_rate'] = $currency_rate;
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $deposit_to;
                $node['account'] = $payment_account;
                $node['customer'] = $expense->clientid;
                $node['date'] = $expense->date;
                $node['tax'] = 0;
                $node['debit'] = 0;
                $node['credit'] = $expense_total;
                $node['description'] = '';
                $node['rel_id'] = $expense_id;
                $node['rel_type'] = 'expense';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['currency_rate'] = $currency_rate;
                $data_insert[] = $node;
            }

            if(get_option('acc_tax_automatic_conversion') == 1){
                if($expense->tax > 0){
                    $this->db->where('id', $expense->tax);
                    $tax = $this->db->get(db_prefix().'taxes')->row();
                    $total_tax = 0;
                    if($tax){
                        $total_tax = ($tax->taxrate/100) * $expense_total;
                    }

                    if($expense->currency_data->name != $currency->name){
                        $total_tax = round($total_tax * $currency_rate, 2);
                    }

                    $tax_mapping = $this->get_tax_mapping($expense->tax);
                    if($tax_mapping){
                        $node = [];
                        $node['split'] = $tax_mapping->expense_payment_account;
                        $node['account'] = $tax_mapping->expense_deposit_to;
                        $node['tax'] = $expense->tax;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['customer'] = $expense->clientid;
                        $node['date'] = $expense->date;
                        $node['description'] = '';
                        $node['rel_id'] = $expense_id;
                        $node['rel_type'] = 'expense';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_mapping->expense_deposit_to;
                        $node['customer'] = $expense->clientid;
                        $node['account'] = $tax_mapping->expense_payment_account;
                        $node['tax'] = $expense->tax;
                        $node['date'] = $expense->date;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $expense_id;
                        $node['rel_type'] = 'expense';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;
                    }else{
                        $node = [];
                        $node['split'] = $tax_payment_account;
                        $node['account'] = $tax_deposit_to;
                        $node['tax'] = $expense->tax;
                        $node['date'] = $expense->date;
                        $node['debit'] = $total_tax;
                        $node['customer'] = $expense->clientid;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $expense_id;
                        $node['rel_type'] = 'expense';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_deposit_to;
                        $node['customer'] = $expense->clientid;
                        $node['account'] = $tax_payment_account;
                        $node['date'] = $expense->date;
                        $node['tax'] = $expense->tax;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $expense_id;
                        $node['rel_type'] = 'expense';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;
                    }
                }

                if($expense->tax2 > 0){
                    $this->db->where('id', $expense->tax2);
                    $tax = $this->db->get(db_prefix().'taxes')->row();
                    $total_tax = 0;
                    if($tax){
                        $total_tax = ($tax->taxrate/100) * $expense_total;
                    }

                    if($expense->currency_data->name != $currency->name){
                        $total_tax = round($total_tax * $currency_rate, 2);
                    }

                    $tax_mapping = $this->get_tax_mapping($expense->tax2);
                    if($tax_mapping){
                        $node = [];
                        $node['split'] = $tax_mapping->expense_payment_account;
                        $node['account'] = $tax_mapping->expense_deposit_to;
                        $node['tax'] = $expense->tax2;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['customer'] = $expense->clientid;
                        $node['date'] = $expense->date;
                        $node['description'] = '';
                        $node['rel_id'] = $expense_id;
                        $node['rel_type'] = 'expense';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_mapping->expense_deposit_to;
                        $node['customer'] = $expense->clientid;
                        $node['account'] = $tax_mapping->expense_payment_account;
                        $node['tax'] = $expense->tax2;
                        $node['date'] = $expense->date;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $expense_id;
                        $node['rel_type'] = 'expense';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;
                    }else{
                        $node = [];
                        $node['split'] = $tax_payment_account;
                        $node['account'] = $tax_deposit_to;
                        $node['tax'] = $expense->tax2;
                        $node['date'] = $expense->date;
                        $node['debit'] = $total_tax;
                        $node['customer'] = $expense->clientid;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $expense_id;
                        $node['rel_type'] = 'expense';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_deposit_to;
                        $node['customer'] = $expense->clientid;
                        $node['account'] = $tax_payment_account;
                        $node['date'] = $expense->date;
                        $node['tax'] = $expense->tax2;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $expense_id;
                        $node['rel_type'] = 'expense';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;
                    }
                }
            }

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    
    /**
     * count invoice not convert yet
     * @param  integer $currency
     * @param  string $where
     * @return object          
     */
    public function count_invoice_not_convert_yet($currency = '', $where = ''){
        $where_currency = '';
        if($currency != ''){
            $where_currency = 'and currency = '.$currency;
        }

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'invoices.id and ' . db_prefix() . 'acc_account_history.rel_type = "invoice") = 0) '.$where_currency);
        return $this->db->count_all_results(db_prefix().'invoices');
    }

    /**
     * count payment not convert yet
     * @param  integer $currency
     * @param  string $where
     * @return object
     */
    public function count_payment_not_convert_yet($currency = '', $where = ''){
        $where_currency = '';
        if($currency != ''){
            $where_currency = 'and currency = '.$currency;
        }

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'invoicepaymentrecords.id and ' . db_prefix() . 'acc_account_history.rel_type = "payment") = 0) '.$where_currency);
        $this->db->join(db_prefix() . 'invoices', db_prefix() . 'invoices.id=' . db_prefix() . 'invoicepaymentrecords.invoiceid', 'left');
        return $this->db->count_all_results(db_prefix().'invoicepaymentrecords');
    }

    /**
     * count expense not convert yet
     * @param  string $where
     * @param  integer $currency
     * @return object
     */
    public function count_expense_not_convert_yet($currency = '', $where = ''){
        $where_currency = '';
        if($currency != ''){
            $where_currency = 'and currency = '.$currency;
        }

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'expenses.id and ' . db_prefix() . 'acc_account_history.rel_type = "expense") = 0) AND (' . db_prefix() . 'expenses.is_bill = 0) '.$where_currency);

        $this->db->join(db_prefix().'expenses_categories', db_prefix() . 'expenses_categories.id = ' . db_prefix() . 'expenses.category');

        $this->db->select('count(*) as count_ex');
        $ex = $this->db->get(db_prefix().'expenses')->row();
        return $ex->count_ex; //$this->db->count_all_results(db_prefix().'expenses');
    }

    /**
     * delete invoice convert
     * @param  integer $invoice_id 
     * @return boolean            
     */
    public function delete_invoice_convert($invoice_id){
        $affectedRows = 0;

        $check = $this->delete_convert($invoice_id,'invoice');
        if($check){
            $affectedRows++;
        }

        $this->db->where('invoiceid', $invoice_id);
        $payments = $this->db->get(db_prefix() . 'invoicepaymentrecords')->result_array();

        foreach ($payments as $key => $value) {
            $check = $this->delete_convert($value['id'],'payment');
            if($check){
                $affectedRows++;
            }
        }

        if($affectedRows > 0){
            return true;
        }

        return false;
    }

    /**
     * invoice status changed
     * @param  array $data 
     * @return boolean       
     */
    public function invoice_status_changed($data){
        if(isset($data['invoice_id']) && isset($data['status'])){
            if($data['status'] == 2){
                $this->db->where('rel_id', $data['invoice_id']);
                $this->db->where('rel_type', 'invoice');
                $this->db->update(db_prefix().'acc_account_history', ['paid' => 1]);
                if ($this->db->affected_rows() > 0) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * get items are not yet auto
     * @return array
     */
    public function get_items_not_yet_auto(){
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_item_automatics where ' . db_prefix() . 'acc_item_automatics.item_id = ' . db_prefix() . 'items.id) = 0)');
        return $this->db->get(db_prefix().'items')->result_array();
    }

    /**
     * add item automatic
     * @param array $data
     * @return boolean
     */
    public function add_item_automatic($data){
        if(isset($data['id'])){
            unset($data['id']);
        }
        $items = [];
        if(isset($data['item'])){
            $items = $data['item'];
            unset($data['item']);
        }
        $data_insert = [];
        foreach ($items as $value) {
            $this->db->where('item_id', $value);
            $count = $this->db->count_all_results(db_prefix() . 'acc_item_automatics');

            if($count == 0){
                $node = [];
                $node['item_id'] = $value;
                $node['inventory_asset_account'] = $data['inventory_asset_account'];
                $node['income_account'] = $data['income_account'];
                $node['expense_account'] = $data['expense_account'];

                $data_insert[] = $node;
            }

        }

        $affectedRows = $this->db->insert_batch(db_prefix().'acc_item_automatics',  $data_insert);

        if ($affectedRows > 0) {
            return true;
        }

        return false;
    }

    /**
     * update item automatic
     * @param array $data
     * @param  integer $id 
     * @return boolean
     */
    public function update_item_automatic($data, $id){
        $this->db->where('id', $id);
        $this->db->update(db_prefix().'acc_item_automatics', $data);
       
        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }

    /**
     * delete item automatic
     * @param integer $id
     * @return boolean
     */

    public function delete_item_automatic($id)
    {
        $this->db->where('id', $id);
        $this->db->delete(db_prefix() . 'acc_item_automatics');
        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }

    /**
     * Gets the item by name.
     *
     * @param      string  $item_name  The itemid
     *
     * @return     object  The item.
     */
    public function get_item_by_name($item_name) {

        $this->db->where('description', $item_name);
        return $this->db->get(db_prefix() . 'items')->row();
    }

    /**
     * Gets the item automatic
     *
     * @param      string  $item_id  The itemid
     *
     * @return     object  The item automatic.
     */
    public function get_item_automatic($item_id) {

        $this->db->where('item_id', $item_id);
        return $this->db->get(db_prefix() . 'acc_item_automatics')->row();
    }

    /**
     * delete banking
     * @param integer $id
     * @return boolean
     */

    public function delete_banking($id)
    {
        $this->db->where('id', $id);
        $this->db->delete(db_prefix() . 'acc_transaction_bankings');
        if ($this->db->affected_rows() > 0) {
            $this->db->where('rel_id', $id);
            $this->db->where('rel_type', 'banking');
            $this->db->delete(db_prefix() . 'acc_account_history');

            return true;
        }
        return false;
    }

    /**
     * add tax mapping
     * @param array $data
     * @return boolean
     */
    public function add_tax_mapping($data){
        if(isset($data['id'])){
            unset($data['id']);
        }
        $taxs = [];
        if(isset($data['tax'])){
            $taxs = $data['tax'];
            unset($data['tax']);
        }
        $data_insert = [];
        foreach ($taxs as $value) {
            $this->db->where('tax_id', $value);
            $count = $this->db->count_all_results(db_prefix() . 'acc_tax_mappings');

            if($count == 0){
                $node = [];
                $node['tax_id'] = $value;
                $node['payment_account'] = $data['payment_account'];
                $node['deposit_to'] = $data['deposit_to'];
                $node['expense_payment_account'] = $data['expense_payment_account'];
                $node['expense_deposit_to'] = $data['expense_deposit_to'];
                $node['purchase_payment_account'] = $data['purchase_payment_account'];
                $node['purchase_deposit_to'] = $data['purchase_deposit_to'];

                $data_insert[] = $node;
            }

        }

        $affectedRows = $this->db->insert_batch(db_prefix().'acc_tax_mappings',  $data_insert);

        if ($affectedRows > 0) {
            return true;
        }

        return false;
    }

    /**
     * update tax mapping
     * @param array $data
     * @param  integer $id 
     * @return boolean
     */
    public function update_tax_mapping($data, $id){
        $this->db->where('id', $id);
        $this->db->update(db_prefix().'acc_tax_mappings', $data);
       
        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }

    /**
     * delete tax mapping
     * @param integer $id
     * @return boolean
     */

    public function delete_tax_mapping($id)
    {
        $this->db->where('id', $id);
        $this->db->delete(db_prefix() . 'acc_tax_mappings');
        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }

    /**
     * get taxes are not yet auto
     * @return array
     */
    public function get_taxes_not_yet_auto(){
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_tax_mappings where ' . db_prefix() . 'acc_tax_mappings.tax_id = ' . db_prefix() . 'taxes.id) = 0)');
        return $this->db->get(db_prefix().'taxes')->result_array();
    }

    /**
     * Gets the tax mapping
     *
     * @param      string  $tax_id  The tax id
     *
     * @return     object  The tax mapping.
     */
    public function get_tax_mapping($tax_id) {

        $this->db->where('tax_id', $tax_id);
        return $this->db->get(db_prefix() . 'acc_tax_mappings')->row();
    }

    /**
     * [currency_converter description]
     * @param  string $from   Currency Code
     * @param  string $to     Currency Code
     * @param  float $amount
     * @return float        
     */
    public function currency_converter($from,$to,$amount = 1)
    {   
        $url = "https://www.google.com/finance/quote/$from-$to";
        $response = $this->api_get($url);
        $string1 = explode('class="YMlKec fxKbKc">', $response);
        if(isset($string1[1])){

            $rate = explode('</div>', $string1[1]);

            if(isset($rate[0])){
                $_rate = str_replace(',', '', $rate[0]);
                $result = $_rate * $amount;
                
                return $result;
            }
        }

        return false;
    }

    /**
     * api get
     * @param  string $url
     * @return string    
     */
    public function api_get($url) {
        $curl = curl_init($url);
        
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_AUTOREFERER, true);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, 120);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 120);
        curl_setopt($curl, CURLOPT_MAXREDIRS, 10);
        
        return curl_exec($curl);
    }

    /**
     * get expense category are not yet auto
     * @return array
     */
    public function get_expense_category_not_yet_auto(){
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_expense_category_mappings where ' . db_prefix() . 'acc_expense_category_mappings.category_id = ' . db_prefix() . 'expenses_categories.id) = 0)');
        return $this->db->get(db_prefix().'expenses_categories')->result_array();
    }

    /**
     * add expense category mapping
     * @param array $data
     * @return boolean
     */
    public function add_expense_category_mapping($data){
        if(isset($data['id'])){
            unset($data['id']);
        }
        $categorys = [];
        if(isset($data['category'])){
            $categorys = $data['category'];
            unset($data['category']);
        }
        
        if (!isset($data['preferred_payment_method'])) {
            $data['preferred_payment_method'] = 0;
        }

        $payment_mode = [];
        if(isset($data['payment_mode'])){
            $payment_mode = $data['payment_mode'];
            unset($data['payment_mode']);
        }

        $payment_account_detail = [];
        if(isset($data['payment_account_detail'])){
            $payment_account_detail = $data['payment_account_detail'];
            unset($data['payment_account_detail']);
        }

        $deposit_to_detail = [];
        if(isset($data['deposit_to_detail'])){
            $deposit_to_detail = $data['deposit_to_detail'];
            unset($data['deposit_to_detail']);
        }

        $affectedRows = 0;
        foreach ($categorys as $value) {
            $this->db->where('category_id', $value);
            $count = $this->db->count_all_results(db_prefix() . 'acc_expense_category_mappings');

            if($count == 0){
                $node = [];
                $node['category_id'] = $value;
                $node['payment_account'] = $data['payment_account'];
                $node['deposit_to'] = $data['deposit_to'];
                $node['preferred_payment_method'] = $data['preferred_payment_method'];

                $this->db->insert(db_prefix().'acc_expense_category_mappings',  $node);

                $insert_id = $this->db->insert_id();

                if ($insert_id) {
                    $affectedRows++;
                    foreach ($payment_mode as $key => $value) {
                        $node = [];
                        $node['category_mapping_id'] = $insert_id;
                        $node['payment_mode_id'] = $value;
                        $node['payment_account'] = $payment_account_detail[$key];
                        $node['deposit_to'] = $deposit_to_detail[$key];

                        $this->db->insert(db_prefix().'acc_expense_category_mapping_details',  $node);
                    }
                }
            }

        }

        if ($affectedRows > 0) {
            return true;
        }

        return false;
    }

    /**
     * update expense category mapping
     * @param array $data
     * @param  integer $id 
     * @return boolean
     */
    public function update_expense_category_mapping($data, $id){
        if (!isset($data['preferred_payment_method'])) {
            $data['preferred_payment_method'] = 0;
        }

        $payment_mode = [];
        if(isset($data['payment_mode'])){
            $payment_mode = $data['payment_mode'];
            unset($data['payment_mode']);
        }

        $payment_account_detail = [];
        if(isset($data['payment_account_detail'])){
            $payment_account_detail = $data['payment_account_detail'];
            unset($data['payment_account_detail']);
        }

        $deposit_to_detail = [];
        if(isset($data['deposit_to_detail'])){
            $deposit_to_detail = $data['deposit_to_detail'];
            unset($data['deposit_to_detail']);
        }

        $this->db->where('id', $id);
        $this->db->update(db_prefix().'acc_expense_category_mappings', $data);

        $this->db->where('category_mapping_id', $id);
        $this->db->delete(db_prefix().'acc_expense_category_mapping_details');
       
        foreach ($payment_mode as $key => $value) {
            $node = [];
            $node['category_mapping_id'] = $id;
            $node['payment_mode_id'] = $value;
            $node['payment_account'] = $payment_account_detail[$key];
            $node['deposit_to'] = $deposit_to_detail[$key];

            $this->db->insert(db_prefix().'acc_expense_category_mapping_details',  $node);
        }

        return true;
    }

    /**
     * delete expense category mapping
     * @param integer $id
     * @return boolean
     */

    public function delete_expense_category_mapping($id)
    {
        $this->db->where('id', $id);
        $this->db->delete(db_prefix() . 'acc_expense_category_mappings');
        if ($this->db->affected_rows() > 0) {

            $this->db->where('category_mapping_id', $id);
            $this->db->delete(db_prefix().'acc_expense_category_mapping_details');

            return true;
        }
        return false;
    }

    /**
     * Gets the expense category mappings
     *
     * @param      string  $category_id  The expense category id
     *
     * @return     object  The expense category mapping.
     */
    public function get_expense_category_mapping($category_id) {

        $this->db->where('category_id', $category_id);
        $expense_category_mapping = $this->db->get(db_prefix() . 'acc_expense_category_mappings')->row();
        if($expense_category_mapping){
            $this->db->where('category_mapping_id', $expense_category_mapping->id);
            $payment_method_mapping = $this->db->get(db_prefix() . 'acc_expense_category_mapping_details')->result_array();

            $expense_category_mapping->payment_method_mapping = $payment_method_mapping;
        }

        return $expense_category_mapping;
    }

    /**
     * get data tax detail report
     * @return array 
     */
    public function get_data_tax_detail_report($data_filter){
        $from_date = date('Y-m-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $accounts = $this->get_accounts();

        $account_name = [];

        foreach ($accounts as $key => $value) {
            $account_name[$value['id']] = $value['name'];
        }

        $data_report = [];
        $data_report['tax_collected_on_sales'] = [];
        $data_report['total_taxable_sales_in_period_before_tax'] = [];

        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '") and tax > 0 and rel_type = "invoice" and debit >= 0');
        if($accounting_method == 'cash'){
            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
        }
        $this->db->order_by('date', 'asc');
        
        $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
        
        $list_invoice = [];        
        $this->load->model('invoices_model');
        foreach ($account_history as $v) {

            if(!in_array($v['rel_id'], $list_invoice)){
                $list_invoice[] = $v['rel_id'];
                $invoice = $this->invoices_model->get($v['rel_id']);


                $data_report['total_taxable_sales_in_period_before_tax'][] = [
                                'date' => date('Y-m-d', strtotime($v['date'])),
                                'type' => _l($v['rel_type']),
                                'description' => $v['description'],
                                'customer' => $v['customer'],
                                'amount' => $invoice->subtotal,
                                'rel_id' => $v['rel_id'],
                                'rel_type' => $v['rel_type'],

                            ];
            }

            $this->db->where('id', $v['tax']);
            $_tax = $this->db->get(db_prefix().'taxes')->row();

            $data_report['tax_collected_on_sales'][] = [
                            'date' => date('Y-m-d', strtotime($v['date'])),
                            'type' => _l($v['rel_type']),
                            'tax_name' => $_tax->name,
                            'tax_rate' => $_tax->taxrate,
                            'description' => $v['description'],
                            'customer' => $v['customer'],
                            'amount' => $v['debit'],
                            'rel_id' => $v['rel_id'],
                            'rel_type' => $v['rel_type'],
                        ];
        }

        $data_report['tax_reclaimable_on_purchases'] = [];
        $data_report['total_taxable_purchases_in_period_before_tax'] = [];

        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '") and tax > 0 and (rel_type = "expense" or rel_type = "purchase_order" or rel_type = "purchase_invoice") and credit >= 0');
     
        $this->db->order_by('date', 'asc');
        
        $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();

        $list_expense = [];        
        $list_purchase_order = [];
        $list_purchase_invoice = [];

        $this->load->model('expenses_model');
        if(acc_get_status_modules('purchase')){
            $this->load->model('purchase/purchase_model');
        }

        foreach ($account_history as $v) {
            if($v['rel_type'] == 'purchase_order'){
                if(!in_array($v['rel_id'], $list_purchase_order)){
                    $list_purchase_order[] = $v['rel_id'];

                    $purchase_order = $this->purchase_model->get_pur_order($v['rel_id']);
                    if($purchase_order){
                        $data_report['total_taxable_purchases_in_period_before_tax'][] = [
                                        'date' => date('Y-m-d', strtotime($v['date'])),
                                        'type' => _l($v['rel_type']),
                                        'description' => $v['description'],
                                        'customer' => $v['customer'],
                                        'amount' => $purchase_order->subtotal,
                                        'rel_id' => $v['rel_id'],
                                        'rel_type' => $v['rel_type'],
                                    ];
                    }
                }
            }elseif($v['rel_type'] == 'purchase_invoice'){
                if(!in_array($v['rel_id'], $list_purchase_invoice)){
                    $list_purchase_invoice[] = $v['rel_id'];

                    $purchase_invoice = $this->purchase_model->get_pur_invoice($v['rel_id']);

                    if($purchase_invoice){
                        $data_report['total_taxable_purchases_in_period_before_tax'][] = [
                                    'date' => date('Y-m-d', strtotime($v['date'])),
                                    'type' => _l($v['rel_type']),
                                    'description' => $v['description'],
                                    'customer' => $v['customer'],
                                    'amount' => $purchase_invoice->subtotal,
                                    'rel_id' => $v['rel_id'],
                                        'rel_type' => $v['rel_type'],
                                ];
                    }
                }
            }else{
                if(!in_array($v['rel_id'], $list_expense)){
                    $list_expense[] = $v['rel_id'];

                    $expense = $this->expenses_model->get($v['rel_id']);

                    if($expense){
                        $data_report['total_taxable_purchases_in_period_before_tax'][] = [
                                    'date' => date('Y-m-d', strtotime($v['date'])),
                                    'type' => _l($v['rel_type']),
                                    'description' => $v['description'],
                                    'customer' => $v['customer'],
                                    'amount' => $expense->amount,
                                    'rel_id' => $v['rel_id'],
                                        'rel_type' => $v['rel_type'],
                                ];
                    }
                }
            }

            $this->db->where('id', $v['tax']);
            $_tax = $this->db->get(db_prefix().'taxes')->row();

            $data_report['tax_reclaimable_on_purchases'][] = [
                            'date' => date('Y-m-d', strtotime($v['date'])),
                            'type' => _l($v['rel_type']),
                            'tax_name' => $_tax->name,
                            'tax_rate' => $_tax->taxrate,
                            'description' => $v['description'],
                            'customer' => $v['customer'],
                            'amount' => $v['credit'],
                            'rel_id' => $v['rel_id'],
                                        'rel_type' => $v['rel_type'],
                        ];
        }
                
        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date];
    }

    /**
     * get data tax summary report
     * @return array 
     */
    public function get_data_tax_summary_report($data_filter){
        $from_date = date('Y-m-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $tax = 0;
        if(isset($data_filter['tax'])){
            $tax = $data_filter['tax'];
        }

        $accounts = $this->get_accounts();

        $account_name = [];

        foreach ($accounts as $key => $value) {
            $account_name[$value['id']] = $value['name'];
        }

        $data_report = [];
        $data_report['tax_collected_on_sales'] = 0;
        $data_report['total_taxable_sales_in_period_before_tax'] = 0;
        $data_report['adjustments_to_tax_on_sales'] = 0;
        $data_report['total_taxable_purchases_in_period_before_tax'] = 0;
        $data_report['tax_reclaimable_on_purchases'] = 0;
        $data_report['other_adjustments'] = 0;
        $data_report['tax_due_or_credit_from_previous_periods'] = 0;
        $data_report['tax_payments_made_this_period'] = 0;
        $data_report['adjustments_to_reclaimable_tax_on_purchases'] = 0;

        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '") and tax = '.$tax.' and rel_type = "invoice" and debit > 0');

        if($accounting_method == 'cash'){
            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
        }
        $this->db->order_by('date', 'asc');
        
        $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
        
        $list_invoice = [];        
        $this->load->model('invoices_model');
        foreach ($account_history as $v) {

            if(!in_array($v['rel_id'], $list_invoice)){
                $list_invoice[] = $v['rel_id'];
                $invoice = $this->invoices_model->get($v['rel_id']);

                $data_report['total_taxable_sales_in_period_before_tax'] += $invoice->subtotal;
            }

            $data_report['tax_collected_on_sales'] += $v['debit'];
        }

        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '") and tax = '.$tax.' and (rel_type = "expense" or rel_type = "purchase_order" or rel_type = "purchase_invoice") and credit > 0');
        
        $this->db->order_by('date', 'asc');
        
        $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();

        $this->load->model('expenses_model');
        if(acc_get_status_modules('purchase')){
            $this->load->model('purchase/purchase_model');
        }

        $list_expense = [];        
        $list_purchase_order = [];        
        $list_purchase_invoice = [];        

        foreach ($account_history as $v) {
            if($v['rel_type'] == 'purchase_order'){
                if(!in_array($v['rel_id'], $list_purchase_order)){
                    $list_purchase_order[] = $v['rel_id'];

                    $purchase_order = $this->purchase_model->get_pur_order($v['rel_id']);

                    if($purchase_order){
                        $data_report['total_taxable_purchases_in_period_before_tax'] += $purchase_order->subtotal;
                    }
                }
            }elseif($v['rel_type'] == 'purchase_invoice'){
                if(!in_array($v['rel_id'], $list_purchase_invoice)){
                    $list_purchase_invoice[] = $v['rel_id'];

                    $purchase_invoice = $this->purchase_model->get_pur_invoice($v['rel_id']);

                    if($purchase_invoice){
                        $data_report['total_taxable_purchases_in_period_before_tax'] += $purchase_invoice->subtotal;
                    }
                }
            }else{
                if(!in_array($v['rel_id'], $list_expense)){
                    $list_expense[] = $v['rel_id'];
                    $expense = $this->expenses_model->get($v['rel_id']);

                    if($expense){
                        $data_report['total_taxable_purchases_in_period_before_tax'] += $expense->amount;
                    }
                }
            }


            $data_report['tax_reclaimable_on_purchases'] += $v['credit'];
        }
                
        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date];
    }

    /**
     * get data tax liability report
     * @return array 
     */
    public function get_data_tax_liability_report($data_filter){
        $from_date = date('Y-m-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $accounts = $this->get_accounts();

        $account_name = [];

        foreach ($accounts as $key => $value) {
            $account_name[$value['id']] = $value['name'];
        }

        $data_report = [];

        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '") and tax > 0 and debit > 0');
        if($accounting_method == 'cash'){
            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
        }
        $this->db->order_by('tax, rel_type', 'asc');
        $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
        
        $list_invoice = [];        
        foreach ($account_history as $v) {
            if(isset($data_report[$v['tax'].'_'.$v['rel_type']])){
                $data_report[$v['tax'].'_'.$v['rel_type']]['amount'] += $v['debit'];
            }else{
                $this->db->where('id', $v['tax']);
                $_tax = $this->db->get(db_prefix().'taxes')->row();

                $data_report[$v['tax'].'_'.$v['rel_type']] = [];
                $data_report[$v['tax'].'_'.$v['rel_type']]['name'] = $_tax->name.' ('._l($v['rel_type']).')('.$_tax->taxrate.'%)';
                $data_report[$v['tax'].'_'.$v['rel_type']]['amount'] = $v['debit'];
            }

        }
                
        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date];
    }

    /**
     * get journal entry next number
     * @return integer
     */
    public function get_journal_entry_next_number()
    {
        $this->db->select('max(number) as max_number');
        $max = $this->db->get(db_prefix().'acc_journal_entries')->row();

        if(is_numeric($max->max_number)){
            return $max->max_number + 1;
        }

        return 1;
    }

    /**
     * add payment mode mapping
     * @param array $data
     * @return boolean
     */
    public function add_payment_mode_mapping($data){
        if(isset($data['id'])){
            unset($data['id']);
        }
        $payment_modes = [];
        if(isset($data['payment_mode'])){
            $payment_modes = $data['payment_mode'];
            unset($data['payment_mode']);
        }
        $data_insert = [];
        foreach ($payment_modes as $value) {
            $this->db->where('payment_mode_id', $value);
            $count = $this->db->count_all_results(db_prefix() . 'acc_payment_mode_mappings');

            if($count == 0){
                $node = [];
                $node['payment_mode_id'] = $value;
                $node['payment_account'] = $data['payment_account'];
                $node['deposit_to'] = $data['deposit_to'];
                $node['expense_payment_account'] = $data['expense_payment_account'];
                $node['expense_deposit_to'] = $data['expense_deposit_to'];
                $node['credit_note_refund_payment_account'] = $data['credit_note_refund_payment_account'];
                $node['credit_note_refund_deposit_to'] = $data['credit_note_refund_deposit_to'];
                
                $data_insert[] = $node;
            }

        }

        $affectedRows = $this->db->insert_batch(db_prefix().'acc_payment_mode_mappings',  $data_insert);

        if ($affectedRows > 0) {
            return true;
        }

        return false;
    }

    /**
     * update payment mode mapping
     * @param array $data
     * @param  integer $id 
     * @return boolean
     */
    public function update_payment_mode_mapping($data, $id){
        $this->db->where('id', $id);
        $this->db->update(db_prefix().'acc_payment_mode_mappings', $data);
       
        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }

    /**
     * delete payment mode mapping
     * @param integer $id
     * @return boolean
     */

    public function delete_payment_mode_mapping($id)
    {
        $this->db->where('id', $id);
        $this->db->delete(db_prefix() . 'acc_payment_mode_mappings');
        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }

    /**
     * get payment mode are not yet auto
     * @return array
     */
    public function get_payment_mode_not_yet_auto(){
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_payment_mode_mappings where ' . db_prefix() . 'acc_payment_mode_mappings.payment_mode_id = ' . db_prefix() . 'payment_modes.id) = 0)');
        return $this->db->get(db_prefix().'payment_modes')->result_array();
    }

    /**
     * Gets the payment mode mappings
     *
     * @param      string  $payment_mode_id  The payment mode id
     *
     * @return     object  The expense category mapping.
     */
    public function get_payment_mode_mapping($payment_mode_id) {

        $this->db->where('payment_mode_id', $payment_mode_id);
        return $this->db->get(db_prefix() . 'acc_payment_mode_mappings')->row();
    }

    /**
     * Change payment mode mapping active
     * @param  mixed $status status(0/1)
     */
    public function change_active_payment_mode_mapping($status)
    {
        $this->db->where('name', 'acc_active_payment_mode_mapping');
        $this->db->update(db_prefix() . 'options', [
            'value' => $status,
        ]);

        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }

    /**
     * Change expense category mapping active
     * @param  mixed $status status(0/1)
     */
    public function change_active_expense_category_mapping($status)
    {
        $this->db->where('name', 'acc_active_expense_category_mapping');
        $this->db->update(db_prefix() . 'options', [
            'value' => $status,
        ]);

        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }

    /**
     * get account data tables
     * @param  array $aColumns           table columns
     * @param  mixed $sIndexColumn       main column in table for bettter performing
     * @param  string $sTable            table name
     * @param  array  $join              join other tables
     * @param  array  $where             perform where in query
     * @param  array  $additionalSelect  select additional fields
     * @param  string $sGroupBy group results
     * @return array
     */
    function get_account_data_tables($aColumns, $sIndexColumn, $sTable, $join = [], $where = [], $additionalSelect = [], $sGroupBy = '', $searchAs = [])
    {
        $accounting_method = get_option('acc_accounting_method');
        
        $CI          = & get_instance();
        $__post      = $CI->input->post();
        $where = implode(' ', $where);
        $where = trim($where);
        if (startsWith($where, 'AND') || startsWith($where, 'OR')) {
            if (startsWith($where, 'OR')) {
                $where = substr($where, 2);
            } else {
                $where = substr($where, 3);
            }

            $this->db->where($where);
        }

        if(!$this->input->post('ft_account') && !$this->input->post('ft_parent_account')){
            $this->db->where('(parent_account is null or parent_account = 0)');
        }

        if($accounting_method == 'cash'){
            $debit = '(SELECT sum(debit) as debit FROM '.db_prefix().'acc_account_history where (account in (select id from '.db_prefix().'acc_accounts where parent_account = a.id) or account = a.id) AND (('.db_prefix().'acc_account_history.rel_type = "invoice" AND '.db_prefix().'acc_account_history.paid = 1) or rel_type != "invoice")) as debit';
            $credit = '(SELECT sum(credit) as credit FROM '.db_prefix().'acc_account_history where (account in (select id from '.db_prefix().'acc_accounts where parent_account = a.id) or account = a.id) AND (('.db_prefix().'acc_account_history.rel_type = "invoice" AND '.db_prefix().'acc_account_history.paid = 1) or rel_type != "invoice")) as credit';
        }else{
            $debit = '(SELECT sum(debit) as debit FROM '.db_prefix().'acc_account_history where (account in (select id from '.db_prefix().'acc_accounts where parent_account = a.id) or account = a.id)) as debit';
            $credit = '(SELECT sum(credit) as credit FROM '.db_prefix().'acc_account_history where (account in (select id from '.db_prefix().'acc_accounts where parent_account = a.id) or account = a.id)) as credit';
        }


        $this->db->select('id, number, name, parent_account, account_type_id, account_detail_type_id, balance, key_name, active, number, description, balance_as_of, '.$debit.', '.$credit.', default_account');

        if($CI->input->post('length') != -1){
            $this->db->limit(intval($CI->input->post('length')), intval($CI->input->post('start')));
        }

        if ($CI->input->post('order')) {
            foreach ($CI->input->post('order') as $key => $val) {
                $columnName = $aColumns[intval($__post['order'][$key]['column'])];
                $dir        = strtoupper($__post['order'][$key]['dir']);

                // Security
                if (!in_array($dir, ['ASC', 'DESC'])) {
                    $dir = 'ASC';
                }

            }

            $this->db->order_by($columnName, $dir);
        }

        $accounts = $this->db->get(db_prefix().'acc_accounts a')->result_array();
        $rResult = [];

        foreach ($accounts as $key => $value) {
            $rResult[] = $value;
            $rResult = $this->get_recursive_account($rResult, $value['id'], $where, 1);
        }

        /* Data set length after filtering */
        $sQuery = '
        SELECT FOUND_ROWS()
        ';
        $_query         = $CI->db->query($sQuery)->result_array();
        $iFilteredTotal = $_query[0]['FOUND_ROWS()'];
        
        /* Total data set length */
        $sQuery = '
        SELECT COUNT(' . $sTable . '.' . $sIndexColumn . ")
        FROM $sTable " . ($where != '' ? 'WHERE '.$where . ' AND (parent_account IS NULL OR parent_account = 0)' : 'WHERE (parent_account IS NULL OR parent_account = 0)');
        $_query = $CI->db->query($sQuery)->result_array();

        $iTotal = $_query[0]['COUNT(' . $sTable . '.' . $sIndexColumn . ')'];
        /*
         * Output
         */
        $output = [
            'draw'                 => $__post['draw'] ? intval($__post['draw']) : 0,
            'iTotalRecords'        => $iTotal,
            'iTotalDisplayRecords' => $iTotal,
            'aaData'               => [],
            ];

        return [
            'rResult' => $rResult,
            'output'  => $output,
            ];
    }

    /**
     * get recursive account
     * @param  array $accounts  
     * @param  integer $account_id
     * @param  string $where     
     * @param  integer $number    
     * @return array            
     */
    public function get_recursive_account($accounts, $account_id, $where, $number){
        $this->db->select('id, number, name, parent_account, account_type_id, account_detail_type_id, balance, key_name, active, number, description, balance_as_of, (SELECT sum(debit) as debit FROM '.db_prefix().'acc_account_history where (account in (select id from '.db_prefix().'acc_accounts where parent_account = a.id) or account = a.id)) as debit, (SELECT sum(credit) as credit FROM '.db_prefix().'acc_account_history where (account in (select id from '.db_prefix().'acc_accounts where parent_account = a.id) or account = a.id)) as credit, default_account');
        if($where != ''){
            $this->db->where($where);
        }

        $this->db->where('parent_account', $account_id);
        $this->db->order_by('number,name', 'asc');
        $account_list = $this->db->get(db_prefix().'acc_accounts a')->result_array();

        if($account_list){
            foreach ($account_list as $key => $value) {
                if($account_id == $value['id']){
                    continue;
                }
                
                foreach ($accounts as $k => $val) {
                    if($value['id'] == $val['id']){
                        unset($accounts[$k]);
                    }
                }

                $value['level'] = $number;
                array_push($accounts, $value);
                $accounts = $this->get_recursive_account($accounts, $value['id'], $where, $number + 1);
            }
        }

        return $accounts;
    }

    /**
     * get data balance sheet comparison recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date         
     * @param  string $last_from_date  
     * @param  string $last_to_date    
     * @param  string $accounting_method    
     * @return array                 
     */
    public function get_data_balance_sheet_comparison_recursive($child_account, $account_id, $account_type_id, $from_date, $to_date, $last_from_date, $last_to_date, $accounting_method, $acc_show_account_numbers, $where_items){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        $data_return = [];
        foreach ($accounts as $val) {
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            if($where_items != ''){
                $this->db->where($where_items);
            }
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $credits = $account_history->credit != '' ? $account_history->credit : 0;
            $debits = $account_history->debit != '' ? $account_history->debit : 0;

            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->where('(date_format(datecreated, \'%Y-%m-%d\') >= "' . $last_from_date . '" and date_format(datecreated, \'%Y-%m-%d\') <= "' . $last_to_date . '")');
            if($where_items != ''){
                $this->db->where($where_items);
            }
            $py_account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $py_credits = $py_account_history->credit != '' ? $py_account_history->credit : 0;
            $py_debits = $py_account_history->debit != '' ? $py_account_history->debit : 0;

            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }

            if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => ($credits - $debits), 'py_amount' => ($py_credits - $py_debits), 'child_account' => $this->get_data_balance_sheet_comparison_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $last_from_date, $last_to_date, $accounting_method, $acc_show_account_numbers, $where_items)];
            }else{
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => ($debits - $credits), 'py_amount' => ($py_debits - $py_credits), 'child_account' => $this->get_data_balance_sheet_comparison_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $last_from_date, $last_to_date, $accounting_method, $acc_show_account_numbers, $where_items)];
            }
        }

        return $child_account; 
    }

    /**
     * get html balance sheet comparision
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_balance_sheet_comparision($child_account, $data_return, $parent_index, $currency, $flag = false, $level = 1){
        $categoryOutput='';
        if ($flag) {
            for ($i = 0; $i < $level; $i++) {
                $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        $total_amount = 0;
        $total_py_amount = 0;
        $data_return['total_amount'] = 0;
        $data_return['total_py_amount'] = 0;
        foreach ($child_account as $val) {

            $data_return['row_index']++;
            $total_amount = $val['amount'];
            $total_py_amount = $val['py_amount'];

            if($flag){
                $balance_url = $val['name'];

            }else{
                $balance_url = '<a href="'.admin_url('accounting/user_register_view/'.$val['account_id'].'?from_date='.$val['from_date'].'&to_date='.$val['to_date']).'" class="text-default-bl">'.$val['name'].'</a>';
            }

            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
              <td>
                '.$categoryOutput.$balance_url.'
              </td>
              <td class="total_amount">
              '.app_format_money($val['amount'], $currency->name).'
              </td>
              <td class="total_amount">
              '.app_format_money($val['py_amount'], $currency->name).'
              </td>
            </tr>';

            if(count($val['child_account']) > 0){
                $t = $data_return['total_amount'];
                $t_py = $data_return['total_py_amount'];
                $data_return = $this->get_html_balance_sheet_comparision($val['child_account'], $data_return, $data_return['row_index'], $currency);

                $total_amount += $data_return['total_amount'];
                $total_py_amount += $data_return['total_py_amount'];
                
                $data_return['row_index']++;

                if($flag){
                    $balance_url = $val['name'];

                }else{
                    $balance_url = '<a href="'.admin_url('accounting/rp_account_history?account='.$val['account_id'].'&from_date='.$val['from_date'].'&to_date='.$val['to_date']).'" class="text-default-bl">'.$val['name'].'</a>';
                }

                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                  <td>
                    '.$categoryOutput._l('total_for').' '.$balance_url.'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_py_amount, $currency->name).'
                  </td>
                </tr>';
                $data_return['total_amount'] += $t;
                $data_return['total_py_amount'] += $t_py;
            }

            $data_return['total_amount'] += $val['amount'];
            $data_return['total_py_amount'] += $val['py_amount'];
        }
        return $data_return; 
    }

    /**
     * get data balance sheet detail recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date         
     * @param  string $accounting_method         
     * @return array                 
     */
    public function get_data_balance_sheet_detail_recursive($child_account, $account_id, $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        $data_return = [];
        foreach ($accounts as $val) {
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('(date < "' . $from_date . '")');
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            if($where_items != ''){
                $this->db->where($where_items);
            }
            $_account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $credits = $_account_history->credit != '' ? $_account_history->credit : 0;
            $debits = $_account_history->debit != '' ? $_account_history->debit : 0;

            if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 10 || $account_type_id == 9 || $account_type_id == 8 || $account_type_id == 7 || $account_type_id == 6){
                $beginning_balance = $credits - $debits;
            }else{
                $beginning_balance = $debits - $credits;
            }

            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            $this->db->order_by('date', 'asc');
            if($where_items != ''){
                $this->db->where($where_items);
            }
            $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
            $node = [];
            $balance = $beginning_balance;
            $amount = 0;
            foreach ($account_history as $v) {
                if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 10 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 7 || $account_type_id == 6){
                    $am = $v['credit'] - $v['debit'];
                }else{
                    $am = $v['debit'] - $v['credit'];
                }

                $node[] =   [
                                'date' => date('Y-m-d', strtotime($v['date'])),
                                'type' => _l($v['rel_type']),
                                'description' => $v['description'],
                                'debit' => $v['debit'],
                                'credit' => $v['credit'],
                                'amount' => $am,
                                'balance' => $balance + $am,
                                'rel_id' => $v['rel_id'],
                                'rel_type' => $v['rel_type'],
                            ];

                $amount += $am;
                $balance += $am;
            }

            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }


            $child_account[] = ['from_date' => $from_date, 'to_date' => $to_date, 'account' => $val['id'], 'name' => $name, 'amount' => $amount, 'balance' => $balance, 'beginning_balance' => $beginning_balance, 'details' => $node, 'child_account' => $this->get_data_balance_sheet_detail_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items)];
        }

        return $child_account; 
    }

    /**
     * get html balance sheet detail
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_balance_sheet_detail($child_account, $data_return, $parent_index, $currency, $flag = false, $level=1){
        $total_amount = 0;
        $balance = 0;
        $data_return['total_amount'] = 0;
        $data_return['total_balance'] = 0;

        $categoryOutput='';
        if ($flag) {
            for ($i = 0; $i < $level; $i++) {
                $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        foreach ($child_account as $value) {
            $balance = $value['beginning_balance'];
            $amount = 0;
            $data_return['row_index']++;
            $_parent_index = $data_return['row_index'];
            if(count($value['details']) > 0 || count($value['child_account']) > 0 || $value['beginning_balance'] != 0){
                if($flag){
                    $balance_url = $value['name'].' ('._l('balance_forward_as_of', _d($value['from_date'])).')';

                }else{
                    $balance_url = '<a href="'.admin_url('accounting/user_register_view/'.$value['account'].'?from_date='.$value['from_date'].'&to_date='.$value['to_date']).'" class="text-default-bl">'.$value['name'].' ('._l('balance_forward_as_of', _d($value['from_date'])).')</a>';
                }

                $data_return['html'] .= '<tr class="treegrid-'.$_parent_index.' treegrid-parent-'.$parent_index.' parent-node expanded">
                    <td class="parent">'.$categoryOutput.$balance_url.'</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td class="total_amount">'.app_format_money($value['beginning_balance'], $currency->name).'</td>
                  </tr>';
            }

            foreach ($value['details'] as $val) { 
                $data_return['row_index']++;
                $amount += $val['amount'];
                $balance = $val['balance'];
                $url = get_url_by_type_id($val['rel_type'], $val['rel_id']);

                if($flag){
                    $balance_url = _d($val['date']);
                }else{
                    $balance_url = '<a href="'.$url.'" class="text-default-bl">'. _d($val['date']).'</a>';
                }

                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' treegrid-parent-'.$_parent_index.'">
                  <td>
                '.$categoryOutput.$balance_url.'
                  </td>
                  <td>
                  '. new_html_entity_decode($val['type']).' 
                  </td>
                  <td>
                  '. new_html_entity_decode($val['description']).' 
                  </td>
                  <td class="total_amount">
                  '. app_format_money($val['debit'], $currency->name).' 
                  </td>
                  <td class="total_amount">
                  '. app_format_money($val['credit'], $currency->name).' 
                  </td>
                  <td class="total_amount">
                  '. app_format_money($val['amount'], $currency->name).' 
                  </td>
                  <td class="total_amount">
                  '. app_format_money($val['balance'], $currency->name).' 
                  </td>
                </tr>';
               }
            $total_amount = $amount;
            $total_balance = $balance;
            $data_return['row_index']++;
            $t = 0;
            $b = 0;
            if(count($value['child_account']) > 0){
                $level++;
                $t = $data_return['total_amount'];
                $b = $data_return['total_balance'];
                $data_return = $this->get_html_balance_sheet_detail($value['child_account'], $data_return, $_parent_index, $currency, $flag, $level);
                $total_amount += $data_return['total_amount'];
                $total_balance += $data_return['total_balance'];
            }

            if(count($value['details']) > 0 || count($value['child_account']) > 0 || $value['beginning_balance'] != 0){
                $data_return['row_index']++;
                $data_return['html'] .= '
                  <tr class="treegrid-'.$data_return['row_index'].' treegrid-parent-'.$parent_index.' tr_total">
                      <td>
                      '._l('total_for', $value['name']).'
                      </td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                    <td class="total_amount">'.app_format_money($balance, $currency->name).'</td>
                </tr>';
                $data_return['total_amount'] += $t;
                $data_return['total_balance'] += $b;
            }

            $data_return['total_amount'] += $amount;
            $data_return['total_balance'] += $balance;
        }


        return $data_return; 
    }

    /**
     * get data balance sheet summary recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date         
     * @param  string $accounting_method         
     * @return array                 
     */
    public function get_data_balance_sheet_summary_recursive($child_account, $account_id, $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        $data_return = [];
        foreach ($accounts as $val) {
            $this->db->where('account', $val['id']);
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            if($where_items != ''){
                $this->db->where($where_items);
            }
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $node = [];
            $balance = 0;
            $amount = 0;

            $credits = $account_history->credit != '' ? $account_history->credit : 0;
            $debits = $account_history->debit != '' ? $account_history->debit : 0;
            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }

            if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $credits - $debits, 'child_account' => $this->get_data_balance_sheet_summary_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items)];

            }else{
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $debits - $credits, 'child_account' => $this->get_data_balance_sheet_summary_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items)];
            }
        }

        return $child_account;
    }

    /**
     * get html balance sheet summary
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_balance_sheet_summary($child_account, $data_return, $parent_index, $currency, $flag = false, $level = 1){
        $categoryOutput='';
        if ($flag) {
            for ($i = 0; $i < $level; $i++) {
                $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        $total_amount = 0;
        $data_return['total_amount'] = 0;
        foreach ($child_account as $val) {

            $data_return['row_index']++;
            $total_amount = $val['amount'];
            if($flag){
                $report_url = $val['name'];
            }else{
                $report_url = '<a href="'.admin_url('accounting/user_register_view/'.$val['account_id'].'?from_date='.$val['from_date'].'&to_date='.$val['to_date']).'" class="text-default-bl">'.$val['name'].'</a>';
            }

            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
              <td>
            '.$categoryOutput.$report_url.'
              </td>
              <td class="total_amount">
              '.app_format_money($val['amount'], $currency->name).'
              </td>
            </tr>';

            if(count($val['child_account']) > 0){
                $level++;
                $t = $data_return['total_amount'];
                $data_return = $this->get_html_balance_sheet_summary($val['child_account'], $data_return, $data_return['row_index'], $currency, $flag, $level);

                $total_amount += $data_return['total_amount'];
                
                $data_return['row_index']++;
                if($flag){
                    $report_url = $val['name'];
                }else{
                    $report_url = '<a href="'.admin_url('accounting/rp_account_history?account='.$val['account_id'].'&from_date='.$val['from_date'].'&to_date='.$val['to_date']).'" class="text-default-bl">'.$val['name'].'</a>';
                }
                
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                  <td>
                '.$categoryOutput._l('total_for').$report_url.'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                </tr>';
                $data_return['total_amount'] += $t;
            }

            $data_return['total_amount'] += $val['amount'];
        }
        return $data_return; 
    }

    /**
     * get data balance sheet summary recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date         
     * @param  string $accounting_method         
     * @return array                 
     */
    public function get_data_balance_sheet_recursive($child_account, $account_id, $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        $data_return = [];
        foreach ($accounts as $val) {
            $this->db->where('account', $val['id']);
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            if($where_items != ''){
                $this->db->where($where_items);
            }
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $node = [];
            $balance = 0;
            $amount = 0;

            $credits = $account_history->credit != '' ? $account_history->credit : 0;
            $debits = $account_history->debit != '' ? $account_history->debit : 0;
            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }


            if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $credits - $debits, 'child_account' => $this->get_data_balance_sheet_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items)];

            }else{
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $debits - $credits, 'child_account' => $this->get_data_balance_sheet_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items)];
            }

        }

        return $child_account;
    }

    /**
     * get html balance sheet
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_balance_sheet($child_account, $data_return, $parent_index, $currency, $flag = false, $level = 1){
        $categoryOutput='';
        if ($flag) {
            for ($i = 0; $i < $level; $i++) {
                $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        $total_amount = 0;
        $data_return['total_amount'] = 0;
        foreach ($child_account as $val) {

            $data_return['row_index']++;
            $total_amount = $val['amount'];

            if($flag){
                $report_url = $val['name'];
            }else{
                $report_url = '<a href="'.admin_url('accounting/user_register_view/'.$val['account_id'].'?from_date='.$val['from_date'].'&to_date='.$val['to_date']).'" class="text-default-bl">'.$val['name'].'</a>';
            }

            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
              <td>
            '.$categoryOutput.$report_url.'
              </td>
              <td class="total_amount">
              '.app_format_money($val['amount'], $currency->name).'
              </td>
            </tr>';

            if(count($val['child_account']) > 0){
                $level++;

                if ($flag) {
                    for ($i = 0; $i < $level; $i++) {
                        $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
                    }
                }

                $t = $data_return['total_amount'];
                $data_return = $this->get_html_balance_sheet($val['child_account'], $data_return, $data_return['row_index'], $currency, $flag, $level);

                $total_amount += $data_return['total_amount'];

                if($flag){
                    $report_url = $val['name'];
                }else{
                    $report_url = '<a href="'.admin_url('accounting/rp_account_history?account='.$val['account_id'].'&from_date='.$val['from_date'].'&to_date='.$val['to_date']).'" class="text-default-bl">'.$val['name'].'</a>';
                }
                
                $data_return['row_index']++;
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                  <td>
                '.$categoryOutput._l('total_for').$report_url.'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                </tr>';
                $data_return['total_amount'] += $t;
            }

            $data_return['total_amount'] += $val['amount'];
        }
        return $data_return; 
    }

    /**
     * get data custom summary recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date         
     * @param  string $accounting_method 
     * @return array                 
     */
    public function get_data_custom_summary_recursive($data){
        $child_account = $data['child_account'];
        $account_id = $data['account_id'];
        $account_type_id = $data['account_type_id'];
        $from_date = $data['from_date'];
        $to_date = $data['to_date'];
        $accounting_method = $data['accounting_method'];
        $acc_show_account_numbers = $data['acc_show_account_numbers'];
        $display_rows_by = $data['display_rows_by'];
        $display_columns_by = $data['display_columns_by'];

        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        $data_return = [];
       
        foreach ($accounts as $val) {
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $credits = $account_history->credit != '' ? $account_history->credit : 0;
            $debits = $account_history->debit != '' ? $account_history->debit : 0;
            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }


            if($account_type_id == 11 || $account_type_id == 12){
                $child_account[] = ['name' => $name, 'amount' => $credits - $debits, 'child_account' => $this->get_data_custom_summary_recursive([
                            'child_account' => [],
                            'account_id' => $val['id'],
                            'account_type_id' => $account_type_id,
                            'from_date' => $from_date,
                            'to_date' => $to_date,
                            'accounting_method' => $accounting_method,
                            'acc_show_account_numbers' => $acc_show_account_numbers,
                            'display_rows_by' => $display_rows_by,
                            'display_columns_by' => $display_columns_by,
                        ])];
            }else{
                $child_account[] = ['name' => $name, 'amount' => $debits - $credits, 'child_account' => $this->get_data_custom_summary_recursive([
                            'child_account' => [],
                            'account_id' => $val['id'],
                            'account_type_id' => $account_type_id,
                            'from_date' => $from_date,
                            'to_date' => $to_date,
                            'accounting_method' => $accounting_method,
                            'acc_show_account_numbers' => $acc_show_account_numbers,
                            'display_rows_by' => $display_rows_by,
                            'display_columns_by' => $display_columns_by,
                        ])];
            }
        }

        return $child_account;
    }

    /**
     * get html custom summary
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_custom_summary($child_account, $data_return, $parent_index, $currency){
        $total_amount = 0;
        $data_return['total_amount'] = 0;
        foreach ($child_account as $val) {

            $data_return['row_index']++;
            $total_amount = $val['amount'];
            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
              <td>
              '.$val['name'].'
              </td>
              <td class="total_amount">
              '.app_format_money($val['amount'], $currency->name).'
              </td>
            </tr>';

            if(count($val['child_account']) > 0){
                $t = $data_return['total_amount'];
                $data_return = $this->get_html_custom_summary($val['child_account'], $data_return, $data_return['row_index'], $currency);

                $total_amount += $data_return['total_amount'];
                
                $data_return['row_index']++;
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                  <td>
                  '._l('total_for', $val['name']).'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                </tr>';
                $data_return['total_amount'] += $t;
            }

            $data_return['total_amount'] += $val['amount'];
        }
        return $data_return; 
    }

    /**
     * get data profit and loss as of total income recursive
     * @param  array $child_account         
     * @param  integer $income      
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date         
     * @return array                 
     */
    public function get_data_profit_and_loss_as_of_total_income_recursive($child_account, $income, $account_id, $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        foreach ($accounts as $val) {
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            if($where_items != ''){
                $this->db->where($where_items);
            }
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

            $credits = $account_history->credit != '' ? $account_history->credit : 0;
            $debits = $account_history->debit != '' ? $account_history->debit : 0;
            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }

            if($account_type_id == 11 || $account_type_id == 12){
                $r_am = $credits - $debits;
            }else{
                $r_am = $debits - $credits;
            }

            if($income != 0){
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $r_am, 'percent' => round((($r_am) / $income) * 100, 2), 'child_account' => $this->get_data_profit_and_loss_as_of_total_income_recursive([], $income, $val['id'], $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items)];
            }else{
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $r_am, 'percent' => 0, 'child_account' => $this->get_data_profit_and_loss_as_of_total_income_recursive([], $income, $val['id'], $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items)];
            }
        }

        return $child_account;
    }

    /**
     * get html profit and loss as of total income
     * @param  array $child_account 
     * @param  integer $income 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_profit_and_loss_as_of_total_income($child_account, $income, $data_return, $parent_index, $currency, $flag = false, $level = 1){
        $categoryOutput='';
           if ($flag) {
            for ($i = 0; $i < $level; $i++) {
                $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        $total_amount = 0;
        $data_return['total_amount'] = 0;
        $data_return['percent'] = 0;
        foreach ($child_account as $val) {
            if($flag){
                $html_a_tag = $val['name'];
            }else{
                $html_a_tag = '<a href="'.admin_url('accounting/user_register_view/'.$val['account_id'].'?from_date='.$val['from_date'].'&to_date='.$val['to_date']).'" class="text-default-bl">'.$val['name'].'</a>';
            }

            $data_return['row_index']++;
            $total_amount = $val['amount'];
            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
              <td>
            '.$categoryOutput.$html_a_tag.'
              </td>
              <td class="total_amount">
              '.app_format_money($val['amount'], $currency->name).'
              </td>
              <td class="total_amount">
              '. new_html_entity_decode($val['percent']).'% 
              </td>
            </tr>';
            

            if(count($val['child_account']) > 0){
                $level++;

                $t = $data_return['total_amount'];
                $p = $data_return['percent'];
                $data_return = $this->get_html_profit_and_loss_as_of_total_income($val['child_account'], $income, $data_return, $data_return['row_index'], $currency, $flag, $level);
                $total_amount += $data_return['total_amount'];

                if($income != 0){
                    $percent = round((($total_amount) / $income) * 100, 2);
                }else{
                    $percent = 0;
                }

                $data_return['row_index']++;
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                  <td>
                '.$categoryOutput._l('total_for').' '.$html_a_tag.'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                  <td class="total_amount">
                  '. new_html_entity_decode($percent).'% 
                  </td>
                </tr>';
                $data_return['total_amount'] += $t;
                $data_return['percent'] += $p;
            }

            $data_return['total_amount'] += $val['amount'];
            $data_return['percent'] += $val['percent'];
        }
        return $data_return; 
    }

    /**
     * get data profit and loss comparison recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date 
     * @param  string $last_from_date       
     * @param  string $last_to_date         
     * @param  string $accounting_method         
     * @return array                 
     */
    public function get_data_profit_and_loss_comparison_recursive($child_account, $account_id, $account_type_id, $from_date, $to_date, $last_from_date, $last_to_date, $accounting_method, $acc_show_account_numbers, $where_items){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        $data_return = [];
       
        foreach ($accounts as $val) {
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            if($where_items != ''){
                $this->db->where($where_items);
            }
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $credits = $account_history->credit != '' ? $account_history->credit : 0;
            $debits = $account_history->debit != '' ? $account_history->debit : 0;

            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->where('(date_format(datecreated, \'%Y-%m-%d\') >= "' . $last_from_date . '" and date_format(datecreated, \'%Y-%m-%d\') <= "' . $last_to_date . '")');
            if($where_items != ''){
                $this->db->where($where_items);
            }
            $py_account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $py_credits = $py_account_history->credit != '' ? $py_account_history->credit : 0;
            $py_debits = $py_account_history->debit != '' ? $py_account_history->debit : 0;

            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }


            if($account_type_id == 11 || $account_type_id == 12){
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'this_year' => $credits - $debits, 'last_year' => $py_credits - $py_debits, 'child_account' => $this->get_data_profit_and_loss_comparison_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $last_from_date, $last_to_date, $accounting_method, $acc_show_account_numbers, $where_items)];
            }else{
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'this_year' => $debits - $credits, 'last_year' => $py_debits - $py_credits, 'child_account' => $this->get_data_profit_and_loss_comparison_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $last_from_date, $last_to_date, $accounting_method, $acc_show_account_numbers, $where_items)];
            }
        }

        return $child_account;
    }

    /**
     * get html profit and loss comparison
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_profit_and_loss_comparison($child_account, $data_return, $parent_index, $currency, $flag = false, $level = 1){
        $categoryOutput='';
           if ($flag) {
            for ($i = 0; $i < $level; $i++) {
                $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        $total_amount = 0;
        $total_py_amount = 0;
        $data_return['total_amount'] = 0;
        $data_return['total_py_amount'] = 0;
        foreach ($child_account as $val) {
            if($flag){
                $html_a_tag = $val['name'];
            }else{
                $html_a_tag = '<a href="'.admin_url('accounting/user_register_view/'.$val['account_id'].'?from_date='.$val['from_date'].'&to_date='.$val['to_date']).'" class="text-default-bl">'.$val['name'].'</a>';
            }

            $data_return['row_index']++;
            $total_amount = $val['this_year'];
            $total_py_amount = $val['last_year'];
            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
              <td>
                '.$categoryOutput.$html_a_tag.'
              </td>
              <td class="total_amount">
              '.app_format_money($val['this_year'], $currency->name).'
              </td>
              <td class="total_amount">
              '.app_format_money($val['last_year'], $currency->name).'
              </td>
            </tr>';
            

            if(count($val['child_account']) > 0){
                $level++;
                $t = $data_return['total_amount'];
                $p = $data_return['total_py_amount'];
                $data_return = $this->get_html_profit_and_loss_comparison($val['child_account'], $data_return, $data_return['row_index'], $currency, $flag, $level);
                $total_amount += $data_return['total_amount'];
                $total_py_amount += $data_return['total_py_amount'];

                $data_return['row_index']++;
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                  <td>
                '.$categoryOutput._l('total_for').' '.$html_a_tag.'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_py_amount, $currency->name).'
                  </td>
                </tr>';
                $data_return['total_amount'] += $t;
                $data_return['total_py_amount'] += $p;
            }

            $data_return['total_amount'] += $val['this_year'];
            $data_return['total_py_amount'] += $val['last_year'];
        }
        return $data_return; 
    }

    /**
     * get data profit and loss detail recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date         
     * @param  string $accounting_method         
     * @return array                 
     */
    public function get_data_profit_and_loss_detail_recursive($child_account, $account_id, $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        foreach ($accounts as $val) {
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            if($where_items != ''){
                $this->db->where($where_items);
            }
            $this->db->order_by('date', 'asc');
            $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
            $node = [];
            $balance = 0;
            $amount = 0;
            foreach ($account_history as $v) {
                if($account_type_id == 11 || $account_type_id == 12){
                    $am = $v['credit'] - $v['debit'];
                }else{
                    $am = $v['debit'] - $v['credit'];
                }
                $node[] =   [
                                'date' => date('Y-m-d', strtotime($v['date'])),
                                'type' => _l($v['rel_type']),
                                'split' => $v['split'] != 0 ? (isset($account_name[$v['split']]) ? $account_name[$v['split']] : '') : '-Split-',
                                'description' => $v['description'],
                                'customer' => $v['customer'],
                                'amount' => $am,
                                'balance' => $balance + $am,
                                'rel_type' => $v['rel_type'],
                                'rel_id' => $v['rel_id'],
                            ];
                $amount += $am;
                $balance += $am;
            }

            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }

            
            $child_account[] = ['from_date' => $from_date, 'to_date' => $to_date, 'account' => $val['id'], 'name' => $name, 'amount' => $amount, 'balance' => $balance, 'details' => $node, 'child_account' =>  $this->get_data_profit_and_loss_detail_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items)];
        }

        return $child_account;
    }
    
    /**
     * get html profit and loss detail
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_profit_and_loss_detail($child_account, $data_return, $parent_index, $currency, $flag = false, $level=1){
        $categoryOutput='';
        if ($flag) {
            for ($i = 0; $i < $level; $i++) {
                $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        $total_amount = 0;
        $data_return['total_amount'] = 0;
        foreach ($child_account as $value) {

            $amount = 0;
            $data_return['row_index']++;
            $_parent_index = $data_return['row_index'];
            if(count($value['details']) > 0 || count($value['child_account']) > 0){
                if($flag){
                    $html_a_tag = $value['name'];
                }else{
                    $html_a_tag = '<a href="'.admin_url('accounting/user_register_view/'.$value['account'].'?from_date='.$value['from_date'].'&to_date='.$value['to_date']).'" class="text-default-bl">'.$value['name'].'</a>';
                }

                $data_return['html'] .= '<tr class="treegrid-'.$_parent_index.' treegrid-parent-'.$parent_index.' parent-node expanded">
                    <td class="parent">'.$categoryOutput.$html_a_tag.'</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>';
            }

            foreach ($value['details'] as $val) { 
                $data_return['row_index']++;
                $amount += $val['amount'];
                $a_tag = _d($val['date']);
                $url = get_url_by_type_id($val['rel_type'], $val['rel_id']);
                if(!$flag){
                    $a_tag = '<a href="'.$url.'" class="text-default-bl">'._d($val['date']).'</a>';
                }

                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' treegrid-parent-'.$_parent_index.'">
                  <td>
                    '.$categoryOutput. $a_tag.'
                  </td>
                  <td>
                  '. new_html_entity_decode($val['type']).' 
                  </td>
                  <td>
                  '. new_html_entity_decode($val['description']).' 
                  </td>
                  <td>
                  '. new_html_entity_decode($val['split']).' 
                  </td>
                  <td class="total_amount">
                  '. app_format_money($val['amount'], $currency->name).' 
                  </td>
                  <td class="total_amount">
                  '. app_format_money($val['balance'], $currency->name).' 
                  </td>
                </tr>';
               }
            $total_amount = $amount;
            $data_return['row_index']++;
           
            if(count($value['child_account']) > 0){
                $level++;
                $t = $data_return['total_amount'];
                $data_return = $this->get_html_profit_and_loss_detail($value['child_account'], $data_return, $_parent_index, $currency, $flag, $level);
                $total_amount += $data_return['total_amount'];

                $html_a_tag = $value['name'];
                if(!$flag){
                    $html_a_tag = '<a href="'.admin_url('accounting/user_register_view/'.$value['account'].'?from_date='.$value['from_date'].'&to_date='.$value['to_date']).'" class="text-default-bl">'.$value['name'].'</a>';
                    
                }
                
                $data_return['row_index']++;
                $data_return['html'] .= '
                  <tr class="treegrid-'.$data_return['row_index'].' treegrid-parent-'.$parent_index.' tr_total">
                    <td style="'.report_pdf_border_top().'">
                    '.$categoryOutput._l('total_for').' '.$html_a_tag.'
                    </td>
                    <td style="'.report_pdf_border_top().'"></td>
                    <td style="'.report_pdf_border_top().'"></td>
                    <td style="'.report_pdf_border_top().'"></td>
                    <td style="'.report_pdf_border_top().'" class="total_amount">
                    '.app_format_money($total_amount, $currency->name).'
                    </td>
                    <td style="'.report_pdf_border_top().'"></td>
                </tr>';
                $data_return['total_amount'] += $t;
            }

            $data_return['total_amount'] += $amount;
        }
        return $data_return; 
    }

    /**
     * get data profit and loss year to date comparison recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date   
     * @param  string $last_from_date       
     * @param  string $last_to_date         
     * @param  string $accounting_method         
     * @return array                 
     */
    public function get_data_profit_and_loss_year_to_date_comparison_recursive($child_account, $account_id, $account_type_id, $from_date, $to_date, $last_from_date, $last_to_date, $accounting_method, $acc_show_account_numbers, $where_items){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        foreach ($accounts as $val) {
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            if($where_items != ''){
                $this->db->where($where_items);
            }
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $credits = $account_history->credit != '' ? $account_history->credit : 0;
            $debits = $account_history->debit != '' ? $account_history->debit : 0;

            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->where('(date_format(datecreated, \'%Y-%m-%d\') >= "' . $last_from_date . '" and date_format(datecreated, \'%Y-%m-%d\') <= "' . $last_to_date . '")');
            if($where_items != ''){
                $this->db->where($where_items);
            }
            $py_account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $py_credits = $py_account_history->credit != '' ? $py_account_history->credit : 0;
            $py_debits = $py_account_history->debit != '' ? $py_account_history->debit : 0;

            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }

            if($account_type_id == 11 || $account_type_id == 12){
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'this_year' => $credits - $debits, 'last_year' => $py_credits - $py_debits, 'child_account' => $this->get_data_profit_and_loss_year_to_date_comparison_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $last_from_date, $last_to_date, $accounting_method, $acc_show_account_numbers, $where_items)];
            }else{
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'this_year' => $debits - $credits, 'last_year' => $py_debits - $py_credits, 'child_account' => $this->get_data_profit_and_loss_year_to_date_comparison_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $last_from_date, $last_to_date, $accounting_method, $acc_show_account_numbers, $where_items)];
            }
        }

        return $child_account;
    }

    /**
     * get html profit and loss year to date comparison
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_profit_and_loss_year_to_date_comparison($child_account, $data_return, $parent_index, $currency){
        $total_amount = 0;
        $total_py_amount = 0;
        $data_return['total_amount'] = 0;
        $data_return['total_py_amount'] = 0;
        foreach ($child_account as $val) {

            $data_return['row_index']++;
            $total_amount = $val['this_year'];
            $total_py_amount = $val['last_year'];
            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
              <td>
              '.$val['name'].'
              </td>
              <td class="total_amount">
              '.app_format_money($val['this_year'], $currency->name).'
              </td>
              <td class="total_amount">
              '.app_format_money($val['last_year'], $currency->name).'
              </td>
            </tr>';

            if(count($val['child_account']) > 0){
                $t = $data_return['total_amount'];
                $p = $data_return['total_py_amount'];
                $data_return = $this->get_html_profit_and_loss_year_to_date_comparison($val['child_account'], $data_return, $data_return['row_index'], $currency);
                $total_amount += $data_return['total_amount'];
                $total_py_amount += $data_return['total_py_amount'];

                $data_return['row_index']++;
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                  <td>
                  '._l('total_for', $val['name']).'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_py_amount, $currency->name).'
                  </td>
                </tr>';
                $data_return['total_amount'] += $t;
                $data_return['total_py_amount'] += $p;
            }

            $data_return['total_amount'] += $val['this_year'];
            $data_return['total_py_amount'] += $val['last_year'];
        }
        return $data_return; 
    }

    /**
     * get data profit and loss recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date   
     * @param  string $accounting_method   
     * @return array                 
     */
    public function get_data_profit_and_loss_recursive($child_account, $account_id, $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        foreach ($accounts as $val) {
            
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            if($where_items != ''){
                $this->db->where($where_items);
            }
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
           
            $credits = $account_history->credit != '' ? $account_history->credit : 0;
            $debits = $account_history->debit != '' ? $account_history->debit : 0;
            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }

            if($account_type_id == 11 || $account_type_id == 12){
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $credits - $debits, 'child_account' => $this->get_data_profit_and_loss_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items)];
            }else{
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $debits - $credits, 'child_account' => $this->get_data_profit_and_loss_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items)];
            }
        }

        return $child_account;
    }

    /**
     * get html profit and loss
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_profit_and_loss($child_account, $data_return, $parent_index, $currency, $flag = false, $level = 1){
        $categoryOutput='';
        if ($flag) {
            for ($i = 0; $i < $level; $i++) {
                $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        $total_amount = 0;
        $data_return['total_amount'] = 0;
        foreach ($child_account as $val) {
            if($flag){
                $html_a_tag = $val['name'];
            }else{
                $html_a_tag = '<a href="'.admin_url('accounting/user_register_view/'.$val['account_id'].'?from_date='.$val['from_date'].'&to_date='.$val['to_date']).'" class="text-default-bl">'.$val['name'].'</a>';
            }

            $data_return['row_index']++;
            $total_amount = $val['amount'];
            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
              <td>
                '.$categoryOutput.$html_a_tag.'
              </td>
              <td class="total_amount">
              '.app_format_money($val['amount'], $currency->name).'
              </td>
            </tr>';

            if(count($val['child_account']) > 0){
                    $level++;
                $t = $data_return['total_amount'];
                $data_return = $this->get_html_custom_summary($val['child_account'], $data_return, $data_return['row_index'], $currency, $flag, $level);

                $total_amount += $data_return['total_amount'];
                
                $data_return['row_index']++;
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                  <td>
                    '.$categoryOutput._l('total_for').' '.$html_a_tag.'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                </tr>';
                $data_return['total_amount'] += $t;
            }

            $data_return['total_amount'] += $val['amount'];
        }
        return $data_return; 
    }

    /**
     * get data statement of cash flows recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  integer $account_detail_type_id 
     * @param  string $from_date       
     * @param  string $to_date   
     * @return array                 
     */
    public function get_data_statement_of_cash_flows_recursive($child_account, $account_id, $account_type_id, $account_detail_type_id, $from_date, $to_date, $acc_show_account_numbers){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        foreach ($accounts as $val) {
            if($val['id'] == 13){
                $this->db->where('(rel_type != "invoice" and rel_type != "expense" and rel_type != "payment")');
            }
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            $this->db->where('account', $val['id']);
            
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $credits = $account_history->credit != '' ? $account_history->credit : 0;
            $debits = $account_history->debit != '' ? $account_history->debit : 0;
            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }


            if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 10 || $account_type_id == 8 || $account_type_id == 7 || $account_type_id == 4 || $account_type_id == 5 || $account_type_id == 6 || $account_type_id == 2 || $account_type_id == 9 || $account_type_id == 1){
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'account_detail_type_id' => $account_detail_type_id, 'name' => $name, 'amount' => $credits - $debits, 'child_account' => $this->get_data_statement_of_cash_flows_recursive([], $val['id'], $account_type_id, $account_detail_type_id, $from_date, $to_date, $acc_show_account_numbers)];
            }else{
                $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'account_detail_type_id' => $account_detail_type_id, 'name' => $name, 'amount' => $debits - $credits, 'child_account' => $this->get_data_statement_of_cash_flows_recursive([], $val['id'], $account_type_id, $account_detail_type_id, $from_date, $to_date, $acc_show_account_numbers)];
            }
        }

        return $child_account;
    }

    /**
     * get html statement of cash flows
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_statement_of_cash_flows($child_account, $data_return, $parent_index, $currency, $flag = false, $level = 1){
        $categoryOutput='';
        if ($flag) {
            for ($i = 0; $i < $level; $i++) {
                $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        $total_amount = 0;
        $data_return['total_amount'] = 0;
        foreach ($child_account as $val) {

            $data_return['row_index']++;
            $total_amount = $val['amount'];
            if($flag){
                $balance_url = $val['name'];

            }else{
                $balance_url = '<a href="'.admin_url('accounting/user_register_view/'.$val['account_id'].'?from_date='.$val['from_date'].'&to_date='.$val['to_date']).'" class="text-default-bl">'.$val['name'].'</a>';
            }


            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
              <td>
            '.$categoryOutput.$balance_url.'
              </td>
              <td class="total_amount">
              '.app_format_money($val['amount'], $currency->name).'
              </td>
            </tr>';

            if(count($val['child_account']) > 0){
                $t = $data_return['total_amount'];
                $data_return = $this->get_html_statement_of_cash_flows($val['child_account'], $data_return, $data_return['row_index'], $currency, $flag, $level);

                $total_amount += $data_return['total_amount'];
                
                $data_return['row_index']++;
                if($flag){
                    $balance_url = $val['name'];

                }else{
                    $balance_url = '<a href="'.admin_url('accounting/rp_account_history?account='.$val['account_id'].'&from_date='.$val['from_date'].'&to_date='.$val['to_date']).'" class="text-default-bl">'.$val['name'].'</a>';
                }

                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                  <td>
                '.$categoryOutput._l('total_for').' '.$balance_url.'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                </tr>';
                $data_return['total_amount'] += $t;
            }

            $data_return['total_amount'] += $val['amount'];
        }
        return $data_return; 
    }

    /**
     * get data statement of changes in equity recursive recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  integer $account_detail_type_id 
     * @param  string $from_date       
     * @param  string $to_date   
     * @param  string $accounting_method   
     * @return array                 
     */
    public function get_data_statement_of_changes_in_equity_recursive($child_account, $account_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        foreach ($accounts as $val) {
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $credits = $account_history->credit != '' ? $account_history->credit : 0;
            $debits = $account_history->debit != '' ? $account_history->debit : 0;
            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }

            
            $child_account[] = ['account_detail_type_id' => $value['id'], 'name' => $name, 'amount' => $credits - $debits, 'child_account' => $this->get_data_statement_of_changes_in_equity_recursive([], $val['id'], $from_date, $to_date, $accounting_method, $acc_show_account_numbers)];
        }

        return $child_account;
    }

    /**
     * get html statement of changes in equity
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_statement_of_changes_in_equity($child_account, $data_return, $parent_index, $currency){
        $total_amount = 0;
        $data_return['total_amount'] = 0;
        foreach ($child_account as $val) {

            $data_return['row_index']++;
            $total_amount = $val['amount'];
            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
              <td>
              '.$val['name'].'
              </td>
              <td class="total_amount">
              '.app_format_money($val['amount'], $currency->name).'
              </td>
            </tr>';

            if(count($val['child_account']) > 0){
                $t = $data_return['total_amount'];
                $data_return = $this->get_html_statement_of_changes_in_equity($val['child_account'], $data_return, $data_return['row_index'], $currency);

                $total_amount += $data_return['total_amount'];
                
                $data_return['row_index']++;
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                  <td>
                  '._l('total_for', $val['name']).'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                </tr>';
                $data_return['total_amount'] += $t;
            }

            $data_return['total_amount'] += $val['amount'];
        }
        return $data_return; 
    }

    /**
     * get data account list recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  array $account_type_name 
     * @param  array $detail_type_name 
     * @return array                 
     */
    public function get_data_account_list_recursive($child_account, $account_id, $account_type_id, $account_type_name, $detail_type_name, $acc_show_account_numbers){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        foreach ($accounts as $val) {
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('account', $val['id']);
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $credits = $account_history->credit != '' ? $account_history->credit : 0;
            $debits = $account_history->debit != '' ? $account_history->debit : 0;
            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }


            $_account_type_name = isset($account_type_name[$val['account_type_id']]) ? $account_type_name[$val['account_type_id']] : '';
            $_detail_type_name = isset($detail_type_name[$val['account_detail_type_id']]) ? $detail_type_name[$val['account_detail_type_id']] : '';

            $child_account[] = ['description' => $val['description'], 'type' => $_account_type_name, 'detail_type' => $_detail_type_name, 'name' => $name, 'amount' => $debits - $credits, 'child_account' => $this->get_data_account_list_recursive([], $val['id'], $account_type_id, $account_type_name, $detail_type_name, $acc_show_account_numbers)];
        }

        return $child_account;
    }

    /**
     * get html account list
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_account_list($child_account, $data_return, $parent_index, $currency, $flag = false, $level = 1){
        $categoryOutput='';
        if ($flag) {
            for ($i = 0; $i < $level; $i++) {
                $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        $total_amount = 0;
        $data_return['total_amount'] = 0;
        foreach ($child_account as $val) {

            $data_return['row_index']++;
            $total_amount = $val['amount'];
            
            $name = '';

            $name .= $val['name'];

            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
              <td>
            '.$categoryOutput.$name.'
              </td>
              <td>
              '.$val['type'].'
              </td>
              <td>
              '.$val['detail_type'].'
              </td>
              <td>
              '.$val['description'].'
              </td>
              <td class="total_amount">
              '.app_format_money($val['amount'], $currency->name).'
              </td>
            </tr>';

            if(count($val['child_account']) > 0){
                $t = $data_return['total_amount'];
                $data_return = $this->get_html_account_list($val['child_account'], $data_return, $data_return['row_index'], $currency);

                $total_amount += $data_return['total_amount'];
                $data_return['row_index']++;
                
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                  <td>
                  '._l('total_for', $val['name']).'
                  </td>
                  <td></td>
                  <td></td>
                  <td></td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                </tr>';
                $data_return['total_amount'] += $t;
            }

            $data_return['total_amount'] += $val['amount'];
        }
        return $data_return; 
    }


    /**
     * get data general ledger recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date   
     * @param  string $accounting_method   
     * @return array                 
     */
    public function get_data_general_ledger_recursive($child_account, $account_id, $account_type_id, $data){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        foreach ($accounts as $val) {
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('(date < "' . $data['from_date'] . '")');
            $this->db->where('account', $val['id']);
            if($data['accounting_method'] == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $_account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $credits = $_account_history->credit != '' ? $_account_history->credit : 0;
            $debits = $_account_history->debit != '' ? $_account_history->debit : 0;

            if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 10 || $account_type_id == 9 || $account_type_id == 8 || $account_type_id == 7 || $account_type_id == 6){
                $beginning_balance = $credits - $debits;
            }else{
                $beginning_balance = $debits - $credits;
            }

            $this->db->where('(date >= "' . $data['from_date'] . '" and date <= "' . $data['to_date'] . '")');
            $this->db->where('account', $val['id']);
            if($data['accounting_method'] == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
            $node = [];
            $balance = $beginning_balance;
            $amount = 0;
            foreach ($account_history as $v) {
                if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 10 || $account_type_id == 9 || $account_type_id == 8 || $account_type_id == 7 || $account_type_id == 6){
                    $am = $v['credit'] - $v['debit'];
                }else{
                    $am = $v['debit'] - $v['credit'];
                }

                $node[] =   [
                    'date' => date('Y-m-d', strtotime($v['date'])),
                    'type' => _l($v['rel_type']),
                    'split_id' => $v['split'] != 0 ? $v['split'] : '',
                    'split' => $v['split'] != 0 ? (isset($account_name[$v['split']]) ? $account_name[$v['split']] : '') : '-Split-',
                    'description' => $v['description'],
                    'number' => $v['number'],
                    'customer' => $v['customer'],
                    'vendor' => $v['vendor'],
                    'debit' => $v['debit'],
                    'credit' => $v['credit'],
                    'amount' => $am,
                    'balance' => $balance + $am,
                    'rel_type' => $v['rel_type'],
                    'rel_id' => $v['rel_id'],
                ];
                
                $amount += $am;
                $balance += $am;
            }

            if($data['acc_show_account_numbers'] == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }

            $_child_account = $this->get_data_general_ledger_recursive([], $val['id'], $account_type_id, $data);

            if($amount != 0 || $_child_account != []){
                $child_account[] = ['from_date' => $data['from_date'], 'to_date' => $data['to_date'], 'account' => $val['id'], 'name' => $name, 'amount' => $amount, 'balance' => $balance, 'details' => $node, 'child_account' => $_child_account, 'beginning_balance' => $beginning_balance];
            }
        }

        return $child_account;
    }

    /**
     * get html general ledger
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_general_ledger($child_account, $data_return, $parent_index, $currency, $flag = false, $level = 1, $show_url = true){

        $categoryOutput='';
        if ($flag) {
            for ($i = 0; $i < $level; $i++) {
                $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        $total_amount = 0;
        $data_return['total_amount'] = 0;
        $balance = 0;
        foreach ($child_account as $value) {
            $amount = 0;
            $data_return['row_index']++;
            $_parent_index = $data_return['row_index'];

            $html_a_tag = $value['name'];
            if(!$flag){
                if($show_url){
                    $html_a_tag = '<a href="'.admin_url('accounting/user_register_view/'.$value['account'].'?from_date='.$value['from_date'].'&to_date='.$value['to_date']).'" class="text-default-bl">'.$value['name'].' ('._l('balance_forward_as_of', _d($value['from_date'])).')</a>';
                }else{

                    $html_a_tag = $value['name'].' ('._l('balance_forward_as_of', _d($value['from_date'])).')';
                }
                
            }

            if(count($value['details']) > 0 || count($value['child_account']) > 0){
                $data_return['html'] .= '<tr class="treegrid-'.$_parent_index.' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' parent-node expanded">
                <td class="parent">'.$categoryOutput.$html_a_tag.'</td>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td class="total_amount">'.app_format_money($value['beginning_balance'], $currency->name).'</td>
                </tr>';
            }
            
            foreach ($value['details'] as $val) {

                $data_return['row_index']++;
                $amount += $val['amount'];
                $balance = $val['balance'];
                $a_tag = _d($val['date']);
                $url = get_url_by_type_id($val['rel_type'], $val['rel_id']);
                $split = $val['split'];
                if(!$flag){
                    if($show_url){
                        $a_tag = '<a href="'.$url.'" class="text-default-bl">'._d($val['date']).'</a>';
                        $split = '<a href="'.admin_url('accounting/user_register_view/'.$val['split_id']).'" class="text-default-bl">'.$val['split'].'</a>';
                    }else{
                        $a_tag = _d($val['date']);
                    }
                }
                $val['name'] = '';
                if($val['customer'] != 0){
                    $val['name'] = get_company_name($val['customer']);
                }elseif ($val['vendor'] != 0) {
                    $val['name'] = acc_get_vendor_name($val['vendor']);
                }
                $number = $val['number'];
                if($val['rel_type'] == 'check'){
                    $number = str_pad($val['number'], 4, '0', STR_PAD_LEFT);
                }

                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' treegrid-parent-'.$_parent_index.'">
                <td>
                '. $categoryOutput.'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'.$a_tag.'
                </td>
                <td>
                '. new_html_entity_decode($number).' 
                </td>
                <td>
                '. new_html_entity_decode($val['type']).' 
                </td>
                <td>
                '. new_html_entity_decode($val['name']).' 
                </td>
                <td>
                '. new_html_entity_decode($val['description']).' 
                </td>
                <td>
                '. new_html_entity_decode($split).'
                </td>
                <td class="total_amount">
                '. app_format_money($val['amount'], $currency->name).' 
                </td>
                <td class="total_amount">
                '. app_format_money($val['balance'], $currency->name).' 
                </td>
                </tr>';
            }
            $total_amount = $amount;
            $data_return['row_index']++;
            $t = 0;
            if(count($value['child_account']) > 0){
                $level++;
                $t = $data_return['total_amount'];
                $data_return = $this->get_html_general_ledger($value['child_account'], $data_return, $_parent_index, $currency, $flag, $level, $show_url);
                $total_amount += $data_return['total_amount'];
            }

            if(count($value['details']) > 0 || count($value['child_account']) > 0){
                $data_return['row_index']++;
                $data_return['html'] .= '
                <tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                <td style="'.report_pdf_border_top().'">'.$categoryOutput._l('total_for').' '. $html_a_tag.'</td>
                <td style="'.report_pdf_border_top().'"></td>
                <td style="'.report_pdf_border_top().'"></td>
                <td style="'.report_pdf_border_top().'"></td>
                <td style="'.report_pdf_border_top().'"></td>
                <td style="'.report_pdf_border_top().'"></td>
                <td class="total_amount" style="'.report_pdf_border_top().'">
                '.app_format_money($total_amount, $currency->name).'
                </td>
                <td class="total_amount" style="'.report_pdf_border_top().'">'.app_format_money($balance, $currency->name).'</td>
                </tr>';
                $data_return['total_amount'] += $t;
            }

            $data_return['total_amount'] += $amount;
        }
        return $data_return; 
    }
    
    /**
     * get data trial balance recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date   
     * @param  string $accounting_method   
     * @return array                 
     */
    public function get_data_trial_balance_recursive($child_account, $account_id, $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        foreach ($accounts as $val) {

            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $credits = $account_history->credit != '' ? $account_history->credit : 0;
            $debits = $account_history->debit != '' ? $account_history->debit : 0;
            if($credits > $debits){
                $credits = $credits - $debits;
                $debits = 0;
            }else{
                $debits = $debits - $credits;
                $credits = 0;
            }
            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }

            $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'debit' => $debits, 'credit' => $credits, 'child_account' => $this->get_data_trial_balance_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers)];
        }

        return $child_account;
    }
    
    /**
     * get html trial balance
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_trial_balance($child_account, $data_return, $parent_index, $currency, $flag = false, $level = 1, $show_url = true){
        $categoryOutput='';
        if ($flag) {
            for ($i = 0; $i < $level; $i++) {
                $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        $total_debit = 0;
        $total_credit = 0;
        $data_return['total_debit'] = 0;
        $data_return['total_credit'] = 0;
        foreach ($child_account as $val) {
            $data_return['row_index']++;
            $total_debit = $val['debit'];
            $total_credit = $val['credit'];

            $html_a_tag = $val['name'];
            if(!$flag){
                if($show_url){
                    $html_a_tag = '<a href="'.admin_url('accounting/user_register_view/'.$val['account_id'].'?from_date='.$val['from_date'].'&to_date='.$val['to_date']).'" class="text-default-bl">'.$val['name'].'</a>';
                }else{
                    $html_a_tag = $val['name'];
                }
            }

            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
              <td>
            '.$categoryOutput.$html_a_tag.'
              </td>
              <td class="total_amount">
              '.app_format_money($val['debit'], $currency->name).'
              </td>
              <td class="total_amount">
              '.app_format_money($val['credit'], $currency->name).'
              </td>
            </tr>';

            if(count($val['child_account']) > 0){
                $d = $data_return['total_debit'];
                $c = $data_return['total_credit'];
                $data_return = $this->get_html_trial_balance($val['child_account'], $data_return, $data_return['row_index'], $currency, $flag, $level, $show_url);

                $total_debit += $data_return['total_debit'];
                $total_credit += $data_return['total_credit'];
                
                $data_return['row_index']++;
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                  <td>
                '.$categoryOutput._l('total_for').' '.$html_a_tag.'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_debit, $currency->name).'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_credit, $currency->name).'
                  </td>
                </tr>';
                $data_return['total_debit'] += $d;
                $data_return['total_credit'] += $c;
            }

            $data_return['total_debit'] += $val['debit'];
            $data_return['total_credit'] += $val['credit'];
        }
        return $data_return; 
    }

    /**
     * get data transaction detail by account recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date   
     * @param  string $accounting_method   
     * @return array                 
     */
    public function get_data_transaction_detail_by_account_recursive($child_account, $account_id, $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        foreach ($accounts as $val) {
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->order_by('date', 'asc');
            $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
            $node = [];
            $balance = 0;
            $amount = 0;
            foreach ($account_history as $v) {
                if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 10 || $account_type_id == 9 || $account_type_id == 8 || $account_type_id == 7 || $account_type_id == 6){
                    $am = $v['credit'] - $v['debit'];
                }else{
                    $am = $v['debit'] - $v['credit'];
                }
                $node[] =   [
                                'date' => date('Y-m-d', strtotime($v['date'])),
                                'type' => _l($v['rel_type']),
                                'description' => $v['description'],
                                'customer' => $v['customer'],
                                'split' => $v['split'] != 0 ? (isset($account_name[$v['split']]) ? $account_name[$v['split']] : '') : '-Split-',
                                'debit' => $v['debit'],
                                'credit' => $v['credit'],
                                'amount' => $am,
                                'balance' => $balance + ($am),
                                'rel_type' => $v['rel_type'],
                                'rel_id' => $v['rel_id'],
                            ];
                $amount += $am;
                $balance += $am;
            }

            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }


            $child_account[] = ['from_date' => $from_date, 'to_date' => $to_date, 'account' => $val['id'], 'name' => $name, 'amount' => $amount, 'balance' => $balance, 'details' => $node, 'child_account' => $this->get_data_transaction_detail_by_account_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers)];
        }

        return $child_account;
    }
    
    /**
     * get html transaction detail by account
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_transaction_detail_by_account($child_account, $data_return, $parent_index, $currency, $flag = false, $level = 1){
        $categoryOutput='';
        if ($flag) {
            for ($i = 0; $i < $level; $i++) {
                $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        $total_amount = 0;
        $data_return['total_amount'] = 0;
        foreach ($child_account as $value) {
            $amount = 0;
            $data_return['row_index']++;
            $_parent_index = $data_return['row_index'];
            $html_a_tag = $value['name'];
            if(!$flag){
                $html_a_tag = '<a href="'.admin_url('accounting/rp_account_history?account='.$value['account'].'&from_date='.$value['from_date'].'&to_date='.$value['to_date']).'" class="text-default-bl">'.$value['name'].'</a>';
                
            }

            if(count($value['details']) > 0 || count($value['child_account']) > 0){
                $data_return['html'] .= '<tr class="treegrid-'.$_parent_index.' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' parent-node expanded">
                    <td class="parent">'.$categoryOutput.$html_a_tag.'</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>';
            }
            
            foreach ($value['details'] as $val) { 
            $data_return['row_index']++;
                $amount += $val['amount'];
                $a_tag = _d($val['date']);
                $url = get_url_by_type_id($val['rel_type'], $val['rel_id']);
                if(!$flag){
                    $a_tag = '<a href="'.$url.'" class="text-default-bl">'._d($val['date']).'</a>';
                }

                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' treegrid-parent-'.$_parent_index.'">
                  <td>
                '. $categoryOutput.'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'.$a_tag.'
                  </td>
                  <td>
                  '. new_html_entity_decode($val['type']).' 
                  </td>
                  <td>
                  '. get_company_name($val['customer']).' 
                  </td>
                  <td>
                  '. new_html_entity_decode($val['description']).' 
                  </td>
                  <td>
                  '. new_html_entity_decode($val['split']).' 
                  </td>
                  <td class="total_amount">
                  '. app_format_money($val['amount'], $currency->name).' 
                  </td>
                  <td class="total_amount">
                  '. app_format_money($val['balance'], $currency->name).' 
                  </td>
                </tr>';
               }
            $total_amount = $amount;
            $data_return['row_index']++;
           
            if(count($value['child_account']) > 0){
                $level++;
                $t = $data_return['total_amount'];
                $data_return = $this->get_html_transaction_detail_by_account($value['child_account'], $data_return, $_parent_index, $currency, $flag, $level);
                $total_amount += $data_return['total_amount'];
                
                $data_return['row_index']++;
                $data_return['html'] .= '
                  <tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                      <td>
                    '.$categoryOutput._l('total_for').' '.$html_a_tag.'
                      </td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                    <td></td>
                </tr>';
                $data_return['total_amount'] += $t;
            }

            $data_return['total_amount'] += $amount;
        }
        return $data_return; 
    }

    /**
     * get data deposit detail recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date   
     * @return array                 
     */
    public function get_data_deposit_detail_recursive($child_account, $account_id, $account_type_id, $from_date, $to_date, $acc_show_account_numbers){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        foreach ($accounts as $val) {

            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            $this->db->where('account', $val['id']);
            $this->db->where('((rel_type = "payment" and debit > 0) or (rel_type = "deposit"  and credit > 0))');
            $this->db->order_by('date', 'asc');
            $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
            $node = [];
            $balance = 0;
            $amount = 0;
            foreach ($account_history as $v) {
                if($account_type_id == 10 || $account_type_id == 9 || $account_type_id == 8 || $account_type_id == 7){
                    $amount += $v['credit'] - $v['debit'];
                    $am = ($v['credit'] - $v['debit']);
                }else{
                    $amount += $v['debit'] - $v['credit'];
                    $am = ($v['debit'] - $v['credit']);
                }

                $node[] =   [
                                'date' => date('Y-m-d', strtotime($v['date'])),
                                'type' => _l($v['rel_type']),
                                'description' => $v['description'],
                                'customer' => $v['customer'],
                                'debit' => $v['debit'],
                                'credit' => $v['credit'],
                                'amount' =>  $am,
                                'rel_type' => $v['rel_type'],
                                'rel_id' => $v['rel_id'],
                            ];
            }

            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }

            $child_account[] = ['account' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $amount, 'details' => $node, 'child_account' => $this->get_data_deposit_detail_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $acc_show_account_numbers)];
            
        }

        return $child_account;
    }

    /**
     * get html transaction detail by account
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_deposit_detail($child_account, $data_return, $parent_index, $currency, $flag = false, $level = 1){
        $categoryOutput='';
        if ($flag) {
            for ($i = 0; $i < $level; $i++) {
                $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        $total_amount = 0;
        $data_return['total_amount'] = 0;
        foreach ($child_account as $value) {
            $amount = 0;
            $data_return['row_index']++;
            $_parent_index = $data_return['row_index'];
            $html_a_tag = $value['name'];
            if(!$flag){
                $html_a_tag = '<a href="'.admin_url('accounting/rp_account_history?account='.$value['account'].'&from_date='.$value['from_date'].'&to_date='.$value['to_date']).'" class="text-default-bl">'.$value['name'].'</a>';
                $account_type_id = get_account_type_id($value['account']);
                if(!in_array($account_type_id, [2,3,4,5,7,8,9,10,16,20,21,22,23,24,25,26])){
                    $html_a_tag = $value['name'];
                }
            }

            if(count($value['details']) > 0 || count($value['child_account']) > 0){
                $data_return['html'] .= '<tr class="treegrid-'.$_parent_index.' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' parent-node expanded">
                    <td class="parent">'.$categoryOutput.$html_a_tag.'</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>';
            }
            
            foreach ($value['details'] as $val) { 
            $data_return['row_index']++;
                $amount += $val['amount'];
                $a_tag = _d($val['date']);

                $url = get_url_by_type_id($val['rel_type'], $val['rel_id']);
                if(!$flag){
                    $a_tag = '<a href="'.$url.'" class="text-default-bl">'._d($val['date']).'</a>';
                }
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' treegrid-parent-'.$_parent_index.'">
                  <td>
                '. $categoryOutput.'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'.$a_tag.'
                  </td>
                  <td>
                  '. new_html_entity_decode($val['type']).' 
                  </td>
                  <td>
                  '. get_company_name($val['customer']).' 
                  </td>
                  <td>
                  '. new_html_entity_decode($val['description']).' 
                  </td>
                  <td class="total_amount">
                  '. app_format_money($val['amount'], $currency->name).' 
                  </td>
                </tr>';
               }
            $total_amount = $amount;
            $data_return['row_index']++;
           
            if(count($value['child_account']) > 0){
                $level++;
                $t = $data_return['total_amount'];
                $data_return = $this->get_html_deposit_detail($value['child_account'], $data_return, $_parent_index, $currency, $flag, $level);
                $total_amount += $data_return['total_amount'];
                
                $data_return['row_index']++;
                $data_return['html'] .= '
                  <tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                      <td>
                '.$categoryOutput._l('total_for').' '.$html_a_tag.'
                      </td>
                    <td></td>
                    <td></td>
                    <td></td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                </tr>';
                $data_return['total_amount'] += $t;
            }

            $data_return['total_amount'] += $amount;
        }
        return $data_return; 
    }
    

    /**
     * add new account type detail
     * @param array $data
     * @return integer
     */
    public function add_account_type_detail($data)
    {
        if (isset($data['id'])) {
            unset($data['id']);
        }

        $this->db->insert(db_prefix() . 'acc_account_type_details', $data);

        $insert_id = $this->db->insert_id();

        if ($insert_id) {
            return true;
        }

        return false;
    }

    /**
     * update account type detail
     * @param array $data
     * @param integer $id
     * @return integer
     */
    public function update_account_type_detail($data, $id)
    {
        if (isset($data['id'])) {
            unset($data['id']);
        }

        $this->db->where('id', $id);
        $this->db->update(db_prefix() . 'acc_account_type_details', $data);

        if ($this->db->affected_rows() > 0) {
            return true;
        }

        return false;
    }

    /**
     * delete account type detail
     * @param integer $id
     * @return boolean
     */

    public function delete_account_type_detail($id)
    {
        $this->db->where('account_detail_type_id',$id);
        $count = $this->db->count_all_results(db_prefix() . 'acc_accounts');
        if($count > 0){
            return 'have_account';
        }

        $this->db->where('id', $id);
        $this->db->delete(db_prefix() . 'acc_account_type_details');
        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }

    /**
     * get account type details
     * @param  integer $id    member group id
     * @param  array  $where
     * @return object
     */
    public function get_data_account_type_details($id = '', $where = [])
    {
        if (is_numeric($id)) {
            $this->db->where('id', $id);
            return $this->db->get(db_prefix() . 'acc_account_type_details')->row();
        }

        $this->db->where($where);
        $this->db->order_by('account_type_id', 'desc');
        $account_type_details = $this->db->get(db_prefix() . 'acc_account_type_details')->result_array();

        $account_types = $this->get_account_types();

        $account_type_name = [];

        foreach ($account_types as $key => $value) {
            $account_type_name[$value['id']] = $value['name'];
        }

        foreach ($account_type_details as $key => $value) {
            $_account_type_name = isset($account_type_name[$value['account_type_id']]) ? $account_type_name[$value['account_type_id']] : '';
            $account_type_details[$key]['account_type_name'] = $_account_type_name;
        }

        return $account_type_details;
    }

    /**
     * Change preferred payment method status / on / off
     * @param  mixed $id     staff id
     * @param  mixed $status status(0/1)
     */
    public function change_preferred_payment_method($id, $status)
    {
        $this->db->where('id', $id);
        $this->db->update(db_prefix() . 'acc_expense_category_mappings', [
            'preferred_payment_method' => $status,
        ]);
    }

    /**
     * count stock import not convert yet
     * @param  integer $currency
     * @param  string $where
     * @return object          
     */
    public function count_stock_import_not_convert_yet($currency = '', $where = ''){
        $where_currency = '';
        if($currency != ''){
            $where_currency = 'and currency = '.$currency;
        }

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'goods_receipt.id and ' . db_prefix() . 'acc_account_history.rel_type = "stock_import") = 0) and approval = 1 '.$where_currency);
        return $this->db->count_all_results(db_prefix().'goods_receipt');
    }

    /**
     * count stock export not convert yet
     * @param  integer $currency
     * @param  string $where
     * @return object          
     */
    public function count_stock_export_not_convert_yet($currency = '', $where = ''){
        $where_currency = '';
        if($currency != ''){
            $where_currency = 'and currency = '.$currency;
        }

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'goods_delivery.id and ' . db_prefix() . 'acc_account_history.rel_type = "stock_export") = 0) and approval = 1 '.$where_currency);
        return $this->db->count_all_results(db_prefix().'goods_delivery');
    }

    /**
     * count loss adjustment not convert yet
     * @param  integer $currency
     * @param  string $where
     * @return object          
     */
    public function count_loss_adjustment_not_convert_yet($currency = '', $where = ''){
        $where_currency = '';
        if($currency != ''){
            $where_currency = 'and currency = '.$currency;
        }

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'wh_loss_adjustment.id and ' . db_prefix() . 'acc_account_history.rel_type = "loss_adjustment") = 0) and status = 1 '.$where_currency);
        return $this->db->count_all_results(db_prefix().'wh_loss_adjustment');
    }

    /**
     * count opening stock not convert yet
     * @param  integer $currency
     * @param  string $where
     * @return object          
     */
    public function count_opening_stock_not_convert_yet($currency = '', $where = ''){
        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $date_financial_year = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.date('Y')));

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'items.id and ' . db_prefix() . 'acc_account_history.rel_type = "opening_stock" and date = "'.$date_financial_year.'") = 0)');
        return $this->db->count_all_results(db_prefix().'items');
    }

    /**
     * update payslip automatic conversion
     *
     * @param      array   $data   The data
     *
     * @return     boolean 
     */
    public function update_payslip_automatic_conversion($data){
        $affectedRows = 0;
        
        if(!isset($data['acc_pl_total_insurance_automatic_conversion'])){
            $data['acc_pl_total_insurance_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_pl_tax_paye_automatic_conversion'])){
            $data['acc_pl_tax_paye_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_pl_net_pay_automatic_conversion'])){
            $data['acc_pl_net_pay_automatic_conversion'] = 0;
        }

        foreach ($data as $key => $value) {
            $this->db->where('name', $key);
            $this->db->update(db_prefix() . 'options', [
                    'value' => $value,
                ]);
            if ($this->db->affected_rows() > 0) {
                $affectedRows++;
            }
        }

        if ($affectedRows > 0) {
            return true;
        }
        return false;
    }

    /**
     * get opening stock data tables
     * @param  array $aColumns           table columns
     * @param  mixed $sIndexColumn       main column in table for bettter performing
     * @param  string $sTable            table name
     * @param  array  $join              join other tables
     * @param  array  $where             perform where in query
     * @param  array  $additionalSelect  select additional fields
     * @param  string $sGroupBy group results
     * @return array
     */
    function get_opening_stock_data_tables($aColumns, $sIndexColumn, $sTable, $join = [], $where = [], $additionalSelect = [], $sGroupBy = '', $searchAs = [])
    {
        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $date_financial_year = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.date('Y')));

        $CI          = & get_instance();
        $__post      = $CI->input->post();
        $where = implode(' ', $where);
        $where = trim($where);
        if (startsWith($where, 'AND') || startsWith($where, 'OR')) {
            if (startsWith($where, 'OR')) {
                $where = substr($where, 2);
            } else {
                $where = substr($where, 3);
            }

            $this->db->where($where);
        }
        
        $this->db->select('*, (select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'items.id and ' . db_prefix() . 'acc_account_history.rel_type = "opening_stock" and ' . db_prefix() . 'acc_account_history.date >= "'.$date_financial_year.'") as count_account_historys');
        $this->db->limit(intval($CI->input->post('length')), intval($CI->input->post('start')));
        $this->db->order_by('id', 'desc');

        $items = $this->db->get(db_prefix().'items')->result_array();

        $rResult = [];

        foreach ($items as $key => $value) {
            $value['opening_stock'] = $this->calculate_opening_stock($value['id'], $date_financial_year);
            $rResult[] = $value;
        }

        /* Data set length after filtering */
        $sQuery = '
        SELECT FOUND_ROWS()
        ';
        $_query         = $CI->db->query($sQuery)->result_array();
        $iFilteredTotal = $_query[0]['FOUND_ROWS()'];
        
        /* Total data set length */
        $sQuery = '
        SELECT COUNT(' . $sTable . '.' . $sIndexColumn . ")
        FROM $sTable " . ($where != '' ? 'WHERE '.$where : $where);
        $_query = $CI->db->query($sQuery)->result_array();

        $iTotal = $_query[0]['COUNT(' . $sTable . '.' . $sIndexColumn . ')'];
        /*
         * Output
         */
        $output = [
            'draw'                 => $__post['draw'] ? intval($__post['draw']) : 0,
            'iTotalRecords'        => $iTotal,
            'iTotalDisplayRecords' => $iTotal,
            'aaData'               => [],
            ];

        return [
            'rResult' => $rResult,
            'output'  => $output,
            ];
    }

    /**
     * get opening stock data
     * @param  integer $item_id 
     * @return object         
     */
    public function get_opening_stock_data($item_id){
        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $date_financial_year = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.date('Y')));

        $this->db->where('id' ,$item_id);
        $item = $this->db->get(db_prefix().'items')->row();

        $item->opening_stock = $this->calculate_opening_stock($item_id, $date_financial_year);

        return $item;
    }

    /**
     * update warehouse automatic conversion
     *
     * @param      array   $data   The data
     *
     * @return     boolean 
     */
    public function update_warehouse_automatic_conversion($data){
        $affectedRows = 0;
        if(!isset($data['acc_wh_stock_import_automatic_conversion'])){
            $data['acc_wh_stock_import_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_wh_stock_import_return_automatic_conversion'])){
            $data['acc_wh_stock_import_return_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_wh_stock_export_automatic_conversion'])){
            $data['acc_wh_stock_export_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_wh_stock_export_profit_automatic_conversion'])){
            $data['acc_wh_stock_export_profit_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_wh_loss_adjustment_automatic_conversion'])){
            $data['acc_wh_loss_adjustment_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_wh_opening_stock_automatic_conversion'])){
            $data['acc_wh_opening_stock_automatic_conversion'] = 0;
        }

        foreach ($data as $key => $value) {
            $this->db->where('name', $key);
            $this->db->update(db_prefix() . 'options', [
                    'value' => $value,
                ]);
            if ($this->db->affected_rows() > 0) {
                $affectedRows++;
            }
        }

        if ($affectedRows > 0) {
            return true;
        }
        return false;
    }

    /**
     * Automatic payslip conversion
     * @param  integer $payslip_id 
     * @return boolean
     */
    public function automatic_payslip_conversion($payslips_id){
        $this->db->where('rel_id', $payslips_id);
        $this->db->where('rel_type', 'payslip');
        $count = $this->db->count_all_results(db_prefix() . 'acc_account_history');

        if($count > 0){
            return false;
        }

        $this->db->where('id', $payslips_id);
        $payslip = $this->db->get(db_prefix(). 'hrp_payslips')->row();

        $this->db->where('payslip_id', $payslips_id);
        $payslip_details = $this->db->get(db_prefix(). 'hrp_payslip_details')->result_array();

        $insurance_payment_account = get_option('acc_pl_total_insurance_payment_account');
        $insurance_deposit_to = get_option('acc_pl_total_insurance_deposit_to');

        $tax_paye_payment_account = get_option('acc_pl_tax_paye_payment_account');
        $tax_paye_deposit_to = get_option('acc_pl_tax_paye_deposit_to');

        $net_pay_payment_account = get_option('acc_pl_net_pay_payment_account');
        $net_pay_deposit_to = get_option('acc_pl_net_pay_deposit_to');

        $affectedRows = 0;

        if($payslip){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($payslip->payslip_month) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }

            $this->load->model('currencies_model');
            $currency = $this->currencies_model->get_base_currency();

            $total_insurance = 0;
            $net_pay = 0;
            $income_tax_paye = 0;
            foreach ($payslip_details as $key => $value) {
                if(is_numeric($value['total_insurance'])){
                    $total_insurance += $value['total_insurance'];
                }

                if(is_numeric($value['net_pay'])){
                    $net_pay += $value['net_pay'];
                }

                if(is_numeric($value['income_tax_paye'])){
                    $income_tax_paye += $value['income_tax_paye'];
                }
            }

            $data_insert = [];

            if(get_option('acc_pl_total_insurance_automatic_conversion') == 1){
                $node = [];
                $node['split'] = $insurance_payment_account;
                $node['account'] = $insurance_deposit_to;
                $node['date'] = $payslip->payslip_month;
                $node['debit'] = $total_insurance;
                $node['credit'] = 0;
                $node['description'] = '';
                $node['rel_id'] = $payslips_id;
                $node['rel_type'] = 'payslip';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $insurance_deposit_to;
                $node['account'] = $insurance_payment_account;
                $node['date'] = $payslip->payslip_month;
                $node['debit'] = 0;
                $node['credit'] = $total_insurance;
                $node['description'] = '';
                $node['rel_id'] = $payslips_id;
                $node['rel_type'] = 'payslip';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;
            }

            if(get_option('acc_pl_tax_paye_automatic_conversion') == 1){
                $node = [];
                $node['split'] = $tax_paye_payment_account;
                $node['account'] = $tax_paye_deposit_to;
                $node['date'] = $payslip->payslip_month;
                $node['debit'] = $income_tax_paye;
                $node['credit'] = 0;
                $node['description'] = '';
                $node['rel_id'] = $payslips_id;
                $node['rel_type'] = 'payslip';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $tax_paye_deposit_to;
                $node['account'] = $tax_paye_payment_account;
                $node['date'] = $payslip->payslip_month;
                $node['debit'] = 0;
                $node['credit'] = $income_tax_paye;
                $node['description'] = '';
                $node['rel_id'] = $payslips_id;
                $node['rel_type'] = 'payslip';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;
            }

            if(get_option('acc_pl_net_pay_automatic_conversion') == 1){
                $node = [];
                $node['split'] = $net_pay_payment_account;
                $node['account'] = $net_pay_deposit_to;
                $node['date'] = $payslip->payslip_month;
                $node['debit'] = $net_pay;
                $node['credit'] = 0;
                $node['description'] = '';
                $node['rel_id'] = $payslips_id;
                $node['rel_type'] = 'payslip';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $net_pay_deposit_to;
                $node['account'] = $net_pay_payment_account;
                $node['date'] = $payslip->payslip_month;
                $node['debit'] = 0;
                $node['credit'] = $net_pay;
                $node['description'] = '';
                $node['rel_id'] = $payslips_id;
                $node['rel_type'] = 'payslip';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;
            }

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Automatic purchase order conversion
     * @param  integer $purchase_order_id 
     * @return boolean
     */
    public function automatic_purchase_order_conversion($purchase_order_id){

        $this->delete_convert($purchase_order_id, 'purchase_order');

        $affectedRows = 0;


        $this->load->model('purchase/purchase_model');
        $purchase_order = $this->purchase_model->get_pur_order($purchase_order_id);

        if($purchase_order->approve_status != 2){
            return false;
        }

        $purchase_order_detail = $this->purchase_model->get_pur_order_detail($purchase_order_id);

        $base_currency = get_base_currency_pur();
        if($purchase_order->currency != 0){
            $base_currency = pur_get_currency_by_id($purchase_order->currency);
        }

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $payment_account = get_option('acc_pur_order_payment_account');
        $deposit_to = get_option('acc_pur_order_deposit_to');
        $tax_payment_account = get_option('acc_pur_tax_payment_account');
        $tax_deposit_to = get_option('acc_pur_tax_deposit_to');

        $item_discount = 0;
        foreach($purchase_order_detail as $row){
            $item_discount += $row['discount_money'];
        }

        if($purchase_order){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($purchase_order->order_date) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }
            
            $data_insert = [];


            foreach ($purchase_order_detail as $value) {

                $item = get_item_hp($value['item_code']);

                $item_id = 0;
                if(isset($item->id)){
                    $item_id = $item->id;
                }

                $currency_rate = 0;
                $item_total = $value['into_money'];
                if($base_currency->name != $currency->name){
                    $currency_rate = $purchase_order->currency_rate;
                    $item_total = round(($value['into_money'] / $currency_rate), 2);
                }

                $item_automatic = $this->get_item_automatic($item_id);

                if($item_automatic){
                    $node = [];
                    $node['split'] = $payment_account;
                    $node['account'] = $item_automatic->expense_account;
                    $node['item'] = $item_id;
                    $node['date'] = $purchase_order->order_date;
                    $node['debit'] = $item_total;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $purchase_order_id;
                    $node['rel_type'] = 'purchase_order';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $item_automatic->expense_account;
                    $node['account'] = $payment_account;
                    $node['item'] = $item_id;
                    $node['date'] = $purchase_order->order_date;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $purchase_order_id;
                    $node['rel_type'] = 'purchase_order';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }else{
                    $node = [];
                    $node['split'] = $payment_account;
                    $node['account'] = $deposit_to;
                    $node['item'] = $item_id;
                    $node['debit'] = $item_total;
                    $node['date'] = $purchase_order->order_date;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $purchase_order_id;
                    $node['rel_type'] = 'purchase_order';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $deposit_to;
                    $node['account'] = $payment_account;
                    $node['item'] = $item_id;
                    $node['date'] = $purchase_order->order_date;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $purchase_order_id;
                    $node['rel_type'] = 'purchase_order';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }

                if(get_option('acc_tax_automatic_conversion') == 1 && $value['tax'] > 0){
                    $tax_payment_account = get_option('acc_pur_tax_payment_account');
                    $tax_deposit_to = get_option('acc_pur_tax_deposit_to');

                    

                    if($purchase_order->discount_type == 'before_tax'){

                        $total_tax = 0;
                        if($value['tax'] != ''){
                            $tax_arr = explode('|', $value['tax']);

                            $tax_rate_arr = [];
                            if($value['tax_rate'] != ''){
                                $tax_rate_arr = explode('|', $value['tax_rate']);
                            }

                            foreach($tax_arr as $k => $tax_it){
                                if(!isset($tax_rate_arr[$k]) ){
                                    $tax_rate_arr[$k] = $this->purchase_model->tax_rate_by_id($tax_it);
                                }

                                $total_tax += $tax_rate_arr[$k]*$value['into_money']/100;
                            }
                        }

                        $total_discount = $item_discount + $purchase_order->discount_total;

                        $t     = ($total_discount / $purchase_order->subtotal) * 100;
                        $total_tax = ($total_tax - $total_tax * $t / 100);

                    }else{
                        $total_tax = ($value['total'] - $value['into_money']);
                        
                    }

                    if($base_currency->name != $currency->name){
                        $currency_rate = $purchase_order->currency_rate;

                        $total_tax = round(($total_tax / $currency_rate), 2);
                    }

                    $tax_mapping = $this->get_tax_mapping($value['tax']);

                    if($tax_mapping){
                        $node = [];
                        $node['split'] = $tax_mapping->purchase_payment_account;
                        $node['account'] = $tax_mapping->purchase_deposit_to;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $purchase_order->order_date;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $purchase_order_id;
                        $node['rel_type'] = 'purchase_order';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_mapping->purchase_deposit_to;
                        $node['account'] = $tax_mapping->purchase_payment_account;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $purchase_order->order_date;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $purchase_order_id;
                        $node['rel_type'] = 'purchase_order';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;
                    }else{
                        $node = [];
                        $node['split'] = $tax_payment_account;
                        $node['account'] = $tax_deposit_to;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $purchase_order->order_date;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $purchase_order_id;
                        $node['rel_type'] = 'purchase_order';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_deposit_to;
                        $node['date'] = $purchase_order->order_date;
                        $node['account'] = $tax_payment_account;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $purchase_order_id;
                        $node['rel_type'] = 'purchase_order';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;
                    }
                }
            }

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Automatic stock import conversion
     * @param  integer $stock_import_id 
     * @return boolean
     */
    public function automatic_stock_import_conversion($stock_import_id){
        if(get_option('acc_wh_stock_import_automatic_conversion') == 0){
            return false;
        }

        $this->delete_convert($stock_import_id, 'stock_import');

        $affectedRows = 0;

        $this->load->model('warehouse/warehouse_model');
        $goods_receipt = $this->warehouse_model->get_goods_receipt($stock_import_id);
        if (!$goods_receipt || $goods_receipt->approval != 1) {
            return false;
        }
        $goods_receipt_detail = $this->warehouse_model->get_goods_receipt_detail($stock_import_id);

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $payment_account = get_option('acc_wh_stock_import_payment_account');
        $deposit_to = get_option('acc_wh_stock_import_deposit_to');

        $tax_payment_account = get_option('acc_expense_tax_payment_account');
        $tax_deposit_to = get_option('acc_expense_tax_deposit_to');

        if($goods_receipt){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($goods_receipt->date_c) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }

            $check_return_order = false;
            $item_price_arr = [];

            if(get_option('acc_wh_stock_import_return_automatic_conversion') == 1){
                $check_return_order = $this->check_return_order($goods_receipt->id);
                if($check_return_order){

                    $payment_account = get_option('acc_wh_stock_import_return_payment_account');
                    $deposit_to = get_option('acc_wh_stock_import_return_deposit_to');

                    $goods_delivery_detail = $this->warehouse_model->get_goods_delivery_detail($check_return_order);

                    foreach ($goods_delivery_detail as $value) {
                        $goods_transaction_detail = $this->accounting_model->get_goods_transaction_detail($value['id']);
                        if($goods_transaction_detail){
                            $item_price = $goods_transaction_detail->purchase_price;
                        }else{
                            if($item_id != 0){
                                $this->db->where('id', $value['commodity_code']);
                                $item = $this->db->get(db_prefix().'items')->row();

                                $item_price = $item->purchase_price;
                            }else{
                                $item_price = $value['unit_price'];
                            }
                        }

                        $item_price_arr[$value['commodity_code']] = $item_price;
                    }

                }
            }
            
            $data_insert = [];
            
            $currency_rate = 1;

            if($goods_receipt->pr_order_id != 0 && $goods_receipt->currency != 0 && $goods_receipt->currency != $currency->id && (float)($goods_receipt->currency_exchange_rate) != 0){
                $currency_rate = $goods_receipt->currency_exchange_rate; 
            }

            foreach ($goods_receipt_detail as $value) {

                $this->db->where('id', $value['commodity_code']);
                $item = $this->db->get(db_prefix().'items')->row();

                $item_id = 0;
                if(isset($item->id)){
                    $item_id = $item->id;
                }

                if($check_return_order && isset($item_price_arr[$item_id])){
                    $item_total = $item_price_arr[$item_id] * $value['quantities'];
                }else{
                    $item_total = round($value['sub_total'] / $currency_rate, 2);
                }

                $item_automatic = $this->get_item_automatic($item_id);

                if($item_automatic && !$check_return_order){
                    $deposit_to = $item_automatic->inventory_asset_account;
                }
                
                $node = [];
                $node['split'] = $payment_account;
                $node['account'] = $deposit_to;
                $node['item'] = $item_id;
                $node['debit'] = $item_total;
                $node['date'] = $goods_receipt->date_c;
                $node['tax'] = 0;
                $node['credit'] = 0;
                $node['description'] = '';
                $node['rel_id'] = $stock_import_id;
                $node['rel_type'] = 'stock_import';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $deposit_to;
                $node['account'] = $payment_account;
                $node['item'] = $item_id;
                $node['date'] = $goods_receipt->date_c;
                $node['tax'] = 0;
                $node['debit'] = 0;
                $node['credit'] = $item_total;
                $node['description'] = '';
                $node['rel_id'] = $stock_import_id;
                $node['rel_type'] = 'stock_import';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;
                

                if(get_option('acc_tax_automatic_conversion') == 1 && $value['tax'] > 0){
                    $tax_payment_account = get_option('acc_expense_tax_payment_account');
                    $tax_deposit_to = get_option('acc_expense_tax_deposit_to');

                    $total_tax = round($value['tax_money'] / $currency_rate, 2);

                    $tax_mapping = $this->get_tax_mapping($value['tax']);

                    if($tax_mapping){
                        $node = [];
                        $node['split'] = $tax_mapping->expense_payment_account;
                        $node['account'] = $tax_mapping->expense_deposit_to;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $goods_receipt->date_c;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_import_id;
                        $node['rel_type'] = 'stock_import';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_mapping->expense_deposit_to;
                        $node['account'] = $tax_mapping->expense_payment_account;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $goods_receipt->date_c;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_import_id;
                        $node['rel_type'] = 'stock_import';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }else{
                        $node = [];
                        $node['split'] = $tax_payment_account;
                        $node['account'] = $tax_deposit_to;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $goods_receipt->date_c;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_import_id;
                        $node['rel_type'] = 'stock_import';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_deposit_to;
                        $node['date'] = $goods_receipt->date_c;
                        $node['account'] = $tax_payment_account;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_import_id;
                        $node['rel_type'] = 'stock_import';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }
                }
            }

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Automatic stock export conversion
     * @param  integer $stock_export_id 
     * @return boolean
     */
    public function automatic_stock_export_conversion($stock_export_id){
        if(get_option('acc_wh_stock_export_automatic_conversion') == 0){
            return false;
        }

        $this->delete_convert( $stock_export_id, 'stock_export');
        $affectedRows = 0;

        $this->load->model('warehouse/warehouse_model');
        $goods_delivery = $this->warehouse_model->get_goods_delivery($stock_export_id);
        if ($goods_delivery->approval != 1) {
            return false;
        }


        $goods_delivery_detail = $this->warehouse_model->get_goods_delivery_detail($stock_export_id);


        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $acc_wh_stock_export_profit_automatic_conversion = get_option('acc_wh_stock_export_profit_automatic_conversion');

        $payment_account = get_option('acc_wh_stock_export_payment_account');
        $deposit_to = get_option('acc_wh_stock_export_deposit_to');

        $profit_payment_account = get_option('acc_wh_stock_export_profit_payment_account');
        $profit_deposit_to = get_option('acc_wh_stock_export_profit_deposit_to');

        $tax_payment_account = get_option('acc_tax_payment_account');
        $tax_deposit_to = get_option('acc_tax_deposit_to');

        if($goods_delivery){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($goods_delivery->date_c) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }
            
            $data_insert = [];


            foreach ($goods_delivery_detail as $value) {

                $goods_transaction_detail = $this->accounting_model->get_goods_transaction_detail($value['id']);
                
                $this->db->where('id', $value['commodity_code']);
                $item = $this->db->get(db_prefix().'items')->row();

                $item_id = 0;
                if(isset($item->id)){
                    $item_id = $item->id;
                }

                if($goods_transaction_detail){
                    $item_amount = $goods_transaction_detail->quantity * $goods_transaction_detail->purchase_price;
                    $profit_item_amount = ($goods_transaction_detail->quantity * $goods_transaction_detail->price) - $item_amount;
                    $item_total = $item_amount + $profit_item_amount;
                }else{
                    if($item_id != 0){
                        $item_amount = $value['quantities'] * $item->purchase_price;
                    }else{
                        $item_amount = $value['quantities'] * $value['unit_price'];
                    }

                    $profit_item_amount = ($value['quantities'] * $value['unit_price']) - $item_amount;
                    $item_total = $item_amount + $profit_item_amount;
                }

                $item_automatic = $this->get_item_automatic($item_id);

                if($item_amount > 0){
                    if($item_automatic){
                        $node = [];
                        $node['split'] = $payment_account;
                        $node['account'] = $item_automatic->inventory_asset_account;
                        $node['item'] = $item_id;
                        $node['date'] = $goods_delivery->date_c;
                        $node['debit'] = $item_amount;
                        $node['tax'] = 0;
                        $node['sub_type'] = 'inventory';
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_export_id;
                        $node['rel_type'] = 'stock_export';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $item_automatic->inventory_asset_account;
                        $node['account'] = $payment_account;
                        $node['item'] = $item_id;
                        $node['date'] = $goods_delivery->date_c;
                        $node['tax'] = 0;
                        $node['sub_type'] = 'inventory';
                        $node['debit'] = 0;
                        $node['credit'] = $item_amount;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_export_id;
                        $node['rel_type'] = 'stock_export';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }else{
                        $node = [];
                        $node['split'] = $payment_account;
                        $node['account'] = $deposit_to;
                        $node['item'] = $item_id;
                        $node['debit'] = $item_amount;
                        $node['date'] = $goods_delivery->date_c;
                        $node['sub_type'] = 'inventory';
                        $node['tax'] = 0;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_export_id;
                        $node['rel_type'] = 'stock_export';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $deposit_to;
                        $node['account'] = $payment_account;
                        $node['item'] = $item_id;
                        $node['date'] = $goods_delivery->date_c;
                        $node['sub_type'] = 'inventory';
                        $node['tax'] = 0;
                        $node['debit'] = 0;
                        $node['credit'] = $item_amount;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_export_id;
                        $node['rel_type'] = 'stock_export';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }
                }

                if($profit_item_amount > 0 && $acc_wh_stock_export_profit_automatic_conversion == 1){
                    if($item_automatic){
                        $node = [];
                        $node['split'] = $profit_payment_account;
                        $node['account'] = $item_automatic->income_account;
                        $node['item'] = $item_id;
                        $node['date'] = $goods_delivery->date_c;
                        $node['debit'] = $profit_item_amount;
                        $node['tax'] = 0;
                        $node['sub_type'] = 'profit';
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_export_id;
                        $node['rel_type'] = 'stock_export';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $item_automatic->income_account;
                        $node['account'] = $profit_payment_account;
                        $node['item'] = $item_id;
                        $node['date'] = $goods_delivery->date_c;
                        $node['tax'] = 0;
                        $node['sub_type'] = 'profit';
                        $node['debit'] = 0;
                        $node['credit'] = $profit_item_amount;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_export_id;
                        $node['rel_type'] = 'stock_export';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }else{
                        $node = [];
                        $node['split'] = $profit_payment_account;
                        $node['account'] = $profit_deposit_to;
                        $node['item'] = $item_id;
                        $node['debit'] = $profit_item_amount;
                        $node['date'] = $goods_delivery->date_c;
                        $node['sub_type'] = 'profit';
                        $node['tax'] = 0;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_export_id;
                        $node['rel_type'] = 'stock_export';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $profit_deposit_to;
                        $node['account'] = $profit_payment_account;
                        $node['item'] = $item_id;
                        $node['date'] = $goods_delivery->date_c;
                        $node['sub_type'] = 'profit';
                        $node['tax'] = 0;
                        $node['debit'] = 0;
                        $node['credit'] = $profit_item_amount;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_export_id;
                        $node['rel_type'] = 'stock_export';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }
                }

                if(get_option('acc_tax_automatic_conversion') == 1 && $value['tax_id'] > 0 && $value['tax_id'] != ''){
                    $tax_payment_account = get_option('acc_tax_payment_account');
                    $tax_deposit_to = get_option('acc_tax_deposit_to');

                    $total_tax = $value['total_money'] - $item_total;

                    $tax_mapping = $this->get_tax_mapping($value['tax_id']);

                    if($tax_mapping){
                        $node = [];
                        $node['split'] = $tax_mapping->payment_account;
                        $node['account'] = $tax_mapping->deposit_to;
                        $node['tax'] = $value['tax_id'];
                        $node['sub_type'] = '';
                        $node['item'] = $item_id;
                        $node['date'] = $goods_delivery->date_c;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_export_id;
                        $node['rel_type'] = 'stock_export';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_mapping->deposit_to;
                        $node['account'] = $tax_mapping->payment_account;
                        $node['tax'] = $value['tax_id'];
                        $node['sub_type'] = '';
                        $node['item'] = $item_id;
                        $node['date'] = $goods_delivery->date_c;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_export_id;
                        $node['rel_type'] = 'stock_export';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }else{
                        $node = [];
                        $node['split'] = $tax_payment_account;
                        $node['account'] = $tax_deposit_to;
                        $node['tax'] = $value['tax_id'];
                        $node['sub_type'] = '';
                        $node['item'] = $item_id;
                        $node['date'] = $goods_delivery->date_c;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_export_id;
                        $node['rel_type'] = 'stock_export';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_deposit_to;
                        $node['date'] = $goods_delivery->date_c;
                        $node['account'] = $tax_payment_account;
                        $node['tax'] = $value['tax_id'];
                        $node['sub_type'] = '';
                        $node['item'] = $item_id;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $stock_export_id;
                        $node['rel_type'] = 'stock_export';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $data_insert[] = $node;
                    }
                }
            }

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Automatic loss adjustment conversion
     * @param  integer $loss_adjustment_id 
     * @return boolean
     */
    public function automatic_loss_adjustment_conversion($loss_adjustment_id){
        if(get_option('acc_wh_loss_adjustment_automatic_conversion') == 0){
            return false;
        }

        $this->delete_convert($loss_adjustment_id, 'loss_adjustment');
        $affectedRows = 0;
        
        $this->load->model('warehouse/warehouse_model');
        $loss_adjustment = $this->warehouse_model->get_loss_adjustment($loss_adjustment_id);
        if ($loss_adjustment->status != 1) {
            return false;
        }
        $loss_adjustment_detail = $this->warehouse_model->get_loss_adjustment_detailt_by_masterid($loss_adjustment_id);

        $decrease_payment_account = get_option('acc_wh_decrease_payment_account');
        $decrease_deposit_to = get_option('acc_wh_decrease_deposit_to');
        $increase_payment_account = get_option('acc_wh_increase_payment_account');
        $increase_deposit_to = get_option('acc_wh_increase_deposit_to');

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        if($loss_adjustment){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime(date('Y-m-d', strtotime($loss_adjustment->time))) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }
            
            $data_insert = [];

            foreach ($loss_adjustment_detail as $value) {
                

                $this->db->where('id', $value['items']);
                $item = $this->db->get(db_prefix().'items')->row();

                $item_id = 0;
                if(isset($item->id)){
                    $item_id = $item->id;
                }

                $price = 0;
                if($value['lot_number'] != ''){
                    $this->db->where('lot_number', $value['lot_number']);
                    $this->db->where('expiry_date', $value['expiry_date']);
                    $receipt_detail = $this->db->get(db_prefix().'goods_receipt_detail')->row();
                    if($receipt_detail){
                        $price = $receipt_detail->unit_price;
                    }else{
                        $this->db->where('id' ,$item_id);
                        $item = $this->db->get(db_prefix().'items')->row();
                        if($item){
                            $price = $item->purchase_price;
                        }
                    }
                }else{
                    $this->db->where('id' ,$item_id);
                    $item = $this->db->get(db_prefix().'items')->row();
                    if($item){
                        $price = $item->purchase_price;
                    }
                }


                $item_automatic = $this->get_item_automatic($item_id);

                if($item_automatic){
                    if($value['current_number'] < $value['updates_number']){
                        $number = $value['updates_number'] - $value['current_number'];
                        $loss_adjustment_payment_account = $increase_payment_account;
                        $loss_adjustment_deposit_to = $item_automatic->inventory_asset_account;
                    }else{
                        $number = $value['current_number'] - $value['updates_number'];
                        $loss_adjustment_payment_account = $item_automatic->inventory_asset_account;
                        $loss_adjustment_deposit_to = $increase_deposit_to;
                    }
                }else{
                    if($value['current_number'] < $value['updates_number']){
                        $number = $value['updates_number'] - $value['current_number'];
                        $loss_adjustment_payment_account = $increase_payment_account;
                        $loss_adjustment_deposit_to = $increase_deposit_to;
                    }else{
                        $number = $value['current_number'] - $value['updates_number'];
                        $loss_adjustment_payment_account = $decrease_payment_account;
                        $loss_adjustment_deposit_to = $decrease_deposit_to;
                    }
                }

                $item_total = $number * $price;

                $node = [];
                $node['split'] = $loss_adjustment_payment_account;
                $node['account'] = $loss_adjustment_deposit_to;
                $node['item'] = $item_id;
                $node['debit'] = $item_total;
                $node['date'] = date('Y-m-d', strtotime($loss_adjustment->time));
                $node['tax'] = 0;
                $node['credit'] = 0;
                $node['description'] = '';
                $node['rel_id'] = $loss_adjustment_id;
                $node['rel_type'] = 'loss_adjustment';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $loss_adjustment_deposit_to;
                $node['account'] = $loss_adjustment_payment_account;
                $node['item'] = $item_id;
                $node['date'] = date('Y-m-d', strtotime($loss_adjustment->time));
                $node['tax'] = 0;
                $node['debit'] = 0;
                $node['credit'] = $item_total;
                $node['description'] = '';
                $node['rel_id'] = $loss_adjustment_id;
                $node['rel_type'] = 'loss_adjustment';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;
            }

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Automatic opening stock conversion
     * @param  integer $loss_adjustment_id 
     * @return boolean
     */
    public function automatic_opening_stock_conversion($opening_stock_id){
        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $date_financial_year = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.date('Y')));

        $this->db->where('rel_id', $opening_stock_id);
        $this->db->where('rel_type', 'opening_stock');
        $this->db->where('date', $date_financial_year);
        $count = $this->db->count_all_results(db_prefix() . 'acc_account_history');
        $affectedRows = 0;
        
        if($count > 0 || get_option('acc_wh_opening_stock_automatic_conversion') == 0){
            return false;
        }

        $opening_stock = $this->get_opening_stock_data($opening_stock_id);

        $deposit_to = get_option('acc_wh_opening_stock_deposit_to');
        $payment_account = get_option('acc_wh_opening_stock_payment_account');


        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        if($opening_stock){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($date_financial_year) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }
            
            $data_insert = [];

            $node = [];
            $node['split'] = $payment_account;
            $node['account'] = $deposit_to;
            $node['debit'] = $opening_stock->opening_stock;
            $node['date'] = $date_financial_year;
            $node['credit'] = 0;
            $node['tax'] = 0;
            $node['description'] = '';
            $node['rel_id'] = $opening_stock_id;
            $node['rel_type'] = 'opening_stock';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $deposit_to;
            $node['account'] = $payment_account;
            $node['date'] = $date_financial_year;
            $node['tax'] = 0;
            $node['debit'] = 0;
            $node['credit'] = $opening_stock->opening_stock;
            $node['description'] = '';
            $node['rel_id'] = $opening_stock_id;
            $node['rel_type'] = 'opening_stock';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * update purchase automatic conversion
     *
     * @param      array   $data   The data
     *
     * @return     boolean 
     */
    public function update_purchase_automatic_conversion($data){
        $affectedRows = 0;
        if(!isset($data['acc_pur_order_automatic_conversion'])){
            $data['acc_pur_order_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_pur_invoice_automatic_conversion'])){
            $data['acc_pur_invoice_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_pur_payment_automatic_conversion'])){
            $data['acc_pur_payment_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_pur_order_return_automatic_conversion'])){
            $data['acc_pur_order_return_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_pur_refund_automatic_conversion'])){
            $data['acc_pur_refund_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_pur_tax_automatic_conversion'])){
            $data['acc_pur_tax_automatic_conversion'] = 0;
        }

        foreach ($data as $key => $value) {
            $this->db->where('name', $key);
            $this->db->update(db_prefix() . 'options', [
                    'value' => $value,
                ]);
            if ($this->db->affected_rows() > 0) {
                $affectedRows++;
            }
        }

        if ($affectedRows > 0) {
            return true;
        }
        return false;
    }

    /**
     * count purchase order not convert yet
     * @param  integer $currency
     * @param  string $where
     * @return object          
     */
    public function count_purchase_order_not_convert_yet($currency = '', $where = ''){
        $where_currency = '';
        if($currency != ''){
            $where_currency = 'and currency = '.$currency;
        }

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'pur_orders.id and ' . db_prefix() . 'acc_account_history.rel_type = "purchase_order") = 0) and approve_status = 2 '.$where_currency);
        return $this->db->count_all_results(db_prefix().'pur_orders');
    }

    /**
     * count purchase payment not convert yet
     * @param  integer $currency
     * @param  string $where
     * @return object          
     */
    public function count_purchase_payment_not_convert_yet($currency = '', $where = ''){
        $where_currency = '';
        if($currency != ''){
            $where_currency = 'and currency = '.$currency;
        }

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'pur_invoice_payment.id and ' . db_prefix() . 'acc_account_history.rel_type = "purchase_payment") = 0) AND (' . db_prefix() . 'pur_invoices.pur_order is not null) and ' . db_prefix() . 'pur_invoice_payment.approval_status = 2 '.$where_currency);
        $this->db->join(db_prefix().'pur_invoices', db_prefix() . 'pur_invoices.id = ' . db_prefix() . 'pur_invoice_payment.pur_invoice', 'left');
        return $this->db->count_all_results(db_prefix().'pur_invoice_payment');
    }

    /**
     * Automatic payment conversion
     * @param  integer $payment_id 
     * @return boolean
     */
    public function automatic_purchase_payment_conversion($payment_id){
        $this->db->where('rel_id', $payment_id);
        $this->db->where('rel_type', 'purchase_payment');
        $count = $this->db->count_all_results(db_prefix() . 'acc_account_history');

        if($count > 0){
            return false;
        }

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $this->load->model('purchase/purchase_model');
        $payment = $this->purchase_model->get_payment_pur_invoice($payment_id);

        if($payment->approval_status != 2){
            return false;
        }

        $purchase_invoice = $this->purchase_model->get_pur_invoice($payment->pur_invoice);

        $base_currency = get_base_currency_pur();
        if($purchase_invoice->currency != 0){
            $base_currency = pur_get_currency_by_id($purchase_invoice->currency);
        }

        $payment_account = get_option('acc_pur_payment_payment_account');
        $deposit_to = get_option('acc_pur_payment_deposit_to');
        $affectedRows = 0;
        $data_insert = [];

        if($payment){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($payment->date) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }

            $currency_rate = 0;
            $payment_total = $payment->amount;
            if($base_currency->name != $currency->name){
                $currency_rate = acc_get_currency_rate($base_currency->name, $currency->name);
                $payment_total = round(($currency_rate * $payment->amount), 2);
            }


            $payment_mode_mapping = $this->get_payment_mode_mapping($payment->paymentmode);

            if($payment_mode_mapping && get_option('acc_active_payment_mode_mapping') == 1){
                $node = [];
                $node['split'] = $payment_mode_mapping->expense_payment_account;
                $node['account'] = $payment_mode_mapping->expense_deposit_to;
                $node['date'] = $payment->date;
                $node['debit'] = $payment_total;
                $node['credit'] = 0;
                $node['tax'] = 0;
                $node['description'] = '';
                $node['rel_id'] = $payment_id;
                $node['rel_type'] = 'purchase_payment';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['currency_rate'] = $currency_rate;
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $payment_mode_mapping->expense_deposit_to;
                $node['account'] = $payment_mode_mapping->expense_payment_account;
                $node['date'] = $payment->date;
                $node['tax'] = 0;
                $node['debit'] = 0;
                $node['credit'] = $payment_total;
                $node['description'] = '';
                $node['rel_id'] = $payment_id;
                $node['rel_type'] = 'purchase_payment';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['currency_rate'] = $currency_rate;
                $data_insert[] = $node;
            }else{
                if(get_option('acc_pur_payment_automatic_conversion') == 1){
                    $node = [];
                    $node['split'] = $payment_account;
                    $node['account'] = $deposit_to;
                    $node['debit'] = $payment_total;
                    $node['credit'] = 0;
                    $node['date'] = $payment->date;
                    $node['description'] = '';
                    $node['rel_id'] = $payment_id;
                    $node['rel_type'] = 'purchase_payment';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $deposit_to;
                    $node['account'] = $payment_account;
                    $node['date'] = $payment->date;
                    $node['debit'] = 0;
                    $node['credit'] = $payment_total;
                    $node['description'] = '';
                    $node['rel_id'] = $payment_id;
                    $node['rel_type'] = 'purchase_payment';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }
            }

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }
    
    public function get_budgets($id = '', $where = []){
        if (is_numeric($id)) {
            $this->db->where('id', $id);
            $budget = $this->db->get(db_prefix() . 'acc_budgets')->row();

            if($budget){
                $this->db->where('budget_id', $id);
                $budget->details = $this->db->get(db_prefix() . 'acc_budget_details')->result_array();
            }
            
            return $budget;
        }

        $this->db->where($where);
        $this->db->order_by('id', 'desc');
        return $this->db->get(db_prefix() . 'acc_budgets')->result_array();
    }

    /**
     * Adds a budget.
     */
    public function add_budget($data){
        $data['name'] = $data['year'].' - '. _l($data['type']);

        $this->db->insert(db_prefix().'acc_budgets', $data);
        $insert_id = $this->db->insert_id();

        if($insert_id){
            return $insert_id;
        }
        return false;
    }

    /**
     * add journal entry
     * @param array $data 
     * @return boolean
     */
    public function update_budget_detail($data){

        $this->db->where('budget_id', $data['budget']);
        $this->db->delete(db_prefix().'acc_budget_details');

        $budget_data = json_decode($data['budget_data']);
        unset($data['budget_data']);

        $columns = $this->get_columns_budget($data['budget'], $data['view_type'], true);
        

        $data_insert = [];
        foreach($budget_data as $row){
            $data_details = array_combine($columns, $row);
            $account_id = '';
            $month = '';
            foreach($data_details as $key => $value){
                if($key == 'account_id'){
                    $account_id = $value;
                }

                if($key != 'account_name' && $key != 'account_id' && $key != 'total' && $value != null){
                    if($data['view_type'] == 'monthly'){
                        $month = explode('_', $key);
                        $data_insert[] = ['budget_id' => $data['budget'], 'month' => $month[0], 'year' => $month[1], 'account' => $account_id, 'amount' => $value];
                    }elseif($data['view_type'] == 'quarterly'){
                        $month = explode('_', $key);

                        if($month[0] == 'q1')
                        {
                            $value_1 = round($value/3);
                            $value_2 = round($value/3);
                            $value_3 = $value - $value_2 - $value_1;
                            $data_insert[] = ['budget_id' => $data['budget'], 'month' => 1, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_1];
                            $data_insert[] = ['budget_id' => $data['budget'], 'month' => 2, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_2];
                            $data_insert[] = ['budget_id' => $data['budget'], 'month' => 3, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_3];
                        }
                        else  if($month[0] == 'q2')
                        {
                            $value_1 = round($value/3);
                            $value_2 = round($value/3);
                            $value_3 = $value - $value_2 - $value_1;
                            $data_insert[] = ['budget_id' => $data['budget'], 'month' => 4, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_1];
                            $data_insert[] = ['budget_id' => $data['budget'], 'month' => 5, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_2];
                            $data_insert[] = ['budget_id' => $data['budget'], 'month' => 6, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_3];
                        }
                        else  if($month[0] == 'q3')
                        {
                            $value_1 = round($value/3);
                            $value_2 = round($value/3);
                            $value_3 = $value - $value_2 - $value_1;
                            $data_insert[] = ['budget_id' => $data['budget'], 'month' => 7, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_1];
                            $data_insert[] = ['budget_id' => $data['budget'], 'month' => 8, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_2];
                            $data_insert[] = ['budget_id' => $data['budget'], 'month' => 9, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_3];
                        }
                        else  if($month[0] == 'q4')
                        {
                            $value_1 = round($value/3);
                            $value_2 = round($value/3);
                            $value_3 = $value - $value_2 - $value_1;
                            $data_insert[] = ['budget_id' => $data['budget'], 'month' => 10, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_1];
                            $data_insert[] = ['budget_id' => $data['budget'], 'month' => 11, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_2];
                            $data_insert[] = ['budget_id' => $data['budget'], 'month' => 12, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_3];
                        }
                    }else{
                        $month = explode('_', $key);

                        $value_1 = round($value/12);
                        $value_2 = $value - ($value_1*11);

                        $data_insert[] = ['budget_id' => $data['budget'], 'month' => 1, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_1];
                        $data_insert[] = ['budget_id' => $data['budget'], 'month' => 2, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_1];
                        $data_insert[] = ['budget_id' => $data['budget'], 'month' => 3, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_1];
                        $data_insert[] = ['budget_id' => $data['budget'], 'month' => 4, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_1];
                        $data_insert[] = ['budget_id' => $data['budget'], 'month' => 5, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_1];
                        $data_insert[] = ['budget_id' => $data['budget'], 'month' => 6, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_1];
                        $data_insert[] = ['budget_id' => $data['budget'], 'month' => 7, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_1];
                        $data_insert[] = ['budget_id' => $data['budget'], 'month' => 8, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_1];
                        $data_insert[] = ['budget_id' => $data['budget'], 'month' => 9, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_1];
                        $data_insert[] = ['budget_id' => $data['budget'], 'month' => 10, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_1];
                        $data_insert[] = ['budget_id' => $data['budget'], 'month' => 11, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_1];
                        $data_insert[] = ['budget_id' => $data['budget'], 'month' => 12, 'year' => $month[1], 'account' => $account_id, 'amount' => $value_2];
                    }
                }
            }
        }

        if(count($data_insert) > 0){
            $affectedRows = $this->db->insert_batch(db_prefix().'acc_budget_details',  $data_insert);
        }

        return true;
    }

    /**
     * check budget.
     */
    public function check_budget($data){

        $this->db->where('year', $data['year']);
        $this->db->where('type', $data['type']);
        $budget = $this->db->get(db_prefix() . 'acc_budgets')->row();

        if($budget){
            return $budget->id;
        }
        return true;
    }

    /**
     * get data budget
     * @param  array  $data_fill 
     * @param  boolean $only_data 
     * @return object             
     */
    public function get_data_budget($data_fill, $only_data = false)
    {
        if(isset($data_fill['view_type'])){
            switch ($data_fill['view_type']) {
                case 'quarterly':
                $data = $this->get_data_budget_quarterly($data_fill, $only_data);
                break;
                case 'yearly':
                $data = $this->get_data_budget_yearly($data_fill, $only_data);
                break;
                case 'monthly':
                $data = $this->get_data_budget_monthly($data_fill, $only_data);
                break;
                default:
                $data = $this->get_data_budget_monthly($data_fill, $only_data);
                break;
            }
        }else{
            $data = $this->get_data_budget_monthly($data_fill, $only_data);
        }

        return $data;
    }

    /**
     * Gets the data budget.
     *
     * @param      object  $data_fill  The data fill
     *
     * @return     array   The data budget.
     */
    public function get_data_budget_monthly($data_fill, $only_data = false)
    {
        if(isset($data_fill['budget']) && $data_fill['budget'] != 0){
            $budget = $this->get_budgets($data_fill['budget']);            
            if($budget){
                $year = $budget->year;
            }else{
                $year = date('Y');
            }
        }elseif(isset($data_fill['year'])){
            $year = $data_fill['year'];
        }else{
            $year = date('Y');
        }

        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $from_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.$year));
        $to_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.($year + 1)));


        $this->db->where('active', 1);
        if(isset($budget)){
            if($budget->type == 'profit_and_loss_accounts'){
                $this->db->where('find_in_set(account_type_id, "11,12,13,14,15")');
            }elseif($budget->type == 'balance_sheet_accounts'){
                $this->db->where('account_type_id not in (11,12,13,14,15)');
            }
        }
        $this->db->where('(parent_account is null or parent_account = 0)');

        $this->db->order_by('id', 'asc');

        $accounts = $this->db->get(db_prefix() . 'acc_accounts')->result_array();

        $data_return = [];
        $rResult = [];

        foreach ($accounts as $key => $value) {
            $rResult[] = $value;
            $rResult = $this->get_recursive_account($rResult, $value['id'], [], 1);
        }

        $data = [];
        if (isset($budget) && !isset($data_fill['clear'])) {
            foreach($budget->details as $detail){
                if($detail['month'] < 10){
                    $detail['month'] = '0'.$detail['month'];
                }
                if(isset($data[$detail['account']])){
                    $data[$detail['account']][$detail['month'].'_'.$detail['year']] = $detail['amount'];
                    $data[$detail['account']]['total'] += $detail['amount'];
                }else{
                    $data[$detail['account']] = [];
                    $data[$detail['account']][$detail['month'].'_'.$detail['year']] = $detail['amount'];
                    $data[$detail['account']]['total'] = $detail['amount'];
                }
            }
        }

        foreach($rResult as $account){
            $name = '';
            if($account['number'] != ''){
                $name = $account['number'].' - ';
            }

            if (isset($account['level'])) {
                for ($i = 0; $i < $account['level']; $i++) {
                    $name .= '          ';
                }
            }

            if ($account['name'] == '') {
                $name .= _l($account['key_name']);
            } else {
                $name .= $account['name'];
            }

            if(isset($data[$account['id']])){
                $data_return[] = array_merge($data[$account['id']], ['account_name' => $name,'account_id' => $account['id']]);
            }else{
                $data_return[] = ['account_name' => $name,'account_id' => $account['id']];
            }
        }

        return $data_return;
    }

    /**
     * Gets the data budget.
     *
     * @param      object  $data_fill  The data fill
     *
     * @return     array   The data budget.
     */
    public function get_data_budget_quarterly($data_fill, $only_data = false)
    {

        if(isset($data_fill['budget']) && $data_fill['budget'] != 0){
            $budget = $this->get_budgets($data_fill['budget']);
            if($budget){
                $year = $budget->year;
            }else{
                $year = date('Y');
            }
        }elseif(isset($data_fill['year'])){
            $year = $data_fill['year'];
        }else{
            $year = date('Y');
        }

        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $from_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.$year));
        $to_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.($year + 1)));


        $this->db->where('active', 1);
        if(isset($budget)){
            if($budget->type == 'profit_and_loss_accounts'){
                $this->db->where('find_in_set(account_type_id, "11,12,13,14,15")');
            }elseif($budget->type == 'balance_sheet_accounts'){
                $this->db->where('account_type_id not in (11,12,13,14,15)');
            }
        }
        $this->db->where('(parent_account is null or parent_account = 0)');

        $this->db->order_by('id', 'asc');

        $accounts = $this->db->get(db_prefix() . 'acc_accounts')->result_array();

        $data_return = [];
        $rResult = [];

        foreach ($accounts as $key => $value) {
            $rResult[] = $value;
            $rResult = $this->get_recursive_account($rResult, $value['id'], [], 1);
        }

        $data = [];
        if (isset($budget) && !isset($data_fill['clear'])) {
            foreach($budget->details as $detail){
                if($detail['month'] < 10){
                    $detail['month'] = '0'.$detail['month'];
                }

                if($detail['month']>=1 && $detail['month']<=3)
                {
                    $t = 'q1_'.$detail['year'];
                }
                else  if($detail['month']>=4 && $detail['month']<=6)
                {
                    $t = 'q2_'.$detail['year'];
                }
                else  if($detail['month']>=7 && $detail['month']<=9)
                {
                    $t = 'q3_'.$detail['year'];
                }
                else  if($detail['month']>=10 && $detail['month']<=12)
                {
                    $t = 'q4_'.$detail['year'];
                }
                
                if(isset($data[$detail['account']])){
                    if(isset($data[$detail['account']][$t])){
                        $data[$detail['account']][$t] += $detail['amount'];
                    }else{
                        $data[$detail['account']][$t] = $detail['amount'];
                    }

                    if(isset($data[$detail['account']]['total'])){
                        $data[$detail['account']]['total'] += $detail['amount'];
                    }else{
                        $data[$detail['account']]['total'] = $detail['amount'];
                    }

                }else{
                    $data[$detail['account']] = [];
                    $data[$detail['account']][$t] = $detail['amount'];
                    $data[$detail['account']]['total'] = $detail['amount'];
                }
            }
        }

        foreach($rResult as $account){
            $name = '';
            if($account['number'] != ''){
                $name = $account['number'].' - ';
            }

            if (isset($account['level'])) {
                for ($i = 0; $i < $account['level']; $i++) {
                    $name .= '          ';
                }
            }

            if ($account['name'] == '') {
                $name .= _l($account['key_name']);
            } else {
                $name .= $account['name'];
            }

            if(isset($data[$account['id']])){
                $data_return[] = array_merge($data[$account['id']], ['account_name' => $name,'account_id' => $account['id']]);
            }else{
                $data_return[] = ['account_name' => $name,'account_id' => $account['id']];
            }
        }

        return $data_return;

    }

    /**
     * Gets the data budget.
     *
     * @param      object  $data_fill  The data fill
     *
     * @return     array   The data budget.
     */
    public function get_data_budget_yearly($data_fill, $only_data = false)
    {
        if(isset($data_fill['budget']) && $data_fill['budget'] != 0){
            $budget = $this->get_budgets($data_fill['budget']);
            if($budget){
                $year = $budget->year;
            }else{
                $year = date('Y');
            }
        }elseif(isset($data_fill['year'])){
            $year = $data_fill['year'];
        }else{
            $year = date('Y');
        }

        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $from_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.$year));
        $to_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.($year + 1)));

        $this->db->where('active', 1);
        if(isset($budget)){
            if($budget->type == 'profit_and_loss_accounts'){
                $this->db->where('find_in_set(account_type_id, "11,12,13,14,15")');
            }elseif($budget->type == 'balance_sheet_accounts'){
                $this->db->where('account_type_id not in (11,12,13,14,15)');
            }
        }
        $this->db->where('(parent_account is null or parent_account = 0)');

        $this->db->order_by('id', 'asc');

        $accounts = $this->db->get(db_prefix() . 'acc_accounts')->result_array();

        $data_return = [];
        $rResult = [];

        foreach ($accounts as $key => $value) {
            $rResult[] = $value;
            $rResult = $this->get_recursive_account($rResult, $value['id'], [], 1);
        }

        $data = [];
        if (isset($budget) && !isset($data_fill['clear'])) {
            foreach($budget->details as $detail){

                if(isset($data[$detail['account']])){
                    if(isset($data[$detail['account']]['_'.$detail['year']])){
                        $data[$detail['account']]['_'.$detail['year']] += $detail['amount'];
                    }else{
                        $data[$detail['account']]['_'.$detail['year']] = $detail['amount'];
                    }

                    $data[$detail['account']]['total'] += $detail['amount'];
                }else{
                    $data[$detail['account']] = [];
                    $data[$detail['account']]['_'.$detail['year']] = $detail['amount'];
                    $data[$detail['account']]['total'] = $detail['amount'];
                }
            }
        }

        foreach($rResult as $account){
            $name = '';
            if($account['number'] != ''){
                $name = $account['number'].' - ';
            }

            if (isset($account['level'])) {
                for ($i = 0; $i < $account['level']; $i++) {
                    $name .= '          ';
                }
            }

            if ($account['name'] == '') {
                $name .= _l($account['key_name']);
            } else {
                $name .= $account['name'];
            }
            if(isset($data[$account['id']])){
                $data_return[] = array_merge(['account_name' => $name,'account_id' => $account['id']], $data[$account['id']]);
            }else{
                $data_return[] = ['account_name' => $name,'account_id' => $account['id']];
            }
        }

        return $data_return;
    }

    /**
     * Gets the nestedheaders budget.
     *
     * @param      integer  $budget_id 
     * @param      string  $budget_type    monthly or quarterly or yearly
     *
     * @return     array   The nestedheaders budget.
     */
    public function get_nestedheaders_budget($budget_id, $budget_type)
    {

        $budget = $this->get_budgets($budget_id);

        $year = $budget->year;
        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $from_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.$year));
        $to_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.($year + 1)));

        $nestedheaders    = [];
        $nestedheaders[] = _l('acc_account');
        $nestedheaders[] = _l('account_id');

        switch ($budget_type) {
            case 'yearly':
                $nestedheaders[] = $year;
                if($acc_first_month_of_financial_year != 'January'){
                    $nestedheaders[] = _l('acc_annual_total');
                    $nestedheaders[] = $year+1;
                }
            break;
            case 'quarterly':
            $nestedheaders[] = _l('acc_annual_total');
            while (strtotime($from_date) < strtotime($to_date)) {
                $month = date('m', strtotime($from_date));
                $year = date('Y', strtotime($from_date));
                if($month>=1 && $month<=3)
                {
                    $t = 'Q1 - '.$year;
                }
                else  if($month>=4 && $month<=6)
                {
                    $t = 'Q2 - '.$year;
                }
                else  if($month>=7 && $month<=9)
                {
                    $t = 'Q3 - '.$year;
                }
                else  if($month>=10 && $month<=12)
                {
                    $t = 'Q4 - '.$year;
                }

                if(!in_array($t, $nestedheaders)){
                    $nestedheaders[] = $t;
                }

                $from_date = date('Y-m-d', strtotime('+1 month', strtotime($from_date)));
            }

            break;
            case 'monthly':
            $nestedheaders[] = _l('acc_annual_total');
            while (strtotime($from_date) < strtotime($to_date)) {

                $month = date('M - Y', strtotime($from_date));

                $nestedheaders[] = $month;

                $from_date = date('Y-m-d', strtotime('+1 month', strtotime($from_date)));

                if(strtotime($from_date) > strtotime($to_date)){
                    $month_2 = date('M - Y', strtotime($to_date));

                    if($month != $month_2){
                        $nestedheaders[] = $month_2;
                    }
                }
            }


            break;
            default:
            break;
        }

        return $nestedheaders;
    }

    /**
     * Gets the columns budget.
     *
     * @param      integer  $budget_id 
     * @param      string  $budget_type    day or week or month
     *
     * @return     array   The columns budget.
     */
    public function get_columns_budget($budget_id, $budget_type, $only_data = false)
    {
        $budget = $this->get_budgets($budget_id);

        $year = $budget->year;

        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $from_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.$year));
        $to_date = date('Y-m-t', strtotime($from_date . '  - 1 month + 1 year '));

       
        if($only_data){
            $columns = ['account_name', 'account_id'];
        }else{
            $columns = [['data' => 'account_name', 'type' => 'text', 'readOnly' => true],
                ['data' => 'account_id', 'type' => 'text', 'readOnly' => true]
            ];
        }

        switch ($budget_type) {
            case 'yearly':
                if($acc_first_month_of_financial_year != 'January'){
                    if($only_data){
                        array_push($columns, 'total');
                    }else{
                        array_push($columns, ['data' => 'total', 'type' => 'numeric', 'numericFormat' => [
                            'pattern' => '0.00'
                        ],'readOnly' => true]);
                    }
                    if($only_data){
                        array_push($columns, '_'.$year);
                        array_push($columns, '_'.($year+1));
                    }else{
                        array_push($columns, ['data' => '_'.$year, 'type' => 'numeric', 'numericFormat' => [
                            'pattern' => '0.00',
                        ]]);
                        array_push($columns, ['data' => '_'.($year+1), 'type' => 'numeric', 'numericFormat' => [
                            'pattern' => '0.00',
                        ]]);
                    }

                }else{
                    if($only_data){
                        array_push($columns, '_'.$year);
                    }else{
                        array_push($columns, ['data' => '_'.$year, 'type' => 'numeric', 'numericFormat' => [
                            'pattern' => '0.00',
                        ]]);
                    }
                }


            break;
            case 'quarterly':
            $nestedheaders = [];
            if($only_data){
                array_push($columns, 'total');
            }else{
                array_push($columns, ['data' => 'total', 'type' => 'numeric', 'numericFormat' => [
                    'pattern' => '0.00'
                ],'readOnly' => true]);
            }
            while (strtotime($from_date) < strtotime($to_date)) {
                $month = date('m', strtotime($from_date));
                $year = date('Y', strtotime($from_date));

                if($month>=1 && $month<=3)
                {
                    $t = 'q1_'.$year;
                }
                else  if($month>=4 && $month<=6)
                {
                    $t = 'q2_'.$year;
                }
                else  if($month>=7 && $month<=9)
                {
                    $t = 'q3_'.$year;
                }
                else  if($month>=10 && $month<=12)
                {
                    $t = 'q4_'.$year;
                }

                if(!in_array($t, $nestedheaders)){
                    $nestedheaders[] = $t;

                    if($only_data){
                        array_push($columns, $t);
                    }else{
                        array_push($columns, ['data' => $t, 'type' => 'numeric', 'numericFormat' => [
                            'pattern' => '0.00',
                        ]]);
                    }
                }

                $from_date = date('Y-m-d', strtotime('+1 month', strtotime($from_date)));
            }


            break;
            case 'monthly':

            if($only_data){
                array_push($columns, 'total');
            }else{
                array_push($columns, ['data' => 'total', 'type' => 'numeric', 'numericFormat' => [
                    'pattern' => '0.00'
                ],'readOnly' => true]);
            }
            while (strtotime($from_date) < strtotime($to_date)) {
                $month = date('m_Y', strtotime($from_date));

                if($only_data){
                    array_push($columns, $month);
                }else{
                    array_push($columns, ['data' => $month, 'type' => 'numeric', 'numericFormat' => [
                        'pattern' => '0.00',
                    ]]);
                }
                $from_date = date('Y-m-d', strtotime('+1 month', strtotime($from_date)));

                if(strtotime($from_date) > strtotime($to_date)){
                    $month_2 = date('m_Y', strtotime($to_date));

                    if($month != $month_2){
                        if($only_data){
                            array_push($columns, $month_2);
                        }else{
                            array_push($columns, ['data' => $month_2, 'type' => 'numeric', 'numericFormat' => [
                                'pattern' => '0.00',
                            ]]);
                        }
                    }
                }
            }


            break;
            default:
            break;
        }

        return $columns;
    }

    /**
     * Gets the columns budget.
     *
     * @param      string  $from_date  The from date format dd/mm/YYYY
     * @param      string  $to_date    To date format dd/mm/YYYY
     *
     * @return     array   The columns budget.
     */
    public function get_columns_budget_by_month($from_date, $to_date)
    {
        $visible = [];
        $visible[1] = get_option('staff_workload_monday_visible');
        $visible[2] = get_option('staff_workload_tuesday_visible');
        $visible[3] = get_option('staff_workload_thursday_visible');
        $visible[4] = get_option('staff_workload_wednesday_visible');
        $visible[5] = get_option('staff_workload_friday_visible');
        $visible[6] = get_option('staff_workload_saturday_visible');
        $visible[7] = get_option('staff_workload_sunday_visible');
        
        
        if (!$this->check_format_date($from_date)) {
            $from_date = to_sql_date($from_date);
        }
        if (!$this->check_format_date($to_date)) {
            $to_date = to_sql_date($to_date);
        }
        $columns = [['data' => 'staff_name', 'type' => 'text', 'readOnly' => true],
        ['data' => 'staff_id', 'type' => 'text', 'readOnly' => true],
        ['data' => 'capacity', 'type' => 'text', 'readOnly' => true],
        ['data' => 'remainCapacityEstimated', 'type' => 'numeric', 'readOnly' => true, 'numericFormat' => ['pattern' => '0.00']],
        ['data' => 'remainCapacity', 'type' => 'numeric', 'readOnly' => true, 'numericFormat' => ['pattern' => '0.00']],
        ['data' => 'staff_department', 'type' => 'text', 'readOnly' => true],
        ['data' => 'staff_role', 'type' => 'text', 'readOnly' => true]];
        while (strtotime($from_date) < strtotime($to_date)) {
            if($visible[date('N', strtotime($from_date))] == 1){
                array_push($columns, ['data' => date('d_m_Y', strtotime($from_date)) . '_e', 'type' => 'numeric', 'numericFormat' => [
                    'pattern' => '0.00',
                ]]);
                array_push($columns, ['data' => date('d_m_Y', strtotime($from_date)) . '_s', 'type' => 'numeric', 'numericFormat' => [
                    'pattern' => '0.00',
                ]]);
            }
            $from_date = date('Y-m-d', strtotime('+1 day', strtotime($from_date)));
        }
        return $columns;
    }

    /**
     * update a budget.
     */
    public function update_budget($data, $id){
        // if(count($data) == 0){
        //     return false;
        // }
        $this->db->where('id', $id);
        $this->db->update(db_prefix().'acc_budgets', $data);

        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }

        /**
     * check reconcile restored
     * @param  [type] $account 
     * @param  [type] $company 
     * @return [type]          
     */
    public function check_reconcile_restored($account){
        $restored = false;

        $this->db->where('account', $account);
        $this->db->where('opening_balance', 0);
        $this->db->where('finish', 1);
        $this->db->order_by('id', 'desc');
        $reconcile = $this->db->get(db_prefix() . 'acc_reconciles')->result_array();

        if(count($reconcile) > 0){
            $reconcile = true;
        }

        return $reconcile;
    }

    /**
     * reconcile restored
     * @param  [type] $account 
     * @return [type]          
     */
    public function reconcile_restored($account)
    {
        $affected_rows=0;
        //get reconcile
        $this->db->where('account', $account);
        $this->db->where('finish', 1);
        $this->db->order_by('ending_date', 'desc');

        $reconcile = $this->db->get(db_prefix() . 'acc_reconciles')->row();

        if($reconcile){
            $this->db->where('reconcile', $reconcile->id);
            $this->db->update(db_prefix() . 'acc_account_history', ['reconcile' => 0]);
 
            if ($this->db->affected_rows() > 0) {
                $affected_rows++;

                $this->db->where('id', $reconcile->id);
                $this->db->delete(db_prefix().'acc_reconciles');

                if ($this->db->affected_rows() > 0) {
                    $affected_rows++;
                }
            }
        }

        if($affected_rows > 0){
            return true;
        }
        return false;
    }

    /**
     * get data accounts receivable ageing detail
     * @return array 
     */
    public function get_data_accounts_receivable_ageing_detail($data_filter){
        $from_date = date('Y-m-01');
        $to_date = date('Y-m-d');
        $this->load->model('invoices_model');

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $data_report = [];
        $data_report['current'] = [];
        $data_report['1_30_days_past_due'] = [];
        $data_report['31_60_days_past_due'] = [];
        $data_report['61_90_days_past_due'] = [];
        $data_report['91_and_over'] = [];

        $where_string = '';
        if(isset($data_filter['customer'])){
            $where_string .= db_prefix().'invoices.clientid in ('. implode(',', $data_filter['customer']) . ')';
        }

        if(isset($data_filter['customer_group'])){
            if($where_string == ''){
                $where_string .= db_prefix().'invoices.clientid in (select customer_id from '.db_prefix().'customer_groups where groupid in ('. implode(',', $data_filter['customer_group']) . '))';
            }else{
                $where_string .= ' AND '.db_prefix().'invoices.clientid in (select customer_id from '.db_prefix().'customer_groups where groupid in ('. implode(',', $data_filter['customer_group']) . '))';
            }
        }

        if($where_string != ''){
            $this->db->where($where_string);
        }

        $this->db->select('*, (select sum(amount) from '.db_prefix() . 'invoicepaymentrecords where invoiceid = '.db_prefix().'invoices.id) as total_payments');
        $this->db->where('(status = 1 or status = 3 or status = 4)');

        $this->db->order_by('date', 'asc');
        
        $invoices = $this->db->get(db_prefix().'invoices')->result_array();
        
        $i = 0;
        foreach ($invoices as $v) {
            $i++;
            if ($i == 1000) {
                break;
            }
            if ($v['status'] == Invoices_model::STATUS_DRAFT) {
                $number = $v['prefix'] . 'DRAFT';
            } else {
                $number = sales_number_format($v['number'], $v['number_format'], $v['prefix'], $v['date']);
            }
            $due_date = $v['duedate'] ? $v['duedate'] : $v['date'];


            $group = '';
            if (strtotime($due_date) >= strtotime($to_date) && strtotime($v['date']) <= strtotime($to_date)) {
                $group = 'current';
            }elseif (strtotime($due_date) >= strtotime($to_date.' - 30 days') && strtotime($due_date) <= strtotime($to_date.' - 1 days')) {
                $group = '1_30_days_past_due';
            }elseif (strtotime($due_date) >= strtotime($to_date.' - 60 days') && strtotime($due_date) <= strtotime($to_date.' - 31 days')) {
                $group = '31_60_days_past_due';
            }elseif (strtotime($due_date) >= strtotime($to_date.' - 90 days') && strtotime($due_date) <= strtotime($to_date.' - 61 days')) {
                $group = '61_90_days_past_due';
            }elseif (strtotime($due_date) <= strtotime($to_date.' - 91 days')) {
                $group = '91_and_over';
            }

            if($group != ''){
                $data_report[$group][] = [
                    'date' => $v['date'],
                    'duedate' => $v['duedate'],
                    'type' => _l('invoice'),
                    'rel_type' => 'invoice',
                    'rel_id' => $v['id'],
                    'number' => $number,
                    'customer' => $v['clientid'],
                    'amount' => $v['total'] - $v['total_payments'],
                ];
            }
        }
        
        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date];
    }

    /**
     * get data accounts payable ageing detail
     * @return array 
     */
    public function get_data_accounts_payable_ageing_detail($data_filter){
        $from_date = date('Y-m-01');
        $to_date = date('Y-m-d');

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }


        $this->db->where('paymentmode', '');
        $expenses = $this->db->get(db_prefix().'expenses')->result_array();

        $list_expenses = [];
        foreach ($expenses as $key => $value) {
            $list_expenses[] = $value['id'];
        }
        $list_expenses = implode(',', $list_expenses);

        $this->db->where('account_detail_type_id', 1004);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();

        $list_accounts = [];
        foreach ($accounts as $key => $value) {
            $list_accounts[] = $value['id'];
        }
        $list_accounts = implode(',', $list_accounts);

        $data_report = [];
        $data_report['current'] = [];
        $data_report['1_30_days_past_due'] = [];
        $data_report['31_60_days_past_due'] = [];
        $data_report['61_90_days_past_due'] = [];
        $data_report['91_and_over'] = [];

        $this->db->select('*, ' . db_prefix() . 'expenses.id as expense_id, ' . db_prefix() . 'taxes.taxrate as taxrate, ' . db_prefix() . 'taxes_2.taxrate as taxrate2');
        $this->db->where('paymentmode', '');
        $this->db->where('is_bill', 0);
        $this->db->join(db_prefix() . 'taxes', '' . db_prefix() . 'taxes.id = ' . db_prefix() . 'expenses.tax', 'left');
        $this->db->join('' . db_prefix() . 'taxes as ' . db_prefix() . 'taxes_2', '' . db_prefix() . 'taxes_2.id = ' . db_prefix() . 'expenses.tax2', 'left');
        $this->db->order_by('date', 'asc');
        $expenses = $this->db->get(db_prefix().'expenses')->result_array();

        foreach ($expenses as $v) {
            $total = $v['amount'];

            if($v['tax'] != 0){
                $total += ($total / 100 * $v['taxrate']);
            }
            if($v['tax2'] != 0){
                $total += ($v['amount'] / 100 * $v['taxrate2']);
            }

            $group = '';
            if (strtotime($v['date']) == strtotime($to_date)) {
                $group = 'current';
            }elseif (strtotime($v['date']) >= strtotime($to_date.' - 30 days') && strtotime($v['date']) <= strtotime($to_date.' - 1 days')) {
                $group = '1_30_days_past_due';
            }elseif (strtotime($v['date']) >= strtotime($to_date.' - 60 days') && strtotime($v['date']) <= strtotime($to_date.' - 31 days')) {
                $group = '31_60_days_past_due';
            }elseif (strtotime($v['date']) >= strtotime($to_date.' - 90 days') && strtotime($v['date']) <= strtotime($to_date.' - 61 days')) {
                $group = '61_90_days_past_due';
            }elseif (strtotime($v['date']) <= strtotime($to_date.' - 91 days')) {
                $group = '91_and_over';
            }

            if($group != ''){
                $data_report[$group][] = [
                    'date' => $v['date'],
                    'duedate' => $v['date'],
                    'type' => _l('expenses'),
                    'number' => '#'.$v['expense_id'],
                    'vendor' => $v['vendor'],
                    'rel_type' => 'expense',
                    'rel_id' => $v['expense_id'],
                    'customer' => $v['clientid'],
                    'amount' => $total,
                ];
            }
        }

        $this->db->where('approved', 1);
        $this->db->where('voided', 0);
        $this->db->where('status != 2');
        $this->db->where('is_bill', 1);
        $this->db->order_by('date', 'asc');
        $expenses = $this->db->get(db_prefix().'expenses')->result_array();
        
        foreach ($expenses as $v) {
            $total = bill_amount_left($v['id']);

            $group = '';
            if (strtotime($v['date']) == strtotime($to_date)) {
                $group = 'current';
            }elseif (strtotime($v['date']) >= strtotime($to_date.' - 30 days') && strtotime($v['date']) <= strtotime($to_date.' - 1 days')) {
                $group = '1_30_days_past_due';
            }elseif (strtotime($v['date']) >= strtotime($to_date.' - 60 days') && strtotime($v['date']) <= strtotime($to_date.' - 31 days')) {
                $group = '31_60_days_past_due';
            }elseif (strtotime($v['date']) >= strtotime($to_date.' - 90 days') && strtotime($v['date']) <= strtotime($to_date.' - 61 days')) {
                $group = '61_90_days_past_due';
            }elseif (strtotime($v['date']) <= strtotime($to_date.' - 91 days')) {
                $group = '91_and_over';
            }

            if($group != ''){
                $data_report[$group][] = [
                    'date' => $v['date'],
                    'duedate' => $v['date'],
                    'type' => _l('bills'),
                    'number' => '#'.$v['id'],
                    'vendor' => $v['vendor'],
                    'rel_type' => 'bill',
                    'rel_id' => $v['id'],
                    'customer' => $v['clientid'],
                    'amount' => $total,
                ];
            }
        }

        if(acc_get_status_modules('purchase')){
            $this->db->where('payment_status != "paid"');
            $this->db->order_by('invoice_date', 'asc');
            $this->db->where('approval_status', 2);
            $pur_invoices = $this->db->get(db_prefix().'pur_invoices')->result_array();
            
            foreach ($pur_invoices as $v) {
                $total = $v['total'];

                if($v['payment_status'] == 'partially_paid'){
                    $total = $this->pur_invoice_amount_left($v['id']);
                }

                $group = '';
                if (strtotime($v['invoice_date']) == strtotime($to_date)) {
                    $group = 'current';
                }elseif (strtotime($v['invoice_date']) >= strtotime($to_date.' - 30 days') && strtotime($v['invoice_date']) <= strtotime($to_date.' - 1 days')) {
                    $group = '1_30_days_past_due';
                }elseif (strtotime($v['invoice_date']) >= strtotime($to_date.' - 60 days') && strtotime($v['invoice_date']) <= strtotime($to_date.' - 31 days')) {
                    $group = '31_60_days_past_due';
                }elseif (strtotime($v['invoice_date']) >= strtotime($to_date.' - 90 days') && strtotime($v['invoice_date']) <= strtotime($to_date.' - 61 days')) {
                    $group = '61_90_days_past_due';
                }elseif (strtotime($v['invoice_date']) <= strtotime($to_date.' - 91 days')) {
                    $group = '91_and_over';
                }
                
                if($group != ''){
                    $data_report[$group][] = [
                        'date' => $v['invoice_date'],
                        'duedate' => $v['invoice_date'],
                        'type' => _l('purchase_invoice'),
                        'number' => $v['invoice_number'],
                        'vendor' => $v['vendor'],
                        'rel_type' => 'purchase_invoice',
                        'rel_id' => $v['id'],
                        'customer' => 0,
                        'amount' => $total,
                    ];
                }
            }
        }

        
        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date];
    }

    /**
     * get data accounts receivable ageing summary
     * @return array 
     */
    public function get_data_accounts_receivable_ageing_summary($data_filter){
        $from_date = date('Y-m-01');
        $to_date = date('Y-m-d');
        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $tax = 0;
        if(isset($data_filter['tax'])){
            $tax = $data_filter['tax'];
        }

        $where_string = '';
        if(isset($data_filter['customer'])){
            $where_string .= db_prefix().'invoices.clientid in ('. implode(',', $data_filter['customer']) . ')';
        }

        if(isset($data_filter['customer_group'])){
            if($where_string == ''){
                $where_string .= db_prefix().'invoices.clientid in (select customer_id from '.db_prefix().'customer_groups where groupid in ('. implode(',', $data_filter['customer_group']) . '))';
            }else{
                $where_string .= ' AND '.db_prefix().'invoices.clientid in (select customer_id from '.db_prefix().'customer_groups where groupid in ('. implode(',', $data_filter['customer_group']) . '))';
            }
        }

        if($where_string != ''){
            $this->db->where($where_string);
        }

        $this->db->where('('.db_prefix().'invoices.status = 1 OR '.db_prefix().'invoices.status = 3 OR '.db_prefix().'invoices.status = 4)');

        $this->db->order_by('date', 'asc');
        
        $invoices = $this->db->get(db_prefix().'invoices')->result_array();
        $data_report = [];

        foreach ($invoices as $v) {
            $total_payments = sum_from_table(db_prefix() . 'invoicepaymentrecords', array('field' => 'amount', 'where' => array('invoiceid' => $v['id'])));
            $total = $v['total'] - $total_payments;
            $due_date = $v['duedate'] ? $v['duedate'] : $v['date'];

            if(!isset($data_report[$v['clientid']])){
                $data_report[$v['clientid']]['current'] = 0;
                $data_report[$v['clientid']]['1_30_days_past_due'] = 0;
                $data_report[$v['clientid']]['31_60_days_past_due'] = 0;
                $data_report[$v['clientid']]['61_90_days_past_due'] = 0;
                $data_report[$v['clientid']]['91_and_over'] = 0;
                $data_report[$v['clientid']]['total'] = 0;
            }

            if (strtotime($due_date) >= strtotime($to_date) && strtotime($v['date']) <= strtotime($to_date)) {
                $data_report[$v['clientid']]['current'] += $total;
            }elseif (strtotime($due_date) >= strtotime($to_date.' - 30 days') && strtotime($due_date) <= strtotime($to_date.' - 1 days')) {
                $data_report[$v['clientid']]['1_30_days_past_due'] += $total;
            }elseif (strtotime($due_date) >= strtotime($to_date.' - 60 days') && strtotime($due_date) <= strtotime($to_date.' - 31 days')) {
                $data_report[$v['clientid']]['31_60_days_past_due'] += $total;
            }elseif (strtotime($due_date) >= strtotime($to_date.' - 90 days') && strtotime($due_date) <= strtotime($to_date.' - 61 days')) {
                $data_report[$v['clientid']]['61_90_days_past_due'] += $total;
            }elseif (strtotime($due_date) <= strtotime($to_date.' - 91 days')) {
                $data_report[$v['clientid']]['91_and_over'] += $total;
            }

            $data_report[$v['clientid']]['total'] += $total;
        }

        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date];
    }

     /**
     * get data accounts payable ageing summary
     * @return array 
     */
     public function get_data_accounts_payable_ageing_summary($data_filter){
        $from_date = date('Y-m-01');
        $to_date = date('Y-m-d');

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $tax = 0;
        if(isset($data_filter['tax'])){
            $tax = $data_filter['tax'];
        }


        $data_report = [];
        $data_report['customer'] = [];
        $data_report['vendor'] = [];

        $this->db->select('*, ' . db_prefix() . 'expenses.id as expense_id, ' . db_prefix() . 'taxes.taxrate as taxrate, ' . db_prefix() . 'taxes_2.taxrate as taxrate2');
        $this->db->where('paymentmode', '');
        $this->db->where('is_bill', 0);
        $this->db->join(db_prefix() . 'taxes', '' . db_prefix() . 'taxes.id = ' . db_prefix() . 'expenses.tax', 'left');
        $this->db->join('' . db_prefix() . 'taxes as ' . db_prefix() . 'taxes_2', '' . db_prefix() . 'taxes_2.id = ' . db_prefix() . 'expenses.tax2', 'left');
        $this->db->order_by('date', 'asc');
        $expenses = $this->db->get(db_prefix().'expenses')->result_array();
        
        foreach ($expenses as $v) {
            $rel_type = 'customer';
            $rel_id = 0;
            if($v['clientid'] > 0){
                $rel_type = 'customer';
                $rel_id = $v['clientid'];
            }elseif ($v['vendor'] > 0) {
                $rel_type = 'vendor';
                $rel_id = $v['vendor'];
            }

            $total = $v['amount'];

            if($v['tax'] != 0){
                $total += ($total / 100 * $v['taxrate']);
            }
            if($v['tax2'] != 0){
                $total += ($v['amount'] / 100 * $v['taxrate2']);
            }

            if(!isset($data_report[$rel_type][$rel_id])){
                $data_report[$rel_type][$rel_id]['current'] = 0;
                $data_report[$rel_type][$rel_id]['1_30_days_past_due'] = 0;
                $data_report[$rel_type][$rel_id]['31_60_days_past_due'] = 0;
                $data_report[$rel_type][$rel_id]['61_90_days_past_due'] = 0;
                $data_report[$rel_type][$rel_id]['91_and_over'] = 0;
                $data_report[$rel_type][$rel_id]['total'] = 0;
            }

            if (strtotime($v['date']) == strtotime($to_date)) {
                $data_report[$rel_type][$rel_id]['current'] += $total;
            }elseif (strtotime($v['date']) >= strtotime($to_date.' - 30 days') && strtotime($v['date']) <= strtotime($to_date.' - 1 days')) {
                $data_report[$rel_type][$rel_id]['1_30_days_past_due'] += $total;
            }elseif (strtotime($v['date']) >= strtotime($to_date.' - 60 days') && strtotime($v['date']) <= strtotime($to_date.' - 31 days')) {
                $data_report[$rel_type][$rel_id]['31_60_days_past_due'] += $total;
            }elseif (strtotime($v['date']) >= strtotime($to_date.' - 90 days') && strtotime($v['date']) <= strtotime($to_date.' - 61 days')) {
                $data_report[$rel_type][$rel_id]['61_90_days_past_due'] += $total;
            }elseif (strtotime($v['date']) <= strtotime($to_date.' - 91 days')) {
                $data_report[$rel_type][$rel_id]['91_and_over'] += $total;
            }

            $data_report[$rel_type][$rel_id]['total'] += $total;
        }

        $this->db->where('approved', 1);
        $this->db->where('voided', 0);
        $this->db->where('status != 2');
        $this->db->where('is_bill', 1);
        $this->db->order_by('date', 'asc');
        $expenses = $this->db->get(db_prefix().'expenses')->result_array();
        
        foreach ($expenses as $v) {

            if($v['vendor'] != ''){
                $total = bill_amount_left($v['id']);

                if(!isset($data_report['vendor'][$v['vendor']])){
                    $data_report['vendor'][$v['vendor']]['current'] = 0;
                    $data_report['vendor'][$v['vendor']]['1_30_days_past_due'] = 0;
                    $data_report['vendor'][$v['vendor']]['31_60_days_past_due'] = 0;
                    $data_report['vendor'][$v['vendor']]['61_90_days_past_due'] = 0;
                    $data_report['vendor'][$v['vendor']]['91_and_over'] = 0;
                    $data_report['vendor'][$v['vendor']]['total'] = 0;
                }

                if (strtotime($v['date']) == strtotime($to_date)) {
                    $data_report['vendor'][$v['vendor']]['current'] += $total;
                }elseif (strtotime($v['date']) >= strtotime($to_date.' - 30 days') && strtotime($v['date']) <= strtotime($to_date.' - 1 days')) {
                    $data_report['vendor'][$v['vendor']]['1_30_days_past_due'] += $total;
                }elseif (strtotime($v['date']) >= strtotime($to_date.' - 60 days') && strtotime($v['date']) <= strtotime($to_date.' - 31 days')) {
                    $data_report['vendor'][$v['vendor']]['31_60_days_past_due'] += $total;
                }elseif (strtotime($v['date']) >= strtotime($to_date.' - 90 days') && strtotime($v['date']) <= strtotime($to_date.' - 61 days')) {
                    $data_report['vendor'][$v['vendor']]['61_90_days_past_due'] += $total;
                }elseif (strtotime($v['date']) <= strtotime($to_date.' - 91 days')) {
                    $data_report['vendor'][$v['vendor']]['91_and_over'] += $total;
                }

                $data_report['vendor'][$v['vendor']]['total'] += $total;
            }

        }


        if(acc_get_status_modules('purchase')){
            $this->db->where('payment_status != "paid"');
            $this->db->order_by('invoice_date', 'asc');
            $this->db->where('approval_status', 2);
            $pur_invoices = $this->db->get(db_prefix().'pur_invoices')->result_array();

            foreach ($pur_invoices as $v) {
                $total = $v['total'];

                if($v['payment_status'] == 'partially_paid'){
                    $total = $this->pur_invoice_amount_left($v['id']);
                }

                if(!isset($data_report['vendor'][$v['vendor']])){
                    $data_report['vendor'][$v['vendor']]['current'] = 0;
                    $data_report['vendor'][$v['vendor']]['1_30_days_past_due'] = 0;
                    $data_report['vendor'][$v['vendor']]['31_60_days_past_due'] = 0;
                    $data_report['vendor'][$v['vendor']]['61_90_days_past_due'] = 0;
                    $data_report['vendor'][$v['vendor']]['91_and_over'] = 0;
                    $data_report['vendor'][$v['vendor']]['total'] = 0;
                }

                if (strtotime($v['invoice_date']) == strtotime($to_date)) {
                    $data_report['vendor'][$v['vendor']]['current'] += $total;
                }elseif (strtotime($v['invoice_date']) >= strtotime($to_date.' - 30 days') && strtotime($v['invoice_date']) <= strtotime($to_date.' - 1 days')) {
                    $data_report['vendor'][$v['vendor']]['1_30_days_past_due'] += $total;
                }elseif (strtotime($v['invoice_date']) >= strtotime($to_date.' - 60 days') && strtotime($v['invoice_date']) <= strtotime($to_date.' - 31 days')) {
                    $data_report['vendor'][$v['vendor']]['31_60_days_past_due'] += $total;
                }elseif (strtotime($v['invoice_date']) >= strtotime($to_date.' - 90 days') && strtotime($v['invoice_date']) <= strtotime($to_date.' - 61 days')) {
                    $data_report['vendor'][$v['vendor']]['61_90_days_past_due'] += $total;
                }elseif (strtotime($v['invoice_date']) <= strtotime($to_date.' - 91 days')) {
                    $data_report['vendor'][$v['vendor']]['91_and_over'] += $total;
                }

                $data_report['vendor'][$v['vendor']]['total'] += $total;
            }
        }

        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date];
    }

    /**
     * get data profit and loss 12 months
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_profit_and_loss_12_months($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');
        $acc_enable_income_statement_modifications = get_option('acc_enable_income_statement_modifications');

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'accrual';

        $where_items = '';
        if(isset($data_filter['items'])){
            $where_items = '(item IN ('. implode(',', $data_filter['items']).'))';
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_accounts = [];
        
        if($acc_enable_income_statement_modifications == 1){
            $data_income = $this->caculate_data_income_profit_and_loss_12_months($data_filter);
            $data_report['income'] = $data_income['income'];
            $data_report['net_income'] = $data_income['net_income'];
        }

        foreach ($account_type_details as $key => $value) {
            if($acc_enable_income_statement_modifications != 1){
                if($value['account_type_id'] == 11){
                    $data_accounts['income'][] = $value;
                }
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $row = [];
                    $start = $month = strtotime($from_date);
                    $end = strtotime($to_date);

                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }

                    while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
                    {
                        $this->db->where('account', $val['id']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                        if($where_items != ''){
                            $this->db->where($where_items);
                        }
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;

                        if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                            $row[date('m-Y', $month)] = $credits - $debits;
                        }else{
                            $row[date('m-Y', $month)] = $debits - $credits;
                        }

                        $month = strtotime("+1 month", $month);
                    }
                    $child_account = $this->get_data_profit_and_loss_12_months_recursive([], $val['id'], $value['account_type_id'], $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items);

                    $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $row, 'child_account' => $child_account];
                        
                }
            }
        }

        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date];
        
    }

    /**
     * get data profit and loss recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date   
     * @param  string $accounting_method   
     * @return array                 
     */
    public function get_data_profit_and_loss_12_months_recursive($child_account, $account_id, $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        foreach ($accounts as $val) {
            $row = [];
            $start = $month = strtotime($from_date);
            $end = strtotime($to_date);
            while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
            {
                $this->db->where('account', $val['id']);
                if($accounting_method == 'cash'){
                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                }
                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                if($where_items != ''){
                    $this->db->where($where_items);
                }
                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                $debits = $account_history->debit != '' ? $account_history->debit : 0;
                if($acc_show_account_numbers == 1 && $val['number'] != ''){
                    $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                }else{
                    $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                }


                if($val['account_type_id'] == 11 || $val['account_type_id'] == 12){
                    $row[date('m-Y', $month)] = $credits - $debits;
                }else{
                    $row[date('m-Y', $month)] = $debits - $credits;
                }

                $month = strtotime("+1 month", $month);
            }

            $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $row, 'child_account' => $this->get_data_profit_and_loss_12_months_recursive([], $val['id'], $account_type_id, $from_date, $to_date, $accounting_method, $acc_show_account_numbers, $where_items)];
                
        }

        return $child_account;
    }

    /**
     * get html profit and loss
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_profit_and_loss_12_months($child_account, $data_return, $parent_index, $currency, $flag = false, $level = 1){
        $categoryOutput='';
        if ($flag) {
            for ($i = 0; $i < $level; $i++) {
                $categoryOutput .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
            }
        }

        $total_amount = 0;
        $data_return['total_amount'] = 0;
        foreach ($child_account as $val) {

            if($flag){
                $report_url = $val['name'];
            }else{
                $report_url = '<a href="'.admin_url('accounting/user_register_view/'.$val['account_id'].'?from_date='.$val['from_date'].'&to_date='.$val['to_date']).'" class="text-default-bl">'.$val['name'].'</a>';
            }

            $data_return['row_index']++;
            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
            <td>
            '.$categoryOutput.$report_url.'
            </td>';
            $total = 0;
            foreach($val['amount'] as $amount){
                $data_return['html'] .= '
                <td class="total_amount">
                '.app_format_money($amount, $currency->name).'
                </td>';
                $total += $amount;

            }
            $total_amount = $total;
            $data_return['html'] .= '
            <td class="total_amount">
            '.app_format_money($total_amount, $currency->name).'
            </td>';
            $data_return['html'] .= '</tr>';
            if(count($val['child_account']) > 0){
                $level++;

                $t = $data_return['total_amount'];
                $data_return = $this->get_html_profit_and_loss_12_months($val['child_account'], $data_return, $data_return['row_index'], $currency, $flag, $level);

                $total_amount += $data_return['total_amount'];
                
                $data_return['row_index']++;
                if($flag){
                    $report_url = $val['name'];
                }else{
                    $report_url = '<a href="'.admin_url('accounting/rp_account_history?account='.$val['account_id'].'&from_date='.$val['from_date'].'&to_date='.$val['to_date']).'" class="text-default-bl">'.$val['name'].'</a>';
                }

                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                <td>
                '.$categoryOutput._l('total_for').$report_url.'
                </td>';
                foreach($val['amount'] as $amount){
                    $data_return['html'] .= '
                    <td class="total_amount"></td>';

                }
                $data_return['html'] .= '<td class="total_amount">
                '.app_format_money($total_amount, $currency->name).'
                </td>
                </tr>';
                $data_return['total_amount'] += $t;
            }

            $data_return['total_amount'] += $total;
        }
        return $data_return; 
    }

    /**
     * get data budget overview
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_budget_overview($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $budget_id = 0;
      
        if(isset($data_filter['budget'])){
            $budget_id = $data_filter['budget'];
        }

        if($budget_id == 0){
            return ['type' => '','data' => []];
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_accounts = [];
        $budget = $this->get_budgets($budget_id);
        
        if($budget->type == 'profit_and_loss_accounts'){
            foreach ($account_type_details as $key => $value) {
                if($value['account_type_id'] == 11){
                    $data_accounts['income'][] = $value;
                }

                if($value['account_type_id'] == 12){
                    $data_accounts['other_income'][] = $value;
                }

                if($value['account_type_id'] == 13){
                    $data_accounts['cost_of_sales'][] = $value;
                }

                if($value['account_type_id'] == 14){
                    $data_accounts['expenses'][] = $value;
                }

                if($value['account_type_id'] == 15){
                    $data_accounts['other_expenses'][] = $value;
                }
            }
        }else{
            foreach ($account_type_details as $key => $value) {
                if($value['account_type_id'] == 1){
                    $data_accounts['accounts_receivable'][] = $value;
                }
                if($value['account_type_id'] == 2){
                    $data_accounts['current_assets'][] = $value;
                }
                if($value['account_type_id'] == 3 || $value['account_type_id'] == 16){
                    $data_accounts['cash_and_cash_equivalents'][] = $value;
                }
                if($value['account_type_id'] == 4){
                    $data_accounts['fixed_assets'][] = $value;
                }
                if($value['account_type_id'] == 5){
                    $data_accounts['non_current_assets'][] = $value;
                }
                if($value['account_type_id'] == 6){
                    $data_accounts['accounts_payable'][] = $value;
                }
                if($value['account_type_id'] == 7){
                    $data_accounts['credit_card'][] = $value;
                }
                if($value['account_type_id'] == 8){
                    $data_accounts['current_liabilities'][] = $value;
                }
                if($value['account_type_id'] == 9){
                    $data_accounts['non_current_liabilities'][] = $value;
                }
                if($value['account_type_id'] == 10){
                    $data_accounts['owner_equity'][] = $value;
                }
            }
        }

        $year = $budget->year;
        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $from_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.$year));
        $to_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.($year + 1)));

        $_from_date = $from_date;

        $headers = [];
        while (strtotime($_from_date) < strtotime($to_date)) {

            $month = date('M - Y', strtotime($_from_date));

            $headers[] = $month;

            $_from_date = date('Y-m-d', strtotime('+1 month', strtotime($_from_date)));

            if(strtotime($_from_date) > strtotime($to_date)){
                $month_2 = date('M - Y', strtotime($to_date));

                if($month != $month_2){
                    $headers[] = $month_2;
                }
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $row = [];
                    $start = $month = strtotime($from_date);
                    $end = strtotime($to_date);

                    while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
                    {
                        $this->db->select('sum(amount) as amount');
                        $this->db->where('account', $val['id']);
                        $this->db->where('budget_id', $budget_id);
                        $this->db->where('month', date('m',$month));
                        $this->db->where('year', date('Y',$month));

                        $budget_data = $this->db->get(db_prefix() . 'acc_budget_details')->row();

                        if($acc_show_account_numbers == 1 && $val['number'] != ''){
                            $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                        }else{
                            $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                        }

                        $row[date('m-Y', $month)] = $budget_data->amount;
                        
                        $month = strtotime("+1 month", $month);
                    }
                    $child_account = $this->get_data_budget_overview_recursive([], $val['id'], $from_date, $to_date, $budget_id, $acc_show_account_numbers);

                    $data_report[$data_key][] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $row, 'child_account' => $child_account];
                        
                }
            }
        }

        return ['type' => $budget->type,'data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date, 'headers' => $headers];
        
    }

    /**
     * get data profit and loss recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date   
     * @param  string $accounting_method   
     * @return array                 
     */
    public function get_data_budget_overview_recursive($child_account, $account_id, $from_date, $to_date, $budget_id, $acc_show_account_numbers){
        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        foreach ($accounts as $val) {
            $row = [];
            $start = $month = strtotime($from_date);
            $end = strtotime($to_date);
            while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
            {
                $this->db->select('sum(amount) as amount');
                $this->db->where('account', $val['id']);
                $this->db->where('budget_id', $budget_id);
                $this->db->where('month', date('m',$month));
                $this->db->where('year', date('Y',$month));

                $budget_data = $this->db->get(db_prefix() . 'acc_budget_details')->row();
                if($acc_show_account_numbers == 1 && $val['number'] != ''){
                    $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                }else{
                    $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                }

                $row[date('m-Y', $month)] = $budget_data->amount;
                        
                $month = strtotime("+1 month", $month);
            }

            $child_account[] = ['account_id' => $val['id'], 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $name, 'amount' => $row, 'child_account' => $this->get_data_budget_overview_recursive([], $val['id'], $from_date, $to_date, $budget_id, $acc_show_account_numbers)];
                
        }

        return $child_account;
    }

    /**
     * get html profit and loss
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_budget_overview($child_account, $data_return, $parent_index, $currency){
        $total_amount = 0;
        $data_return['total_amount'] = 0;
        foreach ($child_account as $val) {
            $data_return['row_index']++;
            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
            <td>
            '.$val['name'].'
            </td>';
            $total = 0;
            foreach($val['amount'] as $amount){
                $data_return['html'] .= '
                <td class="total_amount">
                '.app_format_money($amount, $currency->name).'
                </td>';
                $total += $amount;

            }
            $total_amount = $total;
            $data_return['html'] .= '
            <td class="total_amount">
            '.app_format_money($total_amount, $currency->name).'
            </td>';
            $data_return['html'] .= '</tr>';
            if(count($val['child_account']) > 0){
                $t = $data_return['total_amount'];
                $data_return = $this->get_html_budget_overview($val['child_account'], $data_return, $data_return['row_index'], $currency);

                $total_amount += $data_return['total_amount'];
                
                $data_return['row_index']++;
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                <td>
                '._l('total_for', $val['name']).'
                </td>';
                foreach($val['amount'] as $amount){
                    $data_return['html'] .= '
                    <td class="total_amount"></td>';

                }
                $data_return['html'] .= '<td class="total_amount">
                '.app_format_money($total_amount, $currency->name).'
                </td>
                </tr>';
                $data_return['total_amount'] += $t;
            }

            $data_return['total_amount'] += $total;
        }
        return $data_return; 
    }

    /**
     * get data profit and loss
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_profit_and_loss_budget_vs_actual($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');
        $acc_show_account_numbers = get_option('acc_show_account_numbers');
        $date_financial_year = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.date('Y')));
        $date_financial_year_2 = date('Y-m-t', strtotime($date_financial_year . '  - 1 month + 1 year '));

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $year = date('Y');
        $accounting_method = 'accrual';
        $display_columns = 'total_only';
        $budget_id = 0;
      
        if(isset($data_filter['budget'])){
            $budget_id = $data_filter['budget'];
        }

        if($budget_id == 0){
            return ['data' => []];
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        $budget = $this->get_budgets($budget_id);
        $year = $budget->year;
        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $from_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.$year));
        $to_date = date('Y-m-t', strtotime($from_date . '  - 1 month + 1 year '));

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 11){
                $data_accounts['income'][] = $value;
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }


                    $child_account = $this->get_data_profit_and_loss_budget_vs_actual_recursive([], $val['id'], $value['account_type_id'], $from_date, $to_date, $accounting_method, $budget_id, $acc_show_account_numbers);

                    $budget_amount = $this->get_budget_by_account($budget_id, $val['id'], $from_date, $to_date);

                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                        $amount = $credits - $debits;
                    }else{
                        $amount = $debits - $credits;
                    }

                    $data_report[$data_key][] = ['name' => $name, 'amount' => $amount, 'budget_amount' => $budget_amount, 'child_account' => $child_account];
                }
            }
        }

        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date];
        
    }

    /**
     * get data profit and loss
     * @param  array $data_filter 
     * @return array              
     */
    public function get_data_profit_and_loss_budget_performance($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $date_financial_year = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.date('Y')));
        $date_financial_year_2 = date('Y-m-t', strtotime($date_financial_year . '  - 1 month + 1 year '));

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $year = date('Y');


        $accounting_method = 'accrual';
        $budget_id = 0;
      
        if(isset($data_filter['budget'])){
            $budget_id = $data_filter['budget'];
        }

        if($budget_id == 0){
            return ['data' => []];
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        $budget = $this->get_budgets($budget_id);

        $year = $budget->year;
        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $from_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.$year));
        $to_date = date('Y-m-t', strtotime($from_date . '  - 1 month + 1 year '));

        $last_from_date = date('Y-m-01');
        $last_to_date = date('Y-m-t');
        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 11){
                $data_accounts['income'][] = $value;
            }
            
            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }

            if($value['account_type_id'] == 23){
                $data_accounts['cash_flow_data'][] = $value;
            }                
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('(date >= "' . $last_from_date . '" and date <= "' . $last_to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                        $last_amount = $credits - $debits;
                    }else{
                        $last_amount = $debits - $credits;
                    }
                    $last_budget_amount = $this->get_budget_by_account($budget_id, $val['id'],  $last_from_date, $last_to_date);

                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                        $amount = $credits - $debits;
                    }else{
                        $amount = $debits - $credits;
                    }
                    $budget_amount = $this->get_budget_by_account($budget_id, $val['id'], $from_date, $to_date);

                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }


                    $child_account = $this->get_data_profit_and_loss_budget_performance_recursive([], $val['id'], $value['account_type_id'], $from_date, $to_date, $accounting_method, $budget_id, $acc_show_account_numbers);

                    $data_report[$data_key][] = ['name' => $name, 'last_amount' => $last_amount, 'last_budget_amount' => $last_budget_amount, 'amount' => $amount, 'budget_amount' => $budget_amount, 'child_account' => $child_account];
                }
            }
        }

        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date, 'last_from_date' => $last_from_date, 'last_to_date' => $last_to_date];
        
    }

    /**
     * get html budget variance
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_profit_and_loss_budget_vs_actual($child_account, $data_return, $parent_index, $currency){
        $total_amount = 0;
        $data_return['total_amount'] = 0;
        $data_return['total_budget_amount'] = 0;
        foreach ($child_account as $val) {
            $data_return['row_index']++;
            $total_amount = $val['amount'];
            $total_budget_amount = $val['budget_amount'];

            $percent = 0;
            if($val['amount'] != 0){
                if($val['budget_amount'] != 0){
                    $percent = round(($val['amount'] / $val['budget_amount']) * 100, 2);
                }else{
                    $percent = 100;
                }
            }
            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
              <td>
              '.$val['name'].'
              </td>
              <td class="total_amount">
              '.app_format_money($val['amount'], $currency->name).'
              </td>
              <td class="total_amount">
              '.app_format_money($val['budget_amount'], $currency->name).'
              </td>
              <td class="total_amount">
              '.app_format_money(($val['amount'] - $val['budget_amount']), $currency->name).'
              </td>
              <td class="total_amount">
              '.$percent.'%
              </td>
            </tr>';

            if(count($val['child_account']) > 0){
                $t = $data_return['total_amount'];
                $t_2 = $data_return['total_budget_amount'];
                $data_return = $this->get_html_profit_and_loss_budget_vs_actual($val['child_account'], $data_return, $data_return['row_index'], $currency);

                $total_amount += $data_return['total_amount'];
                $total_budget_amount += $data_return['total_budget_amount'];
                
                $data_return['row_index']++;
                $percent = 0;
                if($total_amount != 0){
                    if($total_budget_amount != 0){
                        $percent = round(($total_amount / $total_budget_amount) * 100, 2);
                    }else{
                        $percent = 100;
                    }
                }
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                  <td>
                  '._l('total_for', $val['name']).'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_budget_amount, $currency->name).'
                  </td>
                  <td class="total_amount">
                  '.app_format_money(($total_amount - $total_budget_amount), $currency->name).'
                  </td>
                  <td class="total_amount">
                  '.$percent.'%
                  </td>
                </tr>';
                $data_return['total_amount'] += $t;
                $data_return['total_budget_amount'] += $t_2;
            }

            $data_return['total_amount'] += $val['amount'];
            $data_return['total_budget_amount'] += $val['budget_amount'];
        }
        return $data_return; 
    }


    /**
     * get html budget comparison
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_profit_and_loss_budget_performance($child_account, $data_return, $parent_index, $currency){
        $total_amount = 0;
        $data_return['total_last_amount'] = 0;
        $data_return['total_last_budget_amount'] = 0;
        $data_return['total_amount'] = 0;
        $data_return['total_budget_amount'] = 0;

        foreach ($child_account as $val) {
            $data_return['row_index']++;
            $total_amount = $val['amount'];
            $total_budget_amount = $val['budget_amount'];
            $total_last_amount = $val['last_amount'];
            $total_last_budget_amount = $val['last_budget_amount'];

            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
              <td>
              '.$val['name'].'
              </td>
              <td class="total_amount">
              '.app_format_money($val['last_amount'], $currency->name).'
              </td>
              <td class="total_amount">
              '.app_format_money($val['last_budget_amount'], $currency->name).'
              </td>
              <td class="total_amount">
              '.app_format_money($val['amount'], $currency->name).'
              </td>
              <td class="total_amount">
              '.app_format_money($val['budget_amount'], $currency->name).'
              </td>
              <td class="total_amount">
              '.app_format_money($val['amount'] - $val['budget_amount'], $currency->name).'
              </td>
            </tr>';

            if(count($val['child_account']) > 0){
                $t = $data_return['total_last_amount'];
                $t_2 = $data_return['total_last_budget_amount'];
                $t_3 = $data_return['total_amount'];
                $t_4 = $data_return['total_budget_amount'];
                $data_return = $this->get_html_profit_and_loss_budget_performance($val['child_account'], $data_return, $data_return['row_index'], $currency);

                $total_last_amount += $data_return['total_last_amount'];
                $total_last_budget_amount += $data_return['total_last_budget_amount'];
                $total_amount += $data_return['total_amount'];
                $total_budget_amount += $data_return['total_budget_amount'];
                
                $data_return['row_index']++;
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                  <td>
                  '._l('total_for', $val['name']).'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_last_amount, $currency->name).'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_last_budget_amount, $currency->name).'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_budget_amount, $currency->name).'
                  </td>
                  <td class="total_amount">
                  '.app_format_money($total_amount - $total_budget_amount, $currency->name).'
                  </td>
                </tr>';
                $data_return['total_last_amount'] += $t;
                $data_return['total_last_budget_amount'] += $t_2;
                $data_return['total_amount'] += $t_3;
                $data_return['total_budget_amount'] += $t_4;
            }

            $data_return['total_last_amount'] += $val['last_amount'];
            $data_return['total_last_budget_amount'] += $val['last_budget_amount'];
            $data_return['total_amount'] += $val['amount'];
            $data_return['total_budget_amount'] += $val['budget_amount'];
        }
        return $data_return; 
    }

    /**
     * get budget by account
     * @param  integer $company    
     * @param  integer $account_id 
     * @param  integer $year       
     * @return integer            
     */
    public function get_budget_by_account($budget_id, $account_id, $from_date, $to_date){
        $month = date('m', strtotime($from_date));
        $year = date('Y', strtotime($from_date));
        $month_2 = date('m', strtotime($to_date));
        $year_2 = date('Y', strtotime($to_date));
        
        $this->db->select('sum(amount) as amount');
        $this->db->where('account', $account_id);
        $this->db->where('budget_id', $budget_id);
        if($year == $year_2){
            $this->db->where('((month >= '.$month.' or month <= '.$month_2.') and year = '.$year.')');
        }else{
            $this->db->where('((month >= '.$month.' and year >= '.$year.' and year < '.$year_2.') or (month <= '.$month_2.' and year > '.$year.' and year <= '.$year_2.'))');
        }

        $data = $this->db->get(db_prefix() . 'acc_budget_details')->row();
        
        if($data->amount){
            return $data->amount;
        }else{
            return 0;
        }
    }

    /**
     * get data balance sheet summary recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date         
     * @param  string $accounting_method         
     * @param  integer $acc_report_show_non_zero         
     * @return array                 
     */
    public function get_data_profit_and_loss_budget_performance_recursive($child_account, $account_id, $account_type_id, $from_date, $to_date, $accounting_method, $budget_id, $acc_show_account_numbers){
        $year = date('Y', strtotime($to_date));
        $last_from_date = date('Y-m-01');
        $last_to_date = date('Y-m-t');

        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        $data_return = [];
        foreach ($accounts as $val) {
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('(date >= "' . $last_from_date . '" and date <= "' . $last_to_date . '")');
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $credits = $account_history->credit != '' ? $account_history->credit : 0;
            $debits = $account_history->debit != '' ? $account_history->debit : 0;
            if($account_type_id == 11 || $account_type_id == 12){
                $last_amount = $credits - $debits;
            }else{
                $last_amount = $debits - $credits;
            }
            $last_budget_amount = $this->get_budget_by_account($budget_id, $val['id'], $last_from_date, $last_to_date);

            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

            $credits = $account_history->credit != '' ? $account_history->credit : 0;
            $debits = $account_history->debit != '' ? $account_history->debit : 0;
            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }


            $budget_amount = $this->get_budget_by_account($budget_id, $val['id'], $from_date, $to_date);
            if($account_type_id == 11 || $account_type_id == 12){
                $amount = $credits - $debits;
            }else{
                $amount = $debits - $credits;
            }

            $child_account[] = ['name' => $name, 'last_amount' => $last_amount, 'last_budget_amount' => $last_budget_amount, 'amount' => $amount, 'budget_amount' => $budget_amount, 'child_account' => $this->get_data_profit_and_loss_budget_performance_recursive([], $val['id'],$account_type_id, $from_date, $to_date, $accounting_method, $budget_id, $acc_show_account_numbers)];

            
        }

        return $child_account;
    }

    /**
     * get data balance sheet summary recursive
     * @param  array $child_account         
     * @param  integer $account_id      
     * @param  integer $account_type_id 
     * @param  string $from_date       
     * @param  string $to_date         
     * @param  string $accounting_method         
     * @param  integer $acc_report_show_non_zero         
     * @return array                 
     */
    public function get_data_profit_and_loss_budget_vs_actual_recursive($child_account, $account_id, $account_type_id, $from_date, $to_date, $accounting_method, $budget_id, $acc_show_account_numbers){
        $year = date('Y', strtotime($to_date));
        $last_from_date = date('Y-m-01');
        $last_to_date = date('Y-m-t');

        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        $data_return = [];
        foreach ($accounts as $val) {
            $this->db->where('account', $val['id']);
            $this->db->where('account', $val['id']);
            if($accounting_method == 'cash'){
                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
            }
            $this->db->select('sum(credit) as credit, sum(debit) as debit');
            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

            $credits = $account_history->credit != '' ? $account_history->credit : 0;
            $debits = $account_history->debit != '' ? $account_history->debit : 0;
            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }


            $budget_amount = $this->get_budget_by_account($budget_id, $val['id'], $from_date, $to_date);
            if($account_type_id == 11 || $account_type_id == 12){
                $amount = $credits - $debits;
            }else{
                $amount = $debits - $credits;
            }

            $child_account[] = ['name' => $name, 'amount' => $amount, 'budget_amount' => $budget_amount, 'child_account' => $this->get_data_profit_and_loss_budget_vs_actual_recursive([], $val['id'],$account_type_id, $from_date, $to_date, $accounting_method, $budget_id, $acc_show_account_numbers)];

            
        }

        return $child_account;
    }

     /**
     * delete budget
     * @param integer $id
     * @return boolean
     */

    public function delete_budget($id)
    {
        $this->db->where('id', $id);
        $this->db->delete(db_prefix() . 'acc_budgets');
        if ($this->db->affected_rows() > 0) {
            $this->db->where('budget_id', $id);
            $this->db->delete(db_prefix() . 'acc_budget_details');

            return true;
        }
        return false;
    }

    /**
     * { insert batch account }
     *
     * @param        $data   The data
     */
    public function insert_batch_account($data){

        $row_update = 0;
        $row_add = 0;
        $data_sub_account = [];
        $data_update_account = [];
        foreach($data as $key => $val){

            if( get_account_by_name($val['name']) != false){
                $data_update_account[] = $data[$key];
                unset($data[$key]);
            }

            if($val['parent_account'] != '' && get_account_by_name($val['name']) == false){
                $data_sub_account[] = $data[$key];
                unset($data[$key]);
            }
        }

        if(count($data) > 0){
            $row_add = $this->db->insert_batch(db_prefix().'acc_accounts',  $data);
        }

        if(count($data_update_account) > 0){
            foreach($data_update_account as $acc){
                $acc_id = get_account_by_name($acc['name']);

                if($acc['parent_account'] != ''){
                    $acc['parent_account'] = $acc['parent_account'];
                }

                $this->db->where('id', $acc_id);
                $this->db->update(db_prefix().'acc_accounts', $acc);
                if($this->db->affected_rows() > 0){
                    $row_update++;
                }
            }
        }

        foreach($data_sub_account as $sub_acc){
            $acc_id = $sub_acc['parent_account'];
            if($acc_id){
                $this->db->where('id', $acc_id);
                $account = $this->db->get(db_prefix().'acc_accounts')->row();

                $this->db->insert(db_prefix().'acc_accounts',[
                    'account_type_id' => $account->account_type_id,
                    'account_detail_type_id' => $account->account_detail_type_id,
                    'name' => $sub_acc['name'],
                    'parent_account' => $acc_id,
                ]);
                $insert_id = $this->db->insert_id();
                if($insert_id){
                    $row_add ++;
                }
            }
        }

        return ['row_updated' => $row_update, 'row_added' => $row_add];
    }

    /**
     * { insert batch budget }
     *
     * @param        $data   The data
     */
    public function insert_batch_budget($data, $budget_id, $import_type){
        $data_insert = [];
        $this->db->where('budget_id', $budget_id);
        $this->db->delete(db_prefix().'acc_budget_details');

        $this->db->where('id', $budget_id);
        $budget = $this->db->get(db_prefix().'acc_budgets')->row();

        $year = $budget->year;

        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $from_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.$year));
        $to_date = date('Y-m-t', strtotime($from_date . '  - 1 month + 1 year '));

        $month_columns = [];
        $_from_date = $from_date;
        while (strtotime($_from_date) < strtotime($to_date)) {
            $month = date('m', strtotime($_from_date));
            $year = date('Y', strtotime($_from_date));
                
            array_push($month_columns, ['month' => $month, 'year' => $year]);

            $_from_date = date('Y-m-d', strtotime('+1 month', strtotime($_from_date)));

            if(strtotime($_from_date) > strtotime($to_date)){
                $month_2 = date('m', strtotime($to_date));
                $year_2 = date('Y', strtotime($to_date));

                if($month != $month_2){
                    array_push($month_columns, ['month' => $month_2, 'year' => $year_2]);
                }
            }
        }

        $quarter_columns = [];
        $_from_date = $from_date;
        while (strtotime($_from_date) <= strtotime($to_date)) {
            $month = date('m', strtotime($_from_date));
            $year = date('Y', strtotime($_from_date));

            if($month>=1 && $month<=3)
            {
                $t = 'quarter_1';
            }
            else  if($month>=4 && $month<=6)
            {
                $t = 'quarter_2';
            }
            else  if($month>=7 && $month<=9)
            {
                $t = 'quarter_3';
            }
            else  if($month>=10 && $month<=12)
            {
                $t = 'quarter_4';
            }

            if(!in_array($t, $quarter_columns)){
                array_push($quarter_columns, $t);
            }

            $_from_date = date('Y-m-d', strtotime('+1 month', strtotime($_from_date)));
        }

        foreach($data as $value){
            $account = $value['account'];

            if($import_type == 'month'){


                $data_insert[] = ['budget_id' => $budget_id, 'amount' => $value['month_1'], 'year' => $month_columns[0]['year'], 'account' => $account, 'month' => $month_columns[0]['month']];
                $data_insert[] = ['budget_id' => $budget_id, 'amount' => $value['month_2'], 'year' => $month_columns[1]['year'], 'account' => $account, 'month' => $month_columns[1]['month']];
                $data_insert[] = ['budget_id' => $budget_id, 'amount' => $value['month_3'], 'year' => $month_columns[2]['year'], 'account' => $account, 'month' => $month_columns[2]['month']];
                $data_insert[] = ['budget_id' => $budget_id, 'amount' => $value['month_4'], 'year' => $month_columns[3]['year'], 'account' => $account, 'month' => $month_columns[3]['month']];
                $data_insert[] = ['budget_id' => $budget_id, 'amount' => $value['month_5'], 'year' => $month_columns[4]['year'], 'account' => $account, 'month' => $month_columns[4]['month']];
                $data_insert[] = ['budget_id' => $budget_id, 'amount' => $value['month_6'], 'year' => $month_columns[5]['year'], 'account' => $account, 'month' => $month_columns[5]['month']];
                $data_insert[] = ['budget_id' => $budget_id, 'amount' => $value['month_7'], 'year' => $month_columns[6]['year'], 'account' => $account, 'month' => $month_columns[6]['month']];
                $data_insert[] = ['budget_id' => $budget_id, 'amount' => $value['month_8'], 'year' => $month_columns[7]['year'], 'account' => $account, 'month' => $month_columns[7]['month']];
                $data_insert[] = ['budget_id' => $budget_id, 'amount' => $value['month_9'], 'year' => $month_columns[8]['year'], 'account' => $account, 'month' => $month_columns[8]['month']];
                $data_insert[] = ['budget_id' => $budget_id, 'amount' => $value['month_10'], 'year' => $month_columns[9]['year'], 'account' => $account, 'month' => $month_columns[9]['month']];
                $data_insert[] = ['budget_id' => $budget_id, 'amount' => $value['month_11'], 'year' => $month_columns[10]['year'], 'account' => $account, 'month' => $month_columns[10]['month']];
                $data_insert[] = ['budget_id' => $budget_id, 'amount' => $value['month_12'], 'year' => $month_columns[11]['year'], 'account' => $account, 'month' => $month_columns[11]['month']];

            }elseif($import_type == 'quarter'){

                $_value = $value;
                $value['quarter_1'] = $_value['quarter_1'];
                $value['quarter_2'] = $_value['quarter_2'];
                $value['quarter_3'] = $_value['quarter_3'];
                $value['quarter_4'] = $_value['quarter_4'];

                if($value['quarter_1'] > 0)
                {
                    $_from_date = $from_date;
                    $_to_date = $to_date;
                    $total_month = 0;
                    $end_month = 0;

                    while (strtotime($_from_date) <= strtotime($_to_date)) {
                        $_month = date('m', strtotime($_from_date));
                        $_year = date('Y', strtotime($_from_date));

                        if($_month>=1 && $_month<=3)
                        {
                            $total_month += 1;
                            $end_month = $_month;
                        }

                        $_from_date = date('Y-m-d', strtotime('+1 month', strtotime($_from_date)));
                    }

                    $_from_date = $from_date;
                    $_to_date = $to_date;
                    while (strtotime($_from_date) <= strtotime($_to_date)) {
                        $_month = date('m', strtotime($_from_date));
                        $_year = date('Y', strtotime($_from_date));
                        $key = $_month-1;
                        if($_month>=1 && $_month<=3)
                        {
                            $value_1 = round($value['quarter_1']/$total_month);
                            if($total_month > 1){
                                $value_2 = $value['quarter_1'] - ($value_1*($total_month - 1));
                            }else{
                                $value_2 = $value['quarter_1'];
                            }

                            if($end_month == $_month){
                                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[$key]['month'], 'year' => $month_columns[$key]['year'], 'account' => $account, 'amount' => $value_2];
                            }else{
                                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[$key]['month'], 'year' => $month_columns[$key]['year'], 'account' => $account, 'amount' => $value_1];
                            }
                        }

                        $_from_date = date('Y-m-d', strtotime('+1 month', strtotime($_from_date)));
                    }
                }
                if($value['quarter_2'] > 0)
                {
                    $_from_date = $from_date;
                    $_to_date = $to_date;
                    $total_month = 0;
                    $end_month = 0;

                    while (strtotime($_from_date) <= strtotime($_to_date)) {
                        $_month = date('m', strtotime($_from_date));
                        $_year = date('Y', strtotime($_from_date));

                        if($_month>=4 && $_month<=6)
                        {
                            $total_month += 1;
                            $end_month = $_month;
                        }

                        $_from_date = date('Y-m-d', strtotime('+1 month', strtotime($_from_date)));
                    }

                    $_from_date = $from_date;
                    $_to_date = $to_date;
                    while (strtotime($_from_date) <= strtotime($_to_date)) {
                        $_month = date('m', strtotime($_from_date));
                        $_year = date('Y', strtotime($_from_date));
                        $key = $_month-1;

                        if($_month>=4 && $_month<=6)
                        {
                            $value_1 = round($value['quarter_2']/$total_month);
                            if($total_month > 1){
                                $value_2 = $value['quarter_2'] - ($value_1*($total_month - 1));
                            }else{
                                $value_2 = $value_1;
                            }

                            if($end_month == $_month){
                                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[$key]['month'], 'year' => $month_columns[$key]['year'], 'account' => $account, 'amount' => $value_2];
                            }else{
                                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[$key]['month'], 'year' => $month_columns[$key]['year'], 'account' => $account, 'amount' => $value_1];
                            }
                        }

                        $_from_date = date('Y-m-d', strtotime('+1 month', strtotime($_from_date)));
                    }
                }
                if($value['quarter_3'] > 0)
                {
                    $_from_date = $from_date;
                    $_to_date = $to_date;
                    $total_month = 0;
                    $end_month = 0;

                    while (strtotime($_from_date) <= strtotime($_to_date)) {
                        $_month = date('m', strtotime($_from_date));
                        $_year = date('Y', strtotime($_from_date));

                        if($_month>=7 && $_month<=9)
                        {
                            $total_month += 1;
                            $end_month = $_month;
                        }

                        $_from_date = date('Y-m-d', strtotime('+1 month', strtotime($_from_date)));
                    }

                    $_from_date = $from_date;
                    $_to_date = $to_date;
                    while (strtotime($_from_date) <= strtotime($_to_date)) {
                        $_month = date('m', strtotime($_from_date));
                        $_year = date('Y', strtotime($_from_date));
                        $key = $_month-1;

                        if($_month>=7 && $_month<=9)
                        {
                            $value_1 = round($value['quarter_3']/$total_month);
                            if($total_month > 1){
                                $value_2 = $value['quarter_3'] - ($value_1*($total_month - 1));
                            }else{
                                $value_2 = $value_1;
                            }

                            if($end_month == $_month){
                                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[$key]['month'], 'year' => $month_columns[$key]['year'], 'account' => $account, 'amount' => $value_2];
                            }else{
                                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[$key]['month'], 'year' => $month_columns[$key]['year'], 'account' => $account, 'amount' => $value_1];
                            }
                        }

                        $_from_date = date('Y-m-d', strtotime('+1 month', strtotime($_from_date)));
                    }
                }
                if($value['quarter_4'] > 0)
                {
                    $_from_date = $from_date;
                    $_to_date = $to_date;
                    $total_month = 0;
                    $end_month = 0;

                    while (strtotime($_from_date) <= strtotime($_to_date)) {
                        $_month = date('m', strtotime($_from_date));
                        $_year = date('Y', strtotime($_from_date));

                        if($_month>=10 && $_month<=12)
                        {
                            $total_month += 1;
                            $end_month = $_month;
                        }

                        $_from_date = date('Y-m-d', strtotime('+1 month', strtotime($_from_date)));
                    }

                    $_from_date = $from_date;
                    $_to_date = $to_date;
                    while (strtotime($_from_date) <= strtotime($_to_date)) {
                        $_month = date('m', strtotime($_from_date));
                        $_year = date('Y', strtotime($_from_date));
                        $key = $_month-1;

                        if($_month>=10 && $_month<=12)
                        {
                            $value_1 = round($value['quarter_4']/$total_month);
                            if($total_month > 1){
                                $value_2 = $value['quarter_4'] - ($value_1*($total_month - 1));
                            }else{
                                $value_2 = $value_1;
                            }

                            if($end_month == $_month){
                                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[$key]['month'], 'year' => $month_columns[$key]['year'], 'account' => $account, 'amount' => $value_2];
                            }else{
                                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[$key]['month'], 'year' => $month_columns[$key]['year'], 'account' => $account, 'amount' => $value_1];
                            }
                        }

                        $_from_date = date('Y-m-d', strtotime('+1 month', strtotime($_from_date)));
                    }
                }

            }elseif($import_type == 'year'){
                $value_1 = round($value['amount']/12);
                $value_2 = $value['amount'] - ($value_1*11);

                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[0]['month'], 'year' =>$month_columns[0]['year'], 'account' => $account, 'amount' => $value_1];
                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[1]['month'], 'year' =>$month_columns[1]['year'], 'account' => $account, 'amount' => $value_1];
                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[2]['month'], 'year' =>$month_columns[2]['year'], 'account' => $account, 'amount' => $value_1];
                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[3]['month'], 'year' =>$month_columns[3]['year'], 'account' => $account, 'amount' => $value_1];
                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[4]['month'], 'year' =>$month_columns[4]['year'], 'account' => $account, 'amount' => $value_1];
                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[5]['month'], 'year' =>$month_columns[5]['year'], 'account' => $account, 'amount' => $value_1];
                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[6]['month'], 'year' =>$month_columns[6]['year'], 'account' => $account, 'amount' => $value_1];
                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[7]['month'], 'year' =>$month_columns[7]['year'], 'account' => $account, 'amount' => $value_1];
                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[8]['month'], 'year' =>$month_columns[8]['year'], 'account' => $account, 'amount' => $value_1];
                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[9]['month'], 'year' =>$month_columns[9]['year'], 'account' => $account, 'amount' => $value_1];
                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[10]['month'], 'year' =>$month_columns[10]['year'], 'account' => $account, 'amount' => $value_1];
                $data_insert[] = ['budget_id' => $budget_id, 'month' => $month_columns[11]['month'], 'year' =>$month_columns[11]['year'], 'account' => $account, 'amount' => $value_2];
            }
        }

        if(count($data_insert) > 0){
            $affectedRows = $this->db->insert_batch(db_prefix().'acc_budget_details',  $data_insert);
        }

        return true;
    }

    /**
     * get html profit and loss
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_custom_summary_report($child_account, $data_return, $parent_index, $currency){
        $total_amount = 0;
        $data_return['total_amount'] = 0;
        foreach ($child_account as $val) {
            $data_return['row_index']++;
            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
            <td>
            '.$val['name'].'
            </td>';
            $total = 0;
            foreach($val['amount'] as $amount){
                $data_return['html'] .= '
                <td class="total_amount">
                '.app_format_money($amount, $currency->name).'
                </td>';
                $total += $amount;

            }
            $total_amount = $total;
            $data_return['html'] .= '
            <td class="total_amount">
            '.app_format_money($total_amount, $currency->name).'
            </td>';
            $data_return['html'] .= '</tr>';
            if(count($val['child_account']) > 0){
                $t = $data_return['total_amount'];
                $data_return = $this->get_html_custom_summary_report($val['child_account'], $data_return, $data_return['row_index'], $currency);

                $total_amount += $data_return['total_amount'];
                
                $data_return['row_index']++;
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                <td>
                '._l('total_for', $val['name']).'
                </td>';
                foreach($val['amount'] as $amount){
                    $data_return['html'] .= '
                    <td class="total_amount"></td>';

                }
                $data_return['html'] .= '<td class="total_amount">
                '.app_format_money($total_amount, $currency->name).'
                </td>
                </tr>';
                $data_return['total_amount'] += $t;
            }

            $data_return['total_amount'] += $total;
        }
        return $data_return; 
    }

    /**
     * get data custom summary report
     * @param  array $data_filter 
     * @return array           
     */
    public function get_data_custom_summary_report_by_customer($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $display_rows_by = 'income_statement';
        $display_columns_by = 'total_only';

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        if(isset($data_filter['display_rows_by'])){
            $display_rows_by = $data_filter['display_rows_by'];
        }

        if(isset($data_filter['display_columns_by'])){
            $display_columns_by = $data_filter['display_columns_by'];
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_accounts = [];

        $clients = $this->clients_model->get();
        $headers = [];

        foreach ($clients as $key => $value) {
            $columns = [];
            switch ($display_columns_by) {
                case 'total_only':
                    $this->db->select('sum(credit) as credit');
                    $this->db->where('customer', $value['userid']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('rel_type != "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $this->db->select('sum(debit) as debit');
                    $this->db->where('customer', $value['userid']);
                    
                    $this->db->where('rel_type = "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                    $columns[] = $credits - $debits;
                  break;

                case 'months':
                    $start = $month = strtotime($from_date);
                    $end = strtotime($to_date);

                    while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
                    {
                        $this->db->select('sum(credit) as credit');
                        $this->db->where('customer', $value['userid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('customer', $value['userid']);
                        
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                        $month = strtotime("+1 month", $month);
                    }
                  break;

                case 'quarters':
                    $start = strtotime($from_date);
                    $end = strtotime($to_date);

                    while ($start < $end) {
                        $month = date('m', $start);
                        $year = date('Y', $start);
                        if($month>=1 && $month<=3)
                        {
                            $start_date = date('Y-m-d', strtotime('1-January-'.$year));  // timestamp or 1-Januray 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                        }
                        else  if($month>=4 && $month<=6)
                        {
                            $start_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                        }
                        else  if($month>=7 && $month<=9)
                        {
                            $start_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                        }
                        else  if($month>=10 && $month<=12)
                        {
                            $start_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-January-'.($year+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                        }

                        $custom_date_select = '(date BETWEEN "' .
                        $start_date .
                        '" AND "' .
                        $end_date . '")';

                        $this->db->select('sum(credit) as credit');
                        $this->db->where('customer', $value['userid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where($custom_date_select);
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('customer', $value['userid']);
                        
                        $this->db->where('rel_type = "expense"');
                        $this->db->where($custom_date_select);
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                       

                        $start = strtotime('+3 month', $start);

                        if($start > $end){
                            $month_2 = date('m', $start);
                            $year_2 = date('Y', $start);
                            
                            if($month_2>=1 && $month_2<=3)
                            {
                                $start_date = date('Y-m-d', strtotime('1-January-'.$year_2));  // timestamp or 1-Januray 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                            }
                            else  if($month_2>=4 && $month_2<=6)
                            {
                                $start_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                            }
                            else  if($month_2>=7 && $month_2<=9)
                            {
                                $start_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                            }
                            else  if($month_2>=10 && $month_2<=12)
                            {
                                $start_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-January-'.($year_2+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                            }

                            if($month . ' - ' . $year != $month_2 . ' - ' . $year_2){
                                $custom_date_select = '(date BETWEEN "' .
                                $start_date .
                                '" AND "' .
                                $end_date . '")';

                                $this->db->select('sum(credit) as credit');
                                $this->db->where('customer', $value['userid']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('rel_type != "expense"');
                                $this->db->where($custom_date_select);
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                                $this->db->select('sum(debit) as debit');
                                $this->db->where('customer', $value['userid']);
                                
                                $this->db->where('rel_type = "expense"');
                                $this->db->where($custom_date_select);
                                $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                                $columns[] = $credits - $debits;
                            }
                        }
                    }
                    break;

                case 'years':
                    $start = strtotime($from_date);
                    $end = strtotime($to_date);

                    while ($start < $end) {
                        $year = date('Y', $start);

                        $this->db->select('sum(credit) as credit');
                        $this->db->where('customer', $value['userid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('year(date) = "' . $year . '"');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('customer', $value['userid']);
                        
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('year(date) = "' . $year . '"');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;

                        $start = strtotime('+1 year', $start);

                        if($start > $end){
                            $year_2 = date('Y', $end);
                      
                            if($year != $year_2){
                                $this->db->select('sum(credit) as credit');
                                $this->db->where('customer', $value['userid']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('rel_type != "expense"');
                                $this->db->where('year(date) = "' . $year_2 . '"');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                                $this->db->select('sum(debit) as debit');
                                $this->db->where('customer', $value['userid']);
                                
                                $this->db->where('rel_type = "expense"');
                                $this->db->where('year(date) = "' . $year_2 . '"');
                                $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                                $columns[] = $credits - $debits;
                            }
                        }
                    }
                    break;

                case 'vendors':
                    $this->load->model('purchase/purchase_model');
                    $vendors = $this->purchase_model->get_vendor();
                    foreach ($vendors as $key => $vendor) {
                        $columns[] = 0;
                    }

                    $this->db->select('sum(credit) as credit');
                    $this->db->where('customer', $value['userid']);
                    $this->db->where('(vendor = 0 or vendor is null)');
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('rel_type != "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $this->db->select('sum(debit) as debit');
                    $this->db->where('customer', $value['userid']);
                    $this->db->where('(vendor = 0 or vendor is null)');
                    $this->db->where('rel_type = "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                    $columns[] = $credits - $debits;
                  break;

                case 'employees':
                  $this->load->model('staff_model');
                  $staffs = $this->staff_model->get();
                  foreach ($staffs as $key => $staff) {
                    $this->db->select('sum(credit) as credit');
                    $this->db->where('customer', $value['userid']);
                    $this->db->where('addedfrom', $staff['staffid']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('rel_type != "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $this->db->select('sum(debit) as debit');
                    $this->db->where('customer', $value['userid']);
                    $this->db->where('addedfrom', $staff['staffid']);
                    $this->db->where('rel_type = "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                    $columns[] = $credits - $debits;
                  }
                  break;

                case 'product_service':
                    $this->load->model('invoice_items_model');
                    $items = $this->invoice_items_model->get();
                    foreach ($items as $key => $item) {
                        $this->db->select('sum(credit) as credit');
                        $this->db->where('customer', $value['userid']);
                        $this->db->where('item', $item['itemid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('customer', $value['userid']);
                        $this->db->where('item', $item['itemid']);
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                    }

                    $this->db->select('sum(credit) as credit');
                    $this->db->where('customer', $value['userid']);
                    $this->db->where('(item = 0 or item is null)');
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('rel_type != "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $this->db->select('sum(debit) as debit');
                    $this->db->where('customer', $value['userid']);
                    $this->db->where('(item = 0 or item is null)');
                    $this->db->where('rel_type = "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                    $columns[] = $credits - $debits;
                    break;
                default:
                  // code...
                  break;
            }

            $data_report[] = ['name' => $value['company'], 'columns' => $columns];
        }

        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date, 'display_rows_by' => $display_rows_by, 'display_columns_by' => $display_columns_by];
    }

    /**
     * get data custom summary report
     * @param  array $data_filter 
     * @return array           
     */
    public function get_data_custom_summary_report_by_income_statement($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $display_rows_by = 'income_statement';
        $display_columns_by = 'total_only';

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        if(isset($data_filter['display_rows_by'])){
            $display_rows_by = $data_filter['display_rows_by'];
        }

        if(isset($data_filter['display_columns_by'])){
            $display_columns_by = $data_filter['display_columns_by'];
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_accounts = [];

        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 11){
                $data_accounts['income'][] = $value;
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }

                    $columns = [];
                    switch ($display_columns_by) {
                        case 'total_only':
                            $this->db->select('sum(credit) as credit, sum(debit) as debit');
                            $this->db->where('account', $val['id']);
                            if($accounting_method == 'cash'){
                                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                            }
                            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                            $credits = $account_history->credit != '' ? $account_history->credit : 0;
                            $debits = $account_history->debit != '' ? $account_history->debit : 0;

                            if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                                $columns[] = $credits - $debits;
                            }else{
                                $columns[] = $debits - $credits;
                            }
                          break;

                        case 'months':
                            $start = $month = strtotime($from_date);
                            $end = strtotime($to_date);

                            while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
                            {
                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('account', $val['id']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;

                                if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }

                                $month = strtotime("+1 month", $month);
                            }
                          break;

                        case 'quarters':
                            $start = strtotime($from_date);
                            $end = strtotime($to_date);

                            while ($start < $end) {
                                $month = date('m', $start);
                                $year = date('Y', $start);
                                if($month>=1 && $month<=3)
                                {
                                    $start_date = date('Y-m-d', strtotime('1-January-'.$year));  // timestamp or 1-Januray 12:00:00 AM
                                    $end_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                                }
                                else  if($month>=4 && $month<=6)
                                {
                                    $start_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM
                                    $end_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                                }
                                else  if($month>=7 && $month<=9)
                                {
                                    $start_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM
                                    $end_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                                }
                                else  if($month>=10 && $month<=12)
                                {
                                    $start_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM
                                    $end_date = date('Y-m-d', strtotime('1-January-'.($year+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                                }

                                $custom_date_select = '(date BETWEEN "' .
                                $start_date .
                                '" AND "' .
                                $end_date . '")';

                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('account', $val['id']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where($custom_date_select);
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;
                                
                                if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }

                                $start = strtotime('+3 month', $start);

                                if($start > $end){
                                    $month_2 = date('m', $start);
                                    $year_2 = date('Y', $start);
                                    
                                    if($month_2>=1 && $month_2<=3)
                                    {
                                        $start_date = date('Y-m-d', strtotime('1-January-'.$year_2));  // timestamp or 1-Januray 12:00:00 AM
                                        $end_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                                    }
                                    else  if($month_2>=4 && $month_2<=6)
                                    {
                                        $start_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM
                                        $end_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                                    }
                                    else  if($month_2>=7 && $month_2<=9)
                                    {
                                        $start_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM
                                        $end_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                                    }
                                    else  if($month_2>=10 && $month_2<=12)
                                    {
                                        $start_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM
                                        $end_date = date('Y-m-d', strtotime('1-January-'.($year_2+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                                    }

                                    if($month . ' - ' . $year != $month_2 . ' - ' . $year_2){
                                        $custom_date_select = '(date BETWEEN "' .
                                        $start_date .
                                        '" AND "' .
                                        $end_date . '")';

                                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                        $this->db->where('account', $val['id']);
                                        if($accounting_method == 'cash'){
                                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                        }
                                        $this->db->where($custom_date_select);
                                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                        $debits = $account_history->debit != '' ? $account_history->debit : 0;

                                        if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                                            $columns[] = $credits - $debits;
                                        }else{
                                            $columns[] = $debits - $credits;
                                        }
                                    }
                                }
                            }
                            break;

                        case 'years':
                            $start = strtotime($from_date);
                            $end = strtotime($to_date);

                            while ($start < $end) {
                                $year = date('Y', $start);

                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('account', $val['id']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('year(date) = "' . $year . '"');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;
                                
                                if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }

                                $start = strtotime('+1 year', $start);

                                if($start > $end){
                                    $year_2 = date('Y', $end);
                              
                                    if($year != $year_2){
                                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                        $this->db->where('account', $val['id']);
                                        if($accounting_method == 'cash'){
                                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                        }
                                        $this->db->where('year(date) = "' . $year_2 . '"');
                                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                        $debits = $account_history->debit != '' ? $account_history->debit : 0;
                                        
                                        if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                                            $columns[] = $credits - $debits;
                                        }else{
                                            $columns[] = $debits - $credits;
                                        }
                                    }
                                }
                            }
                            break;
                        case 'customers':
                            $this->load->model('clients_model');
                            $clients = $this->clients_model->get();
                            foreach ($clients as $key => $client) {
                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('customer', $client['userid']);
                                $this->db->where('account', $val['id']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;
                                
                                if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }
                            }

                            $this->db->select('sum(credit) as credit, sum(debit) as debit');
                            $this->db->where('account', $val['id']);
                            $this->db->where('(customer = 0 or customer is null)');
                            if($accounting_method == 'cash'){
                                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                            }
                            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                            $credits = $account_history->credit != '' ? $account_history->credit : 0;
                            $debits = $account_history->debit != '' ? $account_history->debit : 0;
                            
                            if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                                $columns[] = $credits - $debits;
                            }else{
                                $columns[] = $debits - $credits;
                            }
                          break;

                        case 'vendors':
                            $this->load->model('purchase/purchase_model');
                            $vendors = $this->purchase_model->get_vendor();
                            foreach ($vendors as $key => $vendor) {
                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('account', $val['id']);
                                $this->db->where('vendor', $vendor['userid']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;
                                
                                if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }
                            }

                            $this->db->select('sum(credit) as credit, sum(debit) as debit');
                            $this->db->where('account', $val['id']);
                            $this->db->where('(vendor = 0 or vendor is null)');
                            if($accounting_method == 'cash'){
                                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                            }
                            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                            $credits = $account_history->credit != '' ? $account_history->credit : 0;
                            $debits = $account_history->debit != '' ? $account_history->debit : 0;
                            
                            if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                                $columns[] = $credits - $debits;
                            }else{
                                $columns[] = $debits - $credits;
                            }
                          break;

                        case 'employees':
                          $this->load->model('staff_model');
                          $staffs = $this->staff_model->get();
                          foreach ($staffs as $key => $staff) {
                            $this->db->select('sum(credit) as credit, sum(debit) as debit');
                            $this->db->where('account', $val['id']);
                            $this->db->where('addedfrom', $staff['staffid']);
                            if($accounting_method == 'cash'){
                                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                            }
                            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                            $credits = $account_history->credit != '' ? $account_history->credit : 0;
                            $debits = $account_history->debit != '' ? $account_history->debit : 0;
                            
                            if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                                $columns[] = $credits - $debits;
                            }else{
                                $columns[] = $debits - $credits;
                            }
                          }
                          break;

                        case 'product_service':
                            $this->load->model('invoice_items_model');
                            $items = $this->invoice_items_model->get();
                            foreach ($items as $key => $item) {
                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('account', $val['id']);
                                $this->db->where('item', $item['itemid']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;
                                
                                if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }
                            }
                            $this->db->select('sum(credit) as credit, sum(debit) as debit');
                            $this->db->where('account', $val['id']);
                            $this->db->where('(item = 0 or item is null)');
                            if($accounting_method == 'cash'){
                                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                            }
                            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                            $credits = $account_history->credit != '' ? $account_history->credit : 0;
                            $debits = $account_history->debit != '' ? $account_history->debit : 0;
                            
                            if($value['account_type_id'] == 11 || $value['account_type_id'] == 12){
                                $columns[] = $credits - $debits;
                            }else{
                                $columns[] = $debits - $credits;
                            }
                            
                            break;
                        default:
                          // code...
                          break;
                    }

                    $child_account = $this->get_data_custom_summary_report_by_income_statement_recursive([
                        'child_account' => [],
                        'account_id' => $val['id'],
                        'account_type_id' => $value['account_type_id'],
                        'from_date' => $from_date,
                        'to_date' => $to_date,
                        'accounting_method' => $accounting_method,
                        'acc_show_account_numbers' => $acc_show_account_numbers,
                        'display_rows_by' => $display_rows_by,
                        'display_columns_by' => $display_columns_by,
                    ]);

                    $data_report[$data_key][] = ['name' => $name, 'columns' => $columns, 'child_account' => $child_account];
                }
            }
        }

        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date, 'display_rows_by' => $display_rows_by, 'display_columns_by' => $display_columns_by];
    }

    /**
     * get data custom summary report
     * @param  array $data_filter 
     * @return array           
     */
    public function get_data_custom_summary_report_by_employees($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $display_rows_by = 'income_statement';
        $display_columns_by = 'total_only';

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        if(isset($data_filter['display_rows_by'])){
            $display_rows_by = $data_filter['display_rows_by'];
        }

        if(isset($data_filter['display_columns_by'])){
            $display_columns_by = $data_filter['display_columns_by'];
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_accounts = [];

        $staffs = $this->staff_model->get();
        $headers = [];

        foreach ($staffs as $key => $value) {
            $columns = [];
            switch ($display_columns_by) {
                case 'total_only':
                    $this->db->select('sum(credit) as credit');
                    $this->db->where('addedfrom', $value['staffid']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('rel_type != "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $this->db->select('sum(debit) as debit');
                    $this->db->where('addedfrom', $value['staffid']);
                    
                    $this->db->where('rel_type = "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                    $columns[] = $credits - $debits;
                  break;

                case 'months':
                    $start = $month = strtotime($from_date);
                    $end = strtotime($to_date);

                    while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
                    {
                        $this->db->select('sum(credit) as credit');
                        $this->db->where('addedfrom', $value['staffid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('addedfrom', $value['staffid']);
                        
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                        $month = strtotime("+1 month", $month);
                    }
                  break;

                case 'quarters':
                    $start = strtotime($from_date);
                    $end = strtotime($to_date);

                    while ($start < $end) {
                        $month = date('m', $start);
                        $year = date('Y', $start);
                        if($month>=1 && $month<=3)
                        {
                            $start_date = date('Y-m-d', strtotime('1-January-'.$year));  // timestamp or 1-Januray 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                        }
                        else  if($month>=4 && $month<=6)
                        {
                            $start_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                        }
                        else  if($month>=7 && $month<=9)
                        {
                            $start_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                        }
                        else  if($month>=10 && $month<=12)
                        {
                            $start_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-January-'.($year+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                        }

                        $custom_date_select = '(date BETWEEN "' .
                        $start_date .
                        '" AND "' .
                        $end_date . '")';

                        $this->db->select('sum(credit) as credit');
                        $this->db->where('addedfrom', $value['staffid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where($custom_date_select);
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('addedfrom', $value['staffid']);
                        
                        $this->db->where('rel_type = "expense"');
                        $this->db->where($custom_date_select);
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                       

                        $start = strtotime('+3 month', $start);

                        if($start > $end){
                            $month_2 = date('m', $start);
                            $year_2 = date('Y', $start);
                            
                            if($month_2>=1 && $month_2<=3)
                            {
                                $start_date = date('Y-m-d', strtotime('1-January-'.$year_2));  // timestamp or 1-Januray 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                            }
                            else  if($month_2>=4 && $month_2<=6)
                            {
                                $start_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                            }
                            else  if($month_2>=7 && $month_2<=9)
                            {
                                $start_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                            }
                            else  if($month_2>=10 && $month_2<=12)
                            {
                                $start_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-January-'.($year_2+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                            }

                            if($month . ' - ' . $year != $month_2 . ' - ' . $year_2){
                                $custom_date_select = '(date BETWEEN "' .
                                $start_date .
                                '" AND "' .
                                $end_date . '")';

                                $this->db->select('sum(credit) as credit');
                                $this->db->where('addedfrom', $value['staffid']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('rel_type != "expense"');
                                $this->db->where($custom_date_select);
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                                $this->db->select('sum(debit) as debit');
                                $this->db->where('addedfrom', $value['staffid']);
                                
                                $this->db->where('rel_type = "expense"');
                                $this->db->where($custom_date_select);
                                $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                                $columns[] = $credits - $debits;
                            }
                        }
                    }
                    break;

                case 'years':
                    $start = strtotime($from_date);
                    $end = strtotime($to_date);

                    while ($start < $end) {
                        $year = date('Y', $start);

                        $this->db->select('sum(credit) as credit');
                        $this->db->where('addedfrom', $value['staffid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('year(date) = "' . $year . '"');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('addedfrom', $value['staffid']);
                        
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('year(date) = "' . $year . '"');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;

                        $start = strtotime('+1 year', $start);

                        if($start > $end){
                            $year_2 = date('Y', $end);
                      
                            if($year != $year_2){
                                $this->db->select('sum(credit) as credit');
                                $this->db->where('addedfrom', $value['staffid']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('rel_type != "expense"');
                                $this->db->where('year(date) = "' . $year_2 . '"');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                                $this->db->select('sum(debit) as debit');
                                $this->db->where('addedfrom', $value['staffid']);
                                
                                $this->db->where('rel_type = "expense"');
                                $this->db->where('year(date) = "' . $year_2 . '"');
                                $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                                $columns[] = $credits - $debits;
                            }
                        }
                    }
                    break;

                case 'vendors':
                    $this->load->model('purchase/purchase_model');
                    $vendors = $this->purchase_model->get_vendor();
                    foreach ($vendors as $key => $vendor) {
                        $this->db->select('sum(credit) as credit');
                        $this->db->where('addedfrom', $value['staffid']);
                        $this->db->where('vendor', $vendor['userid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('addedfrom', $value['staffid']);
                        $this->db->where('vendor', $vendor['userid']);
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                    }

                    $this->db->select('sum(credit) as credit');
                    $this->db->where('addedfrom', $value['staffid']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('rel_type != "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $this->db->select('sum(debit) as debit');
                    $this->db->where('addedfrom', $value['staffid']);
                    
                    $this->db->where('rel_type = "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                    $columns[] = $credits - $debits;
                  break;

                case 'customers':
                    $this->load->model('clients_model');
                    $clients = $this->clients_model->get();
                    foreach ($clients as $key => $client) {
                        $this->db->select('sum(credit) as credit');
                        $this->db->where('addedfrom', $value['staffid']);
                        $this->db->where('customer', $client['userid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('addedfrom', $value['staffid']);
                        $this->db->where('customer', $client['userid']);
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                    }

                    $this->db->select('sum(credit) as credit');
                    $this->db->where('addedfrom', $value['staffid']);
                    $this->db->where('(customer = 0 or customer is null)');
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('rel_type != "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $this->db->select('sum(debit) as debit');
                    $this->db->where('addedfrom', $value['staffid']);
                    $this->db->where('(customer = 0 or customer is null)');
                    $this->db->where('rel_type = "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                    $columns[] = $credits - $debits;

                  break;

                case 'product_service':
                    $this->load->model('invoice_items_model');
                    $items = $this->invoice_items_model->get();
                    foreach ($items as $key => $item) {
                        $this->db->select('sum(credit) as credit');
                        $this->db->where('addedfrom', $value['staffid']);
                        $this->db->where('item', $item['itemid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('addedfrom', $value['staffid']);
                        $this->db->where('item', $item['itemid']);
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                    }

                    $this->db->select('sum(credit) as credit');
                    $this->db->where('addedfrom', $value['staffid']);
                    $this->db->where('(item = 0 or item is null)');
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('rel_type != "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $this->db->select('sum(debit) as debit');
                    $this->db->where('addedfrom', $value['staffid']);
                    $this->db->where('(item = 0 or item is null)');
                    $this->db->where('rel_type = "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                    $columns[] = $credits - $debits;
                    break;
                default:
                  // code...
                  break;
            }

            $data_report[] = ['name' => $value['full_name'], 'columns' => $columns];
        }

        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date, 'display_rows_by' => $display_rows_by, 'display_columns_by' => $display_columns_by];
    }

    /**
     * get data custom summary report
     * @param  array $data_filter 
     * @return array           
     */
    public function get_data_custom_summary_report_by_vendors($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $display_rows_by = 'income_statement';
        $display_columns_by = 'total_only';

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        if(isset($data_filter['display_rows_by'])){
            $display_rows_by = $data_filter['display_rows_by'];
        }

        if(isset($data_filter['display_columns_by'])){
            $display_columns_by = $data_filter['display_columns_by'];
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_accounts = [];

        $this->load->model('purchase/purchase_model');
        $vendors = $this->purchase_model->get_vendor();

        $headers = [];

        foreach ($vendors as $key => $value) {
            $columns = [];
            switch ($display_columns_by) {
                case 'total_only':
                    $this->db->select('sum(credit) as credit');
                    $this->db->where('vendor', $value['userid']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('rel_type != "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $this->db->select('sum(debit) as debit');
                    $this->db->where('vendor', $value['userid']);
                    
                    $this->db->where('rel_type = "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                    $columns[] = $credits - $debits;
                  break;

                case 'months':
                    $start = $month = strtotime($from_date);
                    $end = strtotime($to_date);

                    while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
                    {
                        $this->db->select('sum(credit) as credit');
                        $this->db->where('vendor', $value['userid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('vendor', $value['userid']);
                        
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                        $month = strtotime("+1 month", $month);
                    }
                  break;

                case 'quarters':
                    $start = strtotime($from_date);
                    $end = strtotime($to_date);

                    while ($start < $end) {
                        $month = date('m', $start);
                        $year = date('Y', $start);
                        if($month>=1 && $month<=3)
                        {
                            $start_date = date('Y-m-d', strtotime('1-January-'.$year));  // timestamp or 1-Januray 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                        }
                        else  if($month>=4 && $month<=6)
                        {
                            $start_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                        }
                        else  if($month>=7 && $month<=9)
                        {
                            $start_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                        }
                        else  if($month>=10 && $month<=12)
                        {
                            $start_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-January-'.($year+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                        }

                        $custom_date_select = '(date BETWEEN "' .
                        $start_date .
                        '" AND "' .
                        $end_date . '")';

                        $this->db->select('sum(credit) as credit');
                        $this->db->where('vendor', $value['userid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where($custom_date_select);
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('vendor', $value['userid']);
                        
                        $this->db->where('rel_type = "expense"');
                        $this->db->where($custom_date_select);
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                       

                        $start = strtotime('+3 month', $start);

                        if($start > $end){
                            $month_2 = date('m', $start);
                            $year_2 = date('Y', $start);
                            
                            if($month_2>=1 && $month_2<=3)
                            {
                                $start_date = date('Y-m-d', strtotime('1-January-'.$year_2));  // timestamp or 1-Januray 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                            }
                            else  if($month_2>=4 && $month_2<=6)
                            {
                                $start_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                            }
                            else  if($month_2>=7 && $month_2<=9)
                            {
                                $start_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                            }
                            else  if($month_2>=10 && $month_2<=12)
                            {
                                $start_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-January-'.($year_2+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                            }

                            if($month . ' - ' . $year != $month_2 . ' - ' . $year_2){
                                $custom_date_select = '(date BETWEEN "' .
                                $start_date .
                                '" AND "' .
                                $end_date . '")';

                                $this->db->select('sum(credit) as credit');
                                $this->db->where('vendor', $value['userid']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('rel_type != "expense"');
                                $this->db->where($custom_date_select);
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                                $this->db->select('sum(debit) as debit');
                                $this->db->where('vendor', $value['userid']);
                                
                                $this->db->where('rel_type = "expense"');
                                $this->db->where($custom_date_select);
                                $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                                $columns[] = $credits - $debits;
                            }
                        }
                    }
                    break;

                case 'years':
                    $start = strtotime($from_date);
                    $end = strtotime($to_date);

                    while ($start < $end) {
                        $year = date('Y', $start);

                        $this->db->select('sum(credit) as credit');
                        $this->db->where('vendor', $value['userid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('year(date) = "' . $year . '"');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('vendor', $value['userid']);
                        
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('year(date) = "' . $year . '"');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;

                        $start = strtotime('+1 year', $start);

                        if($start > $end){
                            $year_2 = date('Y', $end);
                      
                            if($year != $year_2){
                                $this->db->select('sum(credit) as credit');
                                $this->db->where('vendor', $value['userid']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('rel_type != "expense"');
                                $this->db->where('year(date) = "' . $year_2 . '"');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                                $this->db->select('sum(debit) as debit');
                                $this->db->where('vendor', $value['userid']);
                                
                                $this->db->where('rel_type = "expense"');
                                $this->db->where('year(date) = "' . $year_2 . '"');
                                $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                                $columns[] = $credits - $debits;
                            }
                        }
                    }
                    break;

                case 'customers':
                    $this->load->model('clients_model');
                    $clients = $this->clients_model->get();
                    foreach ($clients as $key => $client) {
                        $columns[] = 0;
                    }

                    $this->db->select('sum(credit) as credit');
                    $this->db->where('vendor', $value['userid']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('rel_type != "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $this->db->select('sum(debit) as debit');
                    $this->db->where('vendor', $value['userid']);
                    
                    $this->db->where('rel_type = "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                    $columns[] = $credits - $debits;
                  break;

                case 'employees':
                  $this->load->model('staff_model');
                  $staffs = $this->staff_model->get();
                  foreach ($staffs as $key => $staff) {
                    $this->db->select('sum(credit) as credit');
                    $this->db->where('vendor', $value['userid']);
                    $this->db->where('addedfrom', $staff['staffid']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('rel_type != "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $this->db->select('sum(debit) as debit');
                    $this->db->where('vendor', $value['userid']);
                    $this->db->where('addedfrom', $staff['staffid']);
                    $this->db->where('rel_type = "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                    $columns[] = $credits - $debits;
                  }
                  break;

                case 'product_service':
                    $this->load->model('invoice_items_model');
                    $items = $this->invoice_items_model->get();
                    foreach ($items as $key => $item) {
                        $this->db->select('sum(credit) as credit');
                        $this->db->where('vendor', $value['userid']);
                        $this->db->where('item', $item['itemid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('vendor', $value['userid']);
                        $this->db->where('item', $item['itemid']);
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                    }

                    $this->db->select('sum(credit) as credit');
                    $this->db->where('vendor', $value['userid']);
                    $this->db->where('(item = 0 or item is null)');
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('rel_type != "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $this->db->select('sum(debit) as debit');
                    $this->db->where('vendor', $value['userid']);
                    $this->db->where('(item = 0 or item is null)');
                    $this->db->where('rel_type = "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                    $columns[] = $credits - $debits;
                    break;
                default:
                  // code...
                  break;
            }

            $data_report[] = ['name' => $value['company'], 'columns' => $columns];
        }

        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date, 'display_rows_by' => $display_rows_by, 'display_columns_by' => $display_columns_by];
    }

    /**
     * get data custom summary report
     * @param  array $data_filter 
     * @return array           
     */
    public function get_data_custom_summary_report_by_product_service($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $display_rows_by = 'income_statement';
        $display_columns_by = 'total_only';

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        if(isset($data_filter['display_rows_by'])){
            $display_rows_by = $data_filter['display_rows_by'];
        }

        if(isset($data_filter['display_columns_by'])){
            $display_columns_by = $data_filter['display_columns_by'];
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_accounts = [];

        $this->load->model('invoice_items_model');
        $items = $this->invoice_items_model->get();

        $headers = [];

        foreach ($items as $key => $value) {
            $columns = [];
            switch ($display_columns_by) {
                case 'total_only':
                    $this->db->select('sum(credit) as credit');
                    $this->db->where('item', $value['itemid']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('rel_type != "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $this->db->select('sum(debit) as debit');
                    $this->db->where('item', $value['itemid']);
                    
                    $this->db->where('rel_type = "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                    $columns[] = $credits - $debits;
                  break;

                case 'months':
                    $start = $month = strtotime($from_date);
                    $end = strtotime($to_date);

                    while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
                    {
                        $this->db->select('sum(credit) as credit');
                        $this->db->where('item', $value['itemid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('item', $value['itemid']);
                        
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                        $month = strtotime("+1 month", $month);
                    }
                  break;

                case 'quarters':
                    $start = strtotime($from_date);
                    $end = strtotime($to_date);

                    while ($start < $end) {
                        $month = date('m', $start);
                        $year = date('Y', $start);
                        if($month>=1 && $month<=3)
                        {
                            $start_date = date('Y-m-d', strtotime('1-January-'.$year));  // timestamp or 1-Januray 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                        }
                        else  if($month>=4 && $month<=6)
                        {
                            $start_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                        }
                        else  if($month>=7 && $month<=9)
                        {
                            $start_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                        }
                        else  if($month>=10 && $month<=12)
                        {
                            $start_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-January-'.($year+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                        }

                        $custom_date_select = '(date BETWEEN "' .
                        $start_date .
                        '" AND "' .
                        $end_date . '")';

                        $this->db->select('sum(credit) as credit');
                        $this->db->where('item', $value['itemid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where($custom_date_select);
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('item', $value['itemid']);
                        
                        $this->db->where('rel_type = "expense"');
                        $this->db->where($custom_date_select);
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                       

                        $start = strtotime('+3 month', $start);

                        if($start > $end){
                            $month_2 = date('m', $start);
                            $year_2 = date('Y', $start);
                            
                            if($month_2>=1 && $month_2<=3)
                            {
                                $start_date = date('Y-m-d', strtotime('1-January-'.$year_2));  // timestamp or 1-Januray 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                            }
                            else  if($month_2>=4 && $month_2<=6)
                            {
                                $start_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                            }
                            else  if($month_2>=7 && $month_2<=9)
                            {
                                $start_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                            }
                            else  if($month_2>=10 && $month_2<=12)
                            {
                                $start_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-January-'.($year_2+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                            }

                            if($month . ' - ' . $year != $month_2 . ' - ' . $year_2){
                                $custom_date_select = '(date BETWEEN "' .
                                $start_date .
                                '" AND "' .
                                $end_date . '")';

                                $this->db->select('sum(credit) as credit');
                                $this->db->where('item', $value['itemid']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('rel_type != "expense"');
                                $this->db->where($custom_date_select);
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                                $this->db->select('sum(debit) as debit');
                                $this->db->where('item', $value['itemid']);
                                
                                $this->db->where('rel_type = "expense"');
                                $this->db->where($custom_date_select);
                                $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                                $columns[] = $credits - $debits;
                            }
                        }
                    }
                    break;

                case 'years':
                    $start = strtotime($from_date);
                    $end = strtotime($to_date);

                    while ($start < $end) {
                        $year = date('Y', $start);

                        $this->db->select('sum(credit) as credit');
                        $this->db->where('item', $value['itemid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('year(date) = "' . $year . '"');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('item', $value['itemid']);
                        
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('year(date) = "' . $year . '"');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;

                        $start = strtotime('+1 year', $start);

                        if($start > $end){
                            $year_2 = date('Y', $end);
                      
                            if($year != $year_2){
                                $this->db->select('sum(credit) as credit');
                                $this->db->where('item', $value['itemid']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('rel_type != "expense"');
                                $this->db->where('year(date) = "' . $year_2 . '"');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                                $this->db->select('sum(debit) as debit');
                                $this->db->where('item', $value['itemid']);
                                
                                $this->db->where('rel_type = "expense"');
                                $this->db->where('year(date) = "' . $year_2 . '"');
                                $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                                $columns[] = $credits - $debits;
                            }
                        }
                    }
                    break;

                case 'vendors':
                    $this->load->model('purchase/purchase_model');
                    $vendors = $this->purchase_model->get_vendor();
                    foreach ($vendors as $key => $vendor) {
                        $this->db->select('sum(credit) as credit');
                        $this->db->where('item', $value['itemid']);
                        $this->db->where('vendor', $vendor['userid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('item', $value['itemid']);
                        $this->db->where('vendor', $vendor['userid']);
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                    }

                    $this->db->select('sum(credit) as credit');
                    $this->db->where('item', $value['itemid']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('rel_type != "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $this->db->select('sum(debit) as debit');
                    $this->db->where('item', $value['itemid']);
                    
                    $this->db->where('rel_type = "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                    $columns[] = $credits - $debits;
                  break;

                case 'customers':
                    $this->load->model('clients_model');
                    $clients = $this->clients_model->get();
                    foreach ($clients as $key => $client) {
                        $this->db->select('sum(credit) as credit');
                        $this->db->where('item', $value['itemid']);
                        $this->db->where('customer', $client['userid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('item', $value['itemid']);
                        $this->db->where('customer', $client['userid']);
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                    }

                    $this->db->select('sum(credit) as credit');
                    $this->db->where('item', $value['itemid']);
                    $this->db->where('(customer = 0 or customer is null)');
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $this->db->where('rel_type != "expense"');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $this->db->select('sum(debit) as debit');
                    $this->db->where('item', $value['itemid']);
                    $this->db->where('(customer = 0 or customer is null)');
                    $this->db->where('rel_type = "expense"');
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                    $columns[] = $credits - $debits;

                  break;

                case 'employees':
                    $this->load->model('staff_model');
                    $staffs = $this->staff_model->get();
                    foreach ($staffs as $key => $staff) {
                        $this->db->select('sum(credit) as credit');
                        $this->db->where('item', $value['itemid']);
                        $this->db->where('addedfrom', $staff['staffid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('rel_type != "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $this->db->select('sum(debit) as debit');
                        $this->db->where('item', $value['itemid']);
                        $this->db->where('addedfrom', $staff['staffid']);
                        $this->db->where('rel_type = "expense"');
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history_2 = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history_2->debit != '' ? $account_history_2->debit : 0;
                        $columns[] = $credits - $debits;
                    }
                  break;
                default:
                  // code...
                  break;
            }

            $data_report[] = ['name' => $value['description'], 'columns' => $columns];
        }

        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date, 'display_rows_by' => $display_rows_by, 'display_columns_by' => $display_columns_by];
    }

    /**
     * get html custom summary
     * @param  array $child_account 
     * @param  array $data_return   
     * @param  integer $parent_index  
     * @param  object $currency      
     * @return array               
     */
    public function get_html_custom_summary_by_income_statement($child_account, $data_return, $parent_index, $currency, $display_columns_by){
        $total_amount = 0;
        $data_return['total_amount'] = 0;
        foreach ($child_account as $val) {

            $data_return['row_index']++;
            $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' expanded">
              <td>
              '.$val['name'].'
              </td>';
            $amount = 0;
            $total_amount = $amount;
            $html_column = '';

            foreach($val['columns'] as $column){
                $amount += $column;
                $html_column .= '<td></td>';
                $data_return['html'] .= '<td class="total_amount">'.app_format_money($column, $currency->name).'</td>';
            }
            if ($display_columns_by != 'total_only') {
                $data_return['html'] .= '<td class="total_amount">
                  '.app_format_money($amount, $currency->name).'
                  </td>
                </tr>';
            }

            if(count($val['child_account']) > 0){
                $t = $data_return['total_amount'];
                $data_return = $this->get_html_custom_summary_by_income_statement($val['child_account'], $data_return, $data_return['row_index'], $currency, $display_columns_by);

                $total_amount += $data_return['total_amount'];
                
                $data_return['row_index']++;
                $data_return['html'] .= '<tr class="treegrid-'.$data_return['row_index'].' '.($parent_index != 0 ? 'treegrid-parent-'.$parent_index : '').' tr_total">
                  <td>
                  '._l('total_for', $val['name']).'
                  </td>';
                    if ($display_columns_by != 'total_only') {
                        $data_return['html'] .= $html_column;
                    }
                $data_return['html'] .= '<td class="total_amount">
                  '.app_format_money($total_amount, $currency->name).'
                  </td>
                </tr>';
                $data_return['total_amount'] += $t;
            }

            $data_return['total_amount'] += $amount;
        }
        return $data_return; 
    }

    /**
     * get data custom summary recursive
     * @param  array $data         
     * @return array                 
     */
    public function get_data_custom_summary_report_by_income_statement_recursive($data){
        $child_account = $data['child_account'];
        $account_id = $data['account_id'];
        $account_type_id = $data['account_type_id'];
        $from_date = $data['from_date'];
        $to_date = $data['to_date'];
        $accounting_method = $data['accounting_method'];
        $acc_show_account_numbers = $data['acc_show_account_numbers'];
        $display_rows_by = $data['display_rows_by'];
        $display_columns_by = $data['display_columns_by'];

        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        $data_return = [];
       
        foreach ($accounts as $val) {
            $columns = [];
            switch ($display_columns_by) {
                case 'total_only':
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;

                    if($account_type_id == 11 || $account_type_id == 12){
                        $columns[] = $credits - $debits;
                    }else{
                        $columns[] = $debits - $credits;
                    }
                  break;

                case 'months':
                    $start = $month = strtotime($from_date);
                    $end = strtotime($to_date);

                    while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
                    {
                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('account', $val['id']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;

                        if($account_type_id == 11 || $account_type_id == 12){
                            $columns[] = $credits - $debits;
                        }else{
                            $columns[] = $debits - $credits;
                        }

                        $month = strtotime("+1 month", $month);
                    }
                  break;

                case 'quarters':
                    $start = strtotime($from_date);
                    $end = strtotime($to_date);

                    while ($start < $end) {
                        $month = date('m', $start);
                        $year = date('Y', $start);
                        if($month>=1 && $month<=3)
                        {
                            $start_date = date('Y-m-d', strtotime('1-January-'.$year));  // timestamp or 1-Januray 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                        }
                        else  if($month>=4 && $month<=6)
                        {
                            $start_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                        }
                        else  if($month>=7 && $month<=9)
                        {
                            $start_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                        }
                        else  if($month>=10 && $month<=12)
                        {
                            $start_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-January-'.($year+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                        }

                        $custom_date_select = '(date BETWEEN "' .
                        $start_date .
                        '" AND "' .
                        $end_date . '")';

                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('account', $val['id']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where($custom_date_select);
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;
                        
                        if($account_type_id == 11 || $account_type_id == 12){
                            $columns[] = $credits - $debits;
                        }else{
                            $columns[] = $debits - $credits;
                        }

                        $start = strtotime('+3 month', $start);

                        if($start > $end){
                            $month_2 = date('m', $start);
                            $year_2 = date('Y', $start);
                            
                            if($month_2>=1 && $month_2<=3)
                            {
                                $start_date = date('Y-m-d', strtotime('1-January-'.$year_2));  // timestamp or 1-Januray 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                            }
                            else  if($month_2>=4 && $month_2<=6)
                            {
                                $start_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                            }
                            else  if($month_2>=7 && $month_2<=9)
                            {
                                $start_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                            }
                            else  if($month_2>=10 && $month_2<=12)
                            {
                                $start_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-January-'.($year_2+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                            }

                            if($month . ' - ' . $year != $month_2 . ' - ' . $year_2){
                                $custom_date_select = '(date BETWEEN "' .
                                $start_date .
                                '" AND "' .
                                $end_date . '")';

                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('account', $val['id']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where($custom_date_select);
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;

                                if($account_type_id == 11 || $account_type_id == 12){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }
                            }
                        }
                    }
                    break;

                case 'years':
                    $start = strtotime($from_date);
                    $end = strtotime($to_date);

                    while ($start < $end) {
                        $year = date('Y', $start);

                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('account', $val['id']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('year(date) = "' . $year . '"');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;
                        
                        if($account_type_id == 11 || $account_type_id == 12){
                            $columns[] = $credits - $debits;
                        }else{
                            $columns[] = $debits - $credits;
                        }

                        $start = strtotime('+1 year', $start);

                        if($start > $end){
                            $year_2 = date('Y', $end);
                      
                            if($year != $year_2){
                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('account', $val['id']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('year(date) = "' . $year_2 . '"');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;
                                
                                if($account_type_id == 11 || $account_type_id == 12){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }
                            }
                        }
                    }
                    break;
                case 'customers':
                    $this->load->model('clients_model');
                    $clients = $this->clients_model->get();
                    foreach ($clients as $key => $client) {
                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('customer', $client['userid']);
                        $this->db->where('account', $val['id']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;
                        
                        if($account_type_id == 11 || $account_type_id == 12){
                            $columns[] = $credits - $debits;
                        }else{
                            $columns[] = $debits - $credits;
                        }
                    }

                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    $this->db->where('(customer = 0 or customer is null)');
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    
                    if($account_type_id == 11 || $account_type_id == 12){
                        $columns[] = $credits - $debits;
                    }else{
                        $columns[] = $debits - $credits;
                    }
                  break;

                case 'vendors':
                    $this->load->model('purchase/purchase_model');
                    $vendors = $this->purchase_model->get_vendor();
                    foreach ($vendors as $key => $vendor) {
                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('account', $val['id']);
                        $this->db->where('vendor', $vendor['userid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;
                        
                        if($account_type_id == 11 || $account_type_id == 12){
                            $columns[] = $credits - $debits;
                        }else{
                            $columns[] = $debits - $credits;
                        }
                    }

                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    $this->db->where('(vendor = 0 or vendor is null)');
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    
                    if($account_type_id == 11 || $account_type_id == 12){
                        $columns[] = $credits - $debits;
                    }else{
                        $columns[] = $debits - $credits;
                    }
                  break;

                case 'employees':
                  $this->load->model('staff_model');
                  $staffs = $this->staff_model->get();
                  foreach ($staffs as $key => $staff) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    $this->db->where('addedfrom', $staff['staffid']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    
                    if($account_type_id == 11 || $account_type_id == 12){
                        $columns[] = $credits - $debits;
                    }else{
                        $columns[] = $debits - $credits;
                    }
                  }
                  break;

                case 'product_service':
                    $this->load->model('invoice_items_model');
                    $items = $this->invoice_items_model->get();
                    foreach ($items as $key => $item) {
                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('account', $val['id']);
                        $this->db->where('item', $item['itemid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;
                        
                        if($account_type_id == 11 || $account_type_id == 12){
                            $columns[] = $credits - $debits;
                        }else{
                            $columns[] = $debits - $credits;
                        }
                    }
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    $this->db->where('(item = 0 or item is null)');
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    
                    if($account_type_id == 11 || $account_type_id == 12){
                        $columns[] = $credits - $debits;
                    }else{
                        $columns[] = $debits - $credits;
                    }
                    
                    break;
                default:
                  // code...
                  break;
            }
            
            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }

            $child_account[] = ['name' => $name, 'columns' => $columns, 'child_account' => $this->get_data_custom_summary_report_by_income_statement_recursive([
                        'child_account' => [],
                        'account_id' => $val['id'],
                        'account_type_id' => $account_type_id,
                        'from_date' => $from_date,
                        'to_date' => $to_date,
                        'accounting_method' => $accounting_method,
                        'acc_show_account_numbers' => $acc_show_account_numbers,
                        'display_rows_by' => $display_rows_by,
                        'display_columns_by' => $display_columns_by,
                    ])];
            
        }

        return $child_account;
    }

    /**
     * get data custom summary report
     * @param  array $data_filter 
     * @return array           
     */
    public function get_data_custom_summary_report_by_balance_sheet($data_filter){
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $display_rows_by = 'income_statement';
        $display_columns_by = 'total_only';

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        if(isset($data_filter['display_rows_by'])){
            $display_rows_by = $data_filter['display_rows_by'];
        }

        if(isset($data_filter['display_columns_by'])){
            $display_columns_by = $data_filter['display_columns_by'];
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_accounts = [];

        foreach ($account_type_details as $key => $value) {
            if($value['account_type_id'] == 1){
                $data_accounts['accounts_receivable'][] = $value;
            }
            if($value['account_type_id'] == 2){
                $data_accounts['current_assets'][] = $value;
            }
            if($value['account_type_id'] == 3 || $value['account_type_id'] == 16){
                $data_accounts['cash_and_cash_equivalents'][] = $value;
            }
            if($value['account_type_id'] == 4){
                $data_accounts['fixed_assets'][] = $value;
            }
            if($value['account_type_id'] == 5){
                $data_accounts['non_current_assets'][] = $value;
            }
            if($value['account_type_id'] == 6){
                $data_accounts['accounts_payable'][] = $value;
            }
            if($value['account_type_id'] == 7){
                $data_accounts['credit_card'][] = $value;
            }
            if($value['account_type_id'] == 8){
                $data_accounts['current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 9){
                $data_accounts['non_current_liabilities'][] = $value;
            }
            if($value['account_type_id'] == 10){
                $data_accounts['owner_equity'][] = $value;
            }

            if($value['account_type_id'] == 11){
                $data_accounts['income'][] = $value;
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }

        foreach ($data_accounts as $data_key => $data_account) {
            $data_report[$data_key] = [];
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('(parent_account is null or parent_account = 0)');
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                        $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                    }else{
                        $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                    }

                    $columns = [];
                    switch ($display_columns_by) {
                        case 'total_only':
                            $this->db->select('sum(credit) as credit, sum(debit) as debit');
                            $this->db->where('account', $val['id']);
                            if($accounting_method == 'cash'){
                                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                            }
                            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                            $credits = $account_history->credit != '' ? $account_history->credit : 0;
                            $debits = $account_history->debit != '' ? $account_history->debit : 0;

                            if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                                $columns[] = $credits - $debits;
                            }else{
                                $columns[] = $debits - $credits;
                            }
                          break;

                        case 'months':
                            $start = $month = strtotime($from_date);
                            $end = strtotime($to_date);

                            while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
                            {
                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('account', $val['id']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;

                                if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }

                                $month = strtotime("+1 month", $month);
                            }
                          break;

                        case 'quarters':
                            $start = strtotime($from_date);
                            $end = strtotime($to_date);

                            while ($start < $end) {
                                $month = date('m', $start);
                                $year = date('Y', $start);
                                if($month>=1 && $month<=3)
                                {
                                    $start_date = date('Y-m-d', strtotime('1-January-'.$year));  // timestamp or 1-Januray 12:00:00 AM
                                    $end_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                                }
                                else  if($month>=4 && $month<=6)
                                {
                                    $start_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM
                                    $end_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                                }
                                else  if($month>=7 && $month<=9)
                                {
                                    $start_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM
                                    $end_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                                }
                                else  if($month>=10 && $month<=12)
                                {
                                    $start_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM
                                    $end_date = date('Y-m-d', strtotime('1-January-'.($year+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                                }

                                $custom_date_select = '(date BETWEEN "' .
                                $start_date .
                                '" AND "' .
                                $end_date . '")';

                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('account', $val['id']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where($custom_date_select);
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;
                                
                                if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }

                                $start = strtotime('+3 month', $start);

                                if($start > $end){
                                    $month_2 = date('m', $start);
                                    $year_2 = date('Y', $start);
                                    
                                    if($month_2>=1 && $month_2<=3)
                                    {
                                        $start_date = date('Y-m-d', strtotime('1-January-'.$year_2));  // timestamp or 1-Januray 12:00:00 AM
                                        $end_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                                    }
                                    else  if($month_2>=4 && $month_2<=6)
                                    {
                                        $start_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM
                                        $end_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                                    }
                                    else  if($month_2>=7 && $month_2<=9)
                                    {
                                        $start_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM
                                        $end_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                                    }
                                    else  if($month_2>=10 && $month_2<=12)
                                    {
                                        $start_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM
                                        $end_date = date('Y-m-d', strtotime('1-January-'.($year_2+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                                    }

                                    if($month . ' - ' . $year != $month_2 . ' - ' . $year_2){
                                        $custom_date_select = '(date BETWEEN "' .
                                        $start_date .
                                        '" AND "' .
                                        $end_date . '")';

                                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                        $this->db->where('account', $val['id']);
                                        if($accounting_method == 'cash'){
                                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                        }
                                        $this->db->where($custom_date_select);
                                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                        $debits = $account_history->debit != '' ? $account_history->debit : 0;

                                        if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                                            $columns[] = $credits - $debits;
                                        }else{
                                            $columns[] = $debits - $credits;
                                        }
                                    }
                                }
                            }
                            break;

                        case 'years':
                            $start = strtotime($from_date);
                            $end = strtotime($to_date);

                            while ($start < $end) {
                                $year = date('Y', $start);

                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('account', $val['id']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('year(date) = "' . $year . '"');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;
                                
                                if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }

                                $start = strtotime('+1 year', $start);

                                if($start > $end){
                                    $year_2 = date('Y', $end);
                              
                                    if($year != $year_2){
                                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                        $this->db->where('account', $val['id']);
                                        if($accounting_method == 'cash'){
                                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                        }
                                        $this->db->where('year(date) = "' . $year_2 . '"');
                                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                        $debits = $account_history->debit != '' ? $account_history->debit : 0;
                                        
                                        if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                                            $columns[] = $credits - $debits;
                                        }else{
                                            $columns[] = $debits - $credits;
                                        }
                                    }
                                }
                            }
                            break;
                        case 'customers':
                            $this->load->model('clients_model');
                            $clients = $this->clients_model->get();
                            foreach ($clients as $key => $client) {
                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('customer', $client['userid']);
                                $this->db->where('account', $val['id']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;
                                
                                if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }
                            }

                            $this->db->select('sum(credit) as credit, sum(debit) as debit');
                            $this->db->where('account', $val['id']);
                            $this->db->where('(customer = 0 or customer is null)');
                            if($accounting_method == 'cash'){
                                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                            }
                            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                            $credits = $account_history->credit != '' ? $account_history->credit : 0;
                            $debits = $account_history->debit != '' ? $account_history->debit : 0;
                            
                            if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                                $columns[] = $credits - $debits;
                            }else{
                                $columns[] = $debits - $credits;
                            }
                          break;

                        case 'vendors':
                            $this->load->model('purchase/purchase_model');
                            $vendors = $this->purchase_model->get_vendor();
                            foreach ($vendors as $key => $vendor) {
                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('account', $val['id']);
                                $this->db->where('vendor', $vendor['userid']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;
                                
                                if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }
                            }

                            $this->db->select('sum(credit) as credit, sum(debit) as debit');
                            $this->db->where('account', $val['id']);
                            $this->db->where('(vendor = 0 or vendor is null)');
                            if($accounting_method == 'cash'){
                                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                            }
                            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                            $credits = $account_history->credit != '' ? $account_history->credit : 0;
                            $debits = $account_history->debit != '' ? $account_history->debit : 0;
                            
                            if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                                $columns[] = $credits - $debits;
                            }else{
                                $columns[] = $debits - $credits;
                            }
                          break;

                        case 'employees':
                          $this->load->model('staff_model');
                          $staffs = $this->staff_model->get();
                          foreach ($staffs as $key => $staff) {
                            $this->db->select('sum(credit) as credit, sum(debit) as debit');
                            $this->db->where('account', $val['id']);
                            $this->db->where('addedfrom', $staff['staffid']);
                            if($accounting_method == 'cash'){
                                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                            }
                            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                            $credits = $account_history->credit != '' ? $account_history->credit : 0;
                            $debits = $account_history->debit != '' ? $account_history->debit : 0;
                            
                            if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                                $columns[] = $credits - $debits;
                            }else{
                                $columns[] = $debits - $credits;
                            }
                          }
                          break;

                        case 'product_service':
                            $this->load->model('invoice_items_model');
                            $items = $this->invoice_items_model->get();
                            foreach ($items as $key => $item) {
                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('account', $val['id']);
                                $this->db->where('item', $item['itemid']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;
                                
                                if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }
                            }
                            $this->db->select('sum(credit) as credit, sum(debit) as debit');
                            $this->db->where('account', $val['id']);
                            $this->db->where('(item = 0 or item is null)');
                            if($accounting_method == 'cash'){
                                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                            }
                            $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                            $credits = $account_history->credit != '' ? $account_history->credit : 0;
                            $debits = $account_history->debit != '' ? $account_history->debit : 0;
                            
                            if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){
                                $columns[] = $credits - $debits;
                            }else{
                                $columns[] = $debits - $credits;
                            }
                            
                            break;
                        default:
                          // code...
                          break;
                    }

                    $child_account = $this->get_data_custom_summary_report_by_balance_sheet_recursive([
                        'child_account' => [],
                        'account_id' => $val['id'],
                        'account_type_id' => $value['account_type_id'],
                        'from_date' => $from_date,
                        'to_date' => $to_date,
                        'accounting_method' => $accounting_method,
                        'acc_show_account_numbers' => $acc_show_account_numbers,
                        'display_rows_by' => $display_rows_by,
                        'display_columns_by' => $display_columns_by,
                    ]);

                    $data_report[$data_key][] = ['name' => $name, 'columns' => $columns, 'child_account' => $child_account];
                }
            }
        }

        $data_total_2 = [];
        foreach ($data_accounts as $data_key => $data_account) {
            if($data_key != 'income' && $data_key != 'other_income' && $data_key != 'cost_of_sales' && $data_key != 'expenses' && $data_key != 'other_expenses'){
                continue;
            }
            $total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                            $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                        }else{
                            $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                        }


                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7){
                        $total += $credits - $debits;
                    }else{
                        $total += $debits - $credits;
                    }

                }
            }
            $data_total_2[$data_key] = $total;
        }

        $income = $data_total_2['income'] + $data_total_2['other_income'];
        $expenses = $data_total_2['expenses'] + $data_total_2['other_expenses'] + $data_total_2['cost_of_sales'];
        $net_income = $income - $expenses;

        return ['data' => $data_report, 'from_date' => $from_date, 'to_date' => $to_date, 'display_rows_by' => $display_rows_by, 'display_columns_by' => $display_columns_by, 'net_income' => $net_income];
    }

    /**
     * get data custom summary recursive
     * @param  array $data         
     * @return array                 
     */
    public function get_data_custom_summary_report_by_balance_sheet_recursive($data){
        $child_account = $data['child_account'];
        $account_id = $data['account_id'];
        $account_type_id = $data['account_type_id'];
        $from_date = $data['from_date'];
        $to_date = $data['to_date'];
        $accounting_method = $data['accounting_method'];
        $acc_show_account_numbers = $data['acc_show_account_numbers'];
        $display_rows_by = $data['display_rows_by'];
        $display_columns_by = $data['display_columns_by'];

        $this->db->where('active', 1);
        $this->db->where('parent_account', $account_id);
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
        $data_return = [];
       
        foreach ($accounts as $val) {
            $columns = [];
            switch ($display_columns_by) {
                case 'total_only':
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;

                    if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                        $columns[] = $credits - $debits;
                    }else{
                        $columns[] = $debits - $credits;
                    }
                  break;

                case 'months':
                    $start = $month = strtotime($from_date);
                    $end = strtotime($to_date);

                    while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
                    {
                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('account', $val['id']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;

                        if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                            $columns[] = $credits - $debits;
                        }else{
                            $columns[] = $debits - $credits;
                        }

                        $month = strtotime("+1 month", $month);
                    }
                  break;

                case 'quarters':
                    $start = strtotime($from_date);
                    $end = strtotime($to_date);

                    while ($start < $end) {
                        $month = date('m', $start);
                        $year = date('Y', $start);
                        if($month>=1 && $month<=3)
                        {
                            $start_date = date('Y-m-d', strtotime('1-January-'.$year));  // timestamp or 1-Januray 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                        }
                        else  if($month>=4 && $month<=6)
                        {
                            $start_date = date('Y-m-d', strtotime('1-April-'.$year));  // timestamp or 1-April 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                        }
                        else  if($month>=7 && $month<=9)
                        {
                            $start_date = date('Y-m-d', strtotime('1-July-'.$year));  // timestamp or 1-July 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                        }
                        else  if($month>=10 && $month<=12)
                        {
                            $start_date = date('Y-m-d', strtotime('1-October-'.$year));  // timestamp or 1-October 12:00:00 AM
                            $end_date = date('Y-m-d', strtotime('1-January-'.($year+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                        }

                        $custom_date_select = '(date BETWEEN "' .
                        $start_date .
                        '" AND "' .
                        $end_date . '")';

                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('account', $val['id']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where($custom_date_select);
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;
                        
                        if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                            $columns[] = $credits - $debits;
                        }else{
                            $columns[] = $debits - $credits;
                        }

                        $start = strtotime('+3 month', $start);

                        if($start > $end){
                            $month_2 = date('m', $start);
                            $year_2 = date('Y', $start);
                            
                            if($month_2>=1 && $month_2<=3)
                            {
                                $start_date = date('Y-m-d', strtotime('1-January-'.$year_2));  // timestamp or 1-Januray 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM means end of 31 March
                            }
                            else  if($month_2>=4 && $month_2<=6)
                            {
                                $start_date = date('Y-m-d', strtotime('1-April-'.$year_2));  // timestamp or 1-April 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM means end of 30 June
                            }
                            else  if($month_2>=7 && $month_2<=9)
                            {
                                $start_date = date('Y-m-d', strtotime('1-July-'.$year_2));  // timestamp or 1-July 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM means end of 30 September
                            }
                            else  if($month_2>=10 && $month_2<=12)
                            {
                                $start_date = date('Y-m-d', strtotime('1-October-'.$year_2));  // timestamp or 1-October 12:00:00 AM
                                $end_date = date('Y-m-d', strtotime('1-January-'.($year_2+1)));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
                            }

                            if($month . ' - ' . $year != $month_2 . ' - ' . $year_2){
                                $custom_date_select = '(date BETWEEN "' .
                                $start_date .
                                '" AND "' .
                                $end_date . '")';

                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('account', $val['id']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where($custom_date_select);
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;

                                if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }
                            }
                        }
                    }
                    break;

                case 'years':
                    $start = strtotime($from_date);
                    $end = strtotime($to_date);

                    while ($start < $end) {
                        $year = date('Y', $start);

                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('account', $val['id']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('year(date) = "' . $year . '"');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;
                        
                        if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                            $columns[] = $credits - $debits;
                        }else{
                            $columns[] = $debits - $credits;
                        }

                        $start = strtotime('+1 year', $start);

                        if($start > $end){
                            $year_2 = date('Y', $end);
                      
                            if($year != $year_2){
                                $this->db->select('sum(credit) as credit, sum(debit) as debit');
                                $this->db->where('account', $val['id']);
                                if($accounting_method == 'cash'){
                                    $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                                }
                                $this->db->where('year(date) = "' . $year_2 . '"');
                                $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                                $credits = $account_history->credit != '' ? $account_history->credit : 0;
                                $debits = $account_history->debit != '' ? $account_history->debit : 0;
                                
                                if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                                    $columns[] = $credits - $debits;
                                }else{
                                    $columns[] = $debits - $credits;
                                }
                            }
                        }
                    }
                    break;
                case 'customers':
                    $this->load->model('clients_model');
                    $clients = $this->clients_model->get();
                    foreach ($clients as $key => $client) {
                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('customer', $client['userid']);
                        $this->db->where('account', $val['id']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;
                        
                        if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                            $columns[] = $credits - $debits;
                        }else{
                            $columns[] = $debits - $credits;
                        }
                    }

                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    $this->db->where('(customer = 0 or customer is null)');
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    
                    if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                        $columns[] = $credits - $debits;
                    }else{
                        $columns[] = $debits - $credits;
                    }
                  break;

                case 'vendors':
                    $this->load->model('purchase/purchase_model');
                    $vendors = $this->purchase_model->get_vendor();
                    foreach ($vendors as $key => $vendor) {
                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('account', $val['id']);
                        $this->db->where('vendor', $vendor['userid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;
                        
                        if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                            $columns[] = $credits - $debits;
                        }else{
                            $columns[] = $debits - $credits;
                        }
                    }

                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    $this->db->where('(vendor = 0 or vendor is null)');
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    
                    if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                        $columns[] = $credits - $debits;
                    }else{
                        $columns[] = $debits - $credits;
                    }
                  break;

                case 'employees':
                  $this->load->model('staff_model');
                  $staffs = $this->staff_model->get();
                  foreach ($staffs as $key => $staff) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    $this->db->where('addedfrom', $staff['staffid']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    
                    if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                        $columns[] = $credits - $debits;
                    }else{
                        $columns[] = $debits - $credits;
                    }
                  }
                  break;

                case 'product_service':
                    $this->load->model('invoice_items_model');
                    $items = $this->invoice_items_model->get();
                    foreach ($items as $key => $item) {
                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('account', $val['id']);
                        $this->db->where('item', $item['itemid']);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;
                        
                        if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                            $columns[] = $credits - $debits;
                        }else{
                            $columns[] = $debits - $credits;
                        }
                    }
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $val['id']);
                    $this->db->where('(item = 0 or item is null)');
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    
                    if($account_type_id == 11 || $account_type_id == 12 || $account_type_id == 8 || $account_type_id == 9 || $account_type_id == 10 || $account_type_id == 7 || $account_type_id == 6){
                        $columns[] = $credits - $debits;
                    }else{
                        $columns[] = $debits - $credits;
                    }
                    
                    break;
                default:
                  // code...
                  break;
            }
            
            if($acc_show_account_numbers == 1 && $val['number'] != ''){
                $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
            }else{
                $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
            }

            $child_account[] = ['name' => $name, 'columns' => $columns, 'child_account' => $this->get_data_custom_summary_report_by_balance_sheet_recursive([
                        'child_account' => [],
                        'account_id' => $val['id'],
                        'account_type_id' => $account_type_id,
                        'from_date' => $from_date,
                        'to_date' => $to_date,
                        'accounting_method' => $accounting_method,
                        'acc_show_account_numbers' => $acc_show_account_numbers,
                        'display_rows_by' => $display_rows_by,
                        'display_columns_by' => $display_columns_by,
                    ])];
            
        }

        return $child_account;
    }

    /**
     * delete all data the account detail types table
     *
     * @param      int   $id     The identifier
     *
     * @return     boolean
     */
    public function reset_account_detail_types()
    {
        $affectedRows = 0;
        if ($this->db->table_exists(db_prefix() . 'acc_account_type_details')) {
            $this->db->query('DROP TABLE `'.db_prefix() .'acc_account_type_details`;');
            $this->db->query('CREATE TABLE ' . db_prefix() . "acc_account_type_details (
              `id` INT(11) NOT NULL AUTO_INCREMENT,
              `account_type_id` INT(11) NOT NULL,
              `name` VARCHAR(255) NOT NULL,
              `note` TEXT NULL,
              `statement_of_cash_flows` VARCHAR(255) NULL,
              PRIMARY KEY (`id`)
            ) AUTO_INCREMENT=200, ENGINE=InnoDB DEFAULT CHARSET=" . $this->db->char_set . ';');
            $affectedRows++;
        }

        if ($affectedRows > 0) {
            return true;
        }
        return false;
    }

    /**
     * Automatic credit note conversion
     * @param  integer $payment_id 
     * @return boolean
     */
    public function automatic_credit_note_conversion($data){
        $this->delete_convert($data['credit_id'], 'credit_note');

        $payment_account = get_option('acc_credit_note_payment_account');
        $deposit_to = get_option('acc_credit_note_deposit_to');
        $affectedRows = 0;

        if(get_option('acc_close_the_books') == 1){
            if(strtotime(date('Y-m-d')) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                return false;
            }
        }

        $this->load->model('invoices_model');
        $invoice = $this->invoices_model->get($data['data']['invoice_id']);

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $payment_total = $data['data']['amount'];
        $currency_rate = 0;
        if($invoice->currency_name != $currency->name){
            $currency_rate = acc_get_currency_rate($invoice->currency_name, $currency->name);
            $payment_total = round($currency_rate * $data['data']['amount'], 2);
        }

        if(get_option('acc_credit_note_automatic_conversion') == 1){
            $node = [];
            $node['split'] = $payment_account;
            $node['account'] = $deposit_to;
            $node['customer'] = $invoice->clientid;
            $node['debit'] = $payment_total;
            $node['credit'] = 0;
            $node['date'] = date('Y-m-d');
            $node['description'] = '';
            $node['rel_id'] = $data['credit_id'];
            $node['rel_type'] = 'credit_note';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $node['currency_rate'] = $currency_rate;
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $deposit_to;
            $node['customer'] = $invoice->clientid;
            $node['account'] = $payment_account;
            $node['date'] = date('Y-m-d');
            $node['debit'] = 0;
            $node['credit'] = $payment_total;
            $node['description'] = '';
            $node['rel_id'] = $data['credit_id'];
            $node['rel_type'] = 'credit_note';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $node['currency_rate'] = $currency_rate;
            $data_insert[] = $node;
        }

        if($data_insert != []){
            $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
        }
            
        if ($affectedRows > 0) {
            return true;
        }

        return false;
    }

    public function get_account_bank_data($bank_id){
        $this->db->where('id', $bank_id);
        $this->db->order_by('id', 'asc');

        $transactions = $this->db->get(db_prefix().'acc_accounts')->result_array();

        $rResult = [];
        foreach ($transactions as $key => $value) {
            $rResult[$key]['plaid_status'] = $value['plaid_status'];
            $rResult[$key]['account_name'] = $value['plaid_account_name'];
        }
         
        return $rResult;
    }

    public function get_plaid_transaction($bank_id){
        $this->db->where('bank_id', $bank_id);
        $this->db->order_by('date', 'desc');

        $transactions = $this->db->get(db_prefix().'acc_transaction_bankings')->result_array();
      
        $account_type_name = [];
        $detail_type_name = [];

        $rResult = [];
        foreach ($transactions as $key => $value) {
            $rResult[$key]['withdrawals'] = $value['withdrawals'] != 0 ? $value['withdrawals'] : '';
            $rResult[$key]['deposits'] = $value['deposits'] != 0 ? $value['deposits'] : '';
            $rResult[$key]['date'] = $value['date'];
            $rResult[$key]['payee'] = $value['description'];
            //$rResult[$key]['check_number'] = $value['check_number'];
            $rResult[$key]['datecreated'] = $value['datecreated'];
        }
         
        return $rResult;
    }

    public function get_last_refresh_data($bank_id){
        $this->db->where('bank_id', $bank_id);
        $this->db->order_by('id', 'desc');
        $this->db->limit(1);
        $refresh_date = $this->db->get(db_prefix().'acc_plaid_transaction_logs')->result_array();

        $rResult = [];
        foreach ($refresh_date as $key => $value) {
            $rResult[$key]['refresh_date'] = $value['last_updated'];
            
            $this->db->where('bank_id', $bank_id);
            $this->db->where('date', $value['last_updated']);
            $count = $this->db->get(db_prefix().'acc_transaction_bankings')->result_array();
            $count = count($count);
            
            $rResult[$key]['count'] = $count;
        }
         
        return $rResult;
    }

    public function get_date_last_updated($bank_id){
        $this->db->where('bank_id', $bank_id);
        $this->db->order_by('last_updated', 'desc');
        $this->db->limit(1);

        $plaid_transaction_log = $this->db->get(db_prefix().'acc_plaid_transaction_logs')->row();

        if($plaid_transaction_log)
        {
            return $plaid_transaction_log->last_updated;
        }

        return '';
    }


    public function get_plaid_link_token(){
        $data = $this->get_plaid_params(); 
        $data['products'] = ["transactions"];
        $data['client_name'] = 'Plaid Test App';
        $data['country_codes'] = ["US"];
        $data['language'] = 'en';
        $data['user'] = ['client_user_id' => 'testUser'];

        $data_string = json_encode($data);

        $plaid_environment = $this->get_plaid_environment();

        $url = $plaid_environment.'link/token/create';

        $curl = curl_init($url);
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($curl, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json',
            'Content-Length: ' . strlen($data_string))
        );
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($curl, CURLOPT_TIMEOUT, 120);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 120);
        curl_setopt($curl, CURLOPT_MAXREDIRS, 10);
        
        $result = curl_exec($curl);

        $result = json_decode($result);

        return isset($result->link_token) ? $result->link_token : '';
    }

    public function get_plaid_params(){
        $plaid_environment = get_option('acc_plaid_environment');

        switch ($plaid_environment) {
            case 'production':
                $secret = get_option('acc_live_secret');
                break;
            case 'sandbox':
                $secret = get_option('acc_sandbox_secret');
                break;
            case 'development':
                $secret = get_option('acc_sandbox_secret');
                break;
            default:
                $secret = get_option('acc_live_secret');
                break;
        }

        $data = array(
            "client_id" => get_option('acc_plaid_client_id'), 
            "secret" => $secret, 
        );
        return $data;
    }

    public function get_plaid_environment(){
        $plaid_environment = get_option('acc_plaid_environment');
        
        switch ($plaid_environment) {
            case 'production':
                return 'https://production.plaid.com/';
                break;
            case 'sandbox':
                return 'https://sandbox.plaid.com/';
                break;
            case 'development':
                return 'https://development.plaid.com/';
                break;
            default:
                return 'https://production.plaid.com/';
                break;
        }
    }

    /**
     * update general setting
     *
     * @param      array   $data   The data
     *
     * @return     boolean 
     */
    public function update_plaid_environment($data){
        foreach ($data as $key => $value) {
            update_option($key, $value);
            
            if ($this->db->affected_rows() > 0) {
                $affectedRows++;
            }
        }
        
        if ($affectedRows > 0) {
            return true;
        }
        return false;
    }

    public function plaid_get_account($access_token){
        $data = $this->get_plaid_params(); 
        $data['access_token'] = $access_token;

        $data_string = json_encode($data);

        $plaid_environment = $this->get_plaid_environment();

        $url = $plaid_environment.'accounts/get';

        $curl = curl_init($url);
        
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($curl, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json',
            'Content-Length: ' . strlen($data_string))
        );
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($curl, CURLOPT_TIMEOUT, 120);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 120);
        curl_setopt($curl, CURLOPT_MAXREDIRS, 10);
        
        $result = curl_exec($curl);

        $result = json_decode($result);

        return $result->accounts;
    }


    public function get_access_token($public_token){
        $data = $this->get_plaid_params(); 
        $data['public_token'] = $public_token;

        $data_string = json_encode($data);

        $plaid_environment = $this->get_plaid_environment();

        $url = $plaid_environment.'item/public_token/exchange';

        $curl = curl_init($url);
        
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($curl, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json',
            'Content-Length: ' . strlen($data_string))
        );
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($curl, CURLOPT_TIMEOUT, 120);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 120);
        curl_setopt($curl, CURLOPT_MAXREDIRS, 10);
        
        $result = curl_exec($curl);

        $result = json_decode($result);

        return $result->access_token;
    }


    public function plaid_get_transactions($data_filter, $retry = 1){
        $data = $this->get_plaid_params(); 
        $data['access_token'] = $data_filter['access_token'];
        $data['start_date'] = $data_filter['start_date'];
        $data['end_date'] = $data_filter['end_date'];
        $data['options'] = ['include_original_description' => true];

        if(isset($data_filter['count'])){
            $data['options']['count'] = $data_filter['count'];
        }

        if(isset($data_filter['offset'])){
            $data['options']['offset'] = $data_filter['offset'];
        }
        
        $data_string = json_encode($data);

        $plaid_environment = $this->get_plaid_environment();

        $url = $plaid_environment.'transactions/get';

        $curl = curl_init($url);
        
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($curl, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json',
            'Content-Length: ' . strlen($data_string))
        );
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($curl, CURLOPT_TIMEOUT, 120);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 120);
        curl_setopt($curl, CURLOPT_MAXREDIRS, 10);
        
        $result = curl_exec($curl);

        $result = json_decode($result);
        if(isset($result->transactions)){
            return $result->transactions;
        }elseif (isset($result->error_code)) {
            return $result;
        }else{
            if($retry < 3){
                return $this->plaid_get_transactions($data_filter, $retry+1);
            }else{
                return false;
            }
        }
    }

    /**
     * add bank reconcile
     * @param array $data 
     * @return  integer or boolean
     */
    public function add_bank_reconcile($data){
        if(isset($data['reconcile_id'])){
            unset($data['reconcile_id']);
        }

        if($data['ending_date'] != ''){
            $data['ending_date'] = to_sql_date($data['ending_date']);
        }

        $data['ending_balance'] = str_replace(',', '', $data['ending_balance']);
        $data['debits_for_period'] = str_replace(',', '', $data['debits_for_period']);
        $data['credits_for_period'] = str_replace(',', '', $data['credits_for_period']);
        $data['beginning_balance'] = str_replace(',', '', $data['beginning_balance']);
        
        $this->db->insert(db_prefix().'acc_bank_reconciles', $data);
        $insert_id = $this->db->insert_id();
        
        if($insert_id){
            return $insert_id;
        }

        return false;
    }

    public function get_bank_reconcile_difference_info($reconcile_id){
        $rs = 0;
        $from_date = '';
        $to_date = '';

        $reconcile = $this->get_bank_reconcile($reconcile_id);
        if($reconcile){
            $to_date = $reconcile->ending_date;
        }

        $recently_reconcile = $this->get_recently_bank_reconcile_by_account($reconcile->account, $reconcile_id);
        if($recently_reconcile){
            $from_date = $recently_reconcile->ending_date;
        }



        $this->db->where('account', $reconcile->account);

        if ($from_date != '' && $to_date != '') {
            $this->db->where('(date > "' . $from_date . '" and date <= "' . $to_date . '")');
        } elseif ($to_date != '' && $from_date == '') {
            $this->db->where('(date <= "' . $to_date . '")');
        }
            
        $this->db->where('('.db_prefix() . 'acc_account_history.bank_reconcile ='. $reconcile->id.' or '.db_prefix() . 'acc_account_history.bank_reconcile = 0)');
       
        $transactions = $this->db->get(db_prefix().'acc_account_history')->result_array();

        $this->db->where('bank_id', $reconcile->account);
        if ($from_date != '' && $to_date != '') {
            $this->db->where('(date > "' . $from_date . '" and date <= "' . $to_date . '")');
        } elseif ($to_date != '' && $from_date == '') {
            $this->db->where('(date <= "' . $to_date . '")');
        }
        $bankings = $this->db->get(db_prefix().'acc_transaction_bankings')->result_array();

        $banking_matched = [];

        $data_return = [];
        $data_return['banking_register_withdrawals'] = 0;
        $data_return['banking_register_deposits'] = 0;
        $data_return['posted_bank_withdrawals'] = 0;
        $data_return['posted_bank_deposits'] = 0;

        foreach($transactions as $tran){
            $data_return['banking_register_withdrawals'] +=  $tran['credit'];
            $data_return['banking_register_deposits'] +=  $tran['debit'];
        }

        foreach($bankings as $bank){
            $data_return['posted_bank_withdrawals'] +=  $bank['withdrawals'];
            $data_return['posted_bank_deposits'] +=  $bank['deposits'];
        }
            
        return $data_return;
    }

    /**
     * get reconcile
     * @param  string $id
     * @param  array  $where
     * @return array or object
     */
    public function get_reconcile($id = '', $where = [])
    {
        if (is_numeric($id)) {
            $this->db->where('id', $id);
            return $this->db->get(db_prefix() . 'acc_reconciles')->row();
        }

        $this->db->where($where);
        $this->db->order_by('id', 'desc');
        return $this->db->get(db_prefix() . 'acc_reconciles')->result_array();
    }

    /**
     * Gets the recently reconcile by account.
     *
     * @param        $bank_account  The bank account
     * @param        $reconcile_id  The reconcile identifier
     */
    public function get_recently_bank_reconcile_by_account($bank_account, $reconcile_id){
        $this->db->where('account', $bank_account);
        $this->db->where('opening_balance', 0);
        
        $this->db->where('id != '.$reconcile_id);
        $this->db->order_by('id', 'desc');
        
        $reconcile = $this->db->get(db_prefix() . 'acc_bank_reconciles')->row();

        if($reconcile){
            return $reconcile;
        }
        return false;
    }

    /**
     * Get account_id by number
     *
     * @param      string  $number  The account number
     * @param      string  $company_id
     *
     * @return     array  The date range report period.
     */
    public function get_account_id_by_number($number = ''){

        $this->db->where('number', $number);
        $account = $this->db->get(db_prefix() . 'acc_accounts')->row();

        if($account){
            return $account->id;
        }

        return false;
    }

    public function match_transactions($reconcile_id, $account_id){
        $rs = 0;
        $from_date = '';
        $to_date = '';

        $reconcile = $this->get_bank_reconcile($reconcile_id);
        if($reconcile){
            $to_date = $reconcile->ending_date;
        }

        if($account_id != ''){
            $recently_reconcile = $this->get_recently_bank_reconcile_by_account($account_id, $reconcile_id);
            if($recently_reconcile){
                $from_date = $recently_reconcile->ending_date;
            }
        }

        $this->db->where('account', $account_id);
        $this->db->where('(cleared != 1 or bank_reconcile = 0)');
        if ($from_date != '' && $to_date != '') {
            $this->db->where('(date > "' . $from_date . '" and date <= "' . $to_date . '")');
        } elseif ($to_date != '' && $from_date == '') {
            $this->db->where('(date <= "' . $to_date . '")');
        }
        $transactions = $this->db->get(db_prefix().'acc_account_history')->result_array();

        $this->db->where('bank_id', $account_id);
        if ($from_date != '' && $to_date != '') {
            $this->db->where('(date > "' . $from_date . '" and date <= "' . $to_date . '")');
        } elseif ($to_date != '' && $from_date == '') {
            $this->db->where('(date <= "' . $to_date . '")');
        }
        $this->db->where('(matched != 1 or reconcile = 0)');
        $bankings = $this->db->get(db_prefix().'acc_transaction_bankings')->result_array();

        $banking_matched = [];

        $data_return = [];
        
        foreach($transactions as $tran){
            
            foreach($bankings as $bank){
                if(in_array($bank['id'], $banking_matched)){
                    continue;
                }
                $check = 1;
                if($tran['date'] != $bank['date']){
                    $check = 0;
                }
                
                if($tran['credit'] != $bank['withdrawals']){
                    $check = 0;
                }

                if($tran['debit'] != $bank['deposits']){
                    $check = 0;
                }
                
                if($check == 1){
                    $banking_matched[] = $bank['id'];

                    $this->db->where('id', $bank['id']);
                    $this->db->update(db_prefix().'acc_transaction_bankings', [
                        'reconcile' => $reconcile_id,
                        'matched' => 1,
                    ]);
                    if($this->db->affected_rows() > 0){
                        $rs++;
                    }

                    $this->db->where('id', $tran['id']);
                    $this->db->update(db_prefix().'acc_account_history', [
                        'bank_reconcile' => $reconcile_id,
                        'cleared' => 1,
                    ]);
                    if($this->db->affected_rows() > 0){
                        $rs++;
                    }

                    $this->db->insert(db_prefix().'acc_matched_transactions', [
                        'account_history_id' => $tran['id'],
                        'history_amount' => 0,
                        'rel_id' => $bank['id'],
                        'rel_type' => 'banking',
                        'amount' => 0,
                        'reconcile' => $reconcile_id,
                    ]);
                    break;
                }
            }
        }


        $this->db->where('account', $account_id);
        $this->db->where('(cleared != 1 or bank_reconcile = 0)');
        if ($from_date != '' && $to_date != '') {
            $this->db->where('(date > "' . $from_date . '" and date <= "' . $to_date . '")');
        } elseif ($to_date != '' && $from_date == '') {
            $this->db->where('(date <= "' . $to_date . '")');
        }
        $new_transactions = $this->db->get(db_prefix().'acc_account_history')->result_array();

        $this->db->where('bank_id', $account_id);
        $this->db->where('(matched != 1 or reconcile = 0)');
        if ($from_date != '' && $to_date != '') {
            $this->db->where('(date > "' . $from_date . '" and date <= "' . $to_date . '")');
        } elseif ($to_date != '' && $from_date == '') {
            $this->db->where('(date <= "' . $to_date . '")');
        }
        $new_bankings = $this->db->get(db_prefix().'acc_transaction_bankings')->result_array();

        foreach($new_transactions as $tran){
            $this->db->where('id', $tran['id']);
            $this->db->update(db_prefix().'acc_account_history', [
                'cleared' => -1,
            ]);
        }

        foreach($new_bankings as $bank){
            $this->db->where('id', $bank['id']);
            $this->db->update(db_prefix().'acc_transaction_bankings', [
                'matched' => -1,
                //'matched_with' => 0,
            ]);
        }

        if($rs > 0){
            return 1;
        }
        return 0;
    }


    public function unmatch_transactions($reconcile_id, $account_id){
        $affected_rows = 0;

        $from_date = '';
        $to_date = '';

        $reconcile = $this->get_bank_reconcile($reconcile_id);
        if($reconcile){
            $to_date = $reconcile->ending_date;
        }

        if($account_id != ''){
            $recently_reconcile = $this->get_recently_bank_reconcile_by_account($account_id, $reconcile_id);
            if($recently_reconcile){
                $from_date = $recently_reconcile->ending_date;
            }
        }

        $this->db->where('added_from_reconcile', 1);
        $this->db->where('bank_reconcile', $reconcile_id);
        $this->db->delete(db_prefix().'acc_account_history');

        $this->db->where('(reconcile = 0 or bank_reconcile = '.$reconcile_id.')');
        if ($from_date != '' && $to_date != '') {
            $this->db->where('(date > "' . $from_date . '" and date <= "' . $to_date . '")');
        } elseif ($to_date != '' && $from_date == '') {
            $this->db->where('(date <= "' . $to_date . '")');
        }
        $this->db->update(db_prefix().'acc_account_history', ['bank_reconcile' => 0, 'cleared' => 0]);
        if ($this->db->affected_rows() > 0) {
            $affected_rows++;
        }

        if ($from_date != '' && $to_date != '') {
            $this->db->where('(date > "' . $from_date . '" and date <= "' . $to_date . '")');
        } elseif ($to_date != '' && $from_date == '') {
            $this->db->where('(date <= "' . $to_date . '")');
        }
        $this->db->where('(reconcile = 0 or reconcile = '.$reconcile_id.')');
        $this->db->update(db_prefix().'acc_transaction_bankings', [
                    'adjusted' => 0,
                    'reconcile' => 0,
                    'matched' => 0,
                    //'matched_with' => 0,
                ]);

        if ($this->db->affected_rows() > 0) {
            $affected_rows++;
        }

        $this->db->where('rel_type', 'banking');
        $this->db->where('reconcile', $reconcile_id);
        $this->db->delete(db_prefix().'acc_matched_transactions');
        
        if ($this->db->affected_rows() > 0) {
            $affected_rows++;
        }

        $this->db->where('id', $reconcile->id);
        $this->db->update(db_prefix().'acc_bank_reconciles', ['finish' => 0]);

        if ($this->db->affected_rows() > 0) {
            $affected_rows++;
        }

        if($affected_rows > 0){
            return true;
        }
        return false;
    }

    public function get_transaction_uncleared($reconcile_id){
        $from_date = '';
        $to_date = '';

        $reconcile = $this->get_bank_reconcile($reconcile_id);
        if($reconcile){
            $to_date = $reconcile->ending_date;
        }

        $recently_reconcile = $this->get_recently_bank_reconcile_by_account($reconcile->account, $reconcile_id);
        if($recently_reconcile){
            $from_date = $recently_reconcile->ending_date;
        }

        $this->db->where('bank_id', $reconcile->account);
        $this->db->where('((matched != 1 and matched != -2) or adjusted = 1)');
        if ($from_date != '' && $to_date != '') {
            $this->db->where('(date > "' . $from_date . '" and date <= "' . $to_date . '")');
        } elseif ($to_date != '' && $from_date == '') {
            $this->db->where('(date <= "' . $to_date . '")');
        }

        $transaction_bankings = $this->db->get(db_prefix().'acc_transaction_bankings')->result_array();

        return $transaction_bankings;
    }

    public function make_adjusting_entry_save($data){
        if($data['type'] == 'add_transaction'){
            $transaction_banking = $this->get_transaction_banking($data['transaction_bank_id']);

            $node = [];
            $node['split'] = $transaction_banking->bank_id;
            $node['account'] = $data['account'];
            //$node['vendor'] = $data['payee'] != '' ? $data['payee'] : 0;
            $node['customer'] = 0;
            $node['debit'] = $transaction_banking->withdrawals;
            $node['date'] = $transaction_banking->date;
            $node['credit'] = $transaction_banking->deposits;
            $node['bank_reconcile'] = $data['reconcile'];
            $node['tax'] = 0;
            $node['cleared'] = 1;
            $node['description'] = $transaction_banking->description;
            $node['rel_id'] = $data['transaction_bank_id'];
            $node['rel_type'] = 'banking';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $node['added_from_reconcile'] = 1;

            $this->db->insert(db_prefix().'acc_account_history', $node);

            $node = [];
            $node['split'] = $data['account'];
            $node['account'] = $transaction_banking->bank_id;
            //$node['vendor'] = $data['payee'] != '' ? $data['payee'] : 0;
            $node['customer'] = 0;
            $node['debit'] = $transaction_banking->deposits;
            $node['date'] = $transaction_banking->date;
            $node['credit'] = $transaction_banking->withdrawals;
            $node['bank_reconcile'] = $data['reconcile'];
            $node['tax'] = 0;
            $node['cleared'] = 1;
            $node['description'] = $transaction_banking->description;
            $node['rel_id'] = $data['transaction_bank_id'];
            $node['rel_type'] = 'banking';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $node['added_from_reconcile'] = 1;

            $this->db->insert(db_prefix().'acc_account_history', $node);

            $insert_id = $this->db->insert_id();

            if ($insert_id) {
                $this->db->where('id', $data['transaction_bank_id']);
                $this->db->update(db_prefix().'acc_transaction_bankings', [
                    'adjusted' => 1,
                    'matched' => 1,
                    'reconcile' => $data['reconcile'],
                ]);

                return true;
            }
        }else{

            $this->db->where('id', $data['transaction']);
            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
            $withdrawal = str_replace(',', '', $data['withdrawal']);
            $deposit = str_replace(',', '', $data['deposit']);
            if($withdrawal > 0){
                $amount = $withdrawal;
            }else{
                $amount = $deposit;
            }

            if ($account_history) {
                $this->db->where('id', $data['transaction']);
                $this->db->update(db_prefix().'acc_account_history', [
                    'bank_reconcile' => $data['reconcile'],
                    'cleared' => 1,
                    'date' => to_sql_date($data['date']),
                    'credit' => $withdrawal,
                    'debit' => $deposit,
                ]);
               
                if($this->db->affected_rows() > 0){
                    // if($account_history->debit != $deposit || $account_history->credit != $withdrawal){
                    //     switch ($account_history->rel_type) {
                    //         case 'payment':
                    //             $this->load->model('payments_model');
                    //             $this->payments_model->update(['amount' => $amount, 'date' => _d($data['date']), 'note' => ''], $account_history->rel_id);
                    //             break;
                    //         case 'invoice':
                    //             $this->load->model('payments_model');
                    //             $this->invoices_model->update(['amount' => $amount, 'date' => _d($data['date']), 'note' => ''], $account_history->rel_id);
                    //             break;
                    //         case 'bill':
                    //             // code...
                    //             break;
                    //         case 'pay_bill':
                    //             // code...
                    //             break;
                    //         case 'check':
                    //             // code...
                    //             break;
                            
                    //         default:
                    //             // code...
                    //             break;
                    //     }
                    // }

                    $this->db->where('id', $data['transaction_bank_id']);
                    $this->db->update(db_prefix().'acc_transaction_bankings', [
                        'adjusted' => 1,
                        'matched' => 1,
                        'reconcile' => $data['reconcile'],
                    ]);

                    return true;
                }
            }
        }

        return false;
    }

    public function leave_it_uncleared($transaction_bank_id){
        $this->db->where('id', $transaction_bank_id);
        $this->db->update(db_prefix().'acc_transaction_bankings', [
            'matched' => -2,
            'adjusted' => 1,
        ]);

        if($this->db->affected_rows() > 0){
            return true;
        }

        return false;

    }

    public function get_transaction_leave_uncleared($bank_account){

        $from_date = date('Y-m-d', strtotime('today - 30 days'));
        $to_date = date('Y-m-d');

        // $recently_reconcile = $this->get_recently_bank_reconcile_by_account($reconcile->account, $reconcile_id);
        // if($recently_reconcile){
        //     $from_date = $recently_reconcile->ending_date;
        // }

        $this->db->where('bank_id', $bank_account);
        $this->db->where('matched = -2');
        if ($from_date != '' && $to_date != '') {
            $this->db->where('(date > "' . $from_date . '" and date <= "' . $to_date . '")');
        } elseif ($to_date != '' && $from_date == '') {
            $this->db->where('(date <= "' . $to_date . '")');
        }

        $transaction_bankings = $this->db->get(db_prefix().'acc_transaction_bankings')->result_array();

        return $transaction_bankings;
    }

    public function get_bank_transaction_uncleared($bank_account){

        $this->db->where('account', $bank_account);
        // $this->db->where('cleared', 0);

        // if ($from_date != '' && $to_date != '') {
        //     $this->db->where('(date > "' . $from_date . '" and date <= "' . $to_date . '")');
        // } elseif ($to_date != '' && $from_date == '') {
        //     $this->db->where('(date <= "' . $to_date . '")');
        // }

        $account_histories = $this->db->get(db_prefix().'acc_account_history')->result_array();

        return $account_histories;
    }

    /**
     * finish reconcile bank account
     * @param  array $data 
     * @return boolean       
     */
    public function finish_reconcile_bank_account($data){

        $this->db->where('id', $data['reconcile']);
        $this->db->update(db_prefix().'acc_bank_reconciles', ['finish' => 1]);

        if ($this->db->affected_rows() > 0) {
            $affectedRows++;
        }

        if ($affectedRows > 0) {
            return true;
        }

        return true;
    }


    /**
     * reconcile restored
     * @param  [type] $account 
     * @param  [type] $company 
     * @return [type]          
     */
    public function reconcile_bank_account_restored($account)
    {
        $affected_rows=0;
        
        $this->db->where('account', $account);
        $this->db->where('finish', 0);
        $this->db->where('opening_balance', 0);
        $this->db->order_by('ending_date', 'desc');

        $reconcile = $this->db->get(db_prefix() . 'acc_bank_reconciles')->row();

        if($reconcile){
            $this->db->where('bank_reconcile', $reconcile->id);
            $this->db->update(db_prefix() . 'acc_account_history', ['bank_reconcile' => 0, 'cleared' => 0]);
    
            $this->db->where('reconcile', $reconcile->id);
            $this->db->update(db_prefix().'acc_transaction_bankings', [
                        'reconcile' => 0,
                        'matched' => 0,
                        //'matched_with' => 0,
                    ]);

            if ($this->db->affected_rows() > 0) {
                $affected_rows++;
            }

            $this->db->where('rel_type', 'banking');
            $this->db->where('reconcile', $reconcile->id);
            $this->db->delete(db_prefix().'acc_matched_transactions');
            
            $this->db->where('id', $reconcile->id);
            $this->db->delete(db_prefix().'acc_bank_reconciles');

            if ($this->db->affected_rows() > 0) {
                $affected_rows++;
            }
        }else{
            //get reconcile
            $this->db->where('account', $account);
            $this->db->where('finish', 1);
            $this->db->where('opening_balance', 0);
            $this->db->order_by('ending_date', 'desc');

            $reconcile = $this->db->get(db_prefix() . 'acc_bank_reconciles')->row();

            if($reconcile){
                $this->db->where('bank_reconcile', $reconcile->id);
                $this->db->update(db_prefix() . 'acc_account_history', ['bank_reconcile' => 0, 'cleared' => 0]);

                $this->db->where('reconcile', $reconcile->id);
                $this->db->update(db_prefix().'acc_transaction_bankings', [
                            'reconcile' => 0,
                            'matched' => 0,
                            //'matched_with' => 0,
                        ]);

                if ($this->db->affected_rows() > 0) {
                    $affected_rows++;
                }

                $this->db->where('rel_type', 'banking');
                $this->db->where('reconcile', $reconcile->id);
                $this->db->delete(db_prefix().'acc_matched_transactions');
                
                $this->db->where('id', $reconcile->id);
                $this->db->delete(db_prefix().'acc_bank_reconciles');

                if ($this->db->affected_rows() > 0) {
                    $affected_rows++;
                }
            }
        }

        if($affected_rows > 0){
            return true;
        }
        return false;
    }

    public function get_data_bank_reconciliation_summary($data_filter){
        $accounts = $this->get_accounts();

        $account_name = [];

        foreach ($accounts as $key => $value) {
            $account_name[$value['id']] = $value['name'];
        }


        $data = [];
        $data['cleared_transactions'] = 0;
        $data['uncleared_transactions'] = 0;
        $data['account_name'] = '';
        $data['beginning_balance'] = 0;
        $data['ending_balance'] = 0;
        $data['statement_ending_date'] = '';
        $data['checks_and_payments'] = 0;
        $data['checks_and_payments_items'] = 0;
        $data['deposits_and_credits_items'] = 0;
        $data['deposits_and_credits'] = 0;
        $data['new_checks_and_payments'] = 0;
        $data['new_checks_and_payments_items'] = 0;
        $data['new_deposits_and_credits_items'] = 0;
        $data['new_deposits_and_credits'] = 0;
        $data['new_transactions'] = 0;

        $data['unclear_checks_and_payments'] = 0;
        $data['unclear_checks_and_payments_items'] = 0;
        $data['unclear_deposits_and_credits_items'] = 0;
        $data['unclear_deposits_and_credits'] = 0;
        $data['register_balance'] = 0;

        if(isset($data_filter['reconcile_account'])){
            $data['account_name'] = (isset($account_name[$data_filter['reconcile_account']]) ? $account_name[$data_filter['reconcile_account']] : '');
        }

        $reconcile_date = '';

        if(isset($data_filter['reconcile_date'])){
            $reconcile_date = to_sql_date($data_filter['reconcile_date']);
        }

        
            
            $this->db->where('(date < "' . $reconcile_date . '")');
            $this->db->where('account', $data_filter['reconcile_account']);
            $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
            $tt_debit = 0;
            $tt_credit = 0;
            foreach($account_history as $history){
                if($history['debit'] > 0){
                    
                    $tt_debit += $history['debit'];
                }else{
                   $tt_credit += $history['credit'];
                   
                }
            }

            $data['beginning_balance'] = $tt_debit - $tt_credit;
            


            $this->db->where('(date >= "' . $reconcile_date . '")');
            $this->db->where('(date <= "' . date('Y-m-d') . '")');
            $this->db->where('account', $data_filter['reconcile_account']);
            $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();

            foreach($account_history as $history){
                if($history['cleared'] == 1){
                    if($history['debit'] > 0){
                        $data['deposits_and_credits_items'] += 1;
                        $data['deposits_and_credits'] += $history['debit'];
                        $data['cleared_transactions'] += $history['debit'];

                    }else{
                        $data['checks_and_payments_items'] += 1;
                        $data['checks_and_payments'] -= $history['credit'];
                        $data['cleared_transactions'] -= $history['credit'];
                    }
                }else{
                    if($history['debit'] > 0){
                        $data['unclear_deposits_and_credits_items'] += 1;
                        $data['unclear_deposits_and_credits'] += $history['debit'];
                        $data['uncleared_transactions'] += $history['debit'];

                    }else{
                        $data['unclear_checks_and_payments_items'] += 1;
                        $data['unclear_checks_and_payments'] -= $history['credit'];
                        $data['uncleared_transactions'] -= $history['credit'];
                    }
                }
            }

            if($data['checks_and_payments_items'] > 1){
                $data['checks_and_payments_items'] .= ' '._l('items');
            }elseif($data['checks_and_payments_items'] == 1){
                $data['checks_and_payments_items'] .= ' '._l('item');
            }

            if($data['deposits_and_credits_items'] > 1){
                $data['deposits_and_credits_items'] .= ' '._l('items');
            }elseif($data['deposits_and_credits_items'] == 1){
                $data['deposits_and_credits_items'] .= ' '._l('item');
            }

            if($data['unclear_checks_and_payments_items'] > 1){
                $data['unclear_checks_and_payments_items'] .= ' '._l('items');
            }elseif($data['unclear_checks_and_payments_items'] == 1){
                $data['unclear_checks_and_payments_items'] .= ' '._l('item');
            }

            if($data['unclear_deposits_and_credits_items'] > 1){
                $data['unclear_deposits_and_credits_items'] .= ' '._l('items');
            }elseif($data['unclear_deposits_and_credits_items'] == 1){
                $data['unclear_deposits_and_credits_items'] .= ' '._l('item');
            }


            $this->db->where('(date > "' . date('Y-m-d') . '")');
            $this->db->where('account', $data_filter['reconcile_account']);
            $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();

            foreach($account_history as $history){
                if($history['debit'] > 0){
                    $data['new_deposits_and_credits_items'] += 1;
                    $data['new_deposits_and_credits'] += $history['debit'];
                    $data['new_transactions'] += $history['debit'];

                }else{
                    $data['new_checks_and_payments_items'] += 1;
                    $data['new_checks_and_payments'] -= $history['credit'];
                    $data['new_transactions'] -= $history['credit'];
                }
            }

            if($data['new_checks_and_payments_items'] > 1){
                $data['new_checks_and_payments_items'] .= ' '._l('items');
            }elseif($data['new_checks_and_payments_items'] == 1){
                $data['new_checks_and_payments_items'] .= ' '._l('item');
            }

            if($data['new_deposits_and_credits_items'] > 1){
                $data['new_deposits_and_credits_items'] .= ' '._l('items');
            }elseif($data['new_deposits_and_credits_items'] == 1){
                $data['new_deposits_and_credits_items'] .= ' '._l('item');
            }

            $data['ending_balance'] =  $data['beginning_balance'] + ($data['uncleared_transactions']) + ($data['cleared_transactions']) + ($data['new_transactions']);
            $data['statement_ending_date'] = $reconcile_date;
        

        return $data;
    }

    public function get_data_bank_reconciliation_detail($data_filter){
        $accounts = $this->get_accounts();

        $account_name = [];

        foreach ($accounts as $key => $value) {
            $account_name[$value['id']] = $value['name'];
        }


        $data = [];
        $data['cleared_transactions'] = 0;
        $data['uncleared_transactions'] = 0;
        $data['account_name'] = '';
        $data['beginning_balance'] = 0;
        $data['ending_balance'] = 0;
        $data['statement_ending_date'] = '';
        $data['checks_and_payments'] = 0;
        $data['checks_and_payments_items'] = 0;
        $data['deposits_and_credits_items'] = 0;
        $data['deposits_and_credits'] = 0;
        $data['deposits_and_credits_details'] = [];
        $data['checks_and_payments_details'] = [];
        $data['unclear_checks_and_payments_details'] = [];
        $data['unclear_deposits_and_credits_details'] = [];

        $data['new_checks_and_payments'] = 0;
        $data['new_checks_and_payments_items'] = 0;
        $data['new_deposits_and_credits_items'] = 0;
        $data['new_deposits_and_credits'] = 0;
        $data['new_deposits_and_credits_details'] = [];
        $data['new_checks_and_payments_details'] = [];
        $data['new_transactions'] = 0;


        $data['unclear_checks_and_payments'] = 0;
        $data['unclear_checks_and_payments_items'] = 0;
        $data['unclear_deposits_and_credits_items'] = 0;
        $data['unclear_deposits_and_credits'] = 0;
        $data['register_balance'] = 0;

        if(isset($data_filter['reconcile_account'])){
            $data['account_name'] = (isset($account_name[$data_filter['reconcile_account']]) ? $account_name[$data_filter['reconcile_account']] : '');
        }

        $reconcile_date = '';

        if(isset($data_filter['reconcile_date'])){
            $reconcile_date = to_sql_date($data_filter['reconcile_date']);
        }


        $this->db->where('(date < "' . $reconcile_date . '")');
        $this->db->where('account', $data_filter['reconcile_account']);
        $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
        $tt_debit = 0;
        $tt_credit = 0;
        foreach($account_history as $history){
            if($history['debit'] > 0){
                
                $tt_debit += $history['debit'];
            }else{
               $tt_credit += $history['credit'];
               
            }
        }

        $data['beginning_balance'] = $tt_debit - $tt_credit;

       
        $this->db->where('(date >= "' . $reconcile_date . '")');
        $this->db->where('(date <= "' . date('Y-m-d') . '")');
        $this->db->where('account', $data_filter['reconcile_account']);
        $this->db->order_by('date', 'asc');
        $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();

        $balance = $data['beginning_balance'];

        foreach($account_history as $history){

            
            if($history['cleared'] == 1){

                $history['name'] = '';
                //$history['number'] = $history['number'];
                $history['description'] = $history['description'];
                $history['split'] = $history['split'] != 0 ? (isset($account_name[$history['split']]) ? $account_name[$history['split']] : '') : '-Split-';
                if($history['customer'] != 0){
                    $history['name'] = get_company_name($history['customer']);
                }elseif ($history['vendor'] != 0) {
                    $history['name'] = acc_get_vendor_name($history['vendor']);
                }


                if($history['debit'] > 0){
                    $data['deposits_and_credits_items'] += 1;
                    $data['deposits_and_credits'] += $history['debit'];
                    $data['cleared_transactions'] += $history['debit'];

                    $balance = $balance+ $history['debit'];
                    $history['balance'] = $balance;
                    $history['amount'] = $history['debit'];

                    $data['deposits_and_credits_details'][] = $history;
                }else{
                    $data['checks_and_payments_items'] += 1;
                    $data['checks_and_payments'] -= $history['credit'];
                    $data['cleared_transactions'] -= $history['credit'];
                    $history['amount'] = -$history['credit'];

                    $balance = $balance - $history['credit'];
                    $history['balance'] = $balance;
                    $data['checks_and_payments_details'][] = $history;
                }
            }else{

                $history['name'] = '';
                //$history['number'] = $history['number'];
                $history['description'] = $history['description'];
                $history['split'] = $history['split'] != 0 ? (isset($account_name[$history['split']]) ? $account_name[$history['split']] : '') : '-Split-';
                if($history['customer'] != 0){
                    $history['name'] = get_company_name($history['customer']);
                }elseif ($history['vendor'] != 0) {
                    $history['name'] = acc_get_vendor_name($history['vendor']);
                }


                if($history['debit'] > 0){
                    $data['unclear_deposits_and_credits_items'] += 1;
                    $data['unclear_deposits_and_credits'] += $history['debit'];
                    $data['uncleared_transactions'] += $history['debit'];

                    $balance = $balance+ $history['debit'];
                    $history['balance'] = $balance;
                    $history['amount'] = $history['debit'];

                    $data['unclear_deposits_and_credits_details'][] = $history;

                }else{
                    $data['unclear_checks_and_payments_items'] += 1;
                    $data['unclear_checks_and_payments'] -= $history['credit'];
                    $data['uncleared_transactions'] -= $history['credit'];
                    $history['amount'] = -$history['credit'];

                    $balance = $balance - $history['credit'];
                    $history['balance'] = $balance;
                    $data['unclear_checks_and_payments_details'][] = $history;
                }
            }
        }

        if($data['checks_and_payments_items'] > 1){
            $data['checks_and_payments_items'] .= ' '._l('items');
        }elseif($data['checks_and_payments_items'] == 1){
            $data['checks_and_payments_items'] .= ' '._l('item');
        }

        if($data['deposits_and_credits_items'] > 1){
            $data['deposits_and_credits_items'] .= ' '._l('items');
        }elseif($data['deposits_and_credits_items'] == 1){
            $data['deposits_and_credits_items'] .= ' '._l('item');
        }

        if($data['unclear_checks_and_payments_items'] > 1){
            $data['unclear_checks_and_payments_items'] .= ' '._l('items');
        }elseif($data['unclear_checks_and_payments_items'] == 1){
            $data['unclear_checks_and_payments_items'] .= ' '._l('item');
        }

        if($data['unclear_deposits_and_credits_items'] > 1){
            $data['unclear_deposits_and_credits_items'] .= ' '._l('items');
        }elseif($data['unclear_deposits_and_credits_items'] == 1){
            $data['unclear_deposits_and_credits_items'] .= ' '._l('item');
        }

        $this->db->where('(date > "' . date('Y-m-d') . '")');
        $this->db->where('account', $data_filter['reconcile_account']);
        $this->db->order_by('date', 'asc');
        $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();

    
        foreach($account_history as $history){
            $history['name'] = '';

            //$history['number'] = $history['number'];
            $history['description'] = $history['description'];
            $history['split'] = $history['split'] != 0 ? (isset($account_name[$history['split']]) ? $account_name[$history['split']] : '') : '-Split-';

            if($history['customer'] != 0){
                $history['name'] = get_company_name($history['customer']);
            }elseif ($history['vendor'] != 0) {
                $history['name'] = acc_get_vendor_name($history['vendor']);
            }

            if($history['debit'] > 0){
                $data['new_deposits_and_credits_items'] += 1;
                $data['new_deposits_and_credits'] += $history['debit'];
                $data['new_transactions'] += $history['debit'];

                $balance = $balance + $history['debit'];
                $history['balance'] = $balance;
                $history['amount'] = $history['debit'];

                $data['new_deposits_and_credits_details'][] = $history;
            }else{
                $data['new_checks_and_payments_items'] += 1;
                $data['new_checks_and_payments'] -= $history['credit'];
                $data['new_transactions'] -= $history['credit'];
                $history['amount'] = -$history['credit'];

                $balance = $balance - $history['credit'];
                $history['balance'] = $balance;
                $data['new_checks_and_payments_details'][] = $history;
            }
        }

        if($data['new_checks_and_payments_items'] > 1){
            $data['new_checks_and_payments_items'] .= ' '._l('items');
        }elseif($data['new_checks_and_payments_items'] == 1){
            $data['new_checks_and_payments_items'] .= ' '._l('item');
        }

        if($data['new_deposits_and_credits_items'] > 1){
            $data['new_deposits_and_credits_items'] .= ' '._l('items');
        }elseif($data['new_deposits_and_credits_items'] == 1){
            $data['new_deposits_and_credits_items'] .= ' '._l('item');
        }

        $data['ending_balance'] =  $data['beginning_balance'] + ($data['uncleared_transactions']) + ($data['cleared_transactions']) + ($data['new_transactions']);
        $data['statement_ending_date'] = $reconcile_date;
        
        return $data;
    }

    /**
     * ajax update reconcile
     * @param  [type] $data 
     * @param  [type] $id   
     * @return [type]       
     */
    public function ajax_update_bank_reconcile($data, $id){
        if(isset($data['company_id'])){
            unset($data['company_id']);
        }
        if($data['ending_date'] != ''){
            $data['ending_date'] = to_sql_date($data['ending_date']);
        }

        $data['ending_balance'] = str_replace(',', '', $data['ending_balance']);
        $data['debits_for_period'] = str_replace(',', '', $data['debits_for_period']);
        $data['credits_for_period'] = str_replace(',', '', $data['credits_for_period']);
        $data['beginning_balance'] = str_replace(',', '', $data['beginning_balance']);

        $this->db->where('id', $id);
        $affectedRows = $this->db->update(db_prefix().'acc_bank_reconciles', $data);

        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }

    public function convert_excel_date($date_number){
        $UNIX_DATE = ($date_number - 25569) * 86400;
        $d = gmdate("d/m/Y", $UNIX_DATE);

        return $d;
    }

    public function remove_invalid_entries(){
        $account_history = $this->db->get(db_prefix().'acc_account_history')->result_array();
        $affectedRows = 0;

        foreach($account_history as $history){
            if(!$this->check_transaction_exists($history['rel_id'], $history['rel_type'])){
                $this->db->where('id', $history['id']);
                $this->db->delete(db_prefix().'acc_account_history');
                $affectedRows++;
            }
        }

        if($affectedRows){
            return true;
        }

        return false;
    }

    public function check_transaction_exists($rel_id, $rel_type){
        switch ($rel_type) {
            case 'invoice':
                $this->db->where('id', $rel_id);
                $invoice = $this->db->get(db_prefix().'invoices')->row();
                if($invoice){
                    return true;
                }
                break;
            case 'payment':
                $this->db->where('id', $rel_id);
                $payment = $this->db->get(db_prefix().'invoicepaymentrecords')->row();
                if($payment){
                    return true;
                }
                break;
            case 'expense':
                $this->db->where('id', $rel_id);
                $expense = $this->db->get(db_prefix().'expenses')->row();
                if($expense){
                    return true;
                }
                break;
            case 'credit_note':
                $this->db->where('id', $rel_id);
                $credit_note = $this->db->get(db_prefix().'credits')->row();
                if($credit_note){
                    return true;
                }
                break;
            case 'stock_export':
                $this->db->where('id', $rel_id);
                $stock_export = $this->db->get(db_prefix().'goods_delivery')->row();
                if($stock_export){
                    return true;
                }
                break;
            case 'stock_import':
                $this->db->where('id', $rel_id);
                $stock_import = $this->db->get(db_prefix().'goods_receipt')->row();
                if($stock_import){
                    return true;
                }
                break;
            case 'loss_adjustment':
                $this->db->where('id', $rel_id);
                $loss_adjustment = $this->db->get(db_prefix().'wh_loss_adjustment')->row();
                if($loss_adjustment){
                    return true;
                }
                break;
            case 'purchase_payment':
                $this->db->where('id', $rel_id);
                $purchase_payment = $this->db->get(db_prefix().'pur_invoice_payment')->row();
                if($purchase_payment){
                    return true;
                }
                break;
            case 'manufacturing_order':
                $this->db->where('id', $rel_id);
                $manufacturing_order = $this->db->get(db_prefix().'mrp_manufacturing_orders')->row();
                if($manufacturing_order){
                    return true;
                }
                break;
            case 'purchase_order_return':
                $this->db->where('id', $rel_id);
                $purchase_order_return = $this->db->get(db_prefix().'wh_order_returns')->row();
                if($purchase_order_return){
                    return true;
                }
                break;
            case 'purchase_refund':
                $this->db->where('id', $rel_id);
                $purchase_refund = $this->db->get(db_prefix().'wh_order_returns_refunds')->row();
                if($purchase_refund){
                    return true;
                }
                break;
            case 'purchase_invoice':
                $this->db->where('id', $rel_id);
                $purchase_invoice = $this->db->get(db_prefix().'pur_invoices')->row();
                if($purchase_invoice){
                    return true;
                }
                break;
            case 'sales_refund':
                $this->db->where('id', $rel_id);
                $sales_refund = $this->db->get(db_prefix().'omni_refunds')->row();
                if($sales_refund){
                    return true;
                }
                break;
            case 'sales_return_order':
                $this->db->where('id', $rel_id);
                $sales_return_order = $this->db->get(db_prefix().'cart')->row();
                if($sales_return_order){
                    return true;
                }
                break;
            case 'fe_asset':
                $this->db->where('id', $rel_id);
                $fe_asset = $this->db->get(db_prefix().'fe_assets')->row();
                if($fe_asset){
                    return true;
                }
                break;
            case 'fe_license':
                $this->db->where('id', $rel_id);
                $fe_license = $this->db->get(db_prefix().'fe_assets')->row();
                if($fe_license){
                    return true;
                }
                break;
            case 'fe_component':
                $this->db->where('id', $rel_id);
                $fe_component = $this->db->get(db_prefix().'fe_assets')->row();
                if($fe_component){
                    return true;
                }
                break;
            case 'fe_consumable':
                $this->db->where('id', $rel_id);
                $fe_consumable = $this->db->get(db_prefix().'fe_assets')->row();
                if($fe_consumable){
                    return true;
                }
                break;
            case 'fe_maintenance':
                $this->db->where('id', $rel_id);
                $fe_maintenance = $this->db->get(db_prefix().'fe_asset_maintenances')->row();
                if($fe_maintenance){
                    return true;
                }
                break;
            case 'fe_depreciation':
                $this->db->where('id', $rel_id);
                $fe_depreciation = $this->db->get(db_prefix().'fe_depreciation_items')->row();
                if($fe_depreciation){
                    return true;
                }
                break;
            case 'purchase_order':
                $this->db->where('id', $rel_id);
                $purchase_order = $this->db->get(db_prefix().'pur_orders')->row();
                if($purchase_order){
                    return true;
                }
                break;
            case 'payslip':
                $this->db->where('id', $rel_id);
                $payslip = $this->db->get(db_prefix().'hrp_payslips')->row();
                if($payslip){
                    return true;
                }
                break;
            default:
                return true;
                break;
        }

        return false;
    }

    /**
     * Automatic manufacturing order conversion
     * @param  integer $loss_adjustment_id 
     * @return boolean
     */
    public function automatic_manufacturing_order_conversion($manufacturing_order_id){
        $this->delete_convert($manufacturing_order_id, 'manufacturing_order');

        $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');

        $date_financial_year = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.date('Y')));

        $affectedRows = 0;

        if(get_option('acc_mrp_manufacturing_order_automatic_conversion') == 0){
            return false;
        }

        $this->load->model('manufacturing/manufacturing_model');
        $_manufacturing_order = $this->manufacturing_model->get_manufacturing_order($manufacturing_order_id);
        $manufacturing_order = $_manufacturing_order['manufacturing_order'];
        $manufacturing_order_costing = $this->manufacturing_model->get_manufacturing_order_costing($manufacturing_order_id);

        if(get_option('acc_close_the_books') == 1){
            if(strtotime($manufacturing_order->date_plan_from) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                return false;
            }
        }

        if($manufacturing_order_costing['total_material_cost'] > 0){
            $payment_account_material_cost = get_option('acc_mrp_material_cost_payment_account');
            $deposit_to_material_cost = get_option('acc_mrp_material_cost_deposit_to');
            $material_cost = $manufacturing_order_costing['total_material_cost'];

            $node = [];
            $node['split'] = $payment_account_material_cost;
            $node['account'] = $deposit_to_material_cost;
            $node['debit'] = $material_cost;
            $node['date'] = $manufacturing_order->date_plan_from;
            $node['tax'] = 0;
            $node['credit'] = 0;
            $node['description'] = '';
            $node['rel_id'] = $manufacturing_order_id;
            $node['rel_type'] = 'manufacturing_order';
            $node['sub_type'] = 'material_cost';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $deposit_to_material_cost;
            $node['date'] = $manufacturing_order->date_plan_from;
            $node['account'] = $payment_account_material_cost;
            $node['tax'] = 0;
            $node['debit'] = 0;
            $node['credit'] = $material_cost;
            $node['description'] = '';
            $node['rel_id'] = $manufacturing_order_id;
            $node['rel_type'] = 'manufacturing_order';
            $node['sub_type'] = 'material_cost';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;
        }
            
        if($manufacturing_order_costing['total_labour_cost'] > 0){
            $payment_account_labour_cost = get_option('acc_mrp_labour_cost_payment_account');
            $deposit_to_labour_cost = get_option('acc_mrp_labour_cost_deposit_to');
            $labour_cost = $manufacturing_order_costing['total_labour_cost'];

            $node = [];
            $node['split'] = $payment_account_labour_cost;
            $node['account'] = $deposit_to_labour_cost;
            $node['debit'] = $labour_cost;
            $node['date'] = $manufacturing_order->date_plan_from;
            $node['tax'] = 0;
            $node['credit'] = 0;
            $node['description'] = '';
            $node['rel_id'] = $manufacturing_order_id;
            $node['rel_type'] = 'manufacturing_order';
            $node['sub_type'] = 'labour_cost';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $deposit_to_labour_cost;
            $node['date'] = $manufacturing_order->date_plan_from;
            $node['account'] = $payment_account_labour_cost;
            $node['tax'] = 0;
            $node['debit'] = 0;
            $node['credit'] = $labour_cost;
            $node['description'] = '';
            $node['rel_id'] = $manufacturing_order_id;
            $node['rel_type'] = 'manufacturing_order';
            $node['sub_type'] = 'labour_cost';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;
        }

        if($data_insert != []){
            $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
        }
            
        if ($affectedRows > 0) {
            return true;
        }

        return false;
    }

    public function get_pur_order_return_data_convert($id, $type){
        $accounts = $this->get_accounts();
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $this->load->model('purchase/purchase_model');
        $order_return = $this->purchase_model->get_order_return($id);
        $order_return_detail = $this->purchase_model->get_order_return_detail($id);
        $base_currency = get_base_currency_pur();
        if($order_return->currency != 0){
            $base_currency = pur_get_currency_by_id($order_return->currency);
        }

        $html = '<table class="table border table-striped no-margin">
                  <tbody>
                    <tr class="project-overview">
                        <td class="bold" width="30%">'. _l('pur_order_return_number').'</td>
                        <td>'. '<a href="' . admin_url('purchase/order_returns#' . $order_return->id) . '">'. $order_return->order_return_number .' - '.$order_return->order_return_name .'</a>'  .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('vendor').'</td>
                        <td>'. '<a href="' . admin_url('purchase/vendor/' . $order_return->company_id) . '" >' .  get_vendor_company_name($order_return->company_id) . '</a>' .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('status').'</td>
                        <td><span class="label label-success">'._l('pur_'.$order_return->status).'</span></td>
                        <td></td>
                     </tr>
                    <tr class="project-overview">
                        <td class="bold">'. _l('pur_total_amount').'</td>
                        <td>'. app_format_money($order_return->total_amount, $base_currency->name) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('pur_discount_total').'</td>
                        <td>'. app_format_money($order_return->discount_total, $base_currency->name) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('pur_total_after_discount').'</td>
                        <td>'. app_format_money($order_return->total_after_discount, $base_currency->name) .'</td>
                        <td></td>
                     </tr>';
        $_html = '';

        

        $amount = 1;
        $currency_rate = 1;
        if($base_currency->name != $currency->name){
            $purchase_order = $this->purchase_model->get_pur_order($order_return->rel_id);
            $currency_rate = $purchase_order->currency_rate;
            $html .= '<tr class="project-overview">
                            <td class="bold">'. _l('currency_rate').'</td>
                            <td>'. round(round($order_return->total_after_discount / $currency_rate, 2)/$order_return->total_after_discount, 6) .'</td>
                         </tr>
                         <tr class="project-overview">
                        <td class="bold">'. _l('amount_after_convert').'</td>
                        <td>'. app_format_money(round($order_return->total_after_discount / $currency_rate, 2), $currency->name) .'</td>
                     </tr>';
            // $amount = acc_get_currency_rate($base_currency->name, $currency->name);

            // $edit_template = "";
            // $edit_template .= render_input('edit_exchange_rate','exchange_rate', $amount, 'number');
            // $edit_template .= "<div class='text-center mtop10'>";
            // $edit_template .= "<button type='button' class='btn btn-success edit_conversion_rate_action'>"._l('copy_task_confirm')."</button>";
            // $edit_template .= "</div>";
            // $_html .= form_hidden('currency_from', $base_currency->name);
            // $_html .= form_hidden('currency_to', $currency->name);
            // $_html .= form_hidden('exchange_rate', $amount);
            // $_html .= form_hidden('convert_amount', $order_return->total_after_discount);
            // $_html .= '<div class="row"><div class="col-md-12"><label class="currency_converter_label th font-medium mbot15 pull-left">1 '.$base_currency->name.' = '.$amount.' '.$currency->name.'</label><a href="#" onclick="return false;" data-placement="bottom" data-toggle="popover" data-content="'. htmlspecialchars($edit_template) .'" data-html="true" data-original-title class="pull-left mleft5 font-medium-xs"><i class="fa fa-pencil-square"></i></a><br></div></div>';
            // $old_currency_rate = $this->get_old_currency_rate($id, $type);
            // if($old_currency_rate != 0){
            //     $html .=   '<tr class="project-overview">
            //                 <td class="bold">'. _l('amount_after_convert').'</td>
            //                 <td>'.app_format_money(round($old_currency_rate*$order_return->total_after_discount, 4), $currency->name).'</td>
            //                 <td>1 '.$base_currency->name.' = '.$old_currency_rate.' '.$currency->name.'</td>
            //              </tr>';
            // }
            // $html .=   '<tr class="project-overview">
            //                 <td class="bold">'. _l('amount_after_convert').'('._l('new').')</td>
            //                 <td class="amount_after_convert">'.app_format_money(round($amount*$order_return->total_after_discount, 4), $currency->name).'</td>
            //                 <td>'.$_html.'</td>
            //              </tr>';
        }

        $html .=  '</tbody>
              </table>';

        if($order_return_detail){
            $payment_account = get_option('acc_pur_order_return_payment_account');
            $deposit_to = get_option('acc_pur_order_return_deposit_to');

            $html .= '<h4>'._l('list_of_items').'</h4>';
            $list_item = [];

            foreach ($order_return_detail as $value) {
                $this->db->where('id', $value['commodity_code']);
                $item = $this->db->get(db_prefix().'items')->row();

                $item_description = $value['commodity_name'];

                $item_id = 0;
                if(isset($item->id)){
                    $item_id = $item->id;
                }

                if($item_id == 0){
                    continue;
                }

                $item_total = round($value['total_after_discount']/$currency_rate, 2);

                $list_item[] = $item_id;

                $this->db->where('rel_id', $id);
                $this->db->where('rel_type', $type);
                $this->db->where('item', $item_id);
                $account_history = $this->db->get(db_prefix(). 'acc_account_history')->result_array();
                
                foreach ($account_history as $key => $val) {
                    if($val['debit'] > 0){
                        $debit = $val['account'];
                    }

                    if($val['credit'] > 0){
                        $credit =  $val['account'];
                    }
                }

                if($account_history){
                    $html .= '
                    <div class="div_content">
                    <h5>'.$item_description.'('.app_format_money($item_total, $currency->name).')</h5>
                    <div class="row">
                            '.form_hidden('item_amount['.$item_id.']', $item_total).'
                          <div class="col-md-6"> '.
                            render_select('payment_account['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'payment_account',$credit,array(),array(),'','',false) .'
                          </div>
                          <div class="col-md-6">
                            '. render_select('deposit_to['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'deposit_to',$debit,array(),array(),'','',false).'
                          </div>
                      </div>
                    </div>';
                }else{
                    $item_automatic = $this->get_item_automatic($item_id);

                    if($item_automatic){
                        $html .= '
                    <div class="div_content">
                        <h5>'.$item_description.'('.app_format_money($item_total, $currency->name).')</h5>
                        <div class="row">
                        '.form_hidden('item_amount['.$item_id.']', $item_total).'
                          <div class="col-md-6"> '.
                            render_select('payment_account['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'payment_account',$payment_account,array(),array(),'','',false) .'
                          </div>
                          <div class="col-md-6">
                            '. render_select('deposit_to['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'deposit_to',$item_automatic->expense_account,array(),array(),'','',false).'
                          </div>
                      </div>
                    </div>';
                    }else{

                        $html .= '
                            <div class="div_content">
                                <h5>'.$item_description.'('.app_format_money($item_total, $currency->name).')</h5>
                                <div class="row">
                                '.form_hidden('item_amount['.$item_id.']', $item_total).'
                                  <div class="col-md-6"> '.
                                    render_select('payment_account['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'payment_account',$payment_account,array(),array(),'','',false) .'
                                  </div>
                                  <div class="col-md-6">
                                    '. render_select('deposit_to['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'deposit_to',$deposit_to,array(),array(),'','',false).'
                                  </div>
                              </div>
                            </div>';
                    }
                }
            }
        }

        return ['html' => $html, 'list_item' => $list_item];
    }

    public function get_pur_refund_data_convert($id, $type){
        $this->load->model('purchase/purchase_model');
        $refund = $this->purchase_model->get_order_return_refund($id);
        $order_return = $this->purchase_model->get_order_return($refund->order_return_id);
        $amount = $refund->amount;

        $base_currency = get_base_currency_pur();
        if($order_return->currency != 0){
            $base_currency = pur_get_currency_by_id($order_return->currency);
        }

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $html = '<table class="table border table-striped no-margin">
                  <tbody>
                     <tr class="project-overview">
                        <td class="bold" width="30%">'. _l('purchase_order_return').'</td>
                        <td>'.'<a href="'.admin_url('purchase/order_returns#' . $order_return->id).'">'. $order_return->order_return_number .' - '.$order_return->order_return_name .'</a>' .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('acc_amount').'</td>
                        <td>'. app_format_money($refund->amount, $base_currency->name) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('expense_dt_table_heading_date').'</td>
                        <td>'. _d($refund->refunded_on) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('payment_modes').'</td>
                        <td>'. get_payment_mode_name_by_id($refund->payment_mode) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('note').'</td>
                        <td colspan="2">'. new_html_entity_decode($refund->note) .'</td>
                        <td></td>
                     </tr>';
        $_html = '';

        

        $amount = 1;

        if($base_currency->name != $currency->name){
            $amount = acc_get_currency_rate($base_currency->name, $currency->name);

            $edit_template = "";
            $edit_template .= render_input('edit_exchange_rate','exchange_rate', $amount, 'number');
            $edit_template .= "<div class='text-center mtop10'>";
            $edit_template .= "<button type='button' class='btn btn-success edit_conversion_rate_action'>"._l('copy_task_confirm')."</button>";
            $edit_template .= "</div>";
            $_html .= form_hidden('currency_from', $base_currency->name);
            $_html .= form_hidden('currency_to', $currency->name);
            $_html .= form_hidden('exchange_rate', $amount);
            $_html .= form_hidden('convert_amount', $refund->amount);
            $_html .= '<div class="row"><div class="col-md-12"><label class="currency_converter_label th font-medium mbot15 pull-left">1 '.$base_currency->name.' = '.$amount.' '.$currency->name.'</label><a href="#" onclick="return false;" data-placement="bottom" data-toggle="popover" data-content="'. htmlspecialchars($edit_template) .'" data-html="true" data-original-title class="pull-left mleft5 font-medium-xs"><i class="fa fa-pencil-square"></i></a><br></div></div>';
            $old_currency_rate = $this->get_old_currency_rate($id, $type);
            if($old_currency_rate != 0){
                $html .=   '<tr class="project-overview">
                            <td class="bold">'. _l('amount_after_convert').'</td>
                            <td>'.app_format_money(round($old_currency_rate*$refund->amount, 4), $currency->name).'</td>
                            <td>1 '.$base_currency->name.' = '.$old_currency_rate.' '.$currency->name.'</td>
                         </tr>';
            }
            $html .=   '<tr class="project-overview">
                            <td class="bold">'. _l('amount_after_convert').'('._l('new').')</td>
                            <td class="amount_after_convert">'.app_format_money(round($amount*$refund->amount, 4), $currency->name).'</td>
                            <td>'.$_html.'</td>
                         </tr>';
        }

        $html .=  '</tbody>
              </table>';

        return ['html' => $html, 'amount' => $amount];
    }

    /**
     * update manufacturing automatic conversion
     *
     * @param      array   $data   The data
     *
     * @return     boolean 
     */
    public function update_manufacturing_automatic_conversion($data){
        $affectedRows = 0;
        
        if(!isset($data['acc_mrp_manufacturing_order_automatic_conversion'])){
            $data['acc_mrp_manufacturing_order_automatic_conversion'] = 0;
        }

        foreach ($data as $key => $value) {
            $this->db->where('name', $key);
            $this->db->update(db_prefix() . 'options', [
                    'value' => $value,
                ]);
            if ($this->db->affected_rows() > 0) {
                $affectedRows++;
            }
        }

        if ($affectedRows > 0) {
            return true;
        }
        return false;
    }

    /**
     * Automatic refund conversion
     * @param  integer $refund_id 
     * @return boolean
     */
    public function automatic_purchase_refund_conversion($refund_id){
        if(get_option('acc_pur_refund_automatic_conversion') == 0){
            return false;
        }
        
        $this->delete_convert($refund_id, 'purchase_refund');

        $this->load->model('purchase/purchase_model');
        $refund = $this->purchase_model->get_order_return_refund($refund_id);
        $order_return = $this->purchase_model->get_order_return($refund->order_return_id);

        $base_currency = get_base_currency_pur();
        if($order_return->currency != 0){
            $base_currency = pur_get_currency_by_id($order_return->currency);
        }

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        if($order_return->status == "finish"){
            $this->automatic_purchase_order_return_conversion($refund->order_return_id);
        }

        $payment_account = get_option('acc_pur_refund_payment_account');
        $deposit_to = get_option('acc_pur_refund_deposit_to');
        $affectedRows = 0;
        $data_insert = [];

        if($refund){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($refund->refunded_on) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }

            $currency_rate = 0;
            $payment_total = $refund->amount;
            if($base_currency->name != $currency->name){
                $currency_rate = acc_get_currency_rate($base_currency->name, $currency->name);
                $payment_total = round(($currency_rate * $refund->amount), 2);
            }
            
            $node = [];
            $node['split'] = $payment_account;
            $node['account'] = $deposit_to;
            $node['debit'] = $payment_total;
            $node['credit'] = 0;
            $node['date'] = $refund->refunded_on;
            $node['description'] = '';
            $node['rel_id'] = $refund_id;
            $node['rel_type'] = 'purchase_refund';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $node['currency_rate'] = $currency_rate;
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $deposit_to;
            $node['account'] = $payment_account;
            $node['date'] = $refund->refunded_on;
            $node['debit'] = 0;
            $node['credit'] = $payment_total;
            $node['description'] = '';
            $node['rel_id'] = $refund_id;
            $node['rel_type'] = 'purchase_refund';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $node['currency_rate'] = $currency_rate;
            $data_insert[] = $node;

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Automatic purchase order return conversion
     * @param  integer $purchase_order_id 
     * @return boolean
     */
    public function automatic_purchase_order_return_conversion($purchase_order_id){
        if(get_option('acc_pur_order_return_automatic_conversion') == 0){
            return false;
        }

        $this->delete_convert($purchase_order_id, 'purchase_order_return');

        $this->load->model('purchase/purchase_model');

        $order_return = $this->purchase_model->get_order_return($purchase_order_id);
        $order_return_detail = $this->purchase_model->get_order_return_detail($purchase_order_id);
        $purchase_order = $this->purchase_model->get_pur_order($order_return->rel_id);

        $base_currency = get_base_currency_pur();
        if($order_return->currency != 0){
            $base_currency = pur_get_currency_by_id($order_return->currency);
        }

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $expense_payment_account = get_option('acc_pur_order_return_payment_account');
        $expense_deposit_to = get_option('acc_pur_order_return_deposit_to');
        $currency_rate = 1;

        if($base_currency->name != $currency->name){
            $currency_rate = $purchase_order->currency_rate;
        }

        foreach ($order_return_detail as $value) {
            $item_total = $value['total_after_discount'];

            if($base_currency->name != $currency->name){
                // $currency_rate = acc_get_currency_rate($base_currency->name, $currency->name);

                $item_total = round(($value['total_after_discount'] / $currency_rate), 2);
            }

            $item_id = $value['commodity_code'];

            $node = [];
            $node['split'] = $expense_payment_account;
            $node['account'] = $expense_deposit_to;
            $node['date'] = $order_return->datecreated;
            $node['item'] = $item_id;
            $node['debit'] = $item_total;
            $node['tax'] = 0;
            $node['credit'] = 0;
            $node['description'] = '';
            $node['rel_id'] = $purchase_order_id;
            $node['rel_type'] = 'purchase_order_return';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $node['currency_rate'] = $currency_rate;
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $expense_deposit_to;
            $node['account'] = $expense_payment_account;
            $node['date'] = $order_return->datecreated;
            $node['item'] = $item_id;
            $node['tax'] = 0;
            $node['debit'] = 0;
            $node['credit'] = $item_total;
            $node['description'] = '';
            $node['rel_id'] = $purchase_order_id;
            $node['rel_type'] = 'purchase_order_return';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $node['currency_rate'] = $currency_rate;
            $data_insert[] = $node;

            // if(get_option('acc_tax_automatic_conversion') == 1 && $value['tax_id'] > 0){
            //     $tax_payment_account = get_option('acc_pur_tax_payment_account');
            //     $tax_deposit_to = get_option('acc_pur_tax_deposit_to');

            //     $total_tax = 0;
            //     if($purchase_order->discount_type == 'before_tax'){
            //         if($value['tax_id'] != ''){
            //             $tax_arr = explode('|', $value['tax_id']);

            //             $tax_rate_arr = [];
            //             if($value['tax_rate'] != ''){
            //                 $tax_rate_arr = explode('|', $value['tax_rate']);
            //             }

            //             foreach($tax_arr as $k => $tax_it){
            //                 if(!isset($tax_rate_arr[$k]) ){
            //                     $tax_rate_arr[$k] = $this->purchase_model->tax_rate_by_id($tax_it);
            //                 }

            //                 $total_tax += $tax_rate_arr[$k]*$value['sub_total']/100;
            //             }
            //         }

            //         $total_discount = $item_discount + $purchase_order->discount_total;

            //         $t     = ($total_discount / $purchase_order->subtotal) * 100;
            //         $total_tax = ($total_tax - $total_tax * $t / 100);

            //     }else{
            //         $total_tax = ($value['total_amount'] - $value['sub_total']);
            //     }

            //     if($base_currency->name != $currency->name){
            //         $currency_rate = $purchase_order->currency_rate;
            //         $total_tax = round(($total_tax / $currency_rate), 2);
            //     }

            //     $tax_mapping = $this->get_tax_mapping($value['tax_id']);

            //     if($tax_mapping){
            //         $node = [];
            //         $node['split'] = $tax_mapping->purchase_deposit_to;
            //         $node['account'] = $tax_mapping->purchase_payment_account;
            //         $node['tax'] = $value['tax_id'];
            //         $node['item'] = $item_id;
            //         $node['date'] = $order_return->datecreated;
            //         $node['debit'] = $total_tax;
            //         $node['credit'] = 0;
            //         $node['description'] = '';
            //         $node['rel_id'] = $purchase_order_id;
            //         $node['rel_type'] = 'purchase_order_return';
            //         $node['datecreated'] = date('Y-m-d H:i:s');
            //         $node['addedfrom'] = get_staff_user_id();
            //         $node['currency_rate'] = $currency_rate;
            //         $data_insert[] = $node;

            //         $node = [];
            //         $node['split'] = $tax_mapping->purchase_payment_account;
            //         $node['account'] = $tax_mapping->purchase_deposit_to;
            //         $node['tax'] = $value['tax_id'];
            //         $node['item'] = $item_id;
            //         $node['date'] = $order_return->datecreated;
            //         $node['debit'] = 0;
            //         $node['credit'] = $total_tax;
            //         $node['description'] = '';
            //         $node['rel_id'] = $purchase_order_id;
            //         $node['rel_type'] = 'purchase_order_return';
            //         $node['datecreated'] = date('Y-m-d H:i:s');
            //         $node['addedfrom'] = get_staff_user_id();
            //         $node['currency_rate'] = $currency_rate;
            //         $data_insert[] = $node;
            //     }else{
            //         $node = [];
            //         $node['split'] = $tax_deposit_to;
            //         $node['account'] = $tax_payment_account;
            //         $node['tax'] = $value['tax_id'];
            //         $node['item'] = $item_id;
            //         $node['date'] = $order_return->datecreated;
            //         $node['debit'] = $total_tax;
            //         $node['credit'] = 0;
            //         $node['description'] = '';
            //         $node['rel_id'] = $purchase_order_id;
            //         $node['rel_type'] = 'purchase_order_return';
            //         $node['datecreated'] = date('Y-m-d H:i:s');
            //         $node['addedfrom'] = get_staff_user_id();
            //         $node['currency_rate'] = $currency_rate;
            //         $data_insert[] = $node;

            //         $node = [];
            //         $node['split'] = $tax_payment_account;
            //         $node['date'] = $order_return->datecreated;
            //         $node['account'] = $tax_deposit_to;
            //         $node['tax'] = $value['tax_id'];
            //         $node['item'] = $item_id;
            //         $node['debit'] = 0;
            //         $node['credit'] = $total_tax;
            //         $node['description'] = '';
            //         $node['rel_id'] = $purchase_order_id;
            //         $node['rel_type'] = 'purchase_order_return';
            //         $node['datecreated'] = date('Y-m-d H:i:s');
            //         $node['addedfrom'] = get_staff_user_id();
            //         $node['currency_rate'] = $currency_rate;
            //         $data_insert[] = $node;
            //     }
            // }
        }

        if($data_insert != []){
            $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
        }
            
        if ($affectedRows > 0) {
            return true;
        }

        return false;
    }

    /**
     * count purchase refund not convert yet
     * @param  integer $currency
     * @param  string $where
     * @return object          
     */
    public function count_purchase_refund_not_convert_yet($currency = '', $where = ''){
        $where_currency = '';
        if($currency != ''){
            $where_currency = 'and currency = '.$currency;
        }

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'wh_order_returns_refunds.id and ' . db_prefix() . 'acc_account_history.rel_type = "purchase_refund") = 0) AND (' . db_prefix() . 'wh_order_returns.id is not null) '.$where_currency);
        $this->db->join(db_prefix().'wh_order_returns', db_prefix() . 'wh_order_returns.id = ' . db_prefix() . 'wh_order_returns_refunds.order_return_id', 'left');
        return $this->db->count_all_results(db_prefix().'wh_order_returns_refunds');
    }

    /**
     * count purchase order return not convert yet
     * @param  integer $currency
     * @param  string $where
     * @return object          
     */
    public function count_purchase_order_return_not_convert_yet($currency = '', $where = ''){
        $where_currency = '';
        if($currency != ''){
            $where_currency = 'and currency = '.$currency;
        }

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'wh_order_returns.id and ' . db_prefix() . 'acc_account_history.rel_type = "purchase_order_return") = 0) and status = "finish" '.$where_currency);
        return $this->db->count_all_results(db_prefix().'wh_order_returns');
    }

    /**
     * count purchase invoice not convert yet
     * @param  integer $currency
     * @param  string $where
     * @return object          
     */
    public function count_purchase_invoice_not_convert_yet($currency = '', $where = ''){
        $where_currency = '';
        if($currency != ''){
            $where_currency = 'and currency = '.$currency;
        }

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'pur_invoices.id and ' . db_prefix() . 'acc_account_history.rel_type = "purchase_invoice") = 0 and approval_status = "2") '.$where_currency);
        return $this->db->count_all_results(db_prefix().'pur_invoices');
    }

    public function get_pur_invoice_data_convert($id, $type){
        $accounts = $this->get_accounts();
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $this->load->model('purchase/purchase_model');
        $pur_invoice = $this->purchase_model->get_pur_invoice($id);
        $pur_invoice_detail = $this->purchase_model->get_pur_invoice_detail($id);
        $list_item = [];

        $base_currency = get_base_currency_pur();
        if($pur_invoice->currency != 0){
            $base_currency = pur_get_currency_by_id($pur_invoice->currency);
        }

        $html = '<table class="table border table-striped no-margin">
                  <tbody>
                    <tr class="project-overview">
                        <td class="bold" width="30%">'. _l('invoice_number').'</td>
                        <td>'. '<a href="' . admin_url('purchase/purchase_invoice/' . $pur_invoice->id) . '">'.$pur_invoice->invoice_number. '</a>'  .'</td>
                        <td></td>
                     </tr>
                     
                     <tr class="project-overview">
                        <td class="bold">'. _l('vendor').'</td>
                        <td>'. '<a href="' . admin_url('purchase/vendor/' . $pur_invoice->vendor) . '" >' .  get_vendor_company_name($pur_invoice->vendor) . '</a>' .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('contract').'</td>
                        <td>'. '<a href="' . admin_url('purchase/contract/' . $pur_invoice->contract) . '" >' .  get_pur_contract_number($pur_invoice->contract) . '</a>' .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('purchase_order').'</td>
                        <td>'. '<a href="' . admin_url('purchase/purchase_order/' . $pur_invoice->pur_order) . '" >' .  get_pur_order_subject($pur_invoice->pur_order) . '</a>' .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('invoice_date').'</td>
                        <td>'. _d($pur_invoice->invoice_date) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('pur_due_date').'</td>
                        <td>'. _d($pur_invoice->duedate) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('invoice_amount').'</td>
                        <td>'. app_format_money($pur_invoice->total, $base_currency->symbol) .'</td>
                        <td></td>
                     </tr>';

                $_html = '';

                $amount = 1;

                if($base_currency->name != $currency->name){
                    $amount = acc_get_currency_rate($base_currency->name, $currency->name);

                    $edit_template = "";
                    $edit_template .= render_input('edit_exchange_rate','exchange_rate', $amount, 'number');
                    $edit_template .= "<div class='text-center mtop10'>";
                    $edit_template .= "<button type='button' class='btn btn-success edit_conversion_rate_action'>"._l('copy_task_confirm')."</button>";
                    $edit_template .= "</div>";
                    $_html .= form_hidden('currency_from', $base_currency->name);
                    $_html .= form_hidden('currency_to', $currency->name);
                    $_html .= form_hidden('exchange_rate', $amount);
                    $_html .= form_hidden('convert_amount', $pur_invoice->total);
                    $_html .= '<div class="row"><div class="col-md-12"><label class="currency_converter_label th font-medium mbot15 pull-left">1 '.$base_currency->name.' = '.$amount.' '.$currency->name.'</label><a href="#" onclick="return false;" data-placement="bottom" data-toggle="popover" data-content="'. htmlspecialchars($edit_template) .'" data-html="true" data-original-title class="pull-left mleft5 font-medium-xs"><i class="fa fa-pencil-square"></i></a><br></div></div>';
                    $old_currency_rate = $this->get_old_currency_rate($id, $type);
                    if($old_currency_rate != 0){
                        $html .=   '<tr class="project-overview">
                                    <td class="bold">'. _l('amount_after_convert').'</td>
                                    <td>'.app_format_money(round($old_currency_rate*$pur_invoice->total, 4), $currency->name).'</td>
                                    <td>1 '.$base_currency->name.' = '.$old_currency_rate.' '.$currency->name.'</td>
                                 </tr>';
                    }
                    $html .=   '<tr class="project-overview">
                                    <td class="bold">'. _l('amount_after_convert').'('._l('new').')</td>
                                    <td class="amount_after_convert">'.app_format_money(round($amount*$pur_invoice->total, 4), $currency->name).'</td>
                                    <td>'.$_html.'</td>
                                 </tr>';
                }

            $html .=  '</tbody>
                  </table>';

        if($pur_invoice_detail){
            $payment_account = get_option('acc_pur_invoice_payment_account');
            $deposit_to = get_option('acc_pur_invoice_deposit_to');

            $html .= '<h4>'._l('list_of_items').'</h4>';
            foreach ($pur_invoice_detail as $value) {
                $this->db->where('id', $value['item_code']);
                $item = $this->db->get(db_prefix().'items')->row();

                $item_description = '';
                if(isset($item) && isset($item->commodity_code) && isset($item->description)){
                   $item_description = $item->commodity_code.' - '.$item->description;
                }

                $item_id = 0;
                if(isset($item->id)){
                    $item_id = $item->id;
                }

                if($item_id == 0){
                    continue;
                }
                $list_item[] = $item_id;

                $this->db->where('rel_id', $id);
                $this->db->where('rel_type', $type);
                $this->db->where('item', $item_id);
                $account_history = $this->db->get(db_prefix(). 'acc_account_history')->result_array();
                
                foreach ($account_history as $key => $val) {
                    if($val['debit'] > 0){
                        $debit = $val['account'];
                    }

                    if($val['credit'] > 0){
                        $credit =  $val['account'];
                    }
                }

                if($account_history){
                    $html .= '
                    <div class="div_content">
                    <h5>'.$item_description.'('.app_format_money($value['into_money'], $base_currency->symbol).')</h5>
                    <div class="row">
                            '.form_hidden('item_amount['.$item_id.']', $value['into_money']).'
                          <div class="col-md-6"> '.
                            render_select('payment_account['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'payment_account',$credit,array(),array(),'','',false) .'
                          </div>
                          <div class="col-md-6">
                            '. render_select('deposit_to['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'deposit_to',$debit,array(),array(),'','',false).'
                          </div>
                      </div>
                    </div>';
                }else{
                    $item_automatic = $this->accounting_model->get_item_automatic($item_id);

                    if($item_automatic){
                        $html .= '
                    <div class="div_content">
                        <h5>'.$item_description.'('.app_format_money($value['into_money'], $base_currency->symbol).')</h5>
                        <div class="row">
                        '.form_hidden('item_amount['.$item_id.']', $value['into_money']).'
                          <div class="col-md-6"> '.
                            render_select('payment_account['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'payment_account',$payment_account,array(),array(),'','',false) .'
                          </div>
                          <div class="col-md-6">
                            '. render_select('deposit_to['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'deposit_to',$item_automatic->expense_account,array(),array(),'','',false).'
                          </div>
                      </div>
                    </div>';
                    }else{

                        $html .= '
                    <div class="div_content">
                        <h5>'.$item_description.'('.app_format_money($value['into_money'], $base_currency->symbol).')</h5>
                        <div class="row">
                        '.form_hidden('item_amount['.$item_id.']', $value['into_money']).'
                          <div class="col-md-6"> '.
                            render_select('payment_account['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'payment_account',$payment_account,array(),array(),'','',false) .'
                          </div>
                          <div class="col-md-6">
                            '. render_select('deposit_to['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'deposit_to',$deposit_to,array(),array(),'','',false).'
                          </div>
                      </div>
                    </div>';
                    }
                }
            }
        }

        return ['html' => $html, 'list_item' => $list_item];
    }

    /**
     * Automatic purchase invoice conversion
     * @param  integer $purchase_invoice_id 
     * @return boolean
     */
    public function automatic_purchase_invoice_conversion($purchase_invoice_id){
        if(get_option('acc_pur_invoice_automatic_conversion') == 0){
            return false;
        }

        $affectedRows = 0;
        
        $this->delete_convert($purchase_invoice_id, 'purchase_invoice');

        $this->load->model('purchase/purchase_model');
        $purchase_invoice = $this->purchase_model->get_pur_invoice($purchase_invoice_id);
        
        if($purchase_invoice->approval_status != 2){
            return false;
        }

        $purchase_invoice_detail = $this->purchase_model->get_pur_invoice_detail($purchase_invoice_id);

        $base_currency = get_base_currency_pur();
        if($purchase_invoice->currency != 0){
            $base_currency = pur_get_currency_by_id($purchase_invoice->currency);
        }

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $payment_account = get_option('acc_pur_invoice_payment_account');
        $deposit_to = get_option('acc_pur_invoice_deposit_to');

        $tax_payment_account = get_option('acc_pur_tax_payment_account');
        $tax_deposit_to = get_option('acc_pur_tax_deposit_to');

        if($purchase_invoice && ($purchase_invoice->pur_order == '' || $purchase_invoice->pur_order == 0)){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($purchase_invoice->invoice_date) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){

                    return false;
                }
            }

            $item_discount = 0;
            foreach($purchase_invoice_detail as $row){
                $item_discount += $row['discount_money'];
            }

            $data_insert = [];
            $currency_rate = 0;
            foreach ($purchase_invoice_detail as $value) {

                $item = get_item_hp($value['item_code']);

                $item_id = 0;
                if(isset($item->id)){
                    $item_id = $item->id;
                }

                $item_total = $value['into_money'];
                if($base_currency->name != $currency->name){
                    $currency_rate = acc_get_currency_rate($base_currency->name, $currency->name);

                    $item_total = round(($currency_rate * $value['into_money']), 2);
                }

                $item_automatic = $this->get_item_automatic($item_id);

                if($item_automatic){
                    $node = [];
                    $node['split'] = $payment_account;
                    $node['account'] = $item_automatic->expense_account;
                    $node['item'] = $item_id;
                    $node['date'] = $purchase_invoice->invoice_date;
                    $node['debit'] = $item_total;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $purchase_invoice_id;
                    $node['rel_type'] = 'purchase_invoice';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $item_automatic->expense_account;
                    $node['account'] = $payment_account;
                    $node['item'] = $item_id;
                    $node['date'] = $purchase_invoice->invoice_date;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $purchase_invoice_id;
                    $node['rel_type'] = 'purchase_invoice';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }else{
                    $node = [];
                    $node['split'] = $payment_account;
                    $node['account'] = $deposit_to;
                    $node['item'] = $item_id;
                    $node['debit'] = $item_total;
                    $node['date'] = $purchase_invoice->invoice_date;
                    $node['tax'] = 0;
                    $node['credit'] = 0;
                    $node['description'] = '';
                    $node['rel_id'] = $purchase_invoice_id;
                    $node['rel_type'] = 'purchase_invoice';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $deposit_to;
                    $node['account'] = $payment_account;
                    $node['item'] = $item_id;
                    $node['date'] = $purchase_invoice->invoice_date;
                    $node['tax'] = 0;
                    $node['debit'] = 0;
                    $node['credit'] = $item_total;
                    $node['description'] = '';
                    $node['rel_id'] = $purchase_invoice_id;
                    $node['rel_type'] = 'purchase_invoice';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
                }
                
                if(get_option('acc_tax_automatic_conversion') == 1 && $value['tax'] > 0){
                    $tax_payment_account = get_option('acc_pur_tax_payment_account');
                    $tax_deposit_to = get_option('acc_pur_tax_deposit_to');

                    if($purchase_invoice->discount_type == 'before_tax'){

                        $total_tax = 0;
                        if($value['tax'] != ''){
                            $tax_arr = explode('|', $value['tax']);

                            $tax_rate_arr = [];
                            if($value['tax_rate'] != ''){
                                $tax_rate_arr = explode('|', $value['tax_rate']);
                            }

                            foreach($tax_arr as $k => $tax_it){
                                if(!isset($tax_rate_arr[$k]) ){
                                    $tax_rate_arr[$k] = $this->purchase_model->tax_rate_by_id($tax_it);
                                }

                                $total_tax += $tax_rate_arr[$k]*$value['into_money']/100;
                            }
                        }

                        $total_discount = $item_discount + $purchase_invoice->discount_total;

                        $t     = ($total_discount / $purchase_invoice->subtotal) * 100;
                        $total_tax = ($total_tax - $total_tax * $t / 100);


                    }else{
                        $total_tax = $value['total'] - $value['into_money'];
                        
                    }

                    if($base_currency->name != $currency->name){
                        $currency_rate = acc_get_currency_rate($base_currency->name, $currency->name);

                        $total_tax = round(($currency_rate * ($total_tax)), 2);
                    }

                    $tax_mapping = $this->get_tax_mapping($value['tax']);

                    if($tax_mapping){
                        $node = [];
                        $node['split'] = $tax_mapping->purchase_payment_account;
                        $node['account'] = $tax_mapping->purchase_deposit_to;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $purchase_invoice->invoice_date;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $purchase_invoice_id;
                        $node['rel_type'] = 'purchase_invoice';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_mapping->purchase_deposit_to;
                        $node['account'] = $tax_mapping->purchase_payment_account;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $purchase_invoice->invoice_date;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $purchase_invoice_id;
                        $node['rel_type'] = 'purchase_invoice';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;
                    }else{
                        $node = [];
                        $node['split'] = $tax_payment_account;
                        $node['account'] = $tax_deposit_to;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['date'] = $purchase_invoice->invoice_date;
                        $node['debit'] = $total_tax;
                        $node['credit'] = 0;
                        $node['description'] = '';
                        $node['rel_id'] = $purchase_invoice_id;
                        $node['rel_type'] = 'purchase_invoice';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;

                        $node = [];
                        $node['split'] = $tax_deposit_to;
                        $node['date'] = $purchase_invoice->invoice_date;
                        $node['account'] = $tax_payment_account;
                        $node['tax'] = $value['tax'];
                        $node['item'] = $item_id;
                        $node['debit'] = 0;
                        $node['credit'] = $total_tax;
                        $node['description'] = '';
                        $node['rel_id'] = $purchase_invoice_id;
                        $node['rel_type'] = 'purchase_invoice';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = get_staff_user_id();
                        $node['currency_rate'] = $currency_rate;
                        $data_insert[] = $node;
                    }
                }
            }

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    public function get_omni_sales_refund_data_convert($id, $type){
        $this->load->model('omni_sales/omni_sales_model');
        $refund = $this->omni_sales_model->get_refund($id);
        $order_return = $this->omni_sales_model->get_cart($refund->order_id);

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $base_currency = $currency;
        if($order_return->currency != 0){
            $base_currency = $this->currencies_model->get($order_return->currency);
        }

        $html = '<table class="table border table-striped no-margin">
                  <tbody>
                     <tr class="project-overview">
                        <td class="bold" width="30%">'. _l('order_return').'</td>
                        <td>'.'<a href="'.admin_url('omni_sales/view_order_detailt/' . $order_return->id).'">'. $order_return->order_number .'</a>' .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('acc_amount').'</td>
                        <td>'. app_format_money($refund->amount, $base_currency->name) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('expense_dt_table_heading_date').'</td>
                        <td>'. _d($refund->refunded_on) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('payment_modes').'</td>
                        <td>'. get_payment_mode_name_by_id($refund->payment_mode) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('note').'</td>
                        <td colspan="2">'. new_html_entity_decode($refund->note) .'</td>
                        <td></td>
                     </tr>';
            $_html = '';

            $amount = 1;

            if($base_currency->name != $currency->name){
                $amount = acc_get_currency_rate($base_currency->name, $currency->name);

                $edit_template = "";
                $edit_template .= render_input('edit_exchange_rate','exchange_rate', $amount, 'number');
                $edit_template .= "<div class='text-center mtop10'>";
                $edit_template .= "<button type='button' class='btn btn-success edit_conversion_rate_action'>"._l('copy_task_confirm')."</button>";
                $edit_template .= "</div>";
                $_html .= form_hidden('currency_from', $base_currency->name);
                $_html .= form_hidden('currency_to', $currency->name);
                $_html .= form_hidden('exchange_rate', $amount);
                $_html .= form_hidden('payment_amount', $refund->amount);
                $_html .= '<div class="row"><div class="col-md-12"><label class="currency_converter_label th font-medium mbot15 pull-left">1 '.$base_currency->name.' = '.$amount.' '.$currency->name.'</label><a href="#" onclick="return false;" data-placement="bottom" data-toggle="popover" data-content="'. htmlspecialchars($edit_template) .'" data-html="true" data-original-title class="pull-left mleft5 font-medium-xs"><i class="fa fa-pencil-square"></i></a><br></div></div>';
                $old_currency_rate = $this->get_old_currency_rate($id, $type);
                if($old_currency_rate != 0){
                    $html .=   '<tr class="project-overview">
                                <td class="bold">'. _l('amount_after_convert').'</td>
                                <td>'.app_format_money(round($old_currency_rate*$refund->amount, 4), $currency->name).'</td>
                                <td>1 '.$base_currency->name.' = '.$old_currency_rate.' '.$currency->name.'</td>
                             </tr>';
                }
                $html .=   '<tr class="project-overview">
                                <td class="bold">'. _l('amount_after_convert').'('._l('new').')</td>
                                <td class="amount_after_convert">'.app_format_money(round($amount*$refund->amount, 4), $currency->name).'</td>
                                <td>'.$_html.'</td>
                             </tr>';
            }

            $html .=  '</tbody>
                  </table>';

        return ['html' => $html];
    }

    public function get_omni_sales_return_order_data_convert($id, $type){
        $accounts = $this->get_accounts();
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $this->load->model('omni_sales/omni_sales_model');
        $order_return = $this->omni_sales_model->get_cart($id);
        $order_return_detail = $this->omni_sales_model->get_cart_detailt_by_cart_id($id);

        $base_currency = $currency;
        if($order_return->currency != 0){
            $base_currency = $this->currencies_model->get($order_return->currency);
        }

        $payment_method =  $order_return->payment_method_title;
          if($payment_method == ''){
            $data_multi_payment = $this->omni_sales_model->get_order_multi_payment($order_return->id);
            if($data_multi_payment){
              foreach ($data_multi_payment as $key => $mtpayment) {
                $payment_method .= $mtpayment['payment_name'].', ';
              }
              $payment_method = rtrim($payment_method, ', ');
            }
            else{
              $this->load->model('payment_modes_model');  
              $data_payment = $this->payment_modes_model->get($order_return->allowed_payment_modes);
              if($data_payment){
                $name = isset($data_payment->name) ? $data_payment->name : '';
                if($name !=''){
                  $payment_method = $name;              
                }            
              }
            }
          } 

          $status = get_status_by_index($order_return->status);

        $html = '<table class="table border table-striped no-margin">
                  <tbody>
                    <tr class="project-overview">
                        <td class="bold" width="30%">'. _l('order_number').'</td>
                        <td>'. '<a href="' . admin_url('omni_sales/view_order_detailt/' . $order_return->id) . '">'. $order_return->order_number .'</a>'  .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('vendor').'</td>
                        <td>'. '<a href="' . admin_url('clients/client/' . $order_return->userid) . '" >' .  $order_return->company . '</a>' .'</td>
                        <td></td>
                     </tr>

                    <tr class="project-overview">
                        <td class="bold">'. _l('date').'</td>
                        <td>'. _d($order_return->datecreator) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('payment_mode').'</td>
                        <td><span>'. $payment_method.'</span></td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('status').'</td>
                        <td><span class="label label-success">'.$status.'</span></td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('total').'</td>
                        <td>'. app_format_money($order_return->total,$base_currency->name) .'</td>
                        <td></td>
                     </tr>';
            $_html = '';

            $amount = 1;

            if($base_currency->name != $currency->name){
                $amount = acc_get_currency_rate($base_currency->name, $currency->name);

                $edit_template = "";
                $edit_template .= render_input('edit_exchange_rate','exchange_rate', $amount, 'number');
                $edit_template .= "<div class='text-center mtop10'>";
                $edit_template .= "<button type='button' class='btn btn-success edit_conversion_rate_action'>"._l('copy_task_confirm')."</button>";
                $edit_template .= "</div>";
                $_html .= form_hidden('currency_from', $base_currency->name);
                $_html .= form_hidden('currency_to', $currency->name);
                $_html .= form_hidden('exchange_rate', $amount);
                $_html .= form_hidden('payment_amount', $order_return->total);
                $_html .= '<div class="row"><div class="col-md-12"><label class="currency_converter_label th font-medium mbot15 pull-left">1 '.$base_currency->name.' = '.$amount.' '.$currency->name.'</label><a href="#" onclick="return false;" data-placement="bottom" data-toggle="popover" data-content="'. htmlspecialchars($edit_template) .'" data-html="true" data-original-title class="pull-left mleft5 font-medium-xs"><i class="fa fa-pencil-square"></i></a><br></div></div>';
                $old_currency_rate = $this->get_old_currency_rate($id, $type);
                if($old_currency_rate != 0){
                    $html .=   '<tr class="project-overview">
                                <td class="bold">'. _l('amount_after_convert').'</td>
                                <td>'.app_format_money(round($old_currency_rate*$order_return->total, 4), $currency->name).'</td>
                                <td>1 '.$base_currency->name.' = '.$old_currency_rate.' '.$currency->name.'</td>
                             </tr>';
                }
                $html .=   '<tr class="project-overview">
                                <td class="bold">'. _l('amount_after_convert').'('._l('new').')</td>
                                <td class="amount_after_convert">'.app_format_money(round($amount*$order_return->total, 4), $currency->name).'</td>
                                <td>'.$_html.'</td>
                             </tr>';
            }

            $html .=  '</tbody>
                  </table>';

        if($order_return_detail){
            $payment_account = get_option('acc_omni_sales_order_return_payment_account');
            $deposit_to = get_option('acc_omni_sales_order_return_deposit_to');

            $html .= '<h4>'._l('list_of_items').'</h4>';
            $list_item = [];

            foreach ($order_return_detail as $value) {

                $this->db->where('id', $value['product_id']);
                $item = $this->db->get(db_prefix().'items')->row();

                $item_description = $value['product_name'];

                $item_id = 0;
                if(isset($item->id)){
                    $item_id = $item->id;
                }

                if($item_id == 0){
                    continue;
                }
                $list_item[] = $item_id;

                $item_total = $value['quantity'] * $value['prices'];
                //  if(isset($data['exchange_rate'])){
                //     $item_total = round(($value['qty'] * $value['rate']) * $data['exchange_rate'], 2);
                // }elseif($currency_converter == 1){
                //     $item_total = round($this->currency_converter($invoice->currency_name, $currency->name, $value['qty'] * $value['rate']), 2);
                // }


                $this->db->where('rel_id', $id);
                $this->db->where('rel_type', $type);
                $this->db->where('item', $item_id);
                $account_history = $this->db->get(db_prefix(). 'acc_account_history')->result_array();
                
                foreach ($account_history as $key => $val) {
                    if($val['debit'] > 0){
                        $debit = $val['account'];
                    }

                    if($val['credit'] > 0){
                        $credit =  $val['account'];
                    }
                }

                if($account_history){
                    $html .= '
                    <div class="div_content">
                    <h5>'.$item_description.'('.app_format_money($item_total, $currency->name).')</h5>
                    <div class="row">
                            '.form_hidden('item_amount['.$item_id.']', $item_total).'
                          <div class="col-md-6"> '.
                            render_select('payment_account['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'payment_account',$credit,array(),array(),'','',false) .'
                          </div>
                          <div class="col-md-6">
                            '. render_select('deposit_to['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'deposit_to',$debit,array(),array(),'','',false).'
                          </div>
                      </div>
                    </div>';
                }else{
                    // $item_automatic = $this->get_item_automatic($item_id);

                    // if($item_automatic){
                    //     $html .= '
                    // <div class="div_content">
                    //     <h5>'.$item_description.'('.app_format_money($item_total, $currency->name).')</h5>
                    //     <div class="row">
                    //     '.form_hidden('item_amount['.$item_id.']', $item_total).'
                    //       <div class="col-md-6"> '.
                    //         render_select('payment_account['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'payment_account',$payment_account,array(),array(),'','',false) .'
                    //       </div>
                    //       <div class="col-md-6">
                    //         '. render_select('deposit_to['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'deposit_to',$item_automatic->expense_account,array(),array(),'','',false).'
                    //       </div>
                    //   </div>
                    // </div>';
                    // }else{
                        $html .= '
                            <div class="div_content">
                                <h5>'.$item_description.'('.app_format_money($item_total, $currency->name).')</h5>
                                <div class="row">
                                '.form_hidden('item_amount['.$item_id.']', $item_total).'
                                  <div class="col-md-6"> '.
                                    render_select('payment_account['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'payment_account',$payment_account,array(),array(),'','',false) .'
                                  </div>
                                  <div class="col-md-6">
                                    '. render_select('deposit_to['.$item_id.']',$accounts,array('id','name', 'account_type_name'),'deposit_to',$deposit_to,array(),array(),'','',false).'
                                  </div>
                              </div>
                            </div>';
                    // }
                }
            }
        }

        return ['html' => $html, 'list_item' => $list_item];
    }

    /**
     * update omni_sales automatic conversion
     *
     * @param      array   $data   The data
     *
     * @return     boolean 
     */
    public function update_omni_sales_automatic_conversion($data){
        $affectedRows = 0;

        if(!isset($data['acc_omni_sales_order_return_automatic_conversion'])){
            $data['acc_omni_sales_order_return_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_omni_sales_refund_automatic_conversion'])){
            $data['acc_omni_sales_refund_automatic_conversion'] = 0;
        }

        foreach ($data as $key => $value) {
            $this->db->where('name', $key);
            $this->db->update(db_prefix() . 'options', [
                    'value' => $value,
                ]);
            if ($this->db->affected_rows() > 0) {
                $affectedRows++;
            }
        }

        if ($affectedRows > 0) {
            return true;
        }
        return false;
    }

    /**
     * Automatic omni sales return order conversion
     * @param  integer $purchase_order_id 
     * @return boolean
     */
    public function automatic_omni_sales_return_order_conversion($sales_return_order_id){
        if(get_option('acc_omni_sales_order_return_automatic_conversion') == 0){
            return false;
        }

        $this->delete_convert($sales_return_order_id, 'sales_return_order');

        $this->load->model('omni_sales/omni_sales_model');
        $sales_return_order = $this->omni_sales_model->get_cart($sales_return_order_id);
        $sales_return_order_detail = $this->omni_sales_model->get_cart_detailt_by_cart_id($sales_return_order_id);

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $base_currency = $currency;
        if($sales_return_order->currency != 0){
            $base_currency = $this->currencies_model->get($sales_return_order->currency);
        }

        $payment_account = get_option('acc_omni_sales_order_return_payment_account');
        $deposit_to = get_option('acc_omni_sales_order_return_deposit_to');

        // $tax_payment_account = get_option('acc_expense_tax_payment_account');
        // $tax_deposit_to = get_option('acc_expense_tax_deposit_to');

        if($sales_return_order){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($sales_return_order->datecreator) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }
            
            $data_insert = [];
            $currency_rate = 0;
            if($base_currency->name != $currency->name){
                $currency_rate = acc_get_currency_rate($base_currency->name, $currency->name);
            }

            foreach ($sales_return_order_detail as $value) {

                $item_id = $value['product_id'];
               
                $item_total = $value['quantity'] * $value['prices'];
                if($base_currency->name != $currency->name){
                    $item_total = round($currency_rate * ($value['quantity'] * $value['prices']), 2);
                }

                //$item_automatic = $this->get_item_automatic($item_id);
            
                $node = [];
                $node['split'] = $payment_account;
                $node['account'] = $deposit_to;
                $node['item'] = $item_id;
                $node['debit'] = $item_total;
                $node['customer'] = $sales_return_order->userid;
                $node['date'] = $sales_return_order->datecreator;
                $node['tax'] = 0;
                $node['credit'] = 0;
                $node['description'] = '';
                $node['rel_id'] = $sales_return_order_id;
                $node['rel_type'] = 'sales_return_order';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['currency_rate'] = $currency_rate;
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $deposit_to;
                $node['account'] = $payment_account;
                $node['item'] = $item_id;
                $node['customer'] = $sales_return_order->userid;
                $node['date'] = $sales_return_order->datecreator;
                $node['tax'] = 0;
                $node['debit'] = 0;
                $node['credit'] = $item_total;
                $node['description'] = '';
                $node['rel_id'] = $sales_return_order_id;
                $node['rel_type'] = 'sales_return_order';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['currency_rate'] = $currency_rate;
                $data_insert[] = $node;

                // if(get_option('acc_tax_automatic_conversion') == 1 && $value['tax'] > 0){
                //     $tax_payment_account = get_option('acc_expense_tax_payment_account');
                //     $tax_deposit_to = get_option('acc_expense_tax_deposit_to');

                //     $total_tax = $value['total'] - $value['into_money'];

                //     $tax_mapping = $this->get_tax_mapping($value['tax']);

                //     if($tax_mapping){
                //         $node = [];
                //         $node['split'] = $tax_mapping->payment_account;
                //         $node['account'] = $tax_mapping->deposit_to;
                //         $node['tax'] = $value['tax'];
                //         $node['item'] = 0;
                //         $node['date'] = $sales_return_order->datecreator;
                //         $node['debit'] = $total_tax;
                //         $node['credit'] = 0;
                //         $node['description'] = '';
                //         $node['rel_id'] = $sales_return_order_id;
                //         $node['rel_type'] = 'sales_return_order';
                //         $node['datecreated'] = date('Y-m-d H:i:s');
                //         $node['addedfrom'] = get_staff_user_id();
                //         $data_insert[] = $node;

                //         $node = [];
                //         $node['split'] = $tax_mapping->deposit_to;
                //         $node['account'] = $tax_mapping->payment_account;
                //         $node['tax'] = $value['tax'];
                //         $node['item'] = 0;
                //         $node['date'] = $sales_return_order->datecreator;
                //         $node['debit'] = 0;
                //         $node['credit'] = $total_tax;
                //         $node['description'] = '';
                //         $node['rel_id'] = $sales_return_order_id;
                //         $node['rel_type'] = 'sales_return_order';
                //         $node['datecreated'] = date('Y-m-d H:i:s');
                //         $node['addedfrom'] = get_staff_user_id();
                //         $data_insert[] = $node;
                //     }else{
                //         $node = [];
                //         $node['split'] = $tax_payment_account;
                //         $node['account'] = $tax_deposit_to;
                //         $node['tax'] = $value['tax'];
                //         $node['item'] = 0;
                //         $node['date'] = $sales_return_order->datecreator;
                //         $node['debit'] = $total_tax;
                //         $node['credit'] = 0;
                //         $node['description'] = '';
                //         $node['rel_id'] = $sales_return_order_id;
                //         $node['rel_type'] = 'sales_return_order';
                //         $node['datecreated'] = date('Y-m-d H:i:s');
                //         $node['addedfrom'] = get_staff_user_id();
                //         $data_insert[] = $node;

                //         $node = [];
                //         $node['split'] = $tax_deposit_to;
                //         $node['date'] = $sales_return_order->datecreator;
                //         $node['account'] = $tax_payment_account;
                //         $node['tax'] = $value['tax'];
                //         $node['item'] = 0;
                //         $node['debit'] = 0;
                //         $node['credit'] = $total_tax;
                //         $node['description'] = '';
                //         $node['rel_id'] = $sales_return_order_id;
                //         $node['rel_type'] = 'sales_return_order';
                //         $node['datecreated'] = date('Y-m-d H:i:s');
                //         $node['addedfrom'] = get_staff_user_id();
                //         $data_insert[] = $node;
                //     }
                // }
            }

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Automatic refund conversion
     * @param  integer $refund_id 
     * @return boolean
     */
    public function automatic_omni_sales_refund_conversion($refund_id){
        if(get_option('acc_omni_sales_refund_automatic_conversion') == 0){
            return false;
        }
        
        $this->delete_convert($refund_id, 'sales_refund');

        $this->load->model('omni_sales/omni_sales_model');
        $refund = $this->omni_sales_model->get_refund($refund_id);
        $order_return = $this->omni_sales_model->get_order_return($refund->order_id);

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $base_currency = $currency;
        if($order_return->currency != 0){
            $base_currency = $this->currencies_model->get($order_return->currency);
        }

        if($order_return->status == "finish"){
            $this->automatic_omni_sales_return_order_conversion($refund->order_id);
        }

        $payment_account = get_option('acc_omni_sales_refund_payment_account');
        $deposit_to = get_option('acc_omni_sales_refund_deposit_to');
        $affectedRows = 0;
        $data_insert = [];

        if($refund){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($refund->refunded_on) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }

            $payment_total = $refund->amount;
            $currency_rate = 0;
            if($base_currency->name != $currency->name){
                $currency_rate = acc_get_currency_rate($base_currency->name, $currency->name);
                $payment_total = round($currency_rate * $refund->amount, 2);
            }

            // $payment_mode_mapping = $this->get_payment_mode_mapping($refund->payment_mode);

            // if($payment_mode_mapping && get_option('acc_active_payment_mode_mapping') == 1){
            //     $node = [];
            //     $node['split'] = $payment_mode_mapping->payment_account;
            //     $node['account'] = $payment_mode_mapping->deposit_to;
            //     $node['date'] = $refund->refunded_on;
            //     $node['debit'] = $payment_total;
            //     $node['credit'] = 0;
            //     $node['tax'] = 0;
            //     $node['description'] = '';
            //     $node['rel_id'] = $refund_id;
            //     $node['rel_type'] = 'purchase_refund';
            //     $node['datecreated'] = date('Y-m-d H:i:s');
            //     $node['addedfrom'] = get_staff_user_id();
            //     $data_insert[] = $node;

            //     $node = [];
            //     $node['split'] = $payment_mode_mapping->deposit_to;
            //     $node['account'] = $payment_mode_mapping->payment_account;
            //     $node['date'] = $refund->refunded_on;
            //     $node['tax'] = 0;
            //     $node['debit'] = 0;
            //     $node['credit'] = $payment_total;
            //     $node['description'] = '';
            //     $node['rel_id'] = $refund_id;
            //     $node['rel_type'] = 'purchase_refund';
            //     $node['datecreated'] = date('Y-m-d H:i:s');
            //     $node['addedfrom'] = get_staff_user_id();
            //     $data_insert[] = $node;
            // }else{
                    $node = [];
                    $node['split'] = $payment_account;
                    $node['account'] = $deposit_to;
                    $node['debit'] = $payment_total;
                    $node['credit'] = 0;
                    $node['date'] = $refund->refunded_on;
                    $node['description'] = '';
                    $node['rel_id'] = $refund_id;
                    $node['rel_type'] = 'sales_refund';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;

                    $node = [];
                    $node['split'] = $deposit_to;
                    $node['account'] = $payment_account;
                    $node['date'] = $refund->refunded_on;
                    $node['debit'] = 0;
                    $node['credit'] = $payment_total;
                    $node['description'] = '';
                    $node['rel_id'] = $refund_id;
                    $node['rel_type'] = 'sales_refund';
                    $node['datecreated'] = date('Y-m-d H:i:s');
                    $node['addedfrom'] = get_staff_user_id();
                    $node['currency_rate'] = $currency_rate;
                    $data_insert[] = $node;
            // }

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * count omni_sales refund not convert yet
     * @param  integer $currency
     * @param  string $where
     * @return object          
     */
    public function count_omni_sales_refund_not_convert_yet($currency = '', $where = ''){
        $where_currency = '';
        if($currency != ''){
            $where_currency = 'and currency = '.$currency;
        }

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'omni_refunds.id and ' . db_prefix() . 'acc_account_history.rel_type = "sales_refund") = 0) AND (' . db_prefix() . 'cart.id is not null) '.$where_currency);
        $this->db->join(db_prefix().'cart', db_prefix() . 'cart.id = ' . db_prefix() . 'omni_refunds.order_id', 'left');
        return $this->db->count_all_results(db_prefix().'omni_refunds');
    }

    /**
     * count omni_sales order return not convert yet
     * @param  integer $currency
     * @param  string $where
     * @return object          
     */
    public function count_omni_sales_order_return_not_convert_yet($currency = '', $where = ''){
        $where_currency = '';
        if($currency != ''){
            $where_currency = 'and currency = '.$currency;
        }

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'cart.id and ' . db_prefix() . 'acc_account_history.rel_type = "sales_return_order") = 0) and status = "5" and original_order_id is not null '.$where_currency);

        return $this->db->count_all_results(db_prefix().'cart');
    }

    /**
     * Gets the bill.
     *
     * @param        $id     The identifier
     */
    public function get_bill($id = '', $where = []){
        $this->db->from(db_prefix() . 'expenses');
        $this->db->where($where);

        if (is_numeric($id)) {
            $this->db->where(db_prefix() . 'expenses.id', $id);
            $bill = $this->db->get()->row();
            if ($bill) {
                $bill->debit_account = $this->get_bill_mapping_details($id, 'debit');
                $bill->credit_account = $this->get_bill_mapping_details($id, 'credit');
                $bill->bill_items = $this->get_bill_mapping_details($id, 'item');
                $bill->attachment            = '';
                $bill->filetype              = '';
                $bill->attachment_added_from = 0;

                $this->db->where('rel_id', $id);
                $this->db->where('rel_type', 'expense');
                $file = $this->db->get(db_prefix() . 'files')->row();

                if ($file) {
                    $bill->attachment            = $file->file_name;
                    $bill->filetype              = $file->filetype;
                    $bill->attachment_added_from = $file->staffid;
                }
            }

            return $bill;
        }
        $this->db->select('*, (SELECT GROUP_CONCAT(account SEPARATOR ",") FROM '.db_prefix().'acc_bill_mappings WHERE bill_id = '.db_prefix().'expenses.id and type = "debit") as account_ids');
        $this->db->order_by('date', 'desc');

        return $this->db->get()->result_array();
    }

    /**
     * get bill mapping details
     * @param  integer  $rel_id 
     * @param  string  $rel_type 
     * @return array                 
     */
    public function get_bill_mapping_details($bill_id, $type){
        $this->db->where('bill_id', $bill_id);
        $this->db->where('type', $type);
        $mapping_details = $this->db->get(db_prefix().'acc_bill_mappings')->result_array();
        return $mapping_details; 
    }

    public function bill_appove_payable($bill_id){
        $bill = $this->get_bill($bill_id);

        $closing_date = strtotime(get_option('acc_closing_date'));
        $bill_date = strtotime($bill->date);
        $current_date = strtotime(date('Y-m-d'));
        if(get_option('acc_close_the_books') == 1){
            if(($current_date < $closing_date && $bill_date < $current_date) || ($current_date >= $closing_date && $bill_date < $closing_date)){
                return 'book_closed';
                die;
            }
        }

        $this->db->where('id', $bill_id);
        $this->db->update(db_prefix() . 'expenses', ['approved' => 1]);

        if ($this->db->affected_rows() > 0) {
            $data_insert = [];
            
            foreach ($bill->debit_account as $debit_account) {
                $node = [];
                $node['account'] = $debit_account['account'];
                $node['debit'] = $debit_account['amount'];
                $node['vendor'] = $bill->vendor;
                $node['date'] = $bill->date;
                $node['split'] = 0;
                $node['credit'] = 0;
                $node['description'] = '';
                $node['bill_item'] = $debit_account['id'];
                $node['rel_id'] = $bill_id;
                $node['rel_type'] = 'bill';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;
            }

            foreach ($bill->credit_account as $credit_account) {
                $node = [];
                $node['account'] = $credit_account['account'];
                $node['credit'] = $credit_account['amount'];
                $node['vendor'] = $bill->vendor;
                $node['date'] = $bill->date;
                $node['debit'] = 0;
                $node['split'] = 0;
                $node['bill_item'] = $debit_account['id'];
                $node['description'] = '';
                $node['rel_id'] = $bill_id;
                $node['rel_type'] = 'bill';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;
            }

            $payment_account = get_option('acc_expense_payment_account');
            $deposit_to = get_option('acc_expense_deposit_to');

            foreach ($bill->bill_items as $item) {

                $item_automatic = $this->get_item_automatic($item['item_id']);

                if($item_automatic){
                    $deposit_to = $item_automatic->expense_account;
                }

                $node = [];
                $node['account'] = $payment_account;
                $node['split'] = $deposit_to;
                $node['credit'] = $item['amount'];
                $node['vendor'] = $bill->vendor;
                $node['date'] = $bill->date;
                $node['debit'] = 0;
                $node['bill_item'] = $item['id'];
                $node['description'] = '';
                $node['rel_id'] = $bill_id;
                $node['rel_type'] = 'bill';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;

                $node = [];
                $node['account'] = $deposit_to;
                $node['split'] = $payment_account;
                $node['credit'] = 0;
                $node['vendor'] = $bill->vendor;
                $node['date'] = $bill->date;
                $node['debit'] = $item['amount'];
                $node['bill_item'] = $item['id'];
                $node['description'] = '';
                $node['rel_id'] = $bill_id;
                $node['rel_type'] = 'bill';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $data_insert[] = $node;
            }

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }

            return true;
        }

        return false;
    }

    public function bill_status_change($bill_id, $status, $date_paid = ''){

        $data_update = [];
        $data_update['status'] = $status;
        if($status == 2){
            if($date_paid != ''){
                $data_update['date_paid'] = $date_paid;
            }else{
                $data_update['date_paid'] = date('Y-m-d');
            }

            $this->db->where('rel_id', $bill_id);
            $this->db->where('rel_type', 'bill');
            $this->db->update(db_prefix().'acc_account_history', ['paid' => 1]);
        }else{
            $this->db->where('rel_id', $bill_id);
            $this->db->where('rel_type', 'bill');
            $this->db->update(db_prefix().'acc_account_history', ['paid' => 0]);
        }
        $this->db->where('id', $bill_id);
        $this->db->update(db_prefix().'expenses', $data_update);

        return true;
    }

    public function void_bill($bill_id, $data){
        $bill = $this->get_bill($bill_id);

        $closing_date = strtotime(get_option('acc_closing_date'));
        $bill_date = strtotime($bill->date);
        $current_date = strtotime(date('Y-m-d'));
        if(get_option('acc_close_the_books') == 1){
            if(($current_date < $closing_date && $bill_date < $current_date) || ($current_date >= $closing_date && $bill_date < $closing_date)){
                return 'book_closed';
            }
        }

        $data['reason_for_void'] = nl2br($data['reason_for_void']);

        $this->db->where('id', $bill_id);
        $this->db->update(db_prefix() . 'expenses', ['voided' => 1, 'reason_for_void' => $data['reason_for_void']]);

        if ($this->db->affected_rows() > 0) {

            $this->db->where('rel_id', $bill_id);
            $this->db->where('rel_type', 'bill');
            $account_history = $this->db->get(db_prefix() . 'acc_account_history')->result_array();

            $data_insert = [];
            

            foreach($account_history as $history){
                $node = $history;
                unset($node['id']);
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();

                if($node['debit'] > 0){
                    $node['credit'] = $node['debit'];
                    $node['debit'] = 0;
                }else{
                    $node['debit'] = $node['credit'];
                    $node['credit'] = 0;
                }
                
                $data_insert[] = $node;
            }

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }

            return true;
        }

        return false;
    }

    public function get_list_pay_bill($bill_id){
        $this->db->where('bill_id', $bill_id);
        return $this->db->get(db_prefix().'acc_pay_bill_details')->result_array();
    }

    /**
     * Gets the pay_bills.
     */
    public function get_pay_bills(){
        return $this->db->get(db_prefix().'acc_pay_bills')->result_array();
    }

    /**
     * Gets the bill.
     *
     * @param        $id     The identifier
     */
    public function get_pay_bill($id = '', $where = []){
        $this->db->from(db_prefix() . 'acc_pay_bills');
        $this->db->where($where);

        if (is_numeric($id)) {
            $this->db->where('id', $id);
            $pay_bill = $this->db->get()->row();
            if ($pay_bill) {
                $pay_bill->attachment            = '';
                $pay_bill->filetype              = '';
                $pay_bill->attachment_added_from = 0;
                $pay_bill->pay_bill_item_paid = $this->get_pay_bill_item_paid('', ['pay_bill_id' => $id]);

                $this->db->where('rel_id', $id);
                $this->db->where('rel_type', 'pay_bill');
                $file = $this->db->get(db_prefix() . 'files')->row();

                if ($file) {
                    $pay_bill->attachment            = $file->file_name;
                    $pay_bill->filetype              = $file->filetype;
                    $pay_bill->attachment_added_from = $file->staffid;
                }
            }

            return $pay_bill;
        }
        $this->db->order_by('date', 'desc');

        return $this->db->get()->result_array();
    }

    /**
     * Adds a pay_bill.
     *
     * @param        $data   The data
     */
    public function add_pay_bill($data){

        $data['date'] = to_sql_date($data['date']);

        if(isset($data['bill_items'])){
            $data['bill_items'] = implode(',', $data['bill_items']);
        }

        if(isset($data['DataTables_Table_0_length'])){
            unset($data['DataTables_Table_0_length']);
        }

        if(isset($data['DataTables_Table_1_length'])){
            unset($data['DataTables_Table_1_length']);
        }

        if(isset($data['DataTables_Table_2_length'])){
            unset($data['DataTables_Table_2_length']);
        }

        $pay_bill_item = [];
        if(isset($data['pay_bill_item'])){
            $pay_bill_item = $data['pay_bill_item'];
            unset($data['pay_bill_item']);
        }

        $pay_bill_amount = [];
        if(isset($data['pay_bill_amount'])){
            $pay_bill_amount = $data['pay_bill_amount'];
            unset($data['pay_bill_amount']);
        }

        $pay_bill_amount_paid = [];
        if(isset($data['pay_bill_amount_paid'])){
            $pay_bill_amount_paid = $data['pay_bill_amount_paid'];
            unset($data['pay_bill_amount_paid']);
        }

        $bills_checked = [];
        if(isset($data['bill_id_check'])){
            $bills_checked = $data['bill_id_check'];
            unset($data['bill_id_check']);
        }

        if(isset($data['bill'])){
            $bills_checked[] = $data['bill'];
            unset($data['bill_id_check']);
        }

        $number_rs = 1;

        $this->db->select('max(pay_number) as number');
        $number = $this->db->get(db_prefix().'acc_pay_bills')->row();
        if($number){
            $number_rs = $number->number +1;
        }

        $data['pay_number'] = $number_rs;

        $data['addedfrom'] = get_staff_user_id();
        $data['dateadded'] = date('Y-m-d H:i:s');
        $this->db->insert(db_prefix() . 'acc_pay_bills', $data);
        $insert_id = $this->db->insert_id();
        if ($insert_id) {
            $this->automatic_pay_bill_conversion($insert_id);
            
            foreach($bills_checked as $bill){
                if($bill != 0){
                    $this->db->insert(db_prefix().'acc_pay_bill_details', [
                        'pay_bill' => $insert_id,
                        'bill_id' => $bill
                    ]);

                    $bill_amount = bill_amount_left($bill, false);
                    if($bill_amount > 0){
                        $this->bill_status_change($bill, 3, $data['date']);
                    }else{
                        $this->bill_status_change($bill, 2, $data['date']);
                    }
                }
            }

            foreach($pay_bill_amount_paid as $item_id => $amount_paid){
                if($amount_paid > 0){
                    $amount = str_replace(',', '', $amount_paid);
                    $item_amount = str_replace(',', '', $pay_bill_amount[$item_id]);
                    $this->db->insert(db_prefix().'acc_pay_bill_item_paid', [
                        'pay_bill_id' => $insert_id,
                        'item_id' => $item_id,
                        'item_name' => $pay_bill_item[$item_id],
                        'item_amount' => $item_amount,
                        'amount_paid' => $amount
                    ]);
                }
            }

            return $insert_id;
        }

        return false;
    }

    /**
     * { update pay_bill }
     *
     * @param        $data   The data
     * @param        $id     The identifier
     *
     * @return     bool    
     */
    public function update_pay_bill($data, $id){
        $affectedRows = 0;
        $data['date'] = to_sql_date($data['date']);

        if(isset($data['bill_items'])){
            $data['bill_items'] = implode(',', $data['bill_items']);
        }

        if(isset($data['payment_method'])){
            unset($data['payment_method']);
        }

        if(isset($data['DataTables_Table_0_length'])){
            unset($data['DataTables_Table_0_length']);
        }

        if(isset($data['DataTables_Table_1_length'])){
            unset($data['DataTables_Table_1_length']);
        }

        $bills_checked = [];
        if(isset($data['bill_id_check'])){
            $bills_checked = $data['bill_id_check'];
            unset($data['bill_id_check']);
        }

        $pay_bill_item = [];
        if(isset($data['pay_bill_item'])){
            $pay_bill_item = $data['pay_bill_item'];
            unset($data['pay_bill_item']);
        }

        $pay_bill_amount = [];
        if(isset($data['pay_bill_amount'])){
            $pay_bill_amount = $data['pay_bill_amount'];
            unset($data['pay_bill_amount']);
        }

        $pay_bill_amount_paid = [];
        if(isset($data['pay_bill_amount_paid'])){
            $pay_bill_amount_paid = $data['pay_bill_amount_paid'];
            unset($data['pay_bill_amount_paid']);
        }

        $this->db->where('pay_bill', $id);
        $old_details = $this->db->get(db_prefix().'acc_pay_bill_details')->result_array();

        $this->db->where('pay_bill', $id);
        $this->db->delete(db_prefix().'acc_pay_bill_details');

        $this->db->where('id', $id);
        $this->db->update(db_prefix() . 'acc_pay_bills', $data);
        if ($this->db->affected_rows() > 0) {
            $this->automatic_pay_bill_conversion($id);
            $affectedRows++;
        }

        foreach($old_details as $detail){
            if($detail['bill_id'] != 0){
                $bill_amount = bill_amount_left($detail['bill_id'], false);
                $bill = $this->get_bill($detail['bill_id']);
                if($bill->amount == $bill_amount){
                    $this->bill_status_change($detail['bill_id'], 0);
                }else{
                    $this->bill_status_change($detail['bill_id'], 3);
                }
            }
        }


        foreach($bills_checked as $bill){
            if($bill != 0){
                $this->db->insert(db_prefix().'acc_pay_bill_details', [
                    'pay_bill' => $id,
                    'bill_id' => $bill
                ]);
            }

            $bill_amount = bill_amount_left($bill, false);
            if($bill_amount > 0){
                $this->bill_status_change($bill, 3, $data['date']);
            }else{
                $this->bill_status_change($bill, 2, $data['date']);
            }
        }

        $this->db->where('pay_bill_id', $id);
        $this->db->delete(db_prefix().'acc_pay_bill_item_paid');

        foreach($pay_bill_amount_paid as $item_id => $amount_paid){
            if($amount_paid > 0){
                $amount = str_replace(',', '', $amount_paid);
                $item_amount = str_replace(',', '', $pay_bill_amount[$item_id]);
                $this->db->insert(db_prefix().'acc_pay_bill_item_paid', [
                    'pay_bill_id' => $id,
                    'item_id' => $item_id,
                    'item_name' => $pay_bill_item[$item_id],
                    'item_amount' => $item_amount,
                    'amount_paid' => $amount
                ]);
            }
        }


        if ($affectedRows > 0) {
            return true;
        }

        return false;
    }

    /**
     * { delete pay_bill }
     *
     * @param        $id     The identifier
     */
    public function delete_pay_bill($id){
        $affectedRows = 0;

        $this->db->where('id', $id);
        $this->db->delete(db_prefix().'acc_pay_bills');
        if($this->db->affected_rows() > 0){

            $pay_bill_details = $this->get_pay_bill_details($id);
            foreach($pay_bill_details as $detail){
                $bill_amount = bill_amount_left($detail['bill_id'], false);
                $bill = $this->get_bill($detail['bill_id']);
                if($bill->amount == $bill_amount){
                    $this->bill_status_change($detail['bill_id'], 0);
                }else{
                    $this->bill_status_change($detail['bill_id'], 3);
                }
            }

            $this->db->where('pay_bill', $id);
            $this->db->delete(db_prefix().'acc_pay_bill_details');
            if($this->db->affected_rows() > 0){ 
                $affectedRows++;
            }

            $this->db->where('pay_bill_id', $id);
            $this->db->delete(db_prefix().'acc_pay_bill_item_paid');
            if($this->db->affected_rows() > 0){ 
                $affectedRows++;
            }

            $this->db->where('rel_id', $id);
            $this->db->where('rel_type', 'pay_bill');
            $this->db->delete(db_prefix().'files');
            if($this->db->affected_rows() > 0){ 
                $affectedRows++;
            }

            $this->db->where('rel_id', $id);
            $this->db->where('rel_type', 'pay_bill');
            $this->db->delete(db_prefix().'acc_account_history');
            if($this->db->affected_rows() > 0){ 
                $affectedRows++;
            }

            if (is_dir(ACCOUTING_MODULE_UPLOAD_FOLDER .'/pay_bills/'. $id)) {
                delete_dir(ACCOUTING_MODULE_UPLOAD_FOLDER .'/pay_bills/'. $id);
            }
        }

        if($affectedRows > 0){
            return true;
        }
        return false;
    }

    /**
     * Delete Expense attachment
     * @param  mixed $id expense id
     * @return boolean
     */
    public function delete_pay_bill_attachment($id)
    {
        if (is_dir(ACCOUTING_MODULE_UPLOAD_FOLDER .'/pay_bills/'. $id)) {
            if (delete_dir(ACCOUTING_MODULE_UPLOAD_FOLDER .'/pay_bills/'. $id)) {
                $this->db->where('rel_id', $id);
                $this->db->where('rel_type', 'pay_bill');
                $this->db->delete(db_prefix() . 'files');
               
                return true;
            }
        }

        return false;
    }

    /**
     * Gets the vendor.
     *
     * @param      string        $id     The identifier
     * @param      array|string  $where  The where
     *
     * @return     <type>        The vendor or list vendors.
     */
    public function get_vendor($id = '', $where = [])
    {
        $this->db->select(implode(',', prefixed_table_fields_array(db_prefix() . 'pur_vendor')) );

        $this->db->join(db_prefix() . 'countries', '' . db_prefix() . 'countries.country_id = ' . db_prefix() . 'pur_vendor.country', 'left');


        if ((is_array($where) && count($where) > 0) || (is_string($where) && $where != '')) {
            $this->db->where($where);
        }

        if (is_numeric($id)) {

            $this->db->where(db_prefix().'pur_vendor.userid', $id);
            $vendor = $this->db->get(db_prefix() . 'pur_vendor')->row();

            if ($vendor && get_option('company_requires_vat_number_field') == 0) {
                $vendor->vat = null;
            }


            return $vendor;

        }

        $this->db->order_by('company', 'asc');

        return $this->db->get(db_prefix() . 'pur_vendor')->result_array();
    }

    /**
     * Gets the bills.
     */
    public function get_bills(){
        return $this->db->get(db_prefix().'expenses')->result_array();
    }

    /**
     * Adds a bill.
     *
     * @param        $data   The data
     */
    public function add_bill($data){
        $debit_account = [];
        $debit_amount = [];
        $credit_account = [];
        $credit_amount = [];

        if(isset($data['debit_account'])){
            $debit_account = $data['debit_account'];
            unset($data['debit_account']);
        }

        if(isset($data['debit_amount'])){
            $debit_amount = $data['debit_amount'];
            unset($data['debit_amount']);
        }

        if(isset($data['credit_account'])){
            $credit_account = $data['credit_account'];
            unset($data['credit_account']);
        }

        if(isset($data['credit_amount'])){
            $credit_amount = $data['credit_amount'];
            unset($data['credit_amount']);
        }

        if(isset($data['item_id'])){
            $item_id = $data['item_id'];
            unset($data['item_id']);
        }

        if(isset($data['item_description'])){
            $item_description = $data['item_description'];
            unset($data['item_description']);
        }

        if(isset($data['item_qty'])){
            $item_qty = $data['item_qty'];
            unset($data['item_qty']);
        }

        if(isset($data['item_cost'])){
            $item_cost = $data['item_cost'];
            unset($data['item_cost']);
        }

        if(isset($data['item_amount'])){
            $item_amount = $data['item_amount'];
            unset($data['item_amount']);
        }

        $data['date'] = to_sql_date($data['date']);
        $data['due_date'] = to_sql_date($data['due_date']);
        $data['note'] = nl2br($data['note']);

        $data['is_bill'] = 1;

        $data['status'] = 0;

        $data['addedfrom'] = get_staff_user_id();
        $data['dateadded'] = date('Y-m-d H:i:s');
        $this->db->insert(db_prefix() . 'expenses', $data);
        $insert_id = $this->db->insert_id();
        if ($insert_id) {
            $data_insert = [];
            foreach($debit_account as $key => $account){
                $amount = str_replace(',', '', $debit_amount[$key]);
                if($amount == '' || $account == ''){
                    continue;
                }
                $row = [];
                $row['bill_id'] = $insert_id;
                $row['type'] = 'debit';
                $row['account'] = $account;
                $row['amount'] = $amount;
                $row['item_id'] = 0;
                $row['qty'] = 0;
                $row['cost'] = 0;
                $row['description'] = '';
                $data_insert[] = $row;
            }

            foreach($credit_account as $key => $account){
                if($amount == '' || $account == ''){
                    continue;
                }

                $amount = str_replace(',', '', $credit_amount[$key]);
                $row = [];
                $row['bill_id'] = $insert_id;
                $row['type'] = 'credit';
                $row['account'] = $account;
                $row['amount'] = $amount;
                $row['item_id'] = 0;
                $row['qty'] = 0;
                $row['cost'] = 0;
                $row['description'] = '';
                $data_insert[] = $row;
            }

            foreach($item_id as $key => $itemid){
                $cost = str_replace(',', '', $item_cost[$key]);
                $amount = str_replace(',', '', $item_amount[$key]);

                if($amount == '' || $itemid == ''){
                    continue;
                }

                $row = [];
                $row['bill_id'] = $insert_id;
                $row['type'] = 'item';
                $row['account'] = 0;
                $row['amount'] = $amount;
                $row['item_id'] = $itemid;
                $row['qty'] = $item_qty[$key];
                $row['cost'] = $cost;
                $row['description'] = $item_description[$key];
                $data_insert[] = $row;
            }

            if($data_insert != []){
                $this->db->insert_batch(db_prefix().'acc_bill_mappings', $data_insert);
            }

            return $insert_id;
        }

        return false;
    }

    /**
     * { update bill }
     *
     * @param        $data   The data
     * @param        $id     The identifier
     *
     * @return     bool    
     */
    public function update_bill($data, $id){
        $debit_account = [];
        $debit_amount = [];
        $credit_account = [];
        $credit_amount = [];

        if(isset($data['debit_account'])){
            $debit_account = $data['debit_account'];
            unset($data['debit_account']);
        }

        if(isset($data['debit_amount'])){
            $debit_amount = $data['debit_amount'];
            unset($data['debit_amount']);
        }

        if(isset($data['credit_account'])){
            $credit_account = $data['credit_account'];
            unset($data['credit_account']);
        }

        if(isset($data['credit_amount'])){
            $credit_amount = $data['credit_amount'];
            unset($data['credit_amount']);
        }

        if(isset($data['item_id'])){
            $item_id = $data['item_id'];
            unset($data['item_id']);
        }

        if(isset($data['item_description'])){
            $item_description = $data['item_description'];
            unset($data['item_description']);
        }

        if(isset($data['item_qty'])){
            $item_qty = $data['item_qty'];
            unset($data['item_qty']);
        }

        if(isset($data['item_cost'])){
            $item_cost = $data['item_cost'];
            unset($data['item_cost']);
        }

        if(isset($data['item_amount'])){
            $item_amount = $data['item_amount'];
            unset($data['item_amount']);
        }

        $data['date'] = to_sql_date($data['date']);
        $data['due_date'] = to_sql_date($data['due_date']);
        $data['note'] = nl2br($data['note']);

        $this->db->where('id', $id);
        $this->db->update(db_prefix() . 'expenses', $data);

        $this->db->where('bill_id', $id);
        $this->db->delete(db_prefix() . 'acc_bill_mappings');

        $data_insert = [];
        foreach($debit_account as $key => $account){
            $amount = str_replace(',', '', $debit_amount[$key]);

            if($amount == '' || $account == ''){
                continue;
            }
            
            $row = [];
            $row['bill_id'] = $id;
            $row['type'] = 'debit';
            $row['account'] = $account;
            $row['amount'] = $amount;
            $row['item_id'] = 0;
            $row['qty'] = 0;
            $row['cost'] = 0;
            $row['description'] = '';
            $data_insert[] = $row;
        }

        foreach($credit_account as $key => $account){
            $amount = str_replace(',', '', $credit_amount[$key]);

            if($amount == '' || $account == ''){
                continue;
            }

            $row = [];
            $row['bill_id'] = $id;
            $row['type'] = 'credit';
            $row['account'] = $account;
            $row['amount'] = $amount;
            $row['item_id'] = 0;
            $row['qty'] = 0;
            $row['cost'] = 0;
            $row['description'] = '';
            $data_insert[] = $row;
        }

        foreach($item_id as $key => $itemid){
            $cost = str_replace(',', '', $item_cost[$key]);
            $amount = str_replace(',', '', $item_amount[$key]);

            if($amount == '' || $itemid == ''){
                continue;
            }

            $row = [];
            $row['bill_id'] = $id;
            $row['type'] = 'item';
            $row['account'] = 0;
            $row['item_id'] = $itemid;
            $row['qty'] = $item_qty[$key];
            $row['cost'] = $cost;
            $row['amount'] = $amount;
            $row['description'] = $item_description[$key];
            $data_insert[] = $row;
        }

        if($data_insert != []){
            $this->db->insert_batch(db_prefix().'acc_bill_mappings', $data_insert);
        }

        return true;
    }

    /**
     * { delete bill }
     *
     * @param        $id     The identifier
     */
    public function delete_bill($id){
        $affectedRows = 0;

        $this->db->where('bill_id', $id);
        $pay_bills = $this->db->count_all_results(db_prefix().'acc_pay_bill_details');

        $this->db->where('bill', $id);
        $checks = $this->db->count_all_results(db_prefix().'acc_check_details');

        if($pay_bills > 0 || $checks > 0){
            return 'paid';
        }

        $this->db->where('id', $id);
        $this->db->delete(db_prefix().'expenses');
        if($this->db->affected_rows() > 0){
            $affectedRows++;

            $this->db->where('rel_id', $id);
            $this->db->where('rel_type', 'expense');
            $this->db->delete(db_prefix().'files');
            if($this->db->affected_rows() > 0){ 
                $affectedRows++;
            }

            $this->db->where('rel_id', $id);
            $this->db->where('rel_type', 'bill');
            $this->db->delete(db_prefix().'acc_account_history');
            if($this->db->affected_rows() > 0){ 
                $affectedRows++;
            }

            if (is_dir(ACCOUTING_MODULE_UPLOAD_FOLDER .'/bills/'. $id)) {
                delete_dir(ACCOUTING_MODULE_UPLOAD_FOLDER .'/bills/'. $id);
            }
        }

        if($affectedRows > 0){
            return true;
        }
        return false;
    }

    /**
     * get bill mapping
     * @param  string $id
     * @param  array  $where
     * @return array or object
     */
    public function get_bill_mapping($id = '', $where = [])
    {
        if (is_numeric($id)) {
            $this->db->where('id', $id);
            return $this->db->get(db_prefix() . 'acc_bill_mappings')->row();
        }

        $this->db->where($where);
        $this->db->order_by('id', 'desc');
        return $this->db->get(db_prefix() . 'acc_bill_mappings')->result_array();
    }

    /**
     * get pay bill item paid
     * @param  string $id
     * @param  array  $where
     * @return array or object
     */
    public function get_pay_bill_item_paid($id = '', $where = [])
    {
        if (is_numeric($id)) {
            $this->db->where('id', $id);
            return $this->db->get(db_prefix() . 'acc_pay_bill_item_paid')->row();
        }

        $this->db->where($where);
        $this->db->order_by('id', 'desc');
        return $this->db->get(db_prefix() . 'acc_pay_bill_item_paid')->result_array();
    }

    public function get_total_bill_item_paid($bill_item_id){
        $this->db->select('sum(amount_paid) as amount');
        $this->db->where('item_id', $bill_item_id);
        $data = $this->db->get('acc_pay_bill_item_paid')->row();
        if($data){
            return $data->amount;
        }

        return 0;
    }

    /**
     * Automatic pay bill conversion
     * @param  integer $expense_id 
     * @return boolean
     */
    public function automatic_pay_bill_conversion($pay_bill_id){
        $this->delete_convert($pay_bill_id, 'pay_bill');

        $pay_bill = $this->get_pay_bill($pay_bill_id);
        $affectedRows = 0;
        $data_insert = [];

        if($pay_bill){
            $deposit_to = $pay_bill->account_debit;
            $payment_account = $pay_bill->account_credit;

            $pay_bill_total = $pay_bill->amount;

            $node = [];
            $node['split'] = $payment_account;
            $node['account'] = $deposit_to;
            $node['debit'] = $pay_bill_total;
            $node['vendor'] = $pay_bill->vendor;
            $node['date'] = $pay_bill->date;
            $node['tax'] = 0;
            $node['credit'] = 0;
            $node['description'] = '';
            $node['rel_id'] = $pay_bill_id;
            $node['rel_type'] = 'pay_bill';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $deposit_to;
            $node['account'] = $payment_account;
            $node['vendor'] = $pay_bill->vendor;
            $node['date'] = $pay_bill->date;
            $node['tax'] = 0;
            $node['debit'] = 0;
            $node['credit'] = $pay_bill_total;
            $node['description'] = '';
            $node['rel_id'] = $pay_bill_id;
            $node['rel_type'] = 'pay_bill';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;
            
            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }

            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    public function add_check($data){

        $data['date'] = to_sql_date($data['date']);
        $data['rel_type'] = 'vendor';
        $data['dateadded'] = date('Y-m-d H:i:s');
        $data['addedfrom'] = get_staff_user_id();
        $data['amount'] = str_replace(',', '', $data['amount']);

        if(isset($data['bill_items'])){
            $data['bill_items'] = implode(',', $data['bill_items']);
        }

        $pay_bill_item = [];
        if(isset($data['pay_bill_item'])){
            $pay_bill_item = $data['pay_bill_item'];
            unset($data['pay_bill_item']);
        }

        $pay_bill_amount = [];
        if(isset($data['pay_bill_amount'])){
            $pay_bill_amount = $data['pay_bill_amount'];
            unset($data['pay_bill_amount']);
        }

        $pay_bill_amount_paid = [];
        if(isset($data['pay_bill_amount_paid'])){
            $pay_bill_amount_paid = $data['pay_bill_amount_paid'];
            unset($data['pay_bill_amount_paid']);
        }

        unset($data['id']);

        if(isset($data['bill_ids'])){
            unset($data['bill_ids']);
        }

        if(isset($data['bank_account_balance'])){
            unset($data['bank_account_balance']);
        }

        if(isset($data['DataTables_Table_0_length'])){
            unset($data['DataTables_Table_0_length']);
        }

        if(isset($data['DataTables_Table_1_length'])){
            unset($data['DataTables_Table_1_length']);
        }

        $bill_check = [];
        if(isset($data['bill_check'])){
            $bill_check = $data['bill_check'];
            unset($data['bill_check']);
        }

        if(!isset($data['include_company_name_address'])){
            $data['include_company_name_address'] = 0;
        }

        if(!isset($data['include_routing_account_numbers'])){
            $data['include_routing_account_numbers'] = 0;
        }

        if(!isset($data['include_check_number'])){
            $data['include_check_number'] = 0;
        }

        if(!isset($data['include_bank_name'])){
            $data['include_bank_name'] = 0;
        }

        if(isset($data['check_number'])){
            if($data['check_number'] != ''){
                $data['number'] = $data['check_number'];
            }
            unset($data['check_number']);
        }

        $data['number'] = str_pad($data['number'], 4, '0', STR_PAD_LEFT);

        if(isset($data['rel_id'])){
            $this->db->where('userid', $data['rel_id']);
            $vendor = $this->db->get(db_prefix() . 'pur_vendor')->row();
            if($vendor){
                $data['vendor_city'] = $vendor->city;
                $data['vendor_zip'] = $vendor->zip;
                $data['vendor_state'] = $vendor->state;
                $data['vendor_address'] = $vendor->address;
            }
        }

        $this->db->insert(db_prefix().'acc_checks', $data);
        $insert_id = $this->db->insert_id();

        if($insert_id){
            foreach($bill_check as $bill_id){
                $this->db->insert(db_prefix().'acc_check_details', [
                    'check_id' => $insert_id,
                    'bill' => $bill_id,
                ]);

                $bill_amount = bill_amount_left($bill_id, false);
                if($bill_amount > 0){
                    $this->bill_status_change($bill_id, 3, $data['date']);
                }else{
                    $this->bill_status_change($bill_id, 2, $data['date']);
                }
            }

            foreach($pay_bill_amount_paid as $item_id => $amount_paid){
                if($amount_paid > 0){
                    $amount = str_replace(',', '', $amount_paid);
                    $item_amount = str_replace(',', '', $pay_bill_amount[$item_id]);
                    $this->db->insert(db_prefix().'acc_pay_bill_item_paid', [
                        'check_id' => $insert_id,
                        'item_id' => $item_id,
                        'item_name' => $pay_bill_item[$item_id],
                        'item_amount' => $item_amount,
                        'amount_paid' => $amount
                    ]);
                }
            }

            $this->automatic_check_conversion($insert_id);

            return $insert_id;
        }

        return false;
    }

    public function update_check($data, $id){
        $affected_rows = 0;

        if(isset($data['bill_items'])){
            $data['bill_items'] = implode(',', $data['bill_items']);
        }

        $pay_bill_item = [];
        if(isset($data['pay_bill_item'])){
            $pay_bill_item = $data['pay_bill_item'];
            unset($data['pay_bill_item']);
        }

        $pay_bill_amount = [];
        if(isset($data['pay_bill_amount'])){
            $pay_bill_amount = $data['pay_bill_amount'];
            unset($data['pay_bill_amount']);
        }

        $pay_bill_amount_paid = [];
        if(isset($data['pay_bill_amount_paid'])){
            $pay_bill_amount_paid = $data['pay_bill_amount_paid'];
            unset($data['pay_bill_amount_paid']);
        }

        if(isset($data['bill_ids'])){
            unset($data['bill_ids']);
        }

        foreach($data as $key => $value){
            if (strpos($key, 'DataTables_Table') !== false) {
                unset($data[$key]);
            }
        }

        if(isset($data['check_number'])){
            if($data['check_number'] != ''){
                $data['number'] = $data['check_number'];
            }
            unset($data['check_number']);
        }

        $data['number'] = str_pad($data['number'], 4, '0', STR_PAD_LEFT);


        if(isset($data['checkbox_signature'])){
            unset($data['checkbox_signature']);
        }

        if(isset($data['signature_available_id'])){
            unset($data['signature_available_id']);
        }

        if(isset($data['checkbox_signature_available'])){
            unset($data['checkbox_signature_available']);
        }

        if(isset($data['signature'])){
            unset($data['signature']);
        }

        $data['amount'] = str_replace(',', '', $data['amount']);
        
        $bill_check = [];
        if(isset($data['bill_check'])){
            $bill_check = $data['bill_check'];
            unset($data['bill_check']);
        }

        $this->db->where('check_id', $id);
        $check_details = $this->db->get(db_prefix().'acc_check_details')->result_array();


        $this->db->where('check_id', $id);
        $this->db->delete(db_prefix().'acc_check_details');

        $data['date'] = to_sql_date($data['date']);
        $data['rel_type'] = 'vendor';

        foreach($check_details as $value){
            $bill_amount = bill_amount_left($value['bill'], false);
            $bill = $this->get_bill($value['bill']);
            if($bill->amount == $bill_amount){
                $this->bill_status_change($value['bill'], 0);
            }else{
                $this->bill_status_change($value['bill'], 3);
            }
        }

        foreach($bill_check as $bill_id){
            $this->db->insert(db_prefix().'acc_check_details', [
                'check_id' => $id,
                'bill' => $bill_id,
            ]);
            $insert_id = $this->db->insert_id();
            if($insert_id){

                $bill_amount = bill_amount_left($bill_id, false);
                if($bill_amount > 0){
                    $this->bill_status_change($bill_id, 3, $data['date']);
                }else{
                    $this->bill_status_change($bill_id, 2, $data['date']);
                }

                $affected_rows++;
            }
        }


        $this->db->where('id', $id);
        $this->db->update(db_prefix().'acc_checks', $data);
        if($this->db->affected_rows() > 0){
            $affected_rows++;

            $this->db->where('check_id', $id);
            $this->db->delete(db_prefix().'acc_pay_bill_item_paid');

            foreach($pay_bill_amount_paid as $item_id => $amount_paid){
                if($amount_paid > 0){
                    $amount = str_replace(',', '', $amount_paid);
                    $item_amount = str_replace(',', '', $pay_bill_amount[$item_id]);
                    $this->db->insert(db_prefix().'acc_pay_bill_item_paid', [
                        'check_id' => $id,
                        'item_id' => $item_id,
                        'item_name' => $pay_bill_item[$item_id],
                        'item_amount' => $item_amount,
                        'amount_paid' => $amount
                    ]);
                }
            }

            $this->automatic_check_conversion($id);
        }

        if( $affected_rows > 0){
            return true;
        }
        return false;
    }

    public function update_signed_check($check){
        $this->db->where('id', $check);
        $this->db->update(db_prefix().'acc_checks', ['signed' => 1]);
        if($this->db->affected_rows() > 0){ 
            return true;
        }
        return false;
    }

    public function get_checks($id = '', $company_id = '', $where = []){
        $this->db->where($where);

        if($id != ''){
            $this->db->where('id', $id);
            $check = $this->db->get(db_prefix().'acc_checks')->row();
            if ($check) {
                $check->pay_bill_item_paid = $this->get_pay_bill_item_paid('', ['check_id' => $id]);
            }

            return $check;
        }

        return $this->db->get(db_prefix().'acc_checks')->result_array();
    }

    /**
     * get next check number
     * @return integer
     */
    public function get_next_check_number()
    {   
        $this->db->select('max(number) as max_number');
        $max = $this->db->get(db_prefix().'acc_checks')->row();
        if(is_numeric($max->max_number)){
            return $max->max_number + 1;
        }

        return 1;
    }


    public function get_balance_by_account_id($account_id, $company_id = ''){

        $accounting_method = get_option('acc_accounting_method');

        if($accounting_method == 'cash'){
            $debit = '(SELECT sum(debit) as debit FROM '.db_prefix().'acc_account_history where (account = '.db_prefix().'acc_accounts.id or parent_account = '.db_prefix().'acc_accounts.id) AND (('.db_prefix().'acc_account_history.rel_type = "invoice" AND '.db_prefix().'acc_account_history.paid = 1) or rel_type != "invoice")) as debit';
            $credit = '(SELECT sum(credit) as credit FROM '.db_prefix().'acc_account_history where (account = '.db_prefix().'acc_accounts.id or parent_account = '.db_prefix().'acc_accounts.id) AND (('.db_prefix().'acc_account_history.rel_type = "invoice" AND '.db_prefix().'acc_account_history.paid = 1) or rel_type != "invoice")) as credit';
        }else{
            $debit = '(SELECT sum(debit) as debit FROM '.db_prefix().'acc_account_history where (account = '.db_prefix().'acc_accounts.id or parent_account = '.db_prefix().'acc_accounts.id)) as debit';
            $credit = '(SELECT sum(credit) as credit FROM '.db_prefix().'acc_account_history where (account = '.db_prefix().'acc_accounts.id or parent_account = '.db_prefix().'acc_accounts.id)) as credit';
        }

        $this->db->select($debit.', '.$credit.', account_type_id');
        $this->db->where('(id = "'. $account_id.'" or parent_account = "'.$account_id.'")');
        $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();

        $balance = 0;
        foreach($accounts as $account){
            $balance += ($account['debit'] - $account['credit']);
        }

        return $balance;
    }

    /**
     * Automatic pay bill conversion
     * @param  integer $expense_id 
     * @return boolean
     */
    public function automatic_check_conversion($check_id){
        $this->delete_convert($check_id, 'check');

        $check = $this->get_check($check_id);
        $affectedRows = 0;
        $data_insert = [];

        $payment_account = $check->bank_account;

        // $debit_and_credit_setup = $this->accounting_model->get_debit_and_credit_setup($check->bank_account);

        // if(isset($debit_and_credit_setup['debit'][0])){
        //     $deposit_to = $debit_and_credit_setup['debit'][0];
        // }else{
            $deposit_to = 87;
        //}

        $check_total = $check->amount;

        $node = [];
        $node['split'] = $payment_account;
        $node['account'] = $deposit_to;
        $node['debit'] = $check_total;
        $node['vendor'] = $check->rel_id;
        $node['number'] = $check->number;
        $node['date'] = $check->date;
        $node['tax'] = 0;
        $node['credit'] = 0;
        $node['description'] = '';
        $node['rel_id'] = $check_id;
        $node['rel_type'] = 'check';
        $node['datecreated'] = date('Y-m-d H:i:s');
        $node['addedfrom'] = get_staff_user_id();
        $data_insert[] = $node;

        $node = [];
        $node['split'] = $deposit_to;
        $node['account'] = $payment_account;
        $node['vendor'] = $check->rel_id;
        $node['number'] = $check->number;
        $node['date'] = $check->date;
        $node['tax'] = 0;
        $node['debit'] = 0;
        $node['credit'] = $check_total;
        $node['description'] = '';
        $node['rel_id'] = $check_id;
        $node['rel_type'] = 'check';
        $node['datecreated'] = date('Y-m-d H:i:s');
        $node['addedfrom'] = get_staff_user_id();
        $data_insert[] = $node;

        if($data_insert != []){
            $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
        }

        if ($affectedRows > 0) {
            return true;
        }

        return false;
    }

    /**
     * Gets the check.
     *
     * @param        $id     The identifier
     */
    public function get_check($id = '', $where = []){
        $this->db->from(db_prefix() . 'acc_checks');
        $this->db->where($where);

        if (is_numeric($id)) {
            $this->db->where(db_prefix() . 'acc_checks.id', $id);
            $check = $this->db->get()->row();
            if ($check) {
                $check->pay_bill_item_paid = $this->get_pay_bill_item_paid('', ['check_id' => $id]);
            }

            return $check;
        }
        $this->db->order_by('date', 'desc');

        return $this->db->get()->result_array();
    }

    public function print_later($check_id, $account){

        $this->db->insert(db_prefix() . 'acc_print_later', ['rel_id' => $check_id, 'rel_type' => 'check', 'account' => $account]);

        if ($this->db->affected_rows() > 0) {
            return true;
        }

        return false;
    }

    /**
     * get print later
     * @param  string $id
     * @param  array  $where
     * @return array or object
     */
    public function get_print_later($id = '', $where = [])
    {
        if (is_numeric($id)) {
            $this->db->where('id', $id);
            return $this->db->get(db_prefix() . 'acc_print_later')->row();
        }

        $this->db->where($where);
        $this->db->order_by('id', 'desc');
        return $this->db->get(db_prefix() . 'acc_print_later')->result_array();
    }

    public function clear_print_later($account){
        $this->db->where('account', $account);
        $this->db->delete(db_prefix() . 'acc_print_later');
        if ($this->db->affected_rows() > 0) {
            return true;
        }

        return false;
    }


    /**
     * Logs a check printed.
     */
    public function log_check_printed($data){
        $logs = 0;
        if(count($data['ids']) > 0){
            foreach($data['ids'] as $check_id){

                $this->db->where('rel_id', $check_id);
                $this->db->where('rel_type', 'check');
                $this->db->delete(db_prefix().'acc_print_later');

                if($data['issue'] == 'true'){
                    $this->db->where('id', $check_id);
                    $this->db->update(db_prefix().'acc_checks', ['issue' => 1]);

                    $this->db->where('rel_id', $check_id);
                    $this->db->where('rel_type', 'check');
                    $this->db->update(db_prefix().'acc_account_history', ['issue' => 1]);
                }

                $this->db->insert(db_prefix().'acc_checks_printed', [
                    'check_id' => $check_id,
                    'bank_account' => $data['bank_account'],
                    'printed_at' => date('Y-m-d H:i:s'),
                    'printed_by' => get_staff_user_id(),
                ]);
                $insert_id = $this->db->insert_id();
                if($insert_id){
                    $logs++;
                }
            }
        }

        if($logs > 0){
            return true;
        }
        return false;
    }


    public function reprint_check($data)
    {   
        $new_checks = [];
        $new_check_number = str_pad($data['new_check_number'], 4, '0', STR_PAD_LEFT);
        foreach($data['reprint_check'] as $reprint_check_id){
            $reprint_check = $this->get_checks($reprint_check_id);

            if($reprint_check){
                $data_insert = (array)$reprint_check;

                $data_insert['number'] = $new_check_number;
                $data_insert['issue'] = 1;
                $data_insert['dateadded'] = date('Y-m-d H:i:s');
                $data_insert['addedfrom'] = get_staff_user_id();

                if(isset($data_insert['pay_bill_item_paid'])){
                    unset($data_insert['pay_bill_item_paid']);
                }

                unset($data_insert['id']);
                $this->db->insert(db_prefix() . 'acc_checks', $data_insert);


                $insert_id = $this->db->insert_id();

                if ($insert_id) {
                    $this->db->where('rel_id', $reprint_check_id);
                    $this->db->where('rel_type', 'check');
                    $this->db->update(db_prefix().'acc_account_history', ['rel_id' => $insert_id, 'number' => $new_check_number]);

                    $this->db->where('check_id', $reprint_check_id);
                    $this->db->update(db_prefix().'acc_check_details', ['check_id' => $insert_id]);

                    $this->db->where('check_id', $reprint_check_id);
                    $this->db->update(db_prefix().'acc_pay_bill_item_paid', ['check_id' => $insert_id]);

                    $this->db->where('id', $reprint_check_id);
                    $this->db->update(db_prefix().'acc_checks', ['issue' => 2]);

                    if($data_insert['signed'] == 1){
                        $path = ACCOUTING_MODULE_UPLOAD_FOLDER .'/checks/signature/' .$insert_id;

                        $file_path = ACCOUTING_MODULE_UPLOAD_FOLDER . '/checks/signature/' . $reprint_check_id.'/signature_'.$reprint_check_id.'.png';
                        _maybe_create_upload_path($path);
                        $sign = copy($file_path, $path.'/signature_'.$insert_id.'.png');
                    }
                    
                    $new_checks[] = $insert_id;
                }
            }
            $new_check_number++;
        }

        return $new_checks;
    }

    /**
     * Delete Expense attachment
     * @param  mixed $id expense id
     * @return boolean
     */
    public function delete_signature_available_attachment($check_id, $file)
    {
        if (is_dir(ACCOUTING_MODULE_UPLOAD_FOLDER .'/signature_is_available/'. $check_id)) {
            if (unlink(ACCOUTING_MODULE_UPLOAD_FOLDER .'/signature_is_available/'. $check_id.'/'.$file->file_name)) {
                $this->db->where('id', $file->id);
                $this->db->delete(db_prefix() . 'files');
               
                return true;
            }
        }

        return false;
    }


    public function void_check($check_id, $data){
        $check = $this->get_checks($check_id);

        $closing_date = strtotime(get_option('acc_closing_date'));
        $check_date = strtotime($check->date);
        $current_date = strtotime(date('Y-m-d'));
        if(get_option('acc_close_the_books') == 1){
            if(($current_date < $closing_date && $check_date < $current_date) || ($current_date >= $closing_date && $check_date < $closing_date)){
                return 'book_closed';
            }
        }

        $data['reason_for_void'] = nl2br($data['reason_for_void']);

        $this->db->where('id', $check_id);
        $this->db->update(db_prefix() . 'acc_checks', ['issue' => 3, 'reason_for_void' => $data['reason_for_void']]);

        if ($this->db->affected_rows() > 0) {
            $this->db->where('check_id', $check_id);
            $this->db->delete(db_prefix().'acc_pay_bill_item_paid');
            
            $this->db->where('rel_id', $check_id);
            $this->db->where('rel_type', 'check');
            $this->db->delete(db_prefix().'acc_print_later');

            $this->db->where('check_id', $check_id);
            $check_details = $this->db->get(db_prefix().'acc_check_details')->result_array();

            foreach($check_details as $detail){
                $bill_amount = bill_amount_left($detail['bill'], false);
                $bill = $this->get_bill($detail['bill']);
                if($bill->amount == $bill_amount){
                    $this->bill_status_change($detail['bill'], 0);
                }else{
                    $this->bill_status_change($detail['bill'], 3);
                }
            }

            $this->db->where('check_id', $check_id);
            $this->db->delete(db_prefix().'acc_check_details');

            $this->db->where('rel_id', $check_id);
            $this->db->where('rel_type', 'check');
            $this->db->delete(db_prefix().'acc_account_history');

            return true;
        }

        return false;
    }

    public function get_pay_bill_details($pay_bill){
        $this->db->where('pay_bill', $pay_bill);
        return $this->db->get(db_prefix().'acc_pay_bill_details')->result_array();
    }


    public function get_fe_asset_data_convert($id, $type){
        $this->load->model('fixed_equipment/fixed_equipment_model');
        $asset = $this->fixed_equipment_model->get_assets($id);
        $model = $this->fixed_equipment_model->get_models($asset->model_id);

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $status_name = '';
        if(is_numeric($asset->status)){
            $status_data = $this->fixed_equipment_model->get_status_labels($asset->status); 
            if($status_data){
              $status_name = $status_data->name;
            }
        }

        $category_name = '';
        if(is_numeric($model->category)){
          $data_category = $this->fixed_equipment_model->get_categories($model->category);
          if($data_category){
            $category_name = $data_category->category_name;
          }
        }

        $supplier_name = '';
        if(is_numeric($asset->supplier_id)){
          $data_supplier = $this->fixed_equipment_model->get_suppliers($asset->supplier_id);
          if($data_supplier){
            $supplier_name = $data_supplier->supplier_name;
          }
        }

        $html = '<table class="table border table-striped no-margin">
                  <tbody>
                    <tr class="project-overview">
                        <td class="bold">'. _l('fe_category').'</td>
                        <td>'. $category_name .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold" width="30%">'. _l('fe_asset_tag').'</td>
                        <td>'.'<a href="'.admin_url('fixed_equipment/detail_asset/'.$asset->id.'?tab=details').'">'. $asset->series .'</a>' .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_purchase_cost').'</td>
                        <td>'. app_format_money($asset->unit_price, $currency->name) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_order_number').'</td>
                        <td>'. $asset->order_number .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_supplier').'</td>
                        <td>'. $supplier_name .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_status').'</td>
                        <td>'. $status_name .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('note').'</td>
                        <td colspan="2">'. new_html_entity_decode($asset->description) .'</td>
                     </tr>';
        
        $html .=   '</tbody>
              </table>';

        return ['html' => $html];
    }


    public function get_fe_license_data_convert($id, $type){
        $this->load->model('fixed_equipment/fixed_equipment_model');
        $asset = $this->fixed_equipment_model->get_assets($id);
        
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $status_name = '';
        if(is_numeric($asset->status)){
            $status_data = $this->fixed_equipment_model->get_status_labels($asset->status); 
            if($status_data){
              $status_name = $status_data->name;
            }
        }


        $category_name = '';
          if(is_numeric($asset->category_id)){
            $data_category = $this->fixed_equipment_model->get_categories($asset->category_id);
            if($data_category){
              $category_name = $data_category->category_name;
            }
          }

        $html = '<table class="table border table-striped no-margin">
                  <tbody>
                    <tr class="project-overview">
                        <td class="bold">'. _l('fe_category').'</td>
                        <td>'. $category_name .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold" width="30%">'. _l('fe_product_key').'</td>
                        <td>'.'<a href="'.admin_url('fixed_equipment/detail_licenses/'.$asset->id.'?tab=details').'">'. $asset->product_key .'</a>' .'</td>
                        <td></td>
                     </tr>
                     
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_licensed_to_name').'</td>
                        <td>'. $asset->licensed_to_name .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_licensed_to_email').'</td>
                        <td>'. $asset->licensed_to_email .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_expiration_date').'</td>
                        <td colspan="2">'. _d($asset->expiration_date) .'</td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_expiration_date').'</td>
                        <td colspan="2">'. _d($asset->termination_date) .'</td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_purchase_order_number').'</td>
                        <td>'. $asset->purchase_order_number .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_purchase_date').'</td>
                        <td>'. _d($asset->date_buy) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_purchase_cost').'</td>
                        <td>'. app_format_money($asset->unit_price, $currency->name) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_seats').'</td>
                        <td>'. $asset->seats .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('note').'</td>
                        <td colspan="2">'. new_html_entity_decode($asset->description) .'</td>
                     </tr>';
        
        $html .=   '</tbody>
              </table>';

        return ['html' => $html];
    }

    public function get_fe_component_data_convert($id, $type){
        $this->load->model('fixed_equipment/fixed_equipment_model');
        $asset = $this->fixed_equipment_model->get_assets($id);
        
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $status_name = '';
        if(is_numeric($asset->status)){
            $status_data = $this->fixed_equipment_model->get_status_labels($asset->status); 
            if($status_data){
              $status_name = $status_data->name;
            }
        }


        $category_name = '';
          if(is_numeric($asset->category_id)){
            $data_category = $this->fixed_equipment_model->get_categories($asset->category_id);
            if($data_category){
              $category_name = $data_category->category_name;
            }
          }

        $html = '<table class="table border table-striped no-margin">
                  <tbody>
                    <tr class="project-overview">
                        <td class="bold">'. _l('fe_category').'</td>
                        <td>'. $category_name .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold" width="30%">'. _l('name').'</td>
                        <td>'.'<a href="'.admin_url('fixed_equipment/detail_components/'.$asset->id).'">'. $asset->assets_name .'</a>' .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_purchase_date').'</td>
                        <td>'. _d($asset->date_buy) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_purchase_cost').'</td>
                        <td>'. app_format_money($asset->unit_price, $currency->name) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('total').'</td>
                        <td>'. $asset->quantity .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('note').'</td>
                        <td colspan="2">'. new_html_entity_decode($asset->description) .'</td>
                     </tr>';
        
        $html .=   '</tbody>
              </table>';

        return ['html' => $html];
    }


    public function get_fe_consumable_data_convert($id, $type){
        $this->load->model('fixed_equipment/fixed_equipment_model');
        $asset = $this->fixed_equipment_model->get_assets($id);
        
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $status_name = '';
        if(is_numeric($asset->status)){
            $status_data = $this->fixed_equipment_model->get_status_labels($asset->status); 
            if($status_data){
              $status_name = $status_data->name;
            }
        }


        $category_name = '';
          if(is_numeric($asset->category_id)){
            $data_category = $this->fixed_equipment_model->get_categories($asset->category_id);
            if($data_category){
              $category_name = $data_category->category_name;
            }
          }

        $html = '<table class="table border table-striped no-margin">
                  <tbody>
                    <tr class="project-overview">
                        <td class="bold">'. _l('fe_category').'</td>
                        <td>'. $category_name .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold" width="30%">'. _l('name').'</td>
                        <td>'.'<a href="'.admin_url('fixed_equipment/detail_consumables/'.$asset->id).'">'. $asset->assets_name .'</a>' .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_purchase_date').'</td>
                        <td>'. _d($asset->date_buy) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_purchase_cost').'</td>
                        <td>'. app_format_money($asset->unit_price, $currency->name) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('total').'</td>
                        <td>'. $asset->quantity .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('note').'</td>
                        <td colspan="2">'. new_html_entity_decode($asset->description) .'</td>
                     </tr>';
        
        $html .=   '</tbody>
              </table>';

        return ['html' => $html];
    }

    public function get_fe_maintenance_data_convert($id, $type){
        $this->load->model('fixed_equipment/fixed_equipment_model');
        $maintenance = $this->fixed_equipment_model->get_asset_maintenances($id);
        
        $this->load->model('departments_model');
        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $serial = '';
        $data_asset = $this->fixed_equipment_model->get_assets($maintenance->asset_id);
        if($data_asset){
            $serial = $data_asset->series;
        }

        $data_location_asset = $this->fixed_equipment_model->get_asset_location_info($maintenance->asset_id);

        $html = '<table class="table border table-striped no-margin">
                  <tbody>
                     <tr class="project-overview">
                        <td class="bold" width="30%">'. _l('fe_asset_name').'</td>
                        <td>'.$this->fixed_equipment_model->get_asset_name($maintenance->asset_id) .'</td>
                        <td></td>
                     </tr>
                    <tr class="project-overview">
                        <td class="bold">'. _l('fe_serial').'</td>
                        <td>'. $serial .'</td>
                        <td></td>
                     </tr>

                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_location').'</td>
                        <td><span class="text-nowrap">'.$data_location_asset->curent_location.'</span></td>
                        <td></td>
                     </tr>

                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_maintenance_type').'</td>
                        <td>'. _l('fe_'.$maintenance->maintenance_type) .'</td>
                        <td></td>
                     </tr>

                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_title').'</td>
                        <td>'. $maintenance->title .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_start_date').'</td>
                        <td>'. _d($maintenance->start_date) .'</td>
                        <td></td>
                     </tr>

                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_completion_date').'</td>
                        <td>'. _d($maintenance->completion_date) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_cost').'</td>
                        <td>'. app_format_money($maintenance->cost, $currency->name) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('note').'</td>
                        <td colspan="2">'. new_html_entity_decode($maintenance->notes) .'</td>
                     </tr>';
        
        $html .=   '</tbody>
              </table>';

        return ['html' => $html];
    }

    public function get_fe_depreciation_data_convert($id, $type){

        $this->load->model('fixed_equipment/fixed_equipment_model');
        $this->db->where('id', $id);
        $depreciation = $this->db->get(db_prefix().'fe_depreciation_items')->row();

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $serial = '';
        $data_asset = $this->fixed_equipment_model->get_assets($depreciation->item_id);
        if($data_asset){
            $serial = $data_asset->series;
        }


        $html = '<table class="table border table-striped no-margin">
                  <tbody>
                     <tr class="project-overview">
                        <td class="bold" width="30%">'. _l('fe_asset_name').'</td>
                        <td>'.$this->fixed_equipment_model->get_asset_name($depreciation->item_id) .'</td>
                        <td></td>
                     </tr>
                    <tr class="project-overview">
                        <td class="bold">'. _l('fe_serial').'</td>
                        <td>'. $serial .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('fe_cost').'</td>
                        <td>'. app_format_money($depreciation->value, $currency->name) .'</td>
                        <td></td>
                     </tr>
                     <tr class="project-overview">
                        <td class="bold">'. _l('date').'</td>
                        <td>'. _d($depreciation->date) .'</td>
                        <td></td>
                     </tr>';
        
        $html .=   '</tbody>
              </table>';

        return ['html' => $html];
    }

   

    public function count_fe_asset_not_convert_yet($where = ''){

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'fe_assets.id and ' . db_prefix() . 'acc_account_history.rel_type = "fe_asset") = 0) AND (' . db_prefix() . 'fe_assets.type = "asset" and active = 1) ');
        return $this->db->count_all_results(db_prefix().'fe_assets');
    }

    public function count_fe_license_not_convert_yet($where = ''){

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'fe_assets.id and ' . db_prefix() . 'acc_account_history.rel_type = "fe_license") = 0) AND (' . db_prefix() . 'fe_assets.type = "license" and active = 1) ');
        return $this->db->count_all_results(db_prefix().'fe_assets');
    }

    public function count_fe_component_not_convert_yet($where = ''){

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'fe_assets.id and ' . db_prefix() . 'acc_account_history.rel_type = "fe_component") = 0) AND (' . db_prefix() . 'fe_assets.type = "component" and active = 1) ');
        return $this->db->count_all_results(db_prefix().'fe_assets');
    }

    public function count_fe_consumable_not_convert_yet($where = ''){

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'fe_assets.id and ' . db_prefix() . 'acc_account_history.rel_type = "fe_consumable") = 0) AND (' . db_prefix() . 'fe_assets.type = "consumable" and active = 1) ');
        return $this->db->count_all_results(db_prefix().'fe_assets');
    }

    public function count_fe_maintenance_not_convert_yet($where = ''){

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'fe_asset_maintenances.id and ' . db_prefix() . 'acc_account_history.rel_type = "fe_maintenance") = 0)');
        return $this->db->count_all_results(db_prefix().'fe_asset_maintenances');
    }

     public function count_fe_depreciation_not_convert_yet($where = ''){

        if($where != ''){
            $this->db->where($where);
        }
        $this->db->where('((select count(*) from ' . db_prefix() . 'acc_account_history where ' . db_prefix() . 'acc_account_history.rel_id = ' . db_prefix() . 'fe_depreciation_items.id and ' . db_prefix() . 'acc_account_history.rel_type = "fe_depreciation") = 0)');
        return $this->db->count_all_results(db_prefix().'fe_depreciation_items');
    }

    /**
     * Automatic asset conversion
     * @param  integer $refund_id 
     * @return boolean
     */
    public function automatic_fe_asset_conversion($asset_id){
        if(get_option('acc_fe_asset_automatic_conversion') == 0){
            return false;
        }
        
        $this->delete_convert($asset_id, 'fe_asset');

        $this->load->model('fixed_equipment/fixed_equipment_model');
        $asset = $this->fixed_equipment_model->get_assets($asset_id);

        $payment_account = get_option('acc_fe_asset_payment_account');
        $deposit_to = get_option('acc_fe_asset_deposit_to');
        $affectedRows = 0;
        $data_insert = [];

        if($asset){
            $date_buy = $asset->date_buy;

            if($date_buy == '' || $date_buy == null){
                $date_buy = date('Y-m-d');
            }

            if(get_option('acc_close_the_books') == 1){
                if(strtotime($date_buy) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }

            $asset_total = $asset->unit_price;
            
            $node = [];
            $node['split'] = $payment_account;
            $node['account'] = $deposit_to;
            $node['debit'] = $asset_total;
            $node['credit'] = 0;
            $node['date'] = $date_buy;
            $node['description'] = '';
            $node['rel_id'] = $asset_id;
            $node['rel_type'] = 'fe_asset';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $deposit_to;
            $node['account'] = $payment_account;
            $node['date'] = $date_buy;
            $node['debit'] = 0;
            $node['credit'] = $asset_total;
            $node['description'] = '';
            $node['rel_id'] = $asset_id;
            $node['rel_type'] = 'fe_asset';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Automatic license conversion
     * @param  integer $refund_id 
     * @return boolean
     */
    public function automatic_fe_license_conversion($license_id){
        if(get_option('acc_fe_license_automatic_conversion') == 0){
            return false;
        }
        
        $this->delete_convert($license_id, 'fe_license');

        $this->load->model('fixed_equipment/fixed_equipment_model');
        $license = $this->fixed_equipment_model->get_assets($license_id);

        $payment_account = get_option('acc_fe_license_payment_account');
        $deposit_to = get_option('acc_fe_license_deposit_to');
        $affectedRows = 0;
        $data_insert = [];

        if($license){
            $date_buy = $license->date_buy;

            if($date_buy == '' || $date_buy == null){
                $date_buy = date('Y-m-d');
            }

            if(get_option('acc_close_the_books') == 1){
                if(strtotime($date_buy) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }

            $license_total = $license->unit_price * $license->seats;
            
            $node = [];
            $node['split'] = $payment_account;
            $node['account'] = $deposit_to;
            $node['debit'] = $license_total;
            $node['credit'] = 0;
            $node['date'] = $date_buy;
            $node['description'] = '';
            $node['rel_id'] = $license_id;
            $node['rel_type'] = 'fe_license';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $deposit_to;
            $node['account'] = $payment_account;
            $node['date'] = $date_buy;
            $node['debit'] = 0;
            $node['credit'] = $license_total;
            $node['description'] = '';
            $node['rel_id'] = $license_id;
            $node['rel_type'] = 'fe_license';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Automatic component conversion
     * @param  integer $refund_id 
     * @return boolean
     */
    public function automatic_fe_component_conversion($component_id){
        if(get_option('acc_fe_component_automatic_conversion') == 0){
            return false;
        }
        
        $this->delete_convert($component_id, 'fe_component');

        $this->load->model('fixed_equipment/fixed_equipment_model');
        $component = $this->fixed_equipment_model->get_assets($component_id);

        $payment_account = get_option('acc_fe_component_payment_account');
        $deposit_to = get_option('acc_fe_component_deposit_to');
        $affectedRows = 0;
        $data_insert = [];

        if($component){
            $date_buy = $component->date_buy;

            if($date_buy == '' || $date_buy == null){
                $date_buy = date('Y-m-d');
            }
            
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($date_buy) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }

            $component_total = $component->unit_price * $component->quantity;
            
            $node = [];
            $node['split'] = $payment_account;
            $node['account'] = $deposit_to;
            $node['debit'] = $component_total;
            $node['credit'] = 0;
            $node['date'] = $date_buy;
            $node['description'] = '';
            $node['rel_id'] = $component_id;
            $node['rel_type'] = 'fe_component';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $deposit_to;
            $node['account'] = $payment_account;
            $node['date'] = $date_buy;
            $node['debit'] = 0;
            $node['credit'] = $component_total;
            $node['description'] = '';
            $node['rel_id'] = $component_id;
            $node['rel_type'] = 'fe_component';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Automatic consumable conversion
     * @param  integer $refund_id 
     * @return boolean
     */
    public function automatic_fe_consumable_conversion($consumable_id){
        if(get_option('acc_fe_consumable_automatic_conversion') == 0){
            return false;
        }
        
        $this->delete_convert($consumable_id, 'fe_consumable');

        $this->load->model('fixed_equipment/fixed_equipment_model');
        $consumable = $this->fixed_equipment_model->get_assets($consumable_id);

        $payment_account = get_option('acc_fe_consumable_payment_account');
        $deposit_to = get_option('acc_fe_consumable_deposit_to');
        $affectedRows = 0;
        $data_insert = [];

        if($consumable){
            $date_buy = $consumable->date_buy;

            if($date_buy == '' || $date_buy == null){
                $date_buy = date('Y-m-d');
            }

            if(get_option('acc_close_the_books') == 1){
                if(strtotime($date_buy) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }

            $consumable_total = $consumable->unit_price * $consumable->quantity;
            
            $node = [];
            $node['split'] = $payment_account;
            $node['account'] = $deposit_to;
            $node['debit'] = $consumable_total;
            $node['credit'] = 0;
            $node['date'] = $date_buy;
            $node['description'] = '';
            $node['rel_id'] = $consumable_id;
            $node['rel_type'] = 'fe_consumable';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $deposit_to;
            $node['account'] = $payment_account;
            $node['date'] = $date_buy;
            $node['debit'] = 0;
            $node['credit'] = $consumable_total;
            $node['description'] = '';
            $node['rel_id'] = $consumable_id;
            $node['rel_type'] = 'fe_consumable';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Automatic maintenance conversion
     * @param  integer $refund_id 
     * @return boolean
     */
    public function automatic_fe_maintenance_conversion($maintenance_id){
        if(get_option('acc_fe_maintenance_automatic_conversion') == 0){
            return false;
        }
        
        $this->delete_convert($maintenance_id, 'fe_maintenance');

        $this->load->model('fixed_equipment/fixed_equipment_model');
        $maintenance = $this->fixed_equipment_model->get_asset_maintenances($maintenance_id);

        $payment_account = get_option('acc_fe_maintenance_payment_account');
        $deposit_to = get_option('acc_fe_maintenance_deposit_to');
        $affectedRows = 0;
        $data_insert = [];

        if($maintenance){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($maintenance->start_date) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }

            $maintenance_total = $maintenance->cost;
            
            $node = [];
            $node['split'] = $payment_account;
            $node['account'] = $deposit_to;
            $node['debit'] = $maintenance_total;
            $node['credit'] = 0;
            $node['date'] = $maintenance->start_date;
            $node['description'] = '';
            $node['rel_id'] = $maintenance_id;
            $node['rel_type'] = 'fe_maintenance';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $deposit_to;
            $node['account'] = $payment_account;
            $node['date'] = $maintenance->start_date;
            $node['debit'] = 0;
            $node['credit'] = $maintenance_total;
            $node['description'] = '';
            $node['rel_id'] = $maintenance_id;
            $node['rel_type'] = 'fe_maintenance';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Automatic depreciation conversion
     * @param  integer $refund_id 
     * @return boolean
     */
    public function automatic_fe_depreciation_conversion($depreciation_id){
        if(get_option('acc_fe_depreciation_automatic_conversion') == 0){
            return false;
        }
        
        $this->delete_convert($depreciation_id, 'fe_depreciation');

        $this->db->where('id', $depreciation_id);
        $depreciation = $this->db->get(db_prefix().'fe_depreciation_items')->row();

        $payment_account = get_option('acc_fe_depreciation_payment_account');
        $deposit_to = get_option('acc_fe_depreciation_deposit_to');
        $affectedRows = 0;
        $data_insert = [];

        if($depreciation){
            if(get_option('acc_close_the_books') == 1){
                if(strtotime($depreciation->date) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                    return false;
                }
            }

            $depreciation_total = $depreciation->value;
            
            $node = [];
            $node['split'] = $payment_account;
            $node['account'] = $deposit_to;
            $node['debit'] = $depreciation_total;
            $node['credit'] = 0;
            $node['date'] = $depreciation->date;
            $node['description'] = '';
            $node['rel_id'] = $depreciation_id;
            $node['rel_type'] = 'fe_depreciation';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $deposit_to;
            $node['account'] = $payment_account;
            $node['date'] = $depreciation->date;
            $node['debit'] = 0;
            $node['credit'] = $depreciation_total;
            $node['description'] = '';
            $node['rel_id'] = $depreciation_id;
            $node['rel_type'] = 'fe_depreciation';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $data_insert[] = $node;

            if($data_insert != []){
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
            }
                
            if ($affectedRows > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * update configure checks
     *
     * @param      array   $data   The data
     *
     * @return     boolean 
     */
    public function update_configure_checks($data){
        $affectedRows = 0;
        if(isset($data['show_bank_address'])){
            unset($data['show_bank_address']);
        }

        if(isset($data['show_2_signatures'])){
            unset($data['show_2_signatures']);
        }
       
       
        foreach ($data as $key => $value) {
            $this->db->where('name', $key);
            $this->db->update(db_prefix() . 'options', [
                    'value' => $value,
                ]);
            if ($this->db->affected_rows() > 0) {
                $affectedRows++;
            }
        }

        if ($affectedRows > 0) {
            return true;
        }
        return false;
    }

    /**
     * Delete Expense attachment
     * @param  mixed $id expense id
     * @return boolean
     */
    public function delete_bill_attachment($id)
    {
        if (is_dir(ACCOUTING_MODULE_UPLOAD_FOLDER .'/expenses/'. $id)) {
            if (delete_dir(ACCOUTING_MODULE_UPLOAD_FOLDER .'/expenses/'. $id)) {
                $this->db->where('rel_id', $id);
                $this->db->where('rel_type', 'expense');
                $this->db->delete(db_prefix() . 'files');
               
                return true;
            }
        }

        return false;
    }

    /**
     * update payslip automatic conversion
     *
     * @param      array   $data   The data
     *
     * @return     boolean 
     */
    public function update_fixed_equipment_automatic_conversion($data){
        $affectedRows = 0;
        
        if(!isset($data['acc_fe_asset_automatic_conversion'])){
            $data['acc_fe_asset_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_fe_license_automatic_conversion'])){
            $data['acc_fe_license_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_fe_component_automatic_conversion'])){
            $data['acc_fe_component_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_fe_consumable_automatic_conversion'])){
            $data['acc_fe_consumable_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_fe_maintenance_automatic_conversion'])){
            $data['acc_fe_maintenance_automatic_conversion'] = 0;
        }

        if(!isset($data['acc_fe_depreciation_automatic_conversion'])){
            $data['acc_fe_depreciation_automatic_conversion'] = 0;
        }

        foreach ($data as $key => $value) {
            $this->db->where('name', $key);
            $this->db->update(db_prefix() . 'options', [
                    'value' => $value,
                ]);
            if ($this->db->affected_rows() > 0) {
                $affectedRows++;
            }
        }

        if ($affectedRows > 0) {
            return true;
        }
        return false;
    }

    public function delete_depreciation_convert_by_asset($asset_id){
        $this->db->where('item_id', $asset_id);
        $depreciation = $this->db->get(db_prefix().'fe_depreciation_items')->result_array();

        foreach($depreciation as $value){
            $this->db->where('rel_id', $value['id']);
            $this->db->where('rel_type', 'fe_depreciation');
            $this->db->delete(db_prefix().'acc_account_history');

            $this->db->where('id', $value['id']);
            $this->db->delete(db_prefix().'fe_depreciation_items');
        }

        return true;
    }

    public function delete_pur_refund_convert_by_order($order_id){
        $this->db->where('order_return_id', $order_id);
        $refunds = $this->db->get(db_prefix().'wh_order_returns_refunds')->result_array();

        foreach($refunds as $value){
            $this->db->where('rel_id', $value['id']);
            $this->db->where('rel_type', 'purchase_refund');
            $this->db->delete(db_prefix().'acc_account_history');
        }

        return true;
    }

    /**
     * Adds a vendor.
     */
    public function add_vendor($data){

        $data['balance'] = str_replace(',', '', $data['balance']);
        if($data['balance'] != '' && $data['balance'] > 0){
            if($data['balance_as_of'] != ''){
                $data['balance_as_of'] = to_sql_date($data['balance_as_of']);
            }else{
                $data['balance_as_of'] = date('Y-m-d');
            }
        }else{
            unset($data['balance']);
            unset($data['balance_as_of']);
        }

        $data = $this->check_zero_columns($data);
        $data['datecreated'] = date('Y-m-d H:i:s');
        $data['addedfrom'] = get_staff_user_id();

        $this->db->insert(db_prefix() . 'pur_vendor', $data);
        $userid = $this->db->insert_id();    
        
        if ($userid) {
            $this->acc_pur_vendor_created(['id' => $userid, 'data' => $data]);
            return $userid;
        }
        return false;
    }

    /**
     * { update vendor }
     *
     * @param      <type>   $data            The data
     * @param      <type>   $id              The identifier
     * @param      boolean  $client_request  The client request
     *
     * @return     boolean 
     */
    public function update_vendor($data, $id)
    {

        $affectedRows = 0;

        $data['balance'] = str_replace(',', '', $data['balance']);
        if($data['balance'] != '' && $data['balance'] > 0){
            if($data['balance_as_of'] != ''){
                $data['balance_as_of'] = to_sql_date($data['balance_as_of']);
            }else{
                $data['balance_as_of'] = date('Y-m-d');
            }
        }else{
            unset($data['balance']);
            unset($data['balance_as_of']);
        }

        $data = $this->check_zero_columns($data);
        $this->acc_pur_vendor_updated($data, $id);

        $this->db->where('userid', $id);
        $this->db->update(db_prefix() . 'pur_vendor', $data);

        if ($this->db->affected_rows() > 0) {
            $affectedRows++;
        }


        if ($affectedRows > 0) {
            return true;
        }

        return false;
    }

    /**
     * { delete vendor }
     *
     * @param      <type>   $id     The identifier
     *
     * @return     boolean  
     */
    public function delete_vendor($id)
    {
        $affectedRows = 0;

        $this->db->where('userid', $id);
        $this->db->delete(db_prefix() . 'pur_vendor');
        if ($this->db->affected_rows() > 0) {
            $affectedRows++;

            
        }
        if ($affectedRows > 0) {

            return true;
        }

        return false;
    }

    /**
     * { check zero columns }
     *
     * @param      <type>  $data   The data
     *
     * @return     array  
     */
    private function check_zero_columns($data)
    {
        if (isset($data['default_currency']) && $data['default_currency'] == '' || !isset($data['default_currency'])) {
            $data['default_currency'] = 0;
        }

        if (isset($data['country']) && $data['country'] == '' || !isset($data['country'])) {
            $data['country'] = 0;
        }

        if (isset($data['billing_country']) && $data['billing_country'] == '' || !isset($data['billing_country'])) {
            $data['billing_country'] = 0;
        }

        if (isset($data['shipping_country']) && $data['shipping_country'] == '' || !isset($data['shipping_country'])) {
            $data['shipping_country'] = 0;
        }

        return $data;
    }

    /**
     * Automatic credit note conversion
     * @param  integer $payment_id 
     * @return boolean
     */
    public function automatic_credit_note_refund_conversion($data){

        if(get_option('acc_credit_note_refund_automatic_conversion') != 1){
            return false;
        }
        $this->delete_convert($data['refund_id'], 'credit_note_refund');

        $payment_account = get_option('acc_credit_note_refund_payment_account');
        $deposit_to = get_option('acc_credit_note_refund_deposit_to');
        $affectedRows = 0;

        if(get_option('acc_close_the_books') == 1){
            if(strtotime($data['refunded_on']) <= strtotime(get_option('acc_closing_date')) && strtotime(date('Y-m-d')) > strtotime(get_option('acc_closing_date'))){
                return false;
            }
        }

        $this->load->model('credit_notes_model');
        $credit_note = $this->credit_notes_model->get($data['credit_note_id']);

        $this->load->model('currencies_model');
        $currency = $this->currencies_model->get_base_currency();

        $payment_total = $data['data']['amount'];
        $currency_rate = 0;
        if($credit_note->currency_name != $currency->name){
            $currency_rate = acc_get_currency_rate($credit_note->currency_name, $currency->name);
            $payment_total = round($currency_rate * $data['data']['amount'], 2);
        }
        $data_insert = [];
        if(get_option('acc_active_payment_mode_mapping') == 1 && $data['data']['payment_mode'] != ''){
            $payment_mode_mapping = $this->get_payment_mode_mapping($data['data']['payment_mode']);

            if($payment_mode_mapping){
                $node = [];
                $node['split'] = $payment_mode_mapping->credit_note_refund_payment_account;
                $node['account'] = $payment_mode_mapping->credit_note_refund_deposit_to;
                $node['debit'] = $payment_total;
                $node['credit'] = 0;
                $node['customer'] = $credit_note->clientid;
                $node['date'] = $data['data']['refunded_on'];
                $node['description'] = '';
                $node['rel_id'] = $data['refund_id'];
                $node['rel_type'] = 'credit_note_refund';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['currency_rate'] = $currency_rate;
                $data_insert[] = $node;

                $node = [];
                $node['split'] = $payment_mode_mapping->credit_note_refund_deposit_to;
                $node['customer'] = $credit_note->clientid;
                $node['account'] = $payment_mode_mapping->credit_note_refund_payment_account;
                $node['date'] = $data['data']['refunded_on'];
                $node['debit'] = 0;
                $node['credit'] = $payment_total;
                $node['description'] = '';
                $node['rel_id'] = $data['refund_id'];
                $node['rel_type'] = 'credit_note_refund';
                $node['datecreated'] = date('Y-m-d H:i:s');
                $node['addedfrom'] = get_staff_user_id();
                $node['currency_rate'] = $currency_rate;
                $data_insert[] = $node;
            }
        }
           
        if(count($data_insert) == 0){
            $node = [];
            $node['split'] = $payment_account;
            $node['account'] = $deposit_to;
            $node['customer'] = $credit_note->clientid;
            $node['debit'] = $payment_total;
            $node['credit'] = 0;
            $node['date'] = $data['data']['refunded_on'];
            $node['description'] = '';
            $node['rel_id'] = $data['refund_id'];
            $node['rel_type'] = 'credit_note_refund';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $node['currency_rate'] = $currency_rate;
            $data_insert[] = $node;

            $node = [];
            $node['split'] = $deposit_to;
            $node['customer'] = $credit_note->clientid;
            $node['account'] = $payment_account;
            $node['date'] = $data['data']['refunded_on'];
            $node['debit'] = 0;
            $node['credit'] = $payment_total;
            $node['description'] = '';
            $node['rel_id'] = $data['refund_id'];
            $node['rel_type'] = 'credit_note_refund';
            $node['datecreated'] = date('Y-m-d H:i:s');
            $node['addedfrom'] = get_staff_user_id();
            $node['currency_rate'] = $currency_rate;
            $data_insert[] = $node;
        }

        if($data_insert != []){
            $affectedRows = $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
        }
            
        if ($affectedRows > 0) {
            return true;
        }

        return false;
    }

    /**
     * get accounts
     * @param  integer $id    member group id
     * @param  array  $where
     * @return object
     */
    public function get_accounts_non_parent($id = '', $where = [])
    {
        if (is_numeric($id)) {
            $this->db->where('id', $id);
            return $this->db->get(db_prefix() . 'acc_accounts')->row();
        }

        $this->db->where($where);
        $this->db->where('active', 1);
        $this->db->where('parent_account IS NULL or parent_account = 0');
        $this->db->order_by('account_type_id,account_detail_type_id', 'desc');
        $accounts = $this->db->get(db_prefix() . 'acc_accounts')->result_array();

        $account_types = $this->accounting_model->get_account_types();
        $detail_types = $this->accounting_model->get_account_type_details();

        $account_type_name = [];
        $detail_type_name = [];

        foreach ($account_types as $key => $value) {
            $account_type_name[$value['id']] = $value['name'];
        }

        foreach ($detail_types as $key => $value) {
            $detail_type_name[$value['id']] = $value['name'];
        }

        foreach ($accounts as $key => $value) {
            if($value['name'] == '' && $value['key_name'] != ''){
                $accounts[$key]['name'] = _l($value['key_name']);
            }
            $_account_type_name = isset($account_type_name[$value['account_type_id']]) ? $account_type_name[$value['account_type_id']] : '';
            $_detail_type_name = isset($detail_type_name[$value['account_detail_type_id']]) ? $detail_type_name[$value['account_detail_type_id']] : '';
            $accounts[$key]['account_type_name'] = $_account_type_name;
            $accounts[$key]['detail_type_name'] = $_detail_type_name;
        }

        return $accounts;
    }

    /**
     * get payee for hansometable
     * @return [type] 
     */
    public function get_payee_for_hansometable()
    {

        $payee = [];

        $this->db->where('active', 1);
        $vendors = $this->db->get(db_prefix() . 'pur_vendor')->result_array();

        foreach($vendors as $vendor){
            $row = [];
            $row['id'] = 'vendor_'.$vendor['userid'];
            $row['label'] = $vendor['company'];

            $payee[] = $row;
        }

        $this->db->where('active', 1);
        $customers = $this->db->get(db_prefix() . 'clients')->result_array();

        foreach($customers as $customer){
            $row = [];
            $row['id'] = 'customer_'.$customer['userid'];
            $row['label'] = $customer['company'];

            $payee[] = $row;
        }

        return $payee;
    }

    public function get_sub_account_dropdown($account_id, $table = 'accounts'){
        $sub_accounts = get_sub_account_by_id($account_id);
        $acc_show_sub_account_numbers = get_option('acc_show_sub_account_numbers');
        $this->load->model('currencies_model');

        $currency = $this->currencies_model->get_base_currency();
        $html = '';
        if($sub_accounts){
            $html = '<div class="btn-group pull-right mleft4 invoice-view-buttons btn-with-tooltip-group _filter_data" data-toggle="tooltip" data-title="'. _l('sub_accounts_list').'"><button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
                   '._l('sub_accounts_list').'
                   </button><ul class="dropdown-menu width300">';

            foreach ($sub_accounts as $key => $value) {
                $name = '';
                if ($acc_show_sub_account_numbers == 1 && $value['number'] != '') {
                    $name .= $value['number'] . ' - ';
                }
                if ($value['name'] == '') {
                    $name .= _l($value['key_name']);
                } else {
                    $name .= $value['name'];
                }
                
                if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 21 || $value['account_type_id'] == 22 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7 || $value['account_type_id'] == 6){

                    $balance = app_format_money($value['credit'] - $value['debit'], $currency->name);
                } else {
                    $balance = app_format_money($value['debit'] - $value['credit'], $currency->name);
                }

                if ($value['balance'] == 0) {
                    if ($value['account_type_id'] == 11 || $value['account_type_id'] == 14) {
                        $value['balance'] = 1;
                    } else {
                        if ($value['credit'] > 0 || $value['debit']) {
                            $value['balance'] = 1;
                        }
                    }
                }

                if ($table == 'accounts') {
                    $html .= '<li><a href="#" onclick="edit_account_name(this,'.$value['id'].'); return false;" data-account_name="'.$value['name'].'" data-number="'.$value['number'].'" data-balance="'.$value['balance'].'" data-balance_as_of="'.$value['balance_as_of'].'" data-account_type_id="'.$value['account_type_id'].'">'.$name.' <small class="pull-right">'.$balance.'</small></a></li>';
                }else{
                    $html .= '<li><a href="'.admin_url('accounting/user_register_view/'.$value['id']).'">'.$name.' <small class="pull-right">'.$balance.'</small></a></li>';
                }

            }    
                      
            $html .= '</ul>
                </div>';
        }

        return $html;
    }

    /**
     * get accounts for hansometable
     * @param  string $id    
     * @param  array  $where 
     * @return [type]        
     */
    public function get_accounts_for_hansometable($id = '', $where = [])
    {
        if (is_numeric($id)) {
            $this->db->where('id', $id);
            return $this->db->get(db_prefix() . 'acc_accounts')->row();
        }

        $this->db->where($where);
        $this->db->where('active', 1);
        $this->db->order_by('id', 'asc');
        $accounts = $this->db->get(db_prefix() . 'acc_accounts')->result_array();

        $account_types = $this->accounting_model->get_account_types();
        $detail_types = $this->accounting_model->get_account_type_details();

        $account_type_name = [];
        $detail_type_name = [];

        foreach ($account_types as $key => $value) {
            $account_type_name[$value['id']] = $value['name'];
        }

        foreach ($detail_types as $key => $value) {
            $detail_type_name[$value['id']] = $value['name'];
        }

        foreach ($accounts as $key => $value) {
            $number = ($value['number'] != '') ? $value['number'] . ' - ' : '';
            if($value['name'] == '' && $value['key_name'] != ''){
                $accounts[$key]['name'] = $number._l($value['key_name']);
            }else{
                $accounts[$key]['name'] = $number.$value['name'];
            }
            $_account_type_name = isset($account_type_name[$value['account_type_id']]) ? $account_type_name[$value['account_type_id']] : '';
            $_detail_type_name = isset($detail_type_name[$value['account_detail_type_id']]) ? $detail_type_name[$value['account_detail_type_id']] : '';
            $accounts[$key]['account_type_name'] = $_account_type_name;
            $accounts[$key]['detail_type_name'] = $_detail_type_name;

            $accounts[$key]['label'] = $value['name'] != '' ? $number.$value['name'].' ('.$_account_type_name.')' : $number._l($value['key_name']).' ('.$_account_type_name.')';

        }

        return $accounts;
    }

    /**
     * get client for hansometable
     * @return [type] 
     */
    public function get_client_for_hansometable()
    {
        $this->db->select('userid as id, company as label');
        $this->db->where('active', 1);
        return $this->db->get(db_prefix() . 'clients')->result_array();

    }

    /**
     * get vendor for hansometable
     * @return [type] 
     */
    public function get_vendor_for_hansometable()
    {
        $this->db->select('userid as id, company as label');
        $this->db->where('active', 1);
        return $this->db->get(db_prefix() . 'pur_vendor')->result_array();
    }

    /**
     * get account history by company
     * @param  [type] $account 
     * @param  [type] $company 
     * @return [type]          
     */
    public function get_account_history_by_company($account, $str_where = '')
    {   
        $result_text = $this->check_account_debit_credit_plus_minus($this->get_accounts($account));

        // income, other income, owner equity, credit card, current liabilities, accounts_receivable, current assets, fixed assets, non current assets, accounts payable: credit is plus, debit is minus
        
        $ending_balance=0;

        if($str_where != ''){
            $this->db->where($str_where);
        }

        $this->db->where('account', $account);
        $this->db->order_by('date', 'asc');

        $account_histories = $this->db->get(db_prefix().'acc_account_history')->result_array();
        foreach ($account_histories as $key => $account_history) {
            if($account_histories[$key]['rel_type'] == 'check'){
                $account_histories[$key]['number'] = str_pad($account_histories[$key]['number'], 4, '0', STR_PAD_LEFT);
            }

            $account_histories[$key]['date'] = $account_history['date'];

            if($account_histories[$key]['vendor'] != 0 && $account_histories[$key]['vendor'] != ''){
                $account_histories[$key]['payee'] = 'vendor_'.$account_histories[$key]['vendor'];
            }

            if($account_histories[$key]['customer'] != 0 && $account_histories[$key]['customer'] != ''){
                $account_histories[$key]['payee'] = 'customer_'.$account_histories[$key]['customer'];
            }

            if($account_histories[$key]['split'] == '' || $account_histories[$key]['split'] == '0'){
                $account_histories[$key]['split'] = $account_histories[$key]['account'];
            }

            if($result_text == 'credit'){
                //credit is plus, debit is minus
                $account_histories[$key]['balance'] = $ending_balance + (float)$account_history['credit'] - (float)$account_history['debit'];
                $ending_balance +=  (float)$account_history['credit'] - (float)$account_history['debit'];
            }else{
                //debit is plus, credit is minus
                $account_histories[$key]['balance'] = $ending_balance + (float)$account_history['debit'] - (float)$account_history['credit'];
                $ending_balance +=  (float)$account_history['debit'] - (float)$account_history['credit'];
            }
        }

        $result_data=[];
        $result_data['ending_balance'] = $ending_balance;
        $result_data['account_history'] = $account_histories;

        return $result_data;
    }

    /**
     * check account debit credit plus minus
     * @param  [type] $account_id 
     * @return [type]             
     */
    public function check_account_debit_credit_plus_minus($account)
    {   

        $result_text='credit';

        // income, other income, owner equity, credit card, current liabilities, accounts_receivable, current assets, fixed assets, non current assets, accounts payable: credit is plus, debit is minus
        $credit_plus=[11,12,10,7,8,1,2,4,5,6];
        $debit_minus=[];

        if($account){
            if(in_array($account->account_type_id, $credit_plus)){
                $result_text='credit'; //credit is plus
            }else{
                $result_text='debit'; //debit is plus
            }
        }

        return $result_text;
    }

     /**
     * register add edit transaction
     * @param  [type] $data 
     * @return [type]       
     */
     public function register_add_edit_transaction($data)
     {   

        $affectedRows = 0;

        $header_key = [
            'id',
            'date',
            'number',
            'payee',
            'split',
            'debit',
            'credit',
            'balance'
        ];
        

        if (isset($data['product_tabs'])) {
            $product_tabs = $data['product_tabs'];
            unset($data['product_tabs']);
        }

        /*update save note*/

        if(isset($product_tabs)){
            $product_tabs_detail = json_decode($product_tabs);

            $es_detail = [];
            $row = [];

            foreach ($product_tabs_detail as $key => $value) {
                if($value[1] != ''){
                    $es_detail[] = array_combine($header_key, $value);
                }                
            }
        }

        $row = [];
        $row['update'] = []; 
        $row['insert'] = []; 
        $row['delete'] = [];
        $total = [];


        foreach ($es_detail as $key => $value) {
            if(isset($value['balance'])){
                unset($value['balance']);
            }

            if($value['id'] != 0){
                $row['delete'][] = $value['id'];
                $row['update'][] = $value;
            }else{
                unset($value['id']);
                $row['insert'][] = $value;
            }

        }

        $from_date_querystring = '';
        $to_date_querystring = '';
        $number_querystring = '';
        $payee_querystring = '';
        $vendor_querystring = '';
        $customer_querystring = '';
        $from_credit_querystring = '';
        $to_credit_querystring = '';
        $from_debit_querystring = '';
        $to_debit_querystring = '';
        $account_querystring = '';

        $account = $data['account'];
        $from_date_filter = $data['from_date_filter'];
        $to_date_filter = $data['to_date_filter'];
        $number_filter = $data['number_filter'];
        $payee_filter = isset($data['payee_filter']) ? $data['payee_filter'] : '';
        $from_credit_filter = $data['from_credit_filter'];
        $to_credit_filter = $data['to_credit_filter'];
        $from_debit_filter = $data['from_debit_filter'];
        $to_debit_filter = $data['to_debit_filter'];
        $account_filter = isset($data['account_filter']) ? $data['account_filter'] : '';

        if($from_date_filter != ''){
            $from_date_querystring = 'date >= "' . to_sql_date($from_date_filter) . '"';
        }

        if($to_date_filter != ''){
            $to_date_querystring = 'date <= "' . to_sql_date($to_date_filter) . '"';
        }

        if($number_filter != ''){
            $number_querystring = 'number = "' . $number_filter . '"';
        }
        
        if (isset($payee_filter) && $payee_filter != '') {
            $vendor_temp = '';
            $customer_temp = '';
            $araylengh = count($payee_filter);
            for ($i = 0; $i < $araylengh; $i++) {
                $payee = explode('_', $payee_filter[$i]);
                if(isset($payee[1])){
                    if($payee[0] == 'vendor'){
                        $vendor_temp = $vendor_temp . $payee[1];
                        if ($i != $araylengh - 1) {
                            $vendor_temp = $vendor_temp . ',';
                        }
                    }else{
                        $customer_temp = $customer_temp . $payee[1];
                        if ($i != $araylengh - 1) {
                            $customer_temp = $customer_temp . ',';
                        }
                    }
                }
            }

            if($vendor_temp != ''){
                $payee_querystring .= 'FIND_IN_SET(vendor, "' . $vendor_temp . '")';
            }

            if($customer_temp != ''){
                if($payee_querystring != ''){
                    $payee_querystring = '('.$payee_querystring.' OR FIND_IN_SET(customer, "' . $customer_temp . '"))';
                }else{
                    $payee_querystring .= 'FIND_IN_SET(customer, "' . $customer_temp . '")';
                }
            }
        }

        if($from_credit_filter != ''){
            $from_credit_querystring = 'credit >= "' . $from_credit_filter . '"';
        }

        if($to_credit_filter != ''){
            $to_credit_querystring = 'credit <= "' . $to_credit_filter . '"';
        }

        if($from_debit_filter != ''){
            $from_debit_querystring = 'credit >= "' . $from_debit_filter . '"';
        }

        if($to_debit_filter != ''){
            $to_debit_querystring = 'credit <= "' . $to_debit_filter . '"';
        }

        if (isset($account_filter) && $account_filter != '') {
            $temp = '';
            $araylengh = count($account_filter);
            for ($i = 0; $i < $araylengh; $i++) {
                $temp = $temp . $account_filter[$i];
                if ($i != $araylengh - 1) {
                    $temp = $temp . ',';
                }
            }
            $account_querystring = 'FIND_IN_SET(split, "' . $temp . '")';
        }

        $arrQuery = array($from_date_querystring, $to_date_querystring, $number_querystring, $payee_querystring, $from_credit_querystring, $to_credit_querystring, $from_debit_querystring, $to_debit_querystring, $account_querystring, );

        $newquerystring = '';
        foreach ($arrQuery as $string) {
            if ($string != '') {
                $newquerystring = $newquerystring . $string . ' AND ';
            }
        }

        $newquerystring = rtrim($newquerystring, "AND ");
        if ($newquerystring == '') {
            $newquerystring = [];
        }

        if(count($row['delete']) > 0){

            $row['delete'] = implode(",",$row['delete']);

            //get id need delete
            $this->db->where($newquerystring);
            $this->db->where('id NOT IN ('.$row['delete'] .') and account = "'.$data['account'].'"');
            $account_history_deletes = $this->db->get(db_prefix().'acc_account_history')->result_array();

            if(count($account_history_deletes) > 0){
                $arr_delete=[];

                foreach ($account_history_deletes as $account_history_delete) {
                    if($account_history_delete['id']%2 == 0){
                        //even number => -1
                        $arr_delete[] = $account_history_delete['id'];
                        $arr_delete[] = $account_history_delete['id']-1;
                    }else{
                        //odd number => +1
                        $arr_delete[] = $account_history_delete['id'];
                        $arr_delete[] = $account_history_delete['id']+1;
                    }
                    
                }

                if(count($arr_delete) > 0){
                    
                    $this->db->where('id IN ('.implode(",",$arr_delete) .')');
                    $this->db->delete(db_prefix().'acc_account_history');
                    if($this->db->affected_rows() > 0){
                        $affectedRows++;
                    }
                }
            }
            
        }


        //insert
        if(count($row['insert']) != 0){
            $insert_data=[];
            foreach ($row['insert'] as $_insert) {
                if($_insert['split'] == ''){
                    continue;
                }

                $customer = 0;
                $vendor = 0;

                $payee = $_insert['payee'] ? explode('_', $_insert['payee']) : [];
                if(isset($payee[1])){
                    if($payee[0] == 'vendor'){
                        $vendor = $payee[1];
                    }else{
                        $customer = $payee[1];
                    }
                }

                array_push($insert_data, [
                    'account' => $data['account'],
                    'rel_id' => 0,
                    'rel_type' => 'user_register_transaction',
                    'debit' => $_insert['debit'],
                    'credit' => $_insert['credit'],
                    'split' => $_insert['split'],
                    'description' => _l('user_register_transaction'),
                    'datecreated' =>  date('Y-m-d H:i:s'),
                    'date' => $_insert['date'],
                    'addedfrom' => get_staff_user_id(),
                    'number' => $_insert['number'],
                    'vendor' => $vendor,
                    'customer' => $customer,
                ]);

                array_push($insert_data, [
                    'account' => $_insert['split'],
                    'rel_id' => 0,
                    'rel_type' => 'user_register_transaction',
                    'debit' => $_insert['credit'],
                    'credit' => $_insert['debit'],
                    'split' => $data['account'],
                    'description' => _l('user_register_transaction'),
                    'datecreated' =>  date('Y-m-d H:i:s'),
                    'date' => $_insert['date'],
                    'addedfrom' => get_staff_user_id(),
                    'number' => $_insert['number'],
                    'vendor' => $vendor,
                    'customer' => $customer,
                ]);


            }
            if(count($insert_data) > 0){
                $affected_rows = $this->db->insert_batch(db_prefix().'acc_account_history', $insert_data);
                if($affected_rows > 0){
                    $affectedRows++;
                }
            }

        }

        //update => update  transaction related
        if(count($row['update']) != 0){
            $update_data=[];
            foreach ($row['update'] as $_update) {
                $customer = 0;
                $vendor = 0;

                $payee = $_update['payee'] ? explode('_', $_update['payee']) : [];
                if(isset($payee[1])){
                    if($payee[0] == 'vendor'){
                        $vendor = $payee[1];
                    }else{
                        $customer = $payee[1];
                    }
                }

                array_push($update_data, [
                    'id' => $_update['id'],
                    'account' => $data['account'],
                    'debit' => $_update['debit'],
                    'credit' => $_update['credit'],
                    'split' => $_update['split'] != '' ? $_update['split'] : $default_account,
                    'datecreated' =>  date('Y-m-d H:i:s'),
                    'date' => $_update['date'],
                    'addedfrom' => get_staff_user_id(),
                    'number' => $_update['number'],
                    'vendor' => $vendor,
                    'customer' => $customer,
                ]);

                //udpate transaction related
                if($_update['id']%2 == 0){
                    //even number => -1

                    array_push($update_data, [
                        'id' => $_update['id']-1,
                        'account' => $_update['split'] != '' ? $_update['split'] : $default_account,
                        'debit' => $_update['credit'],
                        'credit' => $_update['debit'],
                        'split' => $data['account'],
                        'date' => $_update['date'],
                        'addedfrom' => get_staff_user_id(),
                        'number' => $_update['number'],
                        'vendor' => $vendor,
                        'customer' => $customer,
                    ]);


                }else{
                        //odd number => +1
                    array_push($update_data, [
                        'id' => $_update['id']+1,
                        'account' => $_update['split'] != '' ? $_update['split'] : $default_account,
                        'debit' => $_update['credit'],
                        'credit' => $_update['debit'],
                        'split' => $data['account'],
                        'date' => $_update['date'],
                        'addedfrom' => get_staff_user_id(),
                        'number' => $_update['number'],
                        'vendor' => $vendor,
                        'customer' => $customer,
                    ]);
                }
            }

            if(count($update_data) > 0){

                $affected_rows = $this->db->update_batch(db_prefix().'acc_account_history', $update_data, 'id');
                if($affected_rows > 0){
                    $affectedRows++;
                }
            }

        }

        if ($affectedRows > 0) {
            return true;
        }
        return false;

    }

    /**
     * get check details
     * @param  string $id
     * @param  array  $where
     * @return array or object
     */
    public function get_check_details($id = '', $where = [])
    {
        if (is_numeric($id)) {
            $this->db->where('id', $id);
            return $this->db->get(db_prefix() . 'acc_check_details')->row();
        }

        $this->db->where($where);
        $this->db->order_by('id', 'desc');
        return $this->db->get(db_prefix() . 'acc_check_details')->result_array();
    }

    /**
     * get goods transaction detail
     * @param  integer $id
     * @return array
     */
    public function get_goods_transaction_detail($goods_id, $type = 'stock_export') {
        if($type == 'stock_export'){
            $this->db->where('status', 2);
        }else{
            $this->db->where('status', 1);
        }

        $this->db->where('goods_id', $goods_id);

        return $this->db->get(db_prefix() . 'goods_transaction_detail')->row();
    }

    /**
     * get reconcile by bank account
     * @param  integer $account 
     * @return object or boolean          
     */
    public function get_reconcile_by_bank_account($account){
        $this->db->where('account', $account);
        $this->db->order_by('id', 'desc');
        $reconcile = $this->db->get(db_prefix() . 'acc_bank_reconciles')->row();

        if($reconcile){
            return $reconcile;
        }

        return false;
    }

    /**
     * get bank reconcile
     * @param  string $id
     * @param  array  $where
     * @return array or object
     */
    public function get_bank_reconcile($id = '', $where = [])
    {
        if (is_numeric($id)) {
            $this->db->where('id', $id);
            return $this->db->get(db_prefix() . 'acc_bank_reconciles')->row();
        }

        $this->db->where($where);
        $this->db->order_by('id', 'desc');
        return $this->db->get(db_prefix() . 'acc_bank_reconciles')->result_array();
    }

        /**
     * check reconcile restored
     * @param  [type] $account 
     * @param  [type] $company 
     * @return [type]          
     */
    public function check_bank_reconcile_restored($account){
        $restored = false;

        $this->db->where('account', $account);
        $this->db->where('opening_balance', 0);
        $this->db->where('finish', 1);
        $this->db->order_by('id', 'desc');
        $reconcile = $this->db->get(db_prefix() . 'acc_bank_reconciles')->result_array();

        if(count($reconcile) > 0){
            $reconcile = true;
        }

        return $reconcile;
    }

    /**
     * get account history
     * @param  integer $id 
     * @return object    
     */
    public function get_account_history($id){
        $this->db->where('id', $id);
        return $this->db->get(db_prefix() . 'acc_account_history')->row();
    }

    public function remove_wrong_mapping($data_filter){
        $count = 0;
        if(isset($data_filter['type'])){
            $this->db->where('rel_type', $data_filter['type']);

            if(isset($data_filter['from_date'])){
                $this->db->where('('.db_prefix() . 'acc_account_history.date >= "' . $data_filter['from_date'] . '")');
            }

            if(isset($data_filter['to_date'])){
                $this->db->where('('.db_prefix() . 'acc_account_history.date <= "' . $data_filter['to_date'] . '")');
            }

            switch ($data_filter['type']) {
                case 'purchase_payment':
                    $this->db->select(db_prefix() . 'acc_account_history.id as id, '.db_prefix() . 'pur_invoice_payment.id as existing');
                    $this->db->join(db_prefix() . 'pur_invoice_payment', db_prefix() . 'pur_invoice_payment.id=' . db_prefix() . 'acc_account_history.rel_id', 'left');
                    break;

                case 'expense':
                    $this->db->select(db_prefix() . 'acc_account_history.id as id, '.db_prefix() . 'expenses.id as existing');
                    $this->db->join(db_prefix() . 'expenses', db_prefix() . 'expenses.id=' . db_prefix() . 'acc_account_history.rel_id', 'left');
                    $this->db->join(db_prefix() . 'expenses_categories', '' . db_prefix() . 'expenses_categories.id = ' . db_prefix() . 'expenses.category');
                    break;

                case 'credit_note':
                    $this->db->select(db_prefix() . 'acc_account_history.id as id, '.db_prefix() . 'credits.id as existing');
                    $this->db->join(db_prefix() . 'credits', db_prefix() . 'credits.id=' . db_prefix() . 'acc_account_history.rel_id', 'left');
                    break;
                
                case 'invoice':
                    $this->db->select(db_prefix() . 'acc_account_history.id as id, '.db_prefix() . 'invoices.id as existing');
                    $this->db->join(db_prefix() . 'invoices', db_prefix() . 'invoices.id=' . db_prefix() . 'acc_account_history.rel_id', 'left');
                    break;

                default:
                    // code...
                    break;
            }

            $account_history = $this->db->get(db_prefix() . 'acc_account_history')->result_array();

            foreach($account_history as $history){
                if($history['existing'] == ''){
                    $this->db->where('id', $history['id']);
                    $this->db->delete(db_prefix().'acc_account_history');

                    $count++;
                }
            }
        }

        return $count;
    }

    /**
     * update a bank transaction.
     */
    public function update_bank_transaction($data, $id){
        
        $data['date'] = to_sql_date($data['date']);
        $data['withdrawals'] = str_replace(',', '', $data['withdrawals']);
        $data['deposits'] = str_replace(',', '', $data['deposits']);

        $this->db->where('id', $id);
        $this->db->update(db_prefix().'acc_transaction_bankings', $data);

        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }

    /**
     * [update bank account v124 description]
     * @return [type] [description]
     */
    public function update_bank_account_v124(){
        $this->db->where('account_detail_type_id', 14);
        $this->db->update(db_prefix() . 'acc_accounts', [ 
            'account_type_id' => 16 
        ]);

        if ($this->db->affected_rows() > 0) {
            return true;
        }

        return false;
    }

    /**
     * add new account type detail
     * @param array $data
     * @return integer
     */
    public function add_income_statement_modification($data)
    {
        if (isset($data['id'])) {
            unset($data['id']);
        }

        if (isset($data['fomula'])) {
            $options = [];
            $options['fomula'] = $data['fomula'];
            $options['account_fomula'] = $data['account_fomula'];
            $data['options'] = json_encode($options);
            unset($data['fomula']);
            unset($data['account_fomula']);
        }

        $data['dateadded'] = date('Y-m-d H:i:s');
        $data['addedfrom'] = get_staff_user_id();

        $this->db->insert(db_prefix() . 'acc_income_statement_modifications', $data);

        $insert_id = $this->db->insert_id();

        if ($insert_id) {
            return true;
        }

        return false;
    }

    /**
     * update account type detail
     * @param array $data
     * @param integer $id
     * @return integer
     */
    public function update_income_statement_modification($data, $id)
    {
        if (isset($data['id'])) {
            unset($data['id']);
        }

        if (isset($data['fomula'])) {
            $options = [];
            $options['fomula'] = $data['fomula'];
            $options['account_fomula'] = $data['account_fomula'];
            $data['options'] = json_encode($options);
            unset($data['fomula']);
            unset($data['account_fomula']);
        }else{
            $data['options'] = null;
        }


        $this->db->where('id', $id);
        $this->db->update(db_prefix() . 'acc_income_statement_modifications', $data);

        if ($this->db->affected_rows() > 0) {
            return true;
        }

        return false;
    }

    /**
     * delete account type detail
     * @param integer $id
     * @return boolean
     */

    public function delete_income_statement_modification($id)
    {
        $this->db->where('id', $id);
        $this->db->delete(db_prefix() . 'acc_income_statement_modifications');
        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }

    /**
     * get account type details
     * @param  integer $id    member group id
     * @param  array  $where
     * @return object
     */
    public function get_data_income_statement_modifications($id = '', $where = [])
    {
        if (is_numeric($id)) {
            $this->db->where('id', $id);
            return $this->db->get(db_prefix() . 'acc_income_statement_modifications')->row();
        }

        $this->db->where($where);
        $income_statement_modifications = $this->db->get(db_prefix() . 'acc_income_statement_modifications')->result_array();

        return $income_statement_modifications;
    }

    /**
     * delete all data the account detail types table
     *
     * @param      int   $id     The identifier
     *
     * @return     boolean
     */
    public function reset_income_statement_modifications()
    {
        $affectedRows = 0;
        if ($this->db->table_exists(db_prefix() . 'acc_income_statement_modifications')) {

            $this->db->where('id > 0');
            $this->db->delete(db_prefix() . 'acc_income_statement_modifications');
            $affectedRows++;

            $income_account = $this->get_accounts('', '(account_type_id = 11 AND active = 1)');

            $data_insert = [];
            foreach($income_account as $value){
                $node = [];
                $node['account'] = $value['id'];
                $node['name'] = $value['name'];

                $data_insert[] = $node;
            }

            if ($data_insert != []) {
                $affectedRows = $this->db->insert_batch(db_prefix().'acc_income_statement_modifications', $data_insert);
            }
        }

        if ($affectedRows > 0) {
            return true;
        }
        return false;
    }

    /**
     * Change account status / active / inactive
     * @param  mixed $id     staff id
     * @param  mixed $status status(0/1)
     */
    public function change_income_statement_modification_status($id, $status)
    {
        $this->db->where('id', $id);
        $this->db->update(db_prefix() . 'acc_income_statement_modifications', [
            'active' => $status,
        ]);

        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }
    
    public function caculate_data_income_profit_and_loss($data_filter, $return_type = 'profit_and_loss', $total_income = 0){

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'accrual';

        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $where_items = '';
        if(isset($data_filter['items'])){
            $where_items = '(item IN ('. implode(',', $data_filter['items']).'))';
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $income_statement_modifications = $this->get_data_income_statement_modifications('', 'active = 1');
        $data = [];
        $account_amount = [];
        $data_income = [];
        $data_income['income'] = [];
        $data_income['net_income'] = [];

        if($return_type == 'total_amount'){
            $data_income['income'] = 0;
            $data_income['net_income'] = 0;
        }

        foreach ($income_statement_modifications as $key => $value) {
            $type = $value['type'] ? $value['type'] : 'income';
            $account_detail = $this->get_accounts($value['account']);
            $total_amount = 0;
            if(isset($account_detail->id)){
                if(!isset($account_amount[$account_detail->id])){
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $account_detail->id);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                   
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    

                    if($account_detail->account_type_id == 11 || $account_detail->account_type_id == 12 || $account_detail->account_type_id == 8 || $account_detail->account_type_id == 9 || $account_detail->account_type_id == 10 || $account_detail->account_type_id == 7 || $account_detail->account_type_id == 6){
                        $amount = $credits - $debits;
                    }else{
                        $amount = $debits - $credits;
                    }

                    $account_amount[$account_detail->id] = $amount;
                }

                $total_amount = $account_amount[$account_detail->id];
            }
            if($value['options']){
                $options = json_decode($value['options'], true);
                $fomula = $options['fomula'];
                $account_fomula = $options['account_fomula'];

                foreach($account_fomula as $k => $account){
                    $account_fomula_detail = $this->get_accounts($account);

                    if(!$account_fomula_detail){
                        continue;
                    }

                    if(!isset($account_amount[$account_fomula_detail->id])){
                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('account', $account_fomula_detail->id);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        if($where_items != ''){
                            $this->db->where($where_items);
                        }
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                       
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;

                        if($account_fomula_detail->account_type_id == 11 || $account_fomula_detail->account_type_id == 12 || $account_fomula_detail->account_type_id == 8 || $account_fomula_detail->account_type_id == 9 || $account_fomula_detail->account_type_id == 10 || $account_fomula_detail->account_type_id == 7 || $account_fomula_detail->account_type_id == 6){
                            $amount = $credits - $debits;
                        }else{
                            $amount = $debits - $credits;
                        }
                        $account_amount[$account_fomula_detail->id] = $amount;
                    }

                    if($fomula[$k] == '+'){
                        $total_amount += $account_amount[$account_fomula_detail->id];
                    }elseif($fomula[$k] == '-'){
                        $total_amount -= $account_amount[$account_fomula_detail->id];
                    }elseif($fomula[$k] == '/'){
                        if($account_amount[$account_fomula_detail->id] != 0){
                            $total_amount = $total_amount/$account_amount[$account_fomula_detail->id];
                        }else{
                            $total_amount = 0;
                        }
                    }else{
                        $total_amount = $total_amount*$account_amount[$account_fomula_detail->id];
                    }

                }
            }

            if($return_type == 'profit_and_loss'){
                if(isset($account_detail->id)){
                    $data_income[$type][] = ['account_id' => $account_detail->id, 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $value['name'], 'amount' => $total_amount, 'child_account' => []];
                }
            }elseif($return_type == 'total_amount'){
                if(!is_numeric($data_income[$type])){
                    $data_income[$type] = 0;
                }

                $data_income[$type] += $total_amount;
            }elseif($return_type == 'profit_and_loss_as_of_total_income'){
                if($total_income != 0){
                    if(isset($account_detail->id)){
                        $data_income[$type][] = ['account_id' => $account_detail->id, 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $value['name'], 'amount' => $total_amount, 'percent' => round((($total_amount) / $total_income) * 100, 2), 'child_account' => []];
                    }
                }else{
                    if(isset($account_detail->id)){
                        $data_income[$type][] = ['account_id' => $account_detail->id, 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $value['name'], 'amount' => $total_amount, 'percent' => 0, 'child_account' => []];
                    }
                }
            }

        }

        return $data_income;
    }

    public function get_net_income($data_filter){
        $this->load->model('currencies_model');
        $acc_show_account_numbers = get_option('acc_show_account_numbers');
        $acc_enable_income_statement_modifications = get_option('acc_enable_income_statement_modifications');

        $from_date = date('1970-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'accrual';
        $display_columns = 'total_only';
        $date_filter_type = 'from_and_to';

        $where_items = '';
        if(isset($data_filter['items'])){
            $where_items = '(item IN ('. implode(',', $data_filter['items']).'))';
        }

        if(isset($data_filter['display_columns'])){
            $display_columns = $data_filter['display_columns'];
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['date_filter_type'])){
            $date_filter_type = $data_filter['date_filter_type'];
        }

        if(isset($data_filter['from_date']) && $date_filter_type != 'to_date'){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $account_type_details = $this->get_account_type_details();
        $data_report = [];
        $data_accounts = [];
        
        foreach ($account_type_details as $key => $value) {
            if($acc_enable_income_statement_modifications != 1){
                if($value['account_type_id'] == 11){
                    $data_accounts['income'][] = $value;
                }
            }

            if($value['account_type_id'] == 12){
                $data_accounts['other_income'][] = $value;
            }

            if($value['account_type_id'] == 13){
                $data_accounts['cost_of_sales'][] = $value;
            }

            if($value['account_type_id'] == 14){
                $data_accounts['expenses'][] = $value;
            }

            if($value['account_type_id'] == 15){
                $data_accounts['other_expenses'][] = $value;
            }
        }
        $data = [
            'from_date' => $from_date,
            'to_date' => $to_date,
            'accounting_method' => $accounting_method,
            'display_columns' => $display_columns,
            'acc_show_account_numbers' => $acc_show_account_numbers,
        ];

        $data_total = [];
        foreach ($data_accounts as $data_key => $data_account) {
            $total = 0;
            foreach ($data_account as $key => $value) {
                $this->db->where('active', 1);
                $this->db->where('account_detail_type_id', $value['id']);
                $accounts = $this->db->get(db_prefix().'acc_accounts')->result_array();
                foreach ($accounts as $val) {
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    
                    $this->db->where('account', $val['id']);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;
                    if($acc_show_account_numbers == 1 && $val['number'] != ''){
                            $name = $val['name'] != '' ? $val['number'].' - '.$val['name'] : $val['number'].' - '._l($val['key_name']);
                        }else{
                            $name = $val['name'] != '' ? $val['name'] : _l($val['key_name']);
                        }


                    if($value['account_type_id'] == 11 || $value['account_type_id'] == 12 || $value['account_type_id'] == 8 || $value['account_type_id'] == 9 || $value['account_type_id'] == 10 || $value['account_type_id'] == 7){
                        $total += $credits - $debits;
                    }else{
                        $total += $debits - $credits;
                    }

                }
            }

            $data_total[$data_key] = $total;
        }

        if($acc_enable_income_statement_modifications == 1){
            $data_income = $this->caculate_data_income_profit_and_loss($data_filter, 'total_amount');
            $data_total['income'] = $data_income['income'] + $data_income['net_income'];
        }

        $income = $data_total['income'] + $data_total['other_income'];
        $expenses = $data_total['expenses'] + $data_total['other_expenses'] + $data_total['cost_of_sales'];
        $net_income = $income - $expenses;

        return $net_income;
    }

    public function caculate_data_income_profit_and_loss_12_months($data_filter){

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';

        $acc_show_account_numbers = get_option('acc_show_account_numbers');
        $where_items = '';
        if(isset($data_filter['items'])){
            $where_items = '(item IN ('. implode(',', $data_filter['items']).'))';
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        $income_statement_modifications = $this->get_data_income_statement_modifications('', 'active = 1');
        $data = [];
        $account_amount = [];
        $data_income = [];

        foreach ($income_statement_modifications as $key => $value) {
            $type = $value['type'] ? $value['type'] : 'income';
            $account_detail = $this->get_accounts($value['account']);

            $total_amount = 0;
            if(isset($account_detail->id)){
                if(!isset($account_amount[$account_detail->id])){
                    $row = [];
                    $start = $month = strtotime($from_date);
                    $end = strtotime($to_date);

                    while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
                    {
                        $this->db->where('account', $account_detail->id);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                        if($where_items != ''){
                            $this->db->where($where_items);
                        }
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;

                        if($account_detail->account_type_id == 11 || $account_detail->account_type_id == 12 || $account_detail->account_type_id == 8 || $account_detail->account_type_id == 9 || $account_detail->account_type_id == 10 || $account_detail->account_type_id == 7 || $account_detail->account_type_id == 6){
                            $row[date('m-Y', $month)] = $credits - $debits;
                        }else{
                            $row[date('m-Y', $month)] = $debits - $credits;
                        }

                        $month = strtotime("+1 month", $month);
                    }

                    $account_amount[$account_detail->id] = $row;
                }

                $total_amount = $account_amount[$account_detail->id];
            }

            if($value['options']){
                $options = json_decode($value['options'], true);
                $fomula = $options['fomula'];
                $account_fomula = $options['account_fomula'];

                foreach($account_fomula as $k => $account){
                    $account_fomula_detail = $this->get_accounts($account);

                    if(!$account_fomula_detail){
                        continue;
                    }

                    if(!isset($account_amount[$account_fomula_detail->id])){
                        $row = [];
                        $start = $month = strtotime($from_date);
                        $end = strtotime($to_date);

                        while($month <= $end || date('Y-m', $month) == date('Y-m', $end))
                        {
                            $this->db->where('account', $account_fomula_detail->id);
                            if($accounting_method == 'cash'){
                                $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                            }
                            $this->db->select('sum(credit) as credit, sum(debit) as debit');
                            $this->db->where('(month(date) = "' . date('m',$month) . '" and year(date) = "' . date('Y',$month) . '")');
                            if($where_items != ''){
                                $this->db->where($where_items);
                            }
                            $account_history = $this->db->get(db_prefix().'acc_account_history')->row();

                            $credits = $account_history->credit != '' ? $account_history->credit : 0;
                            $debits = $account_history->debit != '' ? $account_history->debit : 0;

                            if($account_fomula_detail->account_type_id == 11 || $account_fomula_detail->account_type_id == 12 || $account_fomula_detail->account_type_id == 8 || $account_fomula_detail->account_type_id == 9 || $account_fomula_detail->account_type_id == 10 || $account_fomula_detail->account_type_id == 7 || $account_fomula_detail->account_type_id == 6){
                                $row[date('m-Y', $month)] = $credits - $debits;
                            }else{
                                $row[date('m-Y', $month)] = $debits - $credits;
                            }

                            $month = strtotime("+1 month", $month);
                        }

                        $account_amount[$account_fomula_detail->id] = $row;
                    }

                    if($fomula[$k] == '+'){
                        foreach($total_amount as $_k => $_val){
                            $total_amount[$_k] += $account_amount[$account_fomula_detail->id][$_k];
                        }
                    }elseif($fomula[$k] == '-'){
                        foreach($total_amount as $_k => $_val){
                            $total_amount[$_k] -= $account_amount[$account_fomula_detail->id][$_k];
                        }
                    }elseif($fomula[$k] == '/'){
                        foreach($total_amount as $_k => $_val){
                            if($account_amount[$account_fomula_detail->id][$_k] != 0){
                                $total_amount[$_k] = $_val/$account_amount[$account_fomula_detail->id][$_k];
                            }else{
                                $total_amount[$_k] = 0;
                            }
                        }
                    }else{
                        foreach($total_amount as $_k => $_val){
                            $total_amount[$_k] = $_val*$account_amount[$account_fomula_detail->id][$_k];
                        }
                    }

                }
            }

            if(isset($account_detail->id)){
                $data_income[$type][] = ['account_id' => $account_detail->id, 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $value['name'], 'amount' => $total_amount, 'child_account' => []];
            }
        }

        return $data_income;
    }

    public function caculate_data_income_profit_and_loss_comparison($data_filter, $type = ''){
        $this_year = date('Y');
        $last_year = $this_year - 1;
        $acc_show_account_numbers = get_option('acc_show_account_numbers');

        $from_date = date('Y-01-01');
        $to_date = date('Y-m-d');
        $accounting_method = 'cash';
        $where_items = '';
        if(isset($data_filter['items'])){
            $where_items = '(item IN ('. implode(',', $data_filter['items']).'))';
        }

        if(isset($data_filter['accounting_method'])){
            $accounting_method = $data_filter['accounting_method'];
        }

        if(isset($data_filter['from_date'])){
            $from_date = to_sql_date($data_filter['from_date']);
        }

        if(isset($data_filter['to_date'])){
            $to_date = to_sql_date($data_filter['to_date']);
        }

        if($type == 'year_to_date'){
            $acc_first_month_of_financial_year = get_option('acc_first_month_of_financial_year');
            $last_from_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.date('Y')));
            $last_to_date = $to_date;

            if($last_from_date > $to_date){
                $last_from_date = date('Y-m-d', strtotime($acc_first_month_of_financial_year . ' 01 '.(date('Y') - 1)));
            }
        }else{
            $last_from_date = date('Y-m-d', strtotime($from_date.' - 1 year'));
            $last_to_date = date('Y-m-d', strtotime($to_date.' - 1 year'));
        }


        $income_statement_modifications = $this->get_data_income_statement_modifications('', 'active = 1');
        $data = [];
        $account_amount = [];
        $data_income = [];

        foreach ($income_statement_modifications as $key => $value) {
            $type = $value['type'] ? $value['type'] : 'income';
            $account_detail = $this->get_accounts($value['account']);

            $total_amount = 0;
            $total_last_amount = 0;
            if(isset($account_detail->id)){
                if(!isset($account_amount[$account_detail->id])){
                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $account_detail->id);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $credits = $account_history->credit != '' ? $account_history->credit : 0;
                    $debits = $account_history->debit != '' ? $account_history->debit : 0;

                    $this->db->select('sum(credit) as credit, sum(debit) as debit');
                    $this->db->where('account', $account_detail->id);
                    if($accounting_method == 'cash'){
                        $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                    }
                    $this->db->where('(date_format(datecreated, \'%Y-%m-%d\') >= "' . $last_from_date . '" and date_format(datecreated, \'%Y-%m-%d\') <= "' . $last_to_date . '")');
                    if($where_items != ''){
                        $this->db->where($where_items);
                    }
                    $py_account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                    $py_credits = $py_account_history->credit != '' ? $py_account_history->credit : 0;
                    $py_debits = $py_account_history->debit != '' ? $py_account_history->debit : 0;

                    if($account_detail->account_type_id == 11 || $account_detail->account_type_id == 12 || $account_detail->account_type_id == 8 || $account_detail->account_type_id == 9 || $account_detail->account_type_id == 10 || $account_detail->account_type_id == 7 || $account_detail->account_type_id == 6){
                        $amount = $credits - $debits;
                        $last_amount = $py_credits - $py_debits;
                    }else{
                        $amount = $debits - $credits;
                        $last_amount = $py_debits - $py_credits;
                    }

                    $account_amount[$account_detail->id] = $amount;
                    $account_amount_last[$account_detail->id] = $last_amount;
                }

                $total_amount = $account_amount[$account_detail->id];
                $total_last_amount = $account_amount_last[$account_detail->id];
            }

            if($value['options']){
                $options = json_decode($value['options'], true);
                $fomula = $options['fomula'];
                $account_fomula = $options['account_fomula'];

                foreach($account_fomula as $k => $account){
                    $account_fomula_detail = $this->get_accounts($account);

                    if(!$account_fomula_detail){
                        continue;
                    }

                    if(!isset($account_amount[$account_fomula_detail->id])){
                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('account', $account_fomula_detail->id);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('(date >= "' . $from_date . '" and date <= "' . $to_date . '")');
                        if($where_items != ''){
                            $this->db->where($where_items);
                        }
                        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $credits = $account_history->credit != '' ? $account_history->credit : 0;
                        $debits = $account_history->debit != '' ? $account_history->debit : 0;

                        $this->db->select('sum(credit) as credit, sum(debit) as debit');
                        $this->db->where('account', $account_fomula_detail->id);
                        if($accounting_method == 'cash'){
                            $this->db->where('((rel_type = "invoice" and paid = 1) or rel_type != "invoice")');
                        }
                        $this->db->where('(date_format(datecreated, \'%Y-%m-%d\') >= "' . $last_from_date . '" and date_format(datecreated, \'%Y-%m-%d\') <= "' . $last_to_date . '")');
                        if($where_items != ''){
                            $this->db->where($where_items);
                        }
                        $py_account_history = $this->db->get(db_prefix().'acc_account_history')->row();
                        $py_credits = $py_account_history->credit != '' ? $py_account_history->credit : 0;
                        $py_debits = $py_account_history->debit != '' ? $py_account_history->debit : 0;

                        if($account_fomula_detail->account_type_id == 11 || $account_fomula_detail->account_type_id == 12 || $account_fomula_detail->account_type_id == 8 || $account_fomula_detail->account_type_id == 9 || $account_fomula_detail->account_type_id == 10 || $account_fomula_detail->account_type_id == 7 || $account_fomula_detail->account_type_id == 6){
                            $amount = $credits - $debits;
                            $last_amount = $py_credits - $py_debits;
                        }else{
                            $amount = $debits - $credits;
                            $last_amount = $py_debits - $py_credits;
                        }

                        $account_amount[$account_fomula_detail->id] = $amount;
                        $account_amount_last[$account_fomula_detail->id] = $last_amount;
                    }

                    if($fomula[$k] == '+'){
                        $total_amount += $account_amount[$account_fomula_detail->id];
                        $total_last_amount += $account_amount_last[$account_fomula_detail->id];
                    }elseif($fomula[$k] == '-'){
                        $total_amount -= $account_amount[$account_fomula_detail->id];
                        $total_last_amount -= $account_amount_last[$account_fomula_detail->id];
                    }elseif($fomula[$k] == '/'){
                        if($account_amount[$account_fomula_detail->id] != 0){
                            $total_amount = $total_amount/$account_amount[$account_fomula_detail->id];
                        }else{
                            $total_amount = 0;
                        }
                        if($account_amount_last[$account_fomula_detail->id] != 0){
                            $total_last_amount = $total_last_amount/$account_amount_last[$account_fomula_detail->id];
                        }else{
                            $total_last_amount = 0;
                        }

                    }else{
                        $total_amount = $total_amount*$account_amount[$account_fomula_detail->id];
                        $total_last_amount = $total_last_amount*$account_amount_last[$account_fomula_detail->id];
                    }

                }
            }

            if(isset($account_detail->id)){
                $data_income[$type][] = ['account_id' => $account_detail->id, 'from_date' => $from_date, 'to_date' => $to_date, 'name' => $value['name'], 'this_year' => $total_amount, 'last_year' => $total_last_amount, 'child_account' => []];
            }
        }

        return $data_income;
    }

    /**
     * get items
     * @param  string $id
     * @param  array  $where
     * @return array or object
     */
    public function get_items($id = '', $where = [])
    {
        if (is_numeric($id)) {
            $this->db->where('id', $id);
            return $this->db->get(db_prefix() . 'items')->row();
        }

        $this->db->where($where);
        $this->db->order_by('id', 'desc');
        return $this->db->get(db_prefix() . 'items')->result_array();
    }

    /**
     * Opening balance Client
     * @param  [type] $data
     * @return [type]      
     */
    public function acc_client_created($data){
        if(isset($data['data']['balance']) && $data['data']['balance'] > 0){
            $this->load->model('payment_modes_model');
            $this->load->model('invoices_model');

            $payment_modes = $this->payment_modes_model->get();

            $__number        = get_option('next_invoice_number');
            $_invoice_number = str_pad($__number, get_option('number_padding_prefixes'), '0', STR_PAD_LEFT);
            $this->db->where('isdefault', 1);
            $curreny = $this->db->get(db_prefix() . 'currencies')->row()->id;

            $invoice_data = [];
            $invoice_data['clientid']                 = $data['id'];
            $invoice_data['billing_street']           = $data['data']['billing_street'];
            $invoice_data['billing_city']             = $data['data']['billing_city'];
            $invoice_data['billing_state']            = $data['data']['billing_state'];
            $invoice_data['billing_zip']              = $data['data']['billing_zip'];
            $invoice_data['billing_country']          = $data['data']['billing_country'];
            $invoice_data['include_shipping']         = 1;
            $invoice_data['show_shipping_on_invoice'] = 1;
            $invoice_data['shipping_street']          = $data['data']['shipping_street'];
            $invoice_data['shipping_city']            = $data['data']['shipping_city'];
            $invoice_data['shipping_state']           = $data['data']['shipping_state'];
            $invoice_data['shipping_zip']             = $data['data']['shipping_zip'];
            
            $invoice_data['date']                     = $data['data']['balance_as_of'];
            $invoice_data['duedate']                  = $data['data']['balance_as_of'];

            $invoice_data['currency']            = $curreny;
            $invoice_data['number']              = $_invoice_number;
            $invoice_data['total']               = $data['data']['balance'];
            $invoice_data['subtotal']            = $data['data']['balance'];
            $payment_model_list = [];
            if ($payment_modes) {
                foreach($payment_modes as $payment_mode){
                    $payment_model_list[] = $payment_mode['id'];
                }
            }
            $invoice_data["allowed_payment_modes"] = $payment_model_list;

            $newitems = [];
            array_push($newitems, array('order' => 1, 'description' => 'Opening balance', 'long_description' => '', 'qty' => 1, 'unit' => '', 'rate' => $data['data']['balance'], 'taxname' => ''));
            $invoice_data['newitems'] = $newitems;

            $invoice_id = $this->invoices_model->add($invoice_data);

            return $invoice_id;
        }

        return false;
    }

    /**
     * [get_invoice_item_tax description]
     * @param  [type] $item
     * @return [type]      
     */
    public function get_invoice_item_tax($item, $invoice){
        $data_return = [];
        $data_return['tax_id'] = [];
        $data_return['tax_amount'] = [];
        $item_total = $item['rate'] * $item['qty'];
        $this->db->where('itemid', $item['id']);
        $item_tax = $this->db->get(db_prefix().'item_tax')->result_array();

        foreach($item_tax as $tax){
            $this->db->where('taxrate', $tax['taxrate']);
            $this->db->where('name', $tax['taxname']);
            $_tax = $this->db->get(db_prefix().'taxes')->row();
            if($_tax){
                $data_return['tax_id'][] = $_tax->id;
                if($invoice->discount_type == 'before_tax'){
                    $total_tax = $item_total * $tax['taxrate'] / 100;
                    $t = ($invoice->discount_total / $invoice->subtotal) * 100;

                    $data_return['tax_amount'][] = ($total_tax - $total_tax*$t/100);
                }else{
                    $data_return['tax_amount'][] = $item_total * $tax['taxrate'] / 100;
                }

            }
        }

        return $data_return;
    }

    /**
     * Opening balance Client
     * @param  [type] $data
     * @param  [type] $id  
     * @return [type]      
     */
    public function acc_client_updated($data, $id){
        $client = $this->clients_model->get($id);
        if($client->balance == NULL && isset($data['balance']) && $data['balance'] > 0){

            $this->load->model('payment_modes_model');
            $this->load->model('invoices_model');

            $payment_modes = $this->payment_modes_model->get();

            $__number        = get_option('next_invoice_number');
            $_invoice_number = str_pad($__number, get_option('number_padding_prefixes'), '0', STR_PAD_LEFT);
            $this->db->where('isdefault', 1);
            $curreny = $this->db->get(db_prefix() . 'currencies')->row()->id;

            $invoice_data = [];
            $invoice_data['clientid']                 = $id;
            $invoice_data['billing_street']           = $client->billing_street;
            $invoice_data['billing_city']             = $client->billing_city;
            $invoice_data['billing_state']            = $client->billing_state;
            $invoice_data['billing_zip']              = $client->billing_zip;
            $invoice_data['billing_country']          = $client->billing_country;
            $invoice_data['include_shipping']         = 1;
            $invoice_data['show_shipping_on_invoice'] = 1;
            $invoice_data['shipping_street']          = $client->shipping_street;
            $invoice_data['shipping_city']            = $client->shipping_city;
            $invoice_data['shipping_state']           = $client->shipping_state;
            $invoice_data['shipping_zip']             = $client->shipping_zip;
            
            $invoice_data['date']                     = $data['balance_as_of'];
            $invoice_data['duedate']                  = $data['balance_as_of'];

            $invoice_data['currency']            = $curreny;
            $invoice_data['number']              = $_invoice_number;
            $invoice_data['total']               = $data['balance'];
            $invoice_data['subtotal']            = $data['balance'];
            $payment_model_list = [];
            if ($payment_modes) {
                foreach($payment_modes as $payment_mode){
                    $payment_model_list[] = $payment_mode['id'];
                }
            }
            $invoice_data["allowed_payment_modes"] = $payment_model_list;

            $newitems = [];
            array_push($newitems, array('order' => 1, 'description' => 'Opening balance', 'long_description' => '', 'qty' => 1, 'unit' => '', 'rate' => $data['balance'], 'taxname' => ''));
            $invoice_data['newitems'] = $newitems;

            $invoice_id = $this->invoices_model->add($invoice_data);

            return $invoice_id;
        }

        return false;
    }

    /**
     * Opening balance Vendor
     * @param  [type] $data
     * @return [type]      
     */
    public function acc_pur_vendor_created($data){
        $data['data']['balance'] = str_replace(',', '', $data['data']['balance']);

        if($data['data']['balance'] > 0){
            
            $bill_data = [];
            $bill_data['vendor']                 = $data['id'];
            $bill_data['note']         = '';
            $bill_data['expense_name'] = _l('opening_balance');
            $bill_data['date']                     = _d($data['data']['balance_as_of']);
            $bill_data['due_date']                  = _d($data['data']['balance_as_of']);
            $bill_data['tax']            = '';
            $bill_data['tax2']            = '';
            $bill_data['paymentmode']            = '';
            $bill_data['reference_no']            = '';
            $bill_data['amount']               = $data['data']['balance'];

            $bill_data['debit_account']            = [52];
            $bill_data['debit_amount']            = [$data['data']['balance']];
            $bill_data['credit_account']            = [87];
            $bill_data['credit_amount']            = [$data['data']['balance']];

            $bill_id = $this->add_bill($bill_data);

            if($bill_id){
                $this->bill_appove_payable($bill_id);
                return $bill_id;
            }
        }

        return false;
    }

    /**
     * Opening balance Vendor
     * @param  [type] $data
     * @param  [type] $id  
     * @return [type]      
     */
    public function acc_pur_vendor_updated($data, $id){
        $vendor = $this->get_vendor($id);
        $data['balance'] = str_replace(',', '', $data['balance']);

        if($vendor->balance == NULL && $data['balance'] > 0){

            $bill_data = [];
            $bill_data['vendor']                 = $id;
            $bill_data['note']         = '';
            $bill_data['expense_name'] = _l('opening_balance');
            $bill_data['date']                     = _d($data['balance_as_of']);
            $bill_data['due_date']                  = _d($data['balance_as_of']);
            $bill_data['tax']            = '';
            $bill_data['tax2']            = '';
            $bill_data['paymentmode']            = '';
            $bill_data['reference_no']            = '';
            $bill_data['amount']               = $data['balance'];

            $bill_data['debit_account']            = [52];
            $bill_data['debit_amount']            = [$data['balance']];
            $bill_data['credit_account']            = [87];
            $bill_data['credit_amount']            = [$data['balance']];

            $bill_id = $this->add_bill($bill_data);

            if($bill_id){
                $this->bill_appove_payable($bill_id);
                return $bill_id;
            }
        }

        return false;
    }

    /**
     * calculate opening stock
     * @param  integer $item_id             
     * @param  date $date_financial_year 
     * @return float                     
     */
    public function calculate_opening_stock($item_id, $date_financial_year) {
        $this->load->model('warehouse/warehouse_model');

        $data = ['commodity_id' => $item_id, 'from_date' => $date_financial_year, 'to_date' => date('Y-m-d'), 'warehouse_id' => ''];
        $from_date = $data['from_date'];
        $to_date = $data['to_date'];

        if(!$this->check_format_date($from_date)){
            $from_date = to_sql_date($from_date);
        }
        if(!$this->check_format_date($to_date)){
            $to_date = to_sql_date($to_date);
        }

        $where_warehouse_id = '';

        $where_warehouse_id_with_internal_i = '';
        $where_warehouse_id_with_internal_e = '';
        if (new_strlen($data['warehouse_id']) > 0) {
            $arr_warehouse_id =  new_explode(',', $data['warehouse_id']);

            foreach ($arr_warehouse_id as $warehouse_id) {
                if ($warehouse_id != '') {

                    if ($where_warehouse_id == '') {
                        $where_warehouse_id .= ' (find_in_set('.$warehouse_id.', '.db_prefix().'goods_transaction_detail.warehouse_id) OR find_in_set('.$warehouse_id.', '.db_prefix().'goods_transaction_detail.to_stock_name) OR find_in_set('.$warehouse_id.', '.db_prefix().'goods_transaction_detail.from_stock_name)';

                        $where_warehouse_id_with_internal_i .= ' (find_in_set('.$warehouse_id.', '.db_prefix().'goods_transaction_detail.warehouse_id) OR find_in_set('.$warehouse_id.', '.db_prefix().'goods_transaction_detail.to_stock_name)';

                        $where_warehouse_id_with_internal_e .= ' (find_in_set('.$warehouse_id.', '.db_prefix().'goods_transaction_detail.warehouse_id) OR find_in_set('.$warehouse_id.', '.db_prefix().'goods_transaction_detail.from_stock_name)';
                        


                    } else {
                        $where_warehouse_id .= ' or find_in_set('.$warehouse_id.', '.db_prefix().'goods_transaction_detail.warehouse_id) OR find_in_set('.$warehouse_id.', '.db_prefix().'goods_transaction_detail.to_stock_name) OR find_in_set('.$warehouse_id.', '.db_prefix().'goods_transaction_detail.from_stock_name)';

                        $where_warehouse_id_with_internal_i .= ' or find_in_set('.$warehouse_id.', '.db_prefix().'goods_transaction_detail.warehouse_id) OR find_in_set('.$warehouse_id.', '.db_prefix().'goods_transaction_detail.to_stock_name) ';

                        $where_warehouse_id_with_internal_e .= ' or find_in_set('.$warehouse_id.', '.db_prefix().'goods_transaction_detail.warehouse_id) OR find_in_set('.$warehouse_id.', '.db_prefix().'goods_transaction_detail.from_stock_name) ';
                        
                    }

                }
            }

            if ($where_warehouse_id != '') {
                $where_warehouse_id .= ')';

                $where_warehouse_id_with_internal_i .= ')';
                $where_warehouse_id_with_internal_e .= ')';
            }
        }

        $where_commodity_id = '';
        if (new_strlen($data['commodity_id']) > 0) {
            $arr_commodity_id =  new_explode(',', $data['commodity_id']);

            foreach ($arr_commodity_id as $commodity_id) {
                if ($commodity_id != '') {

                    if ($where_commodity_id == '') {
                        $where_commodity_id .= ' (find_in_set('.$commodity_id.', '.db_prefix().'goods_transaction_detail.commodity_id) ';
                    } else {
                        $where_commodity_id .= ' or find_in_set('.$commodity_id.', '.db_prefix().'goods_transaction_detail.commodity_id) ';
                    }

                }
            }

            if ($where_commodity_id != '') {
                $where_commodity_id .= ')';
            }
        }

        if($where_commodity_id != ''){
            if($where_warehouse_id != ''){
                $where_warehouse_id .= ' AND '.$where_commodity_id;

                $where_warehouse_id_with_internal_i .= ' AND '.$where_commodity_id;
                $where_warehouse_id_with_internal_e .= ' AND '.$where_commodity_id;
            }else{
                $where_warehouse_id .= $where_commodity_id;

                $where_warehouse_id_with_internal_i .= $where_commodity_id;
                $where_warehouse_id_with_internal_e .= $where_commodity_id;
            }

        }



        //get_commodity_list in warehouse
        if (new_strlen($where_warehouse_id) > 0) {
            $commodity_lists = $this->db->query('SELECT commodity_id, ' . db_prefix() . 'items.commodity_code, ' . db_prefix() . 'items.rate, ' . db_prefix() . 'items.description as commodity_name, ' . db_prefix() . 'ware_unit_type.unit_name FROM ' . db_prefix() . 'goods_transaction_detail
                LEFT JOIN ' . db_prefix() . 'items ON ' . db_prefix() . 'goods_transaction_detail.commodity_id = ' . db_prefix() . 'items.id
                LEFT JOIN ' . db_prefix() . 'ware_unit_type ON ' . db_prefix() . 'items.unit_id = ' . db_prefix() . 'ware_unit_type.unit_type_id where 1=1 AND  '.$where_warehouse_id. ' AND '.db_prefix().'items.active = 1 group by commodity_id')->result_array();

        }else{

            $commodity_lists = $this->db->query('SELECT commodity_id, ' . db_prefix() . 'items.commodity_code, ' . db_prefix() . 'items.rate, ' . db_prefix() . 'items.description as commodity_name, ' . db_prefix() . 'ware_unit_type.unit_name FROM ' . db_prefix() . 'goods_transaction_detail
                LEFT JOIN ' . db_prefix() . 'items ON ' . db_prefix() . 'goods_transaction_detail.commodity_id = ' . db_prefix() . 'items.id
                LEFT JOIN ' . db_prefix() . 'ware_unit_type ON ' . db_prefix() . 'items.unit_id = ' . db_prefix() . 'ware_unit_type.unit_type_id where '.db_prefix().'items.active = 1 group by commodity_id')->result_array();
        }

        //import_openings
        // status = 1 inventory receipt voucher, status = 4 internal delivery voucher
        if (new_strlen($where_warehouse_id) > 0) {
            $import_openings = $this->db->query('SELECT commodity_id, quantity as quantity , purchase_price, price, status, old_quantity FROM ' . db_prefix() . 'goods_transaction_detail
                where ( status = 1 OR status = 4 OR status = 3) AND date_format(date_add,"%Y-%m-%d") < "' . $from_date . '" AND '. $where_warehouse_id_with_internal_i)->result_array();

        }else{

            $import_openings = $this->db->query('SELECT commodity_id, quantity as quantity , purchase_price, price, status, old_quantity FROM ' . db_prefix() . 'goods_transaction_detail
                where ( status = 1 OR status = 4 OR status = 3) AND  date_format(date_add,"%Y-%m-%d") < "' . $from_date . '" ')->result_array();
        }


        $arr_import_openings = [];
        $arr_import_openings_amount = [];
        foreach ($import_openings as $import_opening_key => $import_opening_value) {
            if(isset($arr_import_openings[$import_opening_value['commodity_id']])){

                switch ($import_opening_value['status']) {
                    case '1':
                    $arr_import_openings_amount[$import_opening_value['commodity_id']] += (float)$import_opening_value['quantity']*(float)$import_opening_value['purchase_price'];
                    $arr_import_openings[$import_opening_value['commodity_id']]        += (float)$import_opening_value['quantity'];
                    break;
                    case '3':
                    if(((float)$import_opening_value['quantity'] - (float)$import_opening_value['old_quantity']) > 0){

                        $arr_import_openings_amount[$import_opening_value['commodity_id']] += ((float)$import_opening_value['quantity'] - (float)$import_opening_value['old_quantity'])*(float)$import_opening_value['purchase_price'];
                        $arr_import_openings[$import_opening_value['commodity_id']]        += ((float)$import_opening_value['quantity'] - (float)$import_opening_value['old_quantity']);
                    }
                    break;
                    case '4':
                    $arr_import_openings_amount[$import_opening_value['commodity_id']] += (float)$import_opening_value['quantity']*(float)$import_opening_value['purchase_price'];
                    $arr_import_openings[$import_opening_value['commodity_id']]        += (float)$import_opening_value['quantity'];

                    break;
                    
                }


            }else{
                switch ($import_opening_value['status']) {
                    case '1':
                    $arr_import_openings_amount[$import_opening_value['commodity_id']] = (float)$import_opening_value['quantity']*(float)$import_opening_value['purchase_price'];
                    $arr_import_openings[$import_opening_value['commodity_id']]        = (float)$import_opening_value['quantity'];
                    break;
                    case '3':
                    if(((float)$import_opening_value['quantity'] - (float)$import_opening_value['old_quantity']) > 0){

                        $arr_import_openings_amount[$import_opening_value['commodity_id']] = ((float)$import_opening_value['quantity'] - (float)$import_opening_value['old_quantity'])*(float)$import_opening_value['purchase_price'];
                        $arr_import_openings[$import_opening_value['commodity_id']]        = ((float)$import_opening_value['quantity'] - (float)$import_opening_value['old_quantity']);
                    }
                    break;
                    case '4':
                    $arr_import_openings_amount[$import_opening_value['commodity_id']] = (float)$import_opening_value['quantity']*(float)$import_opening_value['purchase_price'];
                    $arr_import_openings[$import_opening_value['commodity_id']]        = (float)$import_opening_value['quantity'];

                    break;
                    
                }

            }
        }


        //export_openings
        if (new_strlen($where_warehouse_id) > 0) {
            $export_openings = $this->db->query('SELECT commodity_id, quantity as quantity , purchase_price, price, status, old_quantity FROM ' . db_prefix() . 'goods_transaction_detail
                where ( status = 2 OR status = 4 OR status = 3 ) AND date_format(date_add,"%Y-%m-%d") < "' . $from_date . '" AND '.$where_warehouse_id_with_internal_e)->result_array();

        }else{

            $export_openings = $this->db->query('SELECT commodity_id, quantity as quantity , purchase_price, price, status, old_quantity FROM ' . db_prefix() . 'goods_transaction_detail
                where ( status = 2 OR status = 4 OR status = 3 ) AND date_format(date_add,"%Y-%m-%d") < "' . $from_date . '" ')->result_array();
        }

        $arr_export_openings = [];
        $arr_export_openings_amount = [];
        foreach ($export_openings as $export_opening_key => $export_opening_value) {
            //get purchase price of item, before version get sales price.
            
            if($export_opening_value['purchase_price'] != null){
                $purchase_price = $export_opening_value['purchase_price'];
            }else{
                $purchase_price = $this->warehouse_model->get_purchase_price_from_commodity_id($export_opening_value['commodity_id']);
            }

            if(isset($arr_export_openings[$export_opening_value['commodity_id']])){
                switch ($export_opening_value['status']) {
                    case '2':
                    $arr_export_openings_amount[$export_opening_value['commodity_id']] += (float)$export_opening_value['quantity']*(float)$purchase_price;
                    $arr_export_openings[$export_opening_value['commodity_id']]        += (float)$export_opening_value['quantity'];
                    break;
                    case '3':
                    if(((float)$export_opening_value['quantity'] - (float)$export_opening_value['old_quantity']) < 0){

                        $arr_export_openings_amount[$export_opening_value['commodity_id']] += abs((float)$export_opening_value['quantity'] - (float)$export_opening_value['old_quantity'])*(float)$purchase_price;
                        $arr_export_openings[$export_opening_value['commodity_id']]        += abs((float)$export_opening_value['quantity'] - (float)$export_opening_value['old_quantity']);
                    }
                    break;
                    case '4':
                    $arr_export_openings_amount[$export_opening_value['commodity_id']] += (float)$export_opening_value['quantity']*(float)$purchase_price;
                    $arr_export_openings[$export_opening_value['commodity_id']]        += (float)$export_opening_value['quantity'];

                    break;
                    
                }

                
            }else{
                switch ($export_opening_value['status']) {
                    case '2':
                    $arr_export_openings_amount[$export_opening_value['commodity_id']] = (float)$export_opening_value['quantity']*(float)$purchase_price;
                    $arr_export_openings[$export_opening_value['commodity_id']]        = (float)$export_opening_value['quantity'];
                    break;
                    case '3':
                    if(((float)$export_opening_value['quantity'] - (float)$export_opening_value['old_quantity']) < 0){

                        $arr_export_openings_amount[$export_opening_value['commodity_id']] = abs((float)$export_opening_value['quantity'] - (float)$export_opening_value['old_quantity'])*(float)$purchase_price;
                        $arr_export_openings[$export_opening_value['commodity_id']]        = abs((float)$export_opening_value['quantity'] - (float)$export_opening_value['old_quantity']);
                    }
                    break;
                    case '4':
                    $arr_export_openings_amount[$export_opening_value['commodity_id']] = (float)$export_opening_value['quantity']*(float)$purchase_price;
                    $arr_export_openings[$export_opening_value['commodity_id']]        = (float)$export_opening_value['quantity'];

                    break;
                    
                }
            }
        }

        $total_opening_amount = 0;
        foreach ($commodity_lists as $commodity_list_key => $commodity_list) {
            $commodity_list_key++;
           
            $stock_opening_amount = 0;

            $import_opening_amount = isset($arr_import_openings_amount[$commodity_list['commodity_id']]) ? $arr_import_openings_amount[$commodity_list['commodity_id']] : 0;

            $export_opening_amount = isset($arr_export_openings_amount[$commodity_list['commodity_id']]) ? $arr_export_openings_amount[$commodity_list['commodity_id']] : 0;
            

            $stock_opening_amount = (float)$import_opening_amount - (float)$export_opening_amount;
            $total_opening_amount += $stock_opening_amount;

        }
      
        return $total_opening_amount;

    }

    function pur_invoice_amount_left($id){
        $total = 0;

        $this->db->where('id', $id);
        $pur_invoices = $this->db->get(db_prefix().'pur_invoices')->row();

        if($pur_invoices){
            $total = $pur_invoices->total;
        }

        $this->db->select_sum('amount');
        $this->db->where('pur_invoice', $id);
        $this->db->where('approval_status', 2);
        $invoice_payment = $this->db->get(db_prefix().'pur_invoice_payment')->row();
        $totalPayments = $invoice_payment->amount;

        if($total <= $totalPayments){
            return 0;
        }else{
            return round(($total - $totalPayments), 2);
        }
    }

    public function undo_banking_rule($id)
    {
        $this->db->where('id', $id);
        $this->db->update(db_prefix() . 'acc_transaction_bankings', ['matched' => 0, 'reconcile' => 0, 'banking_rule' => 0]);
        if ($this->db->affected_rows() > 0) {

            $this->db->where('rel_id', $id);
            $this->db->where('rel_type', 'banking');
            $this->db->delete(db_prefix() . 'acc_matched_transactions');

            $this->db->where('rel_id', $id);
            $this->db->where('rel_type', 'banking');
            $this->db->delete(db_prefix() . 'acc_account_history');

            return true;
        }
        return false;
    }
    
    public function check_return_order($goods_receipt_id){
        $wh_order_returns = $this->db->where('receipt_delivery_id', $goods_receipt_id)->get(db_prefix().'wh_order_returns')->row();

        if($wh_order_returns){
            return $wh_order_returns->rel_id;
        }

        return false;

    }

    /**
     * check auto create currency rate
     * @return [type]
     */
    public function check_auto_create_currency_rate() {
        $this->load->model('currencies_model');
        $currency_rates = $this->get_currency_rate();
        $currencies = $this->currencies_model->get();
        $currency_generator = $this->currency_generator($currencies);

        foreach ($currency_rates as $key => $currency_rate) {
            if (isset($currency_generator[$currency_rate['from_currency_id'] . '_' . $currency_rate['to_currency_id']])) {
                unset($currency_generator[$currency_rate['from_currency_id'] . '_' . $currency_rate['to_currency_id']]);
            }
        }

        //if have API, will get currency rate from here
        if (count($currency_generator) > 0) {
            $this->db->insert_batch(db_prefix() . 'currency_rates', $currency_generator);
        }

        return true;
    }

    /**
     * currency generator
     * @param  $variants
     * @param  integer $i
     * @return 
     */
    public function currency_generator($currencies) {

        $currency_rates = [];

        foreach ($currencies as $key_1 => $value_1) {
            foreach ($currencies as $key_2 => $value_2) {
                if ($value_1['id'] != $value_2['id']) {
                    $currency_rates[$value_1['id'] . '_' . $value_2['id']] = [
                        'from_currency_id' => $value_1['id'],
                        'from_currency_name' => $value_1['name'],
                        'from_currency_rate' => 1,
                        'to_currency_id' => $value_2['id'],
                        'to_currency_name' => $value_2['name'],
                        'to_currency_rate' => 0,
                        'date_updated' => date('Y-m-d H:i:s'),
                    ];
                }

            }
        }

        return $currency_rates;
    }

    /**
     * get currency rate
     * @param  boolean $id
     * @return [type]
     */
    public function get_currency_rate($id = false) {
        if (is_numeric($id)) {
            $this->db->where('id', $id);
            return $this->db->get(db_prefix() . 'currency_rates')->row();
        }

        if ($id == false) {
            return $this->db->query('select * from ' . db_prefix() . 'currency_rates')->result_array();
        }
    }

    /**
     * update currency rate setting
     *
     * @param      array   $data   The data
     *
     * @return     boolean
     */
    public function update_setting_currency_rate($data) {
        $affectedRows = 0;
        if (!isset($data['cr_automatically_get_currency_rate'])) {
            $data['cr_automatically_get_currency_rate'] = 0;
        }

        foreach ($data as $key => $value) {
            $this->db->where('name', $key);
            $this->db->update(db_prefix() . 'options', [
                'value' => $value,
            ]);
            if ($this->db->affected_rows() > 0) {
                $affectedRows++;
            }
        }

        if ($affectedRows > 0) {
            return true;
        }
        return false;
    }

    /**
     * Gets the currency rate online.
     *
     * @param        $id     The identifier
     *
     * @return     bool    The currency rate online.
     */
    public function get_currency_rate_online($id) {
        $currency_rate = $this->get_currency_rate($id);

        if ($currency_rate) {
            return $this->currency_converter($currency_rate->from_currency_name, $currency_rate->to_currency_name);
        }

        return false;
    }

    /**
     * Gets all currency rate online.
     *
     * @return     bool  All currency rate online.
     */
    public function get_all_currency_rate_online() {
        $currency_rates = $this->get_currency_rate();
        $affectedRows = 0;
        foreach ($currency_rates as $currency_rate) {
            $rate = $this->currency_converter($currency_rate['from_currency_name'], $currency_rate['to_currency_name']);

            $data_update = ['to_currency_rate' => $rate];
            $success = $this->update_currency_rate($data_update, $currency_rate['id']);

            if ($success) {
                $affectedRows++;
            }
        }

        if ($affectedRows > 0) {
            return true;
        }

        return true;
    }

    /**
     * update currency rate
     * @param  [type] $data
     * @return [type]
     */
    public function update_currency_rate($data, $id) {

        $this->db->where('id', $id);
        $this->db->update(db_prefix() . 'currency_rates', ['to_currency_rate' => $data['to_currency_rate'], 'date_updated' => date('Y-m-d H:i:s')]);
        if ($this->db->affected_rows() > 0) {
            $this->db->where('id', $id);
            $current_rate = $this->db->get(db_prefix() . 'currency_rates')->row();

            $data_log['from_currency_id'] = $current_rate->from_currency_id;
            $data_log['from_currency_name'] = $current_rate->from_currency_name;
            $data_log['to_currency_id'] = $current_rate->to_currency_id;
            $data_log['to_currency_name'] = $current_rate->to_currency_name;
            $data_log['from_currency_rate'] = isset($data['from_currency_rate']) ? $data['from_currency_rate'] : '';
            $data_log['to_currency_rate'] = isset($data['to_currency_rate']) ? $data['to_currency_rate'] : '';
            $data_log['date'] = date('Y-m-d H:i:s');
            $this->db->insert(db_prefix() . 'currency_rate_logs', $data_log);
            return true;
        }
        return false;
    }

    /**
     * delete currency rate
     * @param  [type] $id
     * @return [type]
     */
    public function delete_currency_rate($id) {
        $this->db->where('id', $id);
        $this->db->delete(db_prefix() . 'currency_rates');
        if ($this->db->affected_rows() > 0) {
            return true;
        }
        return false;
    }

    /**
     * { cronjob currency rates }
     *
     * @param        $manually  The manually
     *
     * @return     bool    
     */
    public function cronjob_currency_rates($manually) {
        $currency_rates = $this->get_currency_rate();
        foreach ($currency_rates as $currency_rate) {
            $data_insert = $currency_rate;
            $data_insert['date'] = date('Y-m-d');
            unset($data_insert['date_updated']);
            unset($data_insert['id']);

            $this->db->insert(db_prefix() . 'currency_rate_logs', $data_insert);
        }

        if (get_option('cr_automatically_get_currency_rate') == 1) {
            $this->get_all_currency_rate_online();
        }

        $asm_global_amount_expiration = get_option('cr_global_amount_expiration');
        if ($asm_global_amount_expiration != 0 && $asm_global_amount_expiration != '') {
            $this->db->where('date < "' . date('Y-m-d', strtotime(date('Y-m-d') . ' - ' . $asm_global_amount_expiration . ' days')).'"');
            $this->db->delete(db_prefix() . 'currency_rate_logs');
        }
        update_option('cr_date_cronjob_currency_rates', date('Y-m-d'));

        return true;
    }

    public function get_old_currency_rate($rel_id, $rel_type) {
        $this->db->where('rel_id', $rel_id);
        $this->db->where('rel_type', $rel_type);
        $account_history = $this->db->get(db_prefix(). 'acc_account_history')->row();
        
        if($account_history)
        {
            return $account_history->currency_rate;
        }

        return 0;
    }

    public function get_mapping_transaction_ids($rel_type) {
        $this->db->where('rel_type', $rel_type);
        $account_history = $this->db->get(db_prefix(). 'acc_account_history')->result_array();
    
        $arr_ids = [];

        if($account_history)
        {
            foreach ($account_history as $key => $value) {
                $arr_ids[] = $value['rel_id'];
            }

        }

        return $arr_ids;
    }

    public function recurring_journal_entry()
    {

        $auto_operation_hour = 9;
        $hour_now            = date('G');
        if ($hour_now != $auto_operation_hour) {
            return;
        }

        $this->db->from(db_prefix() . 'acc_journal_entries');
        $this->db->where('recurring !=', 0);
        $this->db->where('(cycles != total_cycles OR cycles=0)');
        $journal_entries = $this->db->get()->result_array();

        $_renewals_ids_data = [];
        $total_renewed      = 0;
        foreach ($journal_entries as $journal_entry) {

            // Current date
            $date = new DateTime(date('Y-m-d'));
            // Check if is first recurring
            if (!$journal_entry['last_recurring_date']) {
                $last_recurring_date = date('Y-m-d', strtotime($journal_entry['journal_date']));
            } else {
                $last_recurring_date = date('Y-m-d', strtotime($journal_entry['last_recurring_date']));
            }
            if ($journal_entry['custom_recurring'] == 0) {
                $journal_entry['recurring_type'] = 'MONTH';
            }

            $re_create_at = date('Y-m-d', strtotime('+' . $journal_entry['recurring'] . ' ' . strtoupper($journal_entry['recurring_type']), strtotime($last_recurring_date)));

            if (date('Y-m-d') >= $re_create_at) {

                // Recurring invoice date is okey lets convert it to new invoice
                $_journal_entry                    = $this->get_journal_entry($journal_entry['id']);
                $new_journal_entry_data             = [];
                $new_journal_entry_data['number']   = $this->get_journal_entry_next_number();
                $new_journal_entry_data['journal_date']     = $re_create_at;
                $new_journal_entry_data['amount']       = $_journal_entry->amount;
                $new_journal_entry_data['datecreated'] = date('Y-m-d H-i-s');
                $new_journal_entry_data['addedfrom']         = $_journal_entry->addedfrom;
                $new_journal_entry_data['description']            = clear_textarea_breaks($_journal_entry->description);
                $new_journal_entry_data['is_recurring_from']     = $_journal_entry->id;

                $this->db->insert(db_prefix().'acc_journal_entries', $new_journal_entry_data);
                $insert_id = $this->db->insert_id();
                
                if($insert_id){
                    $data_insert = [];

                    foreach ($_journal_entry->details as $key => $value) {
                        $node = [];
                        $node['account'] = $value['account'];
                        $node['date'] = $re_create_at;
                        $node['number'] = $new_journal_entry_data['number'];
                        $node['debit'] = $value['debit'];
                        $node['credit'] = $value['credit'];
                        $node['description'] = $value['description'];
                        $node['rel_id'] = $insert_id;
                        $node['rel_type'] = 'journal_entry';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = $value['addedfrom'];

                        $data_insert[] = $node;
                    }
                    
                    $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
                    
                    // Update last recurring date to this invoice
                    $this->db->where('id', $journal_entry['id']);
                    $this->db->update(db_prefix() . 'acc_journal_entries', [
                        'last_recurring_date' => $re_create_at,
                    ]);

                    $this->db->where('id', $journal_entry['id']);
                    $this->db->set('total_cycles', 'total_cycles+1', false);
                    $this->db->update(db_prefix() . 'acc_journal_entries');

                }

            }
        }
    }

    public function recurring_journal_entry_by_id($id)
    {
        $this->db->from(db_prefix() . 'acc_journal_entries');
        $this->db->where('id', $id);
        $this->db->where('recurring !=', 0);
        $this->db->where('(cycles != total_cycles OR cycles=0)');
        $journal_entry = $this->db->get()->row();
        if($journal_entry){
            $journal_entry = (array) $journal_entry;

            // Check if is first recurring
            if (!$journal_entry['last_recurring_date']) {
                $last_recurring_date = date('Y-m-d', strtotime($journal_entry['journal_date']));
            } else {
                $last_recurring_date = date('Y-m-d', strtotime($journal_entry['last_recurring_date']));
            }
            if ($journal_entry['custom_recurring'] == 0) {
                $journal_entry['recurring_type'] = 'MONTH';
            }

            $re_create_at = date('Y-m-d', strtotime('+' . $journal_entry['recurring'] . ' ' . strtoupper($journal_entry['recurring_type']), strtotime($last_recurring_date)));

            if (date('Y-m-d') >= $re_create_at) {
                // Recurring invoice date is okey lets convert it to new invoice
                $_journal_entry                    = $this->get_journal_entry($journal_entry['id']);
                $new_journal_entry_data             = [];
                $new_journal_entry_data['number']   = $this->get_journal_entry_next_number();
                $new_journal_entry_data['journal_date']     = $re_create_at;
                $new_journal_entry_data['amount']       = $_journal_entry->amount;
                $new_journal_entry_data['datecreated'] = date('Y-m-d H-i-s');
                $new_journal_entry_data['addedfrom']         = $_journal_entry->addedfrom;
                $new_journal_entry_data['is_recurring_from']     = $_journal_entry->id;

                $this->db->insert(db_prefix().'acc_journal_entries', $new_journal_entry_data);
                $insert_id = $this->db->insert_id();
                
                if($insert_id){
                    $data_insert = [];

                    foreach ($_journal_entry->details as $key => $value) {
                        $node = [];
                        $node['account'] = $value['account'];
                        $node['date'] = $re_create_at;
                        $node['number'] = $new_journal_entry_data['number'];
                        $node['debit'] = $value['debit'];
                        $node['credit'] = $value['credit'];
                        $node['description'] = $value['description'];
                        $node['rel_id'] = $insert_id;
                        $node['rel_type'] = 'journal_entry';
                        $node['datecreated'] = date('Y-m-d H:i:s');
                        $node['addedfrom'] = $value['addedfrom'];

                        $data_insert[] = $node;
                    }
                    
                    $this->db->insert_batch(db_prefix().'acc_account_history', $data_insert);
                    
                    // Update last recurring date to this invoice
                    $this->db->where('id', $journal_entry['id']);
                    $this->db->update(db_prefix() . 'acc_journal_entries', [
                        'last_recurring_date' => $re_create_at,
                    ]);

                    $this->db->where('id', $journal_entry['id']);
                    $this->db->set('total_cycles', 'total_cycles+1', false);
                    $this->db->update(db_prefix() . 'acc_journal_entries');

                    $this->recurring_journal_entry_by_id($id);
                }
            }
        }
    }

    public function add_transaction_save($data){
        $transaction_banking = $this->get_transaction_banking($data['transaction_bank_id']);

        $node = [];
        $node['split'] = $transaction_banking->bank_id;
        $node['account'] = $data['account'];
        $node['vendor'] = $data['vendor'] != '' ? $data['vendor'] : 0;
        $node['customer'] = $data['customer'] != '' ? $data['customer'] : 0;
        $node['debit'] = $transaction_banking->withdrawals;
        $node['date'] = $transaction_banking->date;
        $node['credit'] = $transaction_banking->deposits;
        $node['bank_reconcile'] = $data['transaction_bank_id'];
        $node['tax'] = 0;
        $node['cleared'] = 1;
        $node['description'] = $transaction_banking->description;
        $node['rel_id'] = $data['transaction_bank_id'];
        $node['rel_type'] = 'banking';
        $node['datecreated'] = date('Y-m-d H:i:s');
        $node['addedfrom'] = get_staff_user_id();
        $node['added_from_reconcile'] = 1;

        $this->db->insert(db_prefix().'acc_account_history', $node);

        $node = [];
        $node['split'] = $data['account'];
        $node['account'] = $transaction_banking->bank_id;
        $node['vendor'] = $data['vendor'] != '' ? $data['vendor'] : 0;
        $node['customer'] = $data['customer'] != '' ? $data['customer'] : 0;
        $node['debit'] = $transaction_banking->deposits;
        $node['date'] = $transaction_banking->date;
        $node['credit'] = $transaction_banking->withdrawals;
        $node['bank_reconcile'] = $data['transaction_bank_id'];
        $node['tax'] = 0;
        $node['cleared'] = 1;
        $node['description'] = $transaction_banking->description;
        $node['rel_id'] = $data['transaction_bank_id'];
        $node['rel_type'] = 'banking';
        $node['datecreated'] = date('Y-m-d H:i:s');
        $node['addedfrom'] = get_staff_user_id();
        $node['added_from_reconcile'] = 1;

        $this->db->insert(db_prefix().'acc_account_history', $node);

        $insert_id = $this->db->insert_id();

        if ($insert_id) {
            $this->db->where('id', $data['transaction_bank_id']);
            $this->db->update(db_prefix().'acc_transaction_bankings', [
                'adjusted' => 1,
                'matched' => 1,
                'reconcile' => 1,
            ]);

            return true;
        }

        return false;
    }

    public function match_transaction_save($data){
        $this->db->where('id', $data['transaction']);
        $account_history = $this->db->get(db_prefix().'acc_account_history')->row();
        $withdrawal = str_replace(',', '', $data['withdrawal']);
        $deposit = str_replace(',', '', $data['deposit']);
        if($withdrawal > 0){
            $amount = $withdrawal;
        }else{
            $amount = $deposit;
        }

        if ($account_history) {
            $this->db->where('id', $data['transaction']);
            $this->db->update(db_prefix().'acc_account_history', [
                'bank_reconcile' => $data['transaction_bank_id'],
                'cleared' => 1,
                'date' => to_sql_date($data['date']),
                'credit' => $withdrawal,
                'debit' => $deposit,
            ]);
           
            if($this->db->affected_rows() > 0){
                // if($account_history->debit != $deposit || $account_history->credit != $withdrawal){
                //     switch ($account_history->rel_type) {
                //         case 'payment':
                //             $this->load->model('payments_model');
                //             $this->payments_model->update(['amount' => $amount, 'date' => _d($data['date']), 'note' => ''], $account_history->rel_id);
                //             break;
                //         case 'invoice':
                //             $this->load->model('payments_model');
                //             $this->invoices_model->update(['amount' => $amount, 'date' => _d($data['date']), 'note' => ''], $account_history->rel_id);
                //             break;
                //         case 'bill':
                //             // code...
                //             break;
                //         case 'pay_bill':
                //             // code...
                //             break;
                //         case 'check':
                //             // code...
                //             break;
                        
                //         default:
                //             // code...
                //             break;
                //     }
                // }

                $this->db->where('id', $data['transaction_bank_id']);
                $this->db->update(db_prefix().'acc_transaction_bankings', [
                    'adjusted' => 1,
                    'matched' => 1,
                    'reconcile' => 1,
                ]);

                return true;
            }
        }

        return false;
    }


    public function unmatch_transaction($transaction_bank_id){
        $affected_rows = 0;

        $this->db->where('added_from_reconcile', 1);
        $this->db->where('bank_reconcile', $transaction_bank_id);
        $this->db->delete(db_prefix().'acc_account_history');
        if ($this->db->affected_rows() > 0) {
            $affected_rows++;
        }

        $this->db->where('bank_reconcile', $transaction_bank_id);
        $this->db->update(db_prefix().'acc_account_history', ['bank_reconcile' => 0, 'cleared' => 0]);
        if ($this->db->affected_rows() > 0) {
            $affected_rows++;
        }

        
        $this->db->where('id', $transaction_bank_id);
        $this->db->update(db_prefix().'acc_transaction_bankings', [
                    'adjusted' => 0,
                    'reconcile' => 0,
                    'matched' => 0,
                ]);

        if ($this->db->affected_rows() > 0) {
            $affected_rows++;
        }


        if($affected_rows > 0){
            return true;
        }
        
        return false;
    }
}
