KUJUNTI.ID MINISH3LL
Path : /var/www/html/thb_loan_system/app/Http/Controllers/
(S)h3ll Cr3at0r :
F!le Upl0ad :

B-Con CMD Config cPanel C-Rdp D-Log Info Jump Mass Ransom Symlink vHost Zone-H

Current File : /var/www/html/thb_loan_system/app/Http/Controllers/LoanController.php


<?php

namespace App\Http\Controllers;

use Carbon\Carbon;
use App\Events\InterestWaived;
use App\Events\LoanTransactionUpdated;
use App\Events\RepaymentCreated;
use App\Events\RepaymentReversed;
use App\Events\PayOffReversed;
use App\Events\RepaymentUpdated;
use App\Helpers\GeneralHelper;
use App\Models\Capital;
use App\Models\CustomField;
use App\Models\CustomFieldMeta;
use App\Models\Email;
use App\Models\Guarantor;
use App\Models\JournalEntry;
use App\Models\Loan;
use App\Models\LoanApplication;
use App\Models\LoanCharge;
use App\Models\LoanFee;
use App\Models\LoanGuarantor;
use App\Models\LoanOverduePenalty;
use App\Models\LoanProduct;
use App\Models\LoanProductCharge;
use App\Models\LoanRepayment;
use App\Models\LoanRepaymentMethod;
use App\Models\LoanDisbursedBy;
use App\Models\Borrower;
use App\Models\LoanSchedule;
use App\Models\LoanTransaction;
use App\Models\Setting;
use App\Models\User;
use Cartalyst\Sentinel\Laravel\Facades\Sentinel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\View;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
use Laracasts\Flash\Flash;

class LoanController extends Controller
{
    public function __construct()
    {
        $this->middleware(['sentinel', 'branch']);
    }


    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        if (!Sentinel::hasAccess('loans')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $q = $request->q;
        if($q){
            $data = Loan::query()
            ->whereHas('borrower', function($query){
                return $query->search();
            })
            ->loan_total_penalty()
            ->loan_total_fees()
            ->loan_total_interest()
            ->loan_total_principal()
            ->loan_total_interest_waived()
            ->loan_total_pay_off()
            ->loan_total_paid()
            ->where('branch_id', session('branch_id'))
            ->with(['loan_product:id,name', 'borrower:id,first_name,last_name'])
            ->orderBy('id', 'desc')
            ->when($request->status, function ($query) use ($request) {
                $query->where(function ($query) use ($request) {
                    $query->where('status', '=', $request->status);
                });
            })
            ->paginate(default_paginate());
        }
        else{
            $data = Loan::query()
            ->loan_total_penalty()
            ->loan_total_fees()
            ->loan_total_interest()
            ->loan_total_principal()
            ->loan_total_interest_waived()
            ->loan_total_pay_off()
            ->loan_total_paid()
            ->where('branch_id', session('branch_id'))
            ->with(['loan_product:id,name', 'borrower:id,first_name,last_name'])
            ->orderBy('id', 'desc')
            ->when($request->status, function ($query) use ($request) {
                $query->where(function ($query) use ($request) {
                    $query->where('status', '=', $request->status);
                });
            })
            ->paginate(default_paginate());
        }

        return view('loan.data', compact('data'));
    }

    public function pending_approval(Request $request)
    {
        if (!Sentinel::hasAccess('loans')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        if (empty($request->status)) {
            $data = Loan::all();
        } else {
            $data = Loan::where('branch_id', session('branch_id'))->where('status', $request->status)->get();
        }

        return view('loan.data', compact('data'));
    }

    public function create(Request $request)
    {
        if (!Sentinel::hasAccess('loans.create')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $borrowers = array();
        foreach (Borrower::all() as $key) {
            $borrowers[$key->id] = $key->first_name . ' ' . $key->last_name . '(' . $key->unique_number . ')';
        }
        $users = [];
        foreach (User::all() as $key) {
            $users[$key->id] = $key->first_name . ' ' . $key->last_name;
        }
        $loan_products = array();
        foreach (LoanProduct::all() as $key) {
            $loan_products[$key->id] = $key->name;
        }
        $loan_disbursed_by = array();
        foreach (LoanDisbursedBy::all() as $key) {
            $loan_disbursed_by[$key->id] = $key->name;
        }
        if (isset($request->product_id)) {
            $loan_product = LoanProduct::find($request->product_id);
        } else {
            $loan_product = LoanProduct::first();
        }
        if (isset($request->borrower_id)) {
            $borrower_id = $request->borrower_id;
        } else {
            $borrower_id = '';
        }
        if (empty($loan_product)) {
            Flash::warning("No loan product set. You must first set a loan product");
            return redirect()->back();
        }
        $charges = array();
        foreach (LoanProductCharge::where('loan_product_id', $loan_product->id)->get() as $key) {
            if (!empty($key->charge)) {
                $charges[$key->id] = $key->charge->name;
            }
        }
        //get custom fields
        $custom_fields = CustomField::where('category', 'loans')->get();
        return view(
            'loan.create',
            compact(
                'borrowers',
                'loan_disbursed_by',
                'loan_products',
                'loan_product',
                'borrower_id',
                'custom_fields',
                'charges',
                'users'
            )
        );
    }

    public function reschedule(Request $request, $id)
    {
        if (!Sentinel::hasAccess('loans.reschedule')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();
        }
        $loan = Loan::find($id);
        $loan_products = array();
        foreach (LoanProduct::all() as $key) {
            $loan_products[$key->id] = $key->name;
        }

        $loan_disbursed_by = array();
        foreach (LoanDisbursedBy::all() as $key) {
            $loan_disbursed_by[$key->id] = $key->name;
        }
        if (isset($request->product_id)) {
            $loan_product = LoanProduct::find($request->product_id);
        } else {
            if (empty($loan->product)) {
                $loan_product = LoanProduct::first();
            } else {
                $loan_product = $loan->product;
            }
        }
        if (isset($request->borrower_id)) {
            $borrower_id = $request->borrower_id;
        } else {
            $borrower_id = '';
        }
        if (empty($loan_product)) {
            Flash::warning("No loan product set. You must first set a loan product");
            return redirect()->back();
        }
        $loan_due_items = GeneralHelper::loan_due_items($loan->id);
        $paid_items = GeneralHelper::loan_paid_items($loan->id);
        if ($request->type == 1) {
            $principal = $loan_due_items["principal"] + $loan_due_items["interest"] - $paid_items['principal'] - $paid_items['interest'];
        }
        if ($request->type == 2) {
            $principal = $loan_due_items["principal"] + $loan_due_items["interest"] + $loan_due_items["fees"] - $paid_items['principal'] - $paid_items['interest'] - $paid_items['fees'];
        }
        if ($request->type == 3) {
            $principal = GeneralHelper::loan_total_balance($id);
        }
        if ($request->type == 0) {
            $principal = $loan_due_items["principal"] - $paid_items['principal'];
        }
        $charges = array();
        foreach (LoanProductCharge::where('loan_product_id', $loan_product->id)->get() as $key) {
            if (!empty($key->charge)) {
                $charges[$key->id] = $key->charge->name;
            }
        }
        //get custom fields
        $custom_fields = CustomField::where('category', 'loans')->get();
        return view(
            'loan.reschedule',
            compact(
                'loan_disbursed_by',
                'loan_products',
                'loan_product',
                'borrower_id',
                'custom_fields',
                'charges',
                'principal',
                'loan'
            )
        );
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param \Illuminate\Http\Request $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {

        if (!Sentinel::hasAccess('loans.create')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan_product = LoanProduct::find($request->loan_product_id);
        if ($request->principal > $loan_product->maximum_principal) {
            Flash::warning(translate('principle_greater_than_maximum') . "(" . $loan_product->maximum_principal . ")");
            return redirect()->back()->withInput();
        }

        if ($request->principal < $loan_product->minimum_principal) {
            Flash::warning(translate('principle_less_than_minimum') . "(" . $loan_product->minimum_principal . ")");
            return redirect()->back()->withInput();
        }
        if ($request->interest_rate > $loan_product->maximum_interest_rate) {
            Flash::warning(translate('interest_greater_than_maximum') . "(" . $loan_product->maximum_interest_rate . ")");
            return redirect()->back()->withInput();
        }
        if ($request->interest_rate < $loan_product->minimum_interest_rate) {
            Flash::warning(translate('interest_less_than_minimum') . "(" . $loan_product->minimum_interest_rate . ")");
            return redirect()->back()->withInput();
        }
        /*
        if ($request->pay_off_interest_rate > $loan_product->maximum_interest_rate) {
            Flash::warning(translate('interest_greater_than_maximum') . "(" . $loan_product->maximum_interest_rate . ")");
            return redirect()->back()->withInput();
        }
        if ($request->pay_off_interest_rate < $loan_product->minimum_interest_rate) {
            Flash::warning(translate('interest_less_than_minimum') . "(" . $loan_product->minimum_interest_rate . ")");
            return redirect()->back()->withInput();
        }
        */

        $loan = new Loan();
        $loan->principal = $request->principal;
        $loan->interest_method = $request->interest_method;
        $loan->interest_rate = $request->interest_rate;
        $loan->pay_off_interest_rate = $request->pay_off_interest_rate != 0 ? $request->pay_off_interest_rate : $request->interest_rate;
        $loan->branch_id = session('branch_id');
        $loan->interest_period = $request->interest_period;
        $loan->loan_duration = $request->loan_duration;
        $loan->loan_duration_type = $request->loan_duration_type;
        $loan->repayment_cycle = $request->repayment_cycle;
        $loan->decimal_places = $request->decimal_places;
        $loan->override_interest = isset($request->override_interest) ? $request->override_interest : 0;
        $loan->override_interest_amount = isset($request->override_interest_amount) ? $request->override_interest_amount : 0;
        $loan->grace_on_interest_charged = isset($request->grace_on_interest_charged) ? $request->grace_on_interest_charged : 0;
        $loan->borrower_id = $request->borrower_id;
        $loan->applied_amount = $request->principal;
        $loan->loan_officer_id = $request->loan_officer_id;
        $loan->user_id = Sentinel::getUser()->id;
        $loan->loan_product_id = $request->loan_product_id;
        $loan->release_date = $request->release_date;
        $date = explode('-', $request->release_date);
        $loan->month = $date[1];
        $loan->year = $date[0];
        if (!empty($request->first_payment_date)) {
            $loan->first_payment_date = $request->first_payment_date;
        }
        $loan->description = $request->description;
        $files = array();
        if (!empty($request->file('files'))) {
            $count = 0;
            foreach ($request->file('files') as $key) {
                $file = array('files' => $key);
                $rules = array('files' => 'required|mimes:jpeg,jpg,bmp,png,pdf,docx,xlsx');
                $validator = Validator::make($file, $rules);
                if ($validator->fails()) {
                    Flash::warning(translate('validation_error'));
                    return redirect()->back()->withInput()->withErrors($validator);
                } else {
                    $fname = "loan_" . uniqid() . '.' . $key->guessExtension();
                    $files[$count] = $fname;
                    $key->move(
                        public_path() . '/uploads',
                        $fname
                    );
                }
                $count++;
            }
        }
        $loan->files = serialize($files);
        $loan->save();

        //save custom meta
        $custom_fields = CustomField::where('category', 'loans')->get();
        foreach ($custom_fields as $key) {
            $custom_field = new CustomFieldMeta();
            $id = $key->id;
            $custom_field->name = $request->$id;
            $custom_field->parent_id = $loan->id;
            $custom_field->custom_field_id = $key->id;
            $custom_field->category = "loans";
            $custom_field->save();
        }

        if (!empty($request->charges)) {
            //loop through the array
            foreach ($request->charges as $key) {
                $amount = "charge_amount_" . $key;
                $date = "charge_date_" . $key;
                $loan_charge = new LoanCharge();
                $loan_charge->loan_id = $loan->id;
                $loan_charge->user_id = Sentinel::getUser()->id;
                $loan_charge->charge_id = $key;
                $loan_charge->amount = $request->$amount;
                if (!empty($request->$date)) {
                    $loan_charge->date = $request->$date;
                }
                $loan_charge->save();
            }
        }


        $period = GeneralHelper::loan_period($loan->id);
        $loan = Loan::find($loan->id);
        if ($loan->repayment_cycle == 'daily') {
            $repayment_cycle = 'day';
            $loan->maturity_date = date_format(
                date_add(
                    date_create($request->first_payment_date),
                    date_interval_create_from_date_string($period . ' days')
                ),
                'Y-m-d'
            );
        }
        if ($loan->repayment_cycle == 'weekly') {
            $repayment_cycle = 'week';
            $loan->maturity_date = date_format(
                date_add(
                    date_create($request->first_payment_date),
                    date_interval_create_from_date_string($period . ' weeks')
                ),
                'Y-m-d'
            );
        }
        if ($loan->repayment_cycle == 'monthly') {
            $repayment_cycle = 'month';
            $loan->maturity_date = date_format(
                date_add(
                    date_create($request->first_payment_date),
                    date_interval_create_from_date_string($period . ' months')
                ),
                'Y-m-d'
            );
        }
        if ($loan->repayment_cycle == 'bi_monthly') {
            $repayment_cycle = 'month';
            $loan->maturity_date = date_format(
                date_add(
                    date_create($request->first_payment_date),
                    date_interval_create_from_date_string($period . ' months')
                ),
                'Y-m-d'
            );
        }
        if ($loan->repayment_cycle == 'quarterly') {
            $repayment_cycle = 'month';
            $loan->maturity_date = date_format(
                date_add(
                    date_create($request->first_payment_date),
                    date_interval_create_from_date_string($period . ' months')
                ),
                'Y-m-d'
            );
        }
        if ($loan->repayment_cycle == 'semi_annually') {
            $repayment_cycle = 'month';
            $loan->maturity_date = date_format(
                date_add(
                    date_create($request->first_payment_date),
                    date_interval_create_from_date_string($period . ' months')
                ),
                'Y-m-d'
            );
        }
        if ($loan->repayment_cycle == 'yearly') {
            $repayment_cycle = 'year';
            $loan->maturity_date = date_format(
                date_add(
                    date_create($request->first_payment_date),
                    date_interval_create_from_date_string($period . ' years')
                ),
                'Y-m-d'
            );
        }
        $loan->save();
        GeneralHelper::audit_trail("Added loan with id:" . $loan->id);
        Flash::success(translate('successfully_saved'));
        return redirect('loan/data');
    }


    public function show($loan)
    {
        $this->penalty();
        if (!Sentinel::hasAccess('loans.view')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan_disbursed_by = array();
        foreach (LoanDisbursedBy::all() as $key) {
            $loan_disbursed_by[$key->id] = $key->name;
        }
        $guarantors = array();
        foreach (Guarantor::all() as $key) {
            $guarantors[$key->id] = $key->first_name . ' ' . $key->last_name . '(' . $key->unique_number . ')';
        }
        foreach (LoanGuarantor::where('loan_id', $loan->id)->get() as $key) {
            $guarantors = array_except($guarantors, $key->id);
        }
        $schedules = LoanSchedule::where('loan_id', $loan->id)->orderBy('due_date', 'asc')->get();
        $loanCharges = LoanCharge::where('loan_id', $loan->id)->first();
        $loanChargesType = null;
        if($loanCharges){
            $loanChargesType = $loanCharges->charge?$loanCharges->charge->charge_option:null;
        }
        $custom_fields = CustomFieldMeta::where('category', 'loans')->where('parent_id', $loan->id)->get();
        return view(
            'loan.show',
            compact('loan', 'schedules', 'custom_fields', 'loan_disbursed_by', 'guarantors', 'loanCharges','loanChargesType')
        );
    }

    public function penalty()
    {
        //check for penalties
        //missed payment penalty
        $loans = Loan::where('status', 'disbursed')->get();
        foreach ($loans as $loan) {
            if (!empty($loan->loan_product)) {
                if ($loan->loan_product->enable_late_repayment_penalty == 1) {
                    $schedules = LoanSchedule::where('loan_id', $loan->id)->where(
                        'missed_penalty_applied',
                        0
                    )->orderBy('due_date', 'asc')->get();
                    foreach ($schedules as $schedule) {
                        if ($loan->loan_product->late_repayment_penalty_grace_period > 0) {
                            $date = date_format(
                                date_add(
                                    date_create($schedule->due_date),
                                    date_interval_create_from_date_string($loan->loan_product->late_repayment_penalty_grace_period . ' days')
                                ),
                                'Y-m-d'
                            );
                        } else {
                            $date = date("Y-m-d");
                        }
                        if ($date < date("Y-m-d")) {

                            if (
                                GeneralHelper::loan_total_due_period(
                                    $loan->id,
                                    $schedule->due_date
                                ) > GeneralHelper::loan_total_paid_period(
                                    $loan->id,
                                    $schedule->due_date
                                )
                            ) {
                                $sch = LoanSchedule::find($schedule->id);
                                $sch->missed_penalty_applied = 1;
                                //determine which amount to use
                                if ($loan->loan_product->late_repayment_penalty_type == "fixed") {
                                    $sch->penalty = $sch->penalty + $loan->loan_product->late_repayment_penalty_amount;
                                } else {
                                    if ($loan->loan_product->late_repayment_penalty_calculate == 'overdue_principal') {
                                        $principal = (GeneralHelper::loan_total_principal(
                                                $loan->id,
                                                $schedule->due_date
                                            ) - GeneralHelper::loan_paid_item(
                                                $loan->id,
                                                'principal',
                                                $schedule->due_date
                                            ));
                                        $sch->penalty = $sch->penalty + (($loan->loan_product->late_repayment_penalty_amount / 100) * $principal);
                                    }
                                    if ($loan->loan_product->late_repayment_penalty_calculate == 'overdue_principal_interest') {
                                        $principal = (GeneralHelper::loan_total_principal(
                                                $loan->id,
                                                $schedule->due_date
                                            ) + GeneralHelper::loan_total_interest(
                                                $loan->id,
                                                $schedule->due_date
                                            ) - GeneralHelper::loan_paid_item(
                                                $loan->id,
                                                'principal',
                                                $schedule->due_date
                                            ) - GeneralHelper::loan_paid_item(
                                                $loan->id,
                                                'interest',
                                                $schedule->due_date
                                            ));
                                        $sch->penalty = $sch->penalty + (($loan->loan_product->late_repayment_penalty_amount / 100) * $principal);
                                    }
                                    if ($loan->loan_product->late_repayment_penalty_calculate == 'overdue_principal_interest_fees') {
                                        $principal = (GeneralHelper::loan_total_principal(
                                                $loan->id,
                                                $schedule->due_date
                                            ) + GeneralHelper::loan_total_interest(
                                                $loan->id,
                                                $schedule->due_date
                                            ) + GeneralHelper::loan_total_fees(
                                                $loan->id,
                                                $schedule->due_date
                                            ) - GeneralHelper::loan_paid_item(
                                                $loan->id,
                                                'principal',
                                                $schedule->due_date
                                            ) - GeneralHelper::loan_paid_item(
                                                $loan->id,
                                                'interest',
                                                $schedule->due_date
                                            ) - GeneralHelper::loan_paid_item(
                                                $loan->id,
                                                'fees',
                                                $schedule->due_date
                                            ));
                                        $sch->penalty = $sch->penalty + (($loan->loan_product->late_repayment_penalty_amount / 100) * $principal);
                                    }
                                    if ($loan->loan_product->late_repayment_penalty_calculate == 'total_overdue') {
                                        $principal = (GeneralHelper::loan_total_due_amount(
                                                $loan->id,
                                                $schedule->due_date
                                            ) - GeneralHelper::loan_total_paid(
                                                $loan->id,
                                                $schedule->due_date
                                            ));
                                        $sch->penalty = $sch->penalty + (($loan->loan_product->late_repayment_penalty_amount / 100) * $principal);
                                    }
                                }
                                $sch->save();
                            }
                        }
                    }
                }
            }
        }
    }

    public function approve(Request $request, $id)
    {
        if (!Sentinel::hasAccess('loans.approve')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan = Loan::find($id);

        if (Sentinel::getUser()->max_approval < $loan->principal) {
            Flash::warning(translate('max_approval_exceed'));
            return redirect()->back();
        }
        $loan->status = 'approved';
        $loan->approved_date = $request->approved_date;
        $loan->approved_notes = $request->approved_notes;
        $loan->approved_by_id = Sentinel::getUser()->id;
        $loan->approved_amount = $request->approved_amount;
        $loan->principal = $request->approved_amount;
        $loan->save();
        GeneralHelper::audit_trail("Approved loan with id:" . $loan->id);
        Flash::success(translate('successfully_saved'));
        return redirect('loan/' . $id . '/show');
    }

    public function unapprove($id)
    {
        if (!Sentinel::hasAccess('loans.approve')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan = Loan::find($id);
        if (Sentinel::getUser()->max_approval < $loan->principal) {
            Flash::warning(translate('max_approval_exceed'));
            return redirect()->back();;
        }
        $loan->status = 'pending';
        $loan->save();
        GeneralHelper::audit_trail("Unapproved loan with id:" . $loan->id);
        Flash::success(translate('successfully_saved'));
        return redirect('loan/' . $id . '/show');
    }

    public function disburse(Request $request, $loan)
    {
        if (!Sentinel::hasAccess('loans.disburse')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan = Loan::find($loan->id);
        if (Sentinel::getUser()->max_approval < $loan->principal) {
            Flash::warning(translate('max_approval_exceed'));
            return redirect()->back();;
        }

        if ($request->first_payment_date < $request->disbursed_date) {
            Flash::warning(translate('disburse_date_greater_than_first_payment'));
            return redirect()->back()->withInput();
        }
        //delete previously created schedules and payments
        LoanRepayment::where('loan_id', $loan->id)->delete();
        LoanSchedule::where('loan_id', $loan->id)->delete();
        $interest_rate = GeneralHelper::determine_interest_rate($loan->id);
        $period = GeneralHelper::loan_period($loan->id);

        if ($loan->repayment_cycle == 'daily') {
            $repayment_cycle = '1 days';
            $repayment_type = 'days';
        }
        if ($loan->repayment_cycle == 'weekly') {
            $repayment_cycle = '1 weeks';
            $repayment_type = 'weeks';
        }
        if ($loan->repayment_cycle == 'monthly') {
            $repayment_cycle = 'month';
            $repayment_type = 'months';
        }
        if ($loan->repayment_cycle == 'bi_monthly') {
            $repayment_cycle = '2 months';
            $repayment_type = 'months';
        }
        if ($loan->repayment_cycle == 'quarterly') {
            $repayment_cycle = '4 months';
            $repayment_type = 'months';
        }
        if ($loan->repayment_cycle == 'semi_annually') {
            $repayment_cycle = '6 months';
            $repayment_type = 'months';
        }
        if ($loan->repayment_cycle == 'yearly') {
            $repayment_cycle = '1 years';
            $repayment_type = 'years';
        }
        if (empty($request->first_payment_date)) {
            $first_payment_date = date_format(
                date_add(
                    date_create($request->disbursed_date),
                    date_interval_create_from_date_string($repayment_cycle)
                ),
                'Y-m-d'
            );
        } else {
            $first_payment_date = $request->first_payment_date;
        }
        $loan->maturity_date = date_format(
            date_add(
                date_create($first_payment_date),
                date_interval_create_from_date_string($period . ' ' . $repayment_type)
            ),
            'Y-m-d'
        );
        $loan->status = 'disbursed';
        $loan->loan_disbursed_by_id = $request->loan_disbursed_by_id;
        $loan->disbursed_notes = $request->disbursed_notes;
        $loan->first_payment_date = $first_payment_date;
        $loan->disbursed_by_id = Sentinel::getUser()->id;
        $loan->disbursed_date = $request->disbursed_date;
        $loan->release_date = $request->disbursed_date;
        $dateDisbursed = explode('-', $request->disbursed_date);
        $loan->month = $dateDisbursed[1];
        $loan->year = $dateDisbursed[0];
        $loan->save();

        //generate schedules until period finished
        $next_payment = $first_payment_date;
        $balance = $loan->principal;
        $total_interest = 0;
        $isFullMonth = false;
        $isOverMonth = false;
        $amortizedPrincipal = $loan->principal;
        for ($i = 1; $i <= $period; $i++) {
            $loan_schedule = new LoanSchedule();
            $loan_schedule->loan_id = $loan->id;
            $loan_schedule->branch_id = session('branch_id');
            $loan_schedule->borrower_id = $loan->borrower_id;
            $loan_schedule->description = "Repayment";
            $loan_schedule->due_date = $next_payment;
            $datePayment = explode('-', $next_payment);
            $loan_schedule->month = $datePayment[1];
            $loan_schedule->year = $datePayment[0];
            //determine which method to use
            $due = 0;
            //reducing balance equal installments

            // if ($dateDisbursed[2] >= 16 && $dateDisbursed[2] != $datePayment[2]) {
            if ($dateDisbursed[2] != $datePayment[2]) {
                $diffDays = Carbon::parse($loan->disbursed_date)->diffInDays($first_payment_date);
                $days_of_first_month = Carbon::parse($first_payment_date)->daysInMonth;
            } else {
                $isFullMonth = true;
            }

            if ($loan->interest_method == 'declining_balance_equal_installments') {

                if ($i == 1 && !$isFullMonth) {
                    $principal = $balance / $period;
                    $interest = $balance * $interest_rate / $days_of_first_month * $diffDays;
                    $due = $principal + $interest;
                    $amortizedPrincipal = $balance - $principal;
                } else {
                    //$isFullMonth = $isOverMonth;
                    $due = GeneralHelper::amortized_monthly_payment($loan->id, $amortizedPrincipal, $isFullMonth);
                    $interest = ($interest_rate * $balance);
                    $principal = ($due - $interest);
                }

                $loan_schedule->principal = $principal;
                if ($loan->grace_on_interest_charged >= $i) {
                    $loan_schedule->interest = 0;
                } else {
                    $loan_schedule->interest = $interest;
                }

                $loan_schedule->due = $due;
                //determine next balance
                $balance = ($balance - ($due - $interest));
                $loan_schedule->principal_balance = $balance;
            }
            //reducing balance equal principle
            if ($loan->interest_method == 'declining_balance_equal_principal') {
                $principal = $loan->principal / $period;
                $loan_schedule->principal = ($principal);
                // $interest = ($interest_rate * ($balance));
                if ($i == 1 && !$isFullMonth) {
                    $interest = ((($interest_rate / $days_of_first_month) * $diffDays) * $balance);
                } else {
                    $interest = ($interest_rate * $balance);
                }
                if ($loan->grace_on_interest_charged >= $i) {
                    $loan_schedule->interest = 0;
                } else {
                    $loan_schedule->interest = $interest;
                }
                $loan_schedule->due = $principal + $interest;
                //determine next balance
                //$balance = ($balance - ($principal + $interest));
                $balance = ($balance - ($principal));
                $loan_schedule->principal_balance = $balance;
            }
            //flat  method
            if ($loan->interest_method == 'flat_rate') {
                $principal = $loan->principal / $period;
                // $interest = ($interest_rate * $loan->principal);
                if ($i == 1 && !$isFullMonth) {
                    $interest = ((($interest_rate / $days_of_first_month) * $diffDays) * $loan->principal);
                } else {
                    $interest = ($interest_rate * $loan->principal);
                }
                if ($loan->grace_on_interest_charged >= $i) {
                    $loan_schedule->interest = 0;
                } else {
                    $loan_schedule->interest = $interest;
                }
                $loan_schedule->principal = $principal;
                $loan_schedule->due = $principal + $interest;
                //determine next balance
                $balance = ($balance - $principal);
                $loan_schedule->principal_balance = $balance;
            }
            //interest only method
            if ($loan->interest_method == 'interest_only') {
                if ($i == $period) {
                    $principal = $loan->principal;
                } else {
                    $principal = 0;
                }
                // $interest = ($interest_rate * $loan->principal);
                if ($i == 1 && !$isFullMonth) {
                    $interest = ((($interest_rate / $days_of_first_month) * $diffDays) * $loan->principal);
                } else {
                    $interest = ($interest_rate * $loan->principal);
                }
                if ($loan->grace_on_interest_charged >= $i) {
                    $loan_schedule->interest = 0;
                } else {
                    $loan_schedule->interest = $interest;
                }
                $loan_schedule->principal = $principal;
                $loan_schedule->due = $principal + $interest;
                //determine next balance
                $balance = ($balance - $principal);
                $loan_schedule->principal_balance = $balance;
            }
            $total_interest = $total_interest + $interest;
            //determine next due date
            if ($loan->repayment_cycle == 'daily') {
                $next_payment = date_format(
                    date_add(
                        date_create($next_payment),
                        date_interval_create_from_date_string('1 days')
                    ),
                    'Y-m-d'
                );
            }
            if ($loan->repayment_cycle == 'weekly') {
                $next_payment = date_format(
                    date_add(
                        date_create($next_payment),
                        date_interval_create_from_date_string('1 weeks')
                    ),
                    'Y-m-d'
                );
            }
            if ($loan->repayment_cycle == 'monthly') {
                $next_payment = date_format(
                    date_add(
                        date_create($next_payment),
                        date_interval_create_from_date_string('1 months')
                    ),
                    'Y-m-d'
                );
            }
            if ($loan->repayment_cycle == 'bi_monthly') {
                $next_payment = date_format(
                    date_add(
                        date_create($next_payment),
                        date_interval_create_from_date_string('2 months')
                    ),
                    'Y-m-d'
                );
            }
            if ($loan->repayment_cycle == 'quarterly') {
                $next_payment = date_format(
                    date_add(
                        date_create($next_payment),
                        date_interval_create_from_date_string('4 months')
                    ),
                    'Y-m-d'
                );
            }
            if ($loan->repayment_cycle == 'semi_annually') {
                $next_payment = date_format(
                    date_add(
                        date_create($next_payment),
                        date_interval_create_from_date_string('6 months')
                    ),
                    'Y-m-d'
                );
            }
            if ($loan->repayment_cycle == 'yearly') {
                $next_payment = date_format(
                    date_add(
                        date_create($next_payment),
                        date_interval_create_from_date_string('1 years')
                    ),
                    'Y-m-d'
                );
            }
            if ($i == $period) {
                $loan_schedule->principal_balance = round($balance);
            }
            $loan_schedule->save();
        }
        $loan = Loan::find($loan->id);
        $loan->maturity_date = $next_payment;
        $loan->save();
        $fees_disbursement = 0;
        $fees_installment = 0;
        $fees_due_date = [];
        $fees_due_date_amount = 0;
        foreach ($loan->charges as $key) {
            if (!empty($key->charge)) {
                if ($key->charge->charge_type == "disbursement") {
                    if ($key->charge->charge_option == "fixed") {
                        $fees_disbursement = $fees_disbursement + $key->amount;
                    } else {
                        if ($key->charge->charge_option == "principal_due") {
                            $fees_disbursement = $fees_disbursement + ($key->amount * $loan->principal) / 100;
                        }
                        if ($key->charge->charge_option == "principal_interest") {
                            $fees_disbursement = $fees_disbursement + ($key->amount * ($loan->principal + $total_interest)) / 100;
                        }
                        if ($key->charge->charge_option == "interest_due") {
                            $fees_disbursement = $fees_disbursement + ($key->amount * $total_interest) / 100;
                        }
                        if ($key->charge->charge_option == "original_principal") {
                            $fees_disbursement = $fees_disbursement + ($key->amount * $loan->principal) / 100;
                        }
                        if ($key->charge->charge_option == "total_due") {
                            $fees_disbursement = $fees_disbursement + ($key->amount * ($loan->principal + $total_interest)) / 100;
                        }
                    }
                }
                if ($key->charge->charge_type == "installment_fee") {
                    if ($key->charge->charge_option == "fixed") {
                        $fees_installment = $fees_installment + $key->amount;
                    } else {
                        if ($key->charge->charge_option == "principal_due") {
                            $fees_installment = $fees_installment + ($key->amount * $loan->principal) / 100;
                        }
                        if ($key->charge->charge_option == "principal_interest") {
                            $fees_installment = $fees_installment + ($key->amount * ($loan->principal + $total_interest)) / 100;
                        }
                        if ($key->charge->charge_option == "interest_due") {
                            $fees_installment = $fees_installment + ($key->amount * $total_interest) / 100;
                        }
                        if ($key->charge->charge_option == "original_principal") {
                            $fees_installment = $fees_installment + ($key->amount * $loan->principal) / 100;
                        }
                        if ($key->charge->charge_option == "total_due") {
                            $fees_installment = $fees_installment + ($key->amount * ($loan->principal + $total_interest)) / 100;
                        }
                    }
                }
                if ($key->charge->charge_type == "specified_due_date") {
                    if ($key->charge->charge_option == "fixed") {
                        $fees_due_date_amount = $fees_due_date_amount + $key->amount;
                        $fees_due_date[$key->charge->date] = $key->amount;
                    } else {
                        if ($key->charge->charge_option == "principal_due") {
                            $fees_due_date_amount = $fees_due_date_amount + ($key->amount * $loan->principal) / 100;
                            $fees_due_date[$key->charge->date] = ($key->amount * $loan->principal) / 100;
                        }
                        if ($key->charge->charge_option == "principal_interest") {
                            $fees_due_date_amount = $fees_due_date_amount + ($key->amount * ($loan->principal + $total_interest)) / 100;
                            $fees_due_date[$key->charge->date] = ($key->amount * ($loan->principal + $total_interest)) / 100;
                        }
                        if ($key->charge->charge_option == "interest_due") {
                            $fees_due_date_amount = $fees_due_date_amount + ($key->amount * $total_interest) / 100;
                            $fees_due_date[$key->charge->date] = ($key->amount * $total_interest) / 100;
                        }
                        if ($key->charge->charge_option == "original_principal") {
                            $fees_due_date_amount = $fees_due_date_amount + ($key->amount * $loan->principal) / 100;
                            $fees_due_date[$key->charge->date] = ($key->amount * $loan->principal) / 100;
                        }
                        if ($key->charge->charge_option == "total_due") {
                            $fees_due_date_amount = $fees_due_date_amount + ($key->amount * ($loan->principal + $total_interest)) / 100;
                            $fees_due_date[$key->charge->date] = ($key->amount * ($loan->principal + $total_interest)) / 100;
                        }
                    }
                }
            }
        }
        //add disbursal transaction
        $loan_transaction = new LoanTransaction();
        $loan_transaction->user_id = Sentinel::getUser()->id;
        $loan_transaction->branch_id = session('branch_id');
        $loan_transaction->loan_id = $loan->id;
        $loan_transaction->borrower_id = $loan->borrower_id;
        $loan_transaction->transaction_type = "disbursement";
        $loan_transaction->date = $request->disbursed_date;
        $date = explode('-', $request->disbursed_date);
        $loan_transaction->year = $date[0];
        $loan_transaction->month = $date[1];
        $loan_transaction->debit = $loan->principal;
        $loan_transaction->save();
        //add interest transaction
        $loan_transaction = new LoanTransaction();
        $loan_transaction->user_id = Sentinel::getUser()->id;
        $loan_transaction->branch_id = session('branch_id');
        $loan_transaction->loan_id = $loan->id;
        $loan_transaction->borrower_id = $loan->borrower_id;
        $loan_transaction->transaction_type = "interest";
        $loan_transaction->date = $request->disbursed_date;
        $date = explode('-', $request->disbursed_date);
        $loan_transaction->year = $date[0];
        $loan_transaction->month = $date[1];
        $loan_transaction->debit = $total_interest;
        $loan_transaction->save();
        //add fees transactions
        if ($fees_disbursement > 0) {
            $loan_transaction = new LoanTransaction();
            $loan_transaction->user_id = Sentinel::getUser()->id;
            $loan_transaction->branch_id = session('branch_id');
            $loan_transaction->loan_id = $loan->id;
            $loan_transaction->borrower_id = $loan->borrower_id;
            $loan_transaction->transaction_type = "disbursement_fee";
            $loan_transaction->date = $request->disbursed_date;
            $date = explode('-', $request->disbursed_date);
            $loan_transaction->year = $date[0];
            $loan_transaction->month = $date[1];
            $loan_transaction->debit = $fees_disbursement;
            $loan_transaction->save();

            $loan_transaction = new LoanTransaction();
            $loan_transaction->user_id = Sentinel::getUser()->id;
            $loan_transaction->branch_id = session('branch_id');
            $loan_transaction->loan_id = $loan->id;
            $loan_transaction->borrower_id = $loan->borrower_id;
            $loan_transaction->transaction_type = "repayment_disbursement";
            $loan_transaction->date = $request->disbursed_date;
            $date = explode('-', $request->disbursed_date);
            $loan_transaction->year = $date[0];
            $loan_transaction->month = $date[1];
            $loan_transaction->credit = $fees_disbursement;
            $loan_transaction->save();
            //add journal entry for payment and charge
            if (!empty($loan->loan_product->chart_income_fee)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_income_fee->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->disbursed_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'fee';
                $journal->name = "Fee Income";
                $journal->loan_id = $loan->id;
                $journal->credit = $fees_disbursement;
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
            if (!empty($loan->loan_product->chart_fund_source)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_fund_source->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->disbursed_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'fee';
                $journal->name = "Fee Income";
                $journal->loan_id = $loan->id;
                $journal->debit = $fees_disbursement;
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
        }
        if ($fees_installment > 0) {
            $loan_transaction = new LoanTransaction();
            $loan_transaction->user_id = Sentinel::getUser()->id;
            $loan_transaction->branch_id = session('branch_id');
            $loan_transaction->loan_id = $loan->id;
            $loan_transaction->borrower_id = $loan->borrower_id;
            $loan_transaction->transaction_type = "installment_fee";
            $loan_transaction->reversible = 1;
            $loan_transaction->date = $request->disbursed_date;
            $date = explode('-', $request->disbursed_date);
            $loan_transaction->year = $date[0];
            $loan_transaction->month = $date[1];
            $loan_transaction->debit = $fees_installment;
            $loan_transaction->save();
            //add installment to schedules
            foreach (LoanSchedule::where('loan_id', $loan->id)->get() as $key) {
                $schedule = LoanSchedule::find($key->id);
                $schedule->fees = $fees_installment;
                $schedule->save();
            }
        }
        if ($fees_due_date_amount > 0) {
            foreach ($fees_due_date as $key => $value) {
                $due_date = GeneralHelper::determine_due_date($loan->id, $key);
                if (!empty($due_date)) {
                    $schedule = LoanSchedule::where('loan_id', $loan->id)->where('due_date', $due_date)->first();
                    $schedule->fees = $schedule->fees + $value;
                    $schedule->save();
                    $loan_transaction = new LoanTransaction();
                    $loan_transaction->user_id = Sentinel::getUser()->id;
                    $loan_transaction->branch_id = session('branch_id');
                    $loan_transaction->loan_id = $loan->id;
                    $loan_transaction->loan_schedule_id = $schedule->id;
                    $loan_transaction->reversible = 1;
                    $loan_transaction->borrower_id = $loan->borrower_id;
                    $loan_transaction->transaction_type = "specified_due_date_fee";
                    $loan_transaction->date = $due_date;
                    $date = explode('-', $due_date);
                    $loan_transaction->year = $date[0];
                    $loan_transaction->month = $date[1];
                    $loan_transaction->debit = $value;
                    $loan_transaction->save();
                }
            }
        }
        //debit and credit the necessary accounts
        if (!empty($loan->loan_product->chart_fund_source)) {
            $journal = new JournalEntry();
            $journal->user_id = Sentinel::getUser()->id;
            $journal->account_id = $loan->loan_product->chart_fund_source->id;
            $journal->branch_id = $loan->branch_id;
            $journal->date = $request->disbursed_date;
            $journal->year = $date[0];
            $journal->month = $date[1];
            $journal->borrower_id = $loan->borrower_id;
            $journal->transaction_type = 'disbursement';
            $journal->name = "Loan Disbursement";
            $journal->loan_id = $loan->id;
            $journal->credit = $loan->principal;
            $journal->reference = $loan->id;
            $journal->save();
        } else {
            //alert admin that no account has been set
        }
        if (!empty($loan->loan_product->chart_loan_portfolio)) {
            $journal = new JournalEntry();
            $journal->user_id = Sentinel::getUser()->id;
            $journal->account_id = $loan->loan_product->chart_loan_portfolio->id;
            $journal->branch_id = $loan->branch_id;
            $journal->date = $request->disbursed_date;
            $journal->year = $date[0];
            $journal->month = $date[1];
            $journal->borrower_id = $loan->borrower_id;
            $journal->transaction_type = 'disbursement';
            $journal->name = "Loan Disbursement";
            $journal->loan_id = $loan->id;
            $journal->debit = $loan->principal;
            $journal->reference = $loan->id;
            $journal->save();
        } else {
            //alert admin that no account has been set
        }
        if ($loan->loan_product->accounting_rule == "accrual_upfront") {
            //we need to save the accrued interest in journal here
            if (!empty($loan->loan_product->chart_receivable_interest)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_receivable_interest->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->disbursed_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'accrual';
                $journal->name = "Accrued Interest";
                $journal->loan_id = $loan->id;
                $journal->debit = $total_interest;
                $journal->reference = $loan->id;
                $journal->save();
            }
            if (!empty($loan->loan_product->chart_income_interest)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_income_interest->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->disbursed_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'accrual';
                $journal->name = "Accrued Interest";
                $journal->loan_id = $loan->id;
                $journal->credit = $total_interest;
                $journal->reference = $loan->id;
                $journal->save();
            }
        }
        GeneralHelper::audit_trail("Disbursed loan with id:" . $loan->id);
        Flash::success(translate('successfully_saved'));
        return redirect('loan/' . $loan->id . '/show');
    }

    public function rescheduleStore(Request $request, $id)
    {
        // dd($request);
        if (!Sentinel::hasAccess('loans.reschedule')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $l = Loan::find($id);
        $l->status = 'rescheduled';
        $l->save();
        $loan = new Loan();
        $loan->principal = $request->principal;
        $loan->status = "disbursed";
        $loan->interest_method = $request->interest_method;
        $loan->interest_rate = $request->interest_rate;
        $loan->pay_off_interest_rate = $l->pay_off_interest_rate;
        $loan->branch_id = session('branch_id');
        $loan->interest_period = $request->interest_period;
        $loan->loan_duration = $request->loan_duration;
        $loan->loan_duration_type = $request->loan_duration_type;
        $loan->repayment_cycle = $request->repayment_cycle;
        $loan->decimal_places = $request->decimal_places;
        $loan->override_interest = $request->override_interest;
        $loan->override_interest_amount = $request->override_interest_amount;
        $loan->grace_on_interest_charged = $request->grace_on_interest_charged;
        $loan->borrower_id = $l->borrower_id;
        $loan->applied_amount = $request->principal;
        $loan->user_id = Sentinel::getUser()->id;
        $loan->loan_product_id = $request->loan_product_id;
        $loan->release_date = $request->release_date;
        $dateDisbursed = explode('-', $request->release_date);
        $loan->month = $dateDisbursed[1];
        $loan->year = $dateDisbursed[0];
        if (!empty($request->first_payment_date)) {
            $loan->first_payment_date = $request->first_payment_date;
        }
        $loan->description = $request->description;
        $files = array();
        if (!empty($request->file('files'))) {
            $count = 0;
            foreach ($request->file('files') as $key) {
                $file = array('files' => $key);
                $rules = array('files' => 'required|mimes:jpeg,jpg,bmp,png,pdf,docx,xlsx');
                $validator = Validator::make($file, $rules);
                if ($validator->fails()) {
                    Flash::warning(translate('validation_error'));
                    return redirect()->back()->withInput()->withErrors($validator);
                } else {
                    $files[$count] = $key->getClientOriginalName();
                    $key->move(
                        public_path() . '/uploads',
                        $key->getClientOriginalName()
                    );
                }
                $count++;
            }
        }
        $loan->files = serialize($files);
        $loan->save();
        $interest_rate = GeneralHelper::determine_interest_rate($loan->id);
        $period = GeneralHelper::loan_period($loan->id);
        //save custom meta
        $custom_fields = CustomField::where('category', 'loans')->get();
        foreach ($custom_fields as $key) {
            $custom_field = new CustomFieldMeta();
            $id = $key->id;
            $custom_field->name = $request->$id;
            $custom_field->parent_id = $loan->id;
            $custom_field->custom_field_id = $key->id;
            $custom_field->category = "loans";
            $custom_field->save();
        }
        if ($loan->repayment_cycle == 'daily') {
            $repayment_cycle = '1 days';
            $repayment_type = 'days';
        }
        if ($loan->repayment_cycle == 'weekly') {
            $repayment_cycle = '1 weeks';
            $repayment_type = 'weeks';
        }
        if ($loan->repayment_cycle == 'monthly') {
            $repayment_cycle = 'month';
            $repayment_type = 'months';
        }
        if ($loan->repayment_cycle == 'bi_monthly') {
            $repayment_cycle = '2 months';
            $repayment_type = 'months';
        }
        if ($loan->repayment_cycle == 'quarterly') {
            $repayment_cycle = '4 months';
            $repayment_type = 'months';
        }
        if ($loan->repayment_cycle == 'semi_annually') {
            $repayment_cycle = '6 months';
            $repayment_type = 'months';
        }
        if ($loan->repayment_cycle == 'yearly') {
            $repayment_cycle = '1 years';
            $repayment_type = 'years';
        }
        if (empty($request->first_payment_date)) {
            $first_payment_date = date_format(
                date_add(
                    date_create($request->disbursed_date),
                    date_interval_create_from_date_string($repayment_cycle)
                ),
                'Y-m-d'
            );
        } else {
            $first_payment_date = $request->first_payment_date;
        }
        $loan->maturity_date = date_format(
            date_add(
                date_create($first_payment_date),
                date_interval_create_from_date_string($period . ' ' . $repayment_type)
            ),
            'Y-m-d'
        );
        $loan->status = 'disbursed';
        $loan->loan_disbursed_by_id = $request->loan_disbursed_by_id;
        $loan->disbursed_notes = $request->disbursed_notes;
        $loan->first_payment_date = $first_payment_date;
        $loan->disbursed_by_id = Sentinel::getUser()->id;
        $loan->disbursed_date = $request->disbursed_date;
        $loan->release_date = $request->disbursed_date;
        //$date = explode('-', $request->disbursed_date);
        $date = explode('-', $request->release_date);
        $loan->month = $date[1];
        $loan->year = $date[0];
        $loan->save();

        //generate schedules until period finished
        $next_payment = $first_payment_date;
        $balance = $loan->principal;
        $total_interest = 0;
        $isFullMonth = false;
        $isOverMonth = false;
        $amortizedPrincipal = $loan->principal;
        for ($i = 1; $i <= $period; $i++) {
            $loan_schedule = new LoanSchedule();
            $loan_schedule->loan_id = $loan->id;
            $loan_schedule->branch_id = session('branch_id');
            $loan_schedule->borrower_id = $loan->borrower_id;
            $loan_schedule->description = "Repayment";
            $loan_schedule->due_date = $next_payment;
            $datePayment = explode('-', $next_payment);
            $loan_schedule->month = $datePayment[1];
            $loan_schedule->year = $datePayment[0];
            //determine which method to use
            $due = 0;

            // if ($dateDisbursed[2] >= 16 && $dateDisbursed[2] != $datePayment[2]) {
            if ($dateDisbursed[2] != $datePayment[2]) {
                $diffDays = Carbon::parse($loan->disbursed_date)->diffInDays($first_payment_date);
                $days_of_first_month = Carbon::parse($first_payment_date)->daysInMonth;

                //$days_of_month = Carbon::parse($next_payment)->daysInMonth;
                //if($diffDays - $days_of_first_month == 0 ) $isFullMonth = true;
                //if($diffDays - $days_of_first_month > 0) $isOverMonth = true;
            } else {
                $isFullMonth = true;
            }

            // $diffDays = Carbon::parse($loan->disbursed_date)->diffInDays($first_payment_date);
            // $days_of_first_month = Carbon::parse($first_payment_date)->daysInMonth;
            // if($diffDays - $days_of_first_month == 0 ) $isFullMonth = true;
            // if($diffDays - $days_of_first_month > 0) $isOverMonth = true;
            //reducing balance equal installments
            if ($loan->interest_method == 'declining_balance_equal_installments') {
                if ($i == 1 && !$isFullMonth) {
                    $principal = $balance / $period;
                    $interest = $balance * $interest_rate / $days_of_first_month * $diffDays;
                    $due = $principal + $interest;
                    $amortizedPrincipal = $balance - $principal;
                } else {
                    $due = GeneralHelper::amortized_monthly_payment($loan->id, $amortizedPrincipal, $isFullMonth);
                    $interest = ($interest_rate * $balance);
                    $principal = ($due - $interest);
                }

                $loan_schedule->principal = $principal;
                if ($loan->grace_on_interest_charged >= $i) {
                    $loan_schedule->interest = 0;
                } else {
                    $loan_schedule->interest = $interest;
                }

                $loan_schedule->due = $due;
                //determine next balance
                $balance = ($balance - ($due - $interest));
                $loan_schedule->principal_balance = $balance;
            }
            //reducing balance equal principle
            if ($loan->interest_method == 'declining_balance_equal_principal') {
                $principal = $loan->principal / $period;
                $loan_schedule->principal = ($principal);
                //$interest = ($interest_rate * $balance);
                if ($i == 1 && !$isFullMonth) {
                    $interest = ((($interest_rate / $days_of_first_month) * $diffDays) * $balance);
                } else {
                    $interest = ($interest_rate * $balance);
                }

                if ($loan->grace_on_interest_charged >= $i) {
                    $loan_schedule->interest = 0;
                } else {
                    $loan_schedule->interest = $interest;
                }
                $loan_schedule->due = $principal + $interest;
                //determine next balance
                //$balance = ($balance - ($principal + $interest));
                $balance = $balance - $principal;
                $loan_schedule->principal_balance = $balance;
            }
            //flat  method
            if ($loan->interest_method == 'flat_rate') {
                $principal = $loan->principal / $period;
                //$interest = ($interest_rate * $loan->principal);
                if ($i == 1 && !$isFullMonth) {
                    $interest = ((($interest_rate / $days_of_first_month) * $diffDays) * $loan->principal);
                } else {
                    $interest = ($interest_rate * $loan->principal);
                }
                if ($loan->grace_on_interest_charged >= $i) {
                    $loan_schedule->interest = 0;
                } else {
                    $loan_schedule->interest = $interest;
                }
                $loan_schedule->principal = $principal;
                $loan_schedule->due = $principal + $interest;
                //determine next balance
                $balance = ($balance - $principal);
                $loan_schedule->principal_balance = $balance;
            }
            //interest only method
            if ($loan->interest_method == 'interest_only') {
                if ($i == $period) {
                    $principal = $loan->principal;
                } else {
                    $principal = 0;
                }
                //$interest = ($interest_rate * $loan->principal);
                if ($i == 1 && !$isFullMonth) {
                    $interest = ((($interest_rate / $days_of_first_month) * $diffDays) * $loan->principal);
                } else {
                    $interest = ($interest_rate * $loan->principal);
                }
                if ($loan->grace_on_interest_charged >= $i) {
                    $loan_schedule->interest = 0;
                } else {
                    $loan_schedule->interest = $interest;
                }
                $loan_schedule->principal = $principal;
                $loan_schedule->due = $principal + $interest;
                //determine next balance
                $balance = ($balance - $principal);
                $loan_schedule->principal_balance = $balance;
            }
            $total_interest = $total_interest + $interest;
            //determine next due date
            if ($loan->repayment_cycle == 'daily') {
                $next_payment = date_format(
                    date_add(
                        date_create($next_payment),
                        date_interval_create_from_date_string('1 days')
                    ),
                    'Y-m-d'
                );
            }
            if ($loan->repayment_cycle == 'weekly') {
                $next_payment = date_format(
                    date_add(
                        date_create($next_payment),
                        date_interval_create_from_date_string('1 weeks')
                    ),
                    'Y-m-d'
                );
            }
            if ($loan->repayment_cycle == 'monthly') {
                $next_payment = date_format(
                    date_add(
                        date_create($next_payment),
                        date_interval_create_from_date_string('1 months')
                    ),
                    'Y-m-d'
                );
            }
            if ($loan->repayment_cycle == 'bi_monthly') {
                $next_payment = date_format(
                    date_add(
                        date_create($next_payment),
                        date_interval_create_from_date_string('2 months')
                    ),
                    'Y-m-d'
                );
            }
            if ($loan->repayment_cycle == 'quarterly') {
                $next_payment = date_format(
                    date_add(
                        date_create($next_payment),
                        date_interval_create_from_date_string('4 months')
                    ),
                    'Y-m-d'
                );
            }
            if ($loan->repayment_cycle == 'semi_annually') {
                $next_payment = date_format(
                    date_add(
                        date_create($next_payment),
                        date_interval_create_from_date_string('6 months')
                    ),
                    'Y-m-d'
                );
            }
            if ($loan->repayment_cycle == 'yearly') {
                $next_payment = date_format(
                    date_add(
                        date_create($next_payment),
                        date_interval_create_from_date_string('1 years')
                    ),
                    'Y-m-d'
                );
            }
            if ($i == $period) {
                $loan_schedule->principal_balance = round($balance);
            }
            $loan_schedule->save();
        }
        $loan = Loan::find($loan->id);
        $loan->maturity_date = $next_payment;
        $loan->save();
        $fees_disbursement = 0;
        $fees_installment = 0;
        $fees_due_date = [];
        $fees_due_date_amount = 0;
        foreach ($loan->charges as $key) {
            if (!empty($key->charge)) {
                if ($key->charge->charge_type == "disbursement") {
                    if ($key->charge->charge_option == "fixed") {
                        $fees_disbursement = $fees_disbursement + $key->amount;
                    } else {
                        if ($key->charge->charge_option == "principal_due") {
                            $fees_disbursement = $fees_disbursement + ($key->amount * $loan->principal) / 100;
                        }
                        if ($key->charge->charge_option == "principal_interest") {
                            $fees_disbursement = $fees_disbursement + ($key->amount * ($loan->principal + $total_interest)) / 100;
                        }
                        if ($key->charge->charge_option == "interest_due") {
                            $fees_disbursement = $fees_disbursement + ($key->amount * $total_interest) / 100;
                        }
                        if ($key->charge->charge_option == "original_principal") {
                            $fees_disbursement = $fees_disbursement + ($key->amount * $loan->principal) / 100;
                        }
                        if ($key->charge->charge_option == "total_due") {
                            $fees_disbursement = $fees_disbursement + ($key->amount * ($loan->principal + $total_interest)) / 100;
                        }
                    }
                }
                if ($key->charge->charge_type == "installment_fee") {
                    if ($key->charge->charge_option == "fixed") {
                        $fees_installment = $fees_installment + $key->amount;
                    } else {
                        if ($key->charge->charge_option == "principal_due") {
                            $fees_installment = $fees_installment + ($key->amount * $loan->principal) / 100;
                        }
                        if ($key->charge->charge_option == "principal_interest") {
                            $fees_installment = $fees_installment + ($key->amount * ($loan->principal + $total_interest)) / 100;
                        }
                        if ($key->charge->charge_option == "interest_due") {
                            $fees_installment = $fees_installment + ($key->amount * $total_interest) / 100;
                        }
                        if ($key->charge->charge_option == "original_principal") {
                            $fees_installment = $fees_installment + ($key->amount * $loan->principal) / 100;
                        }
                        if ($key->charge->charge_option == "total_due") {
                            $fees_installment = $fees_installment + ($key->amount * ($loan->principal + $total_interest)) / 100;
                        }
                    }
                }
                if ($key->charge->charge_type == "specified_due_date") {
                    if ($key->charge->charge_option == "fixed") {
                        $fees_due_date_amount = $fees_due_date_amount + $key->amount;
                        $fees_due_date[$key->charge->date] = $key->amount;
                    } else {
                        if ($key->charge->charge_option == "principal_due") {
                            $fees_due_date_amount = $fees_due_date_amount + ($key->amount * $loan->principal) / 100;
                            $fees_due_date[$key->charge->date] = ($key->amount * $loan->principal) / 100;
                        }
                        if ($key->charge->charge_option == "principal_interest") {
                            $fees_due_date_amount = $fees_due_date_amount + ($key->amount * ($loan->principal + $total_interest)) / 100;
                            $fees_due_date[$key->charge->date] = ($key->amount * ($loan->principal + $total_interest)) / 100;
                        }
                        if ($key->charge->charge_option == "interest_due") {
                            $fees_due_date_amount = $fees_due_date_amount + ($key->amount * $total_interest) / 100;
                            $fees_due_date[$key->charge->date] = ($key->amount * $total_interest) / 100;
                        }
                        if ($key->charge->charge_option == "original_principal") {
                            $fees_due_date_amount = $fees_due_date_amount + ($key->amount * $loan->principal) / 100;
                            $fees_due_date[$key->charge->date] = ($key->amount * $loan->principal) / 100;
                        }
                        if ($key->charge->charge_option == "total_due") {
                            $fees_due_date_amount = $fees_due_date_amount + ($key->amount * ($loan->principal + $total_interest)) / 100;
                            $fees_due_date[$key->charge->date] = ($key->amount * ($loan->principal + $total_interest)) / 100;
                        }
                    }
                }
            }
        }
        //add disbursal transaction
        $loan_transaction = new LoanTransaction();
        $loan_transaction->user_id = Sentinel::getUser()->id;
        $loan_transaction->branch_id = session('branch_id');
        $loan_transaction->loan_id = $loan->id;
        $loan_transaction->borrower_id = $loan->borrower_id;
        $loan_transaction->transaction_type = "disbursement";
        $loan_transaction->date = $request->disbursed_date;
        //$date = explode('-', $request->disbursed_date);
        $date = explode('-', $request->release_date);
        $loan_transaction->year = $date[0];
        $loan_transaction->month = $date[1];
        $loan_transaction->debit = $loan->principal;
        $loan_transaction->save();
        //add interest transaction
        $loan_transaction = new LoanTransaction();
        $loan_transaction->user_id = Sentinel::getUser()->id;
        $loan_transaction->branch_id = session('branch_id');
        $loan_transaction->loan_id = $loan->id;
        $loan_transaction->borrower_id = $loan->borrower_id;
        $loan_transaction->transaction_type = "interest";
        $loan_transaction->date = $request->disbursed_date;
        //$date = explode('-', $request->disbursed_date);
        $date = explode('-', $request->release_date);
        $loan_transaction->year = $date[0];
        $loan_transaction->month = $date[1];
        $loan_transaction->debit = $total_interest;
        $loan_transaction->save();
        //add fees transactions
        if ($fees_disbursement > 0) {
            $loan_transaction = new LoanTransaction();
            $loan_transaction->user_id = Sentinel::getUser()->id;
            $loan_transaction->branch_id = session('branch_id');
            $loan_transaction->loan_id = $loan->id;
            $loan_transaction->borrower_id = $loan->borrower_id;
            $loan_transaction->transaction_type = "disbursement_fee";
            $loan_transaction->date = $request->disbursed_date;
            //$date = explode('-', $request->disbursed_date);
            $date = explode('-', $request->release_date);
            $loan_transaction->year = $date[0];
            $loan_transaction->month = $date[1];
            $loan_transaction->debit = $fees_disbursement;
            $loan_transaction->save();

            $loan_transaction = new LoanTransaction();
            $loan_transaction->user_id = Sentinel::getUser()->id;
            $loan_transaction->branch_id = session('branch_id');
            $loan_transaction->loan_id = $loan->id;
            $loan_transaction->borrower_id = $loan->borrower_id;
            $loan_transaction->transaction_type = "repayment_disbursement";
            $loan_transaction->date = $request->disbursed_date;
            //$date = explode('-', $request->disbursed_date);
            $date = explode('-', $request->release_date);
            $loan_transaction->year = $date[0];
            $loan_transaction->month = $date[1];
            $loan_transaction->credit = $fees_disbursement;
            $loan_transaction->save();
            //add journal entry for payment and charge
            if (!empty($loan->loan_product->chart_income_fee)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_income_fee->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->disbursed_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'fee';
                $journal->name = "Fee Income";
                $journal->loan_id = $loan->id;
                $journal->credit = $fees_disbursement;
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
            if (!empty($loan->loan_product->chart_fund_source)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_fund_source->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->disbursed_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'fee';
                $journal->name = "Fee Income";
                $journal->loan_id = $loan->id;
                $journal->debit = $fees_disbursement;
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
        }
        if ($fees_installment > 0) {
            $loan_transaction = new LoanTransaction();
            $loan_transaction->user_id = Sentinel::getUser()->id;
            $loan_transaction->branch_id = session('branch_id');
            $loan_transaction->loan_id = $loan->id;
            $loan_transaction->borrower_id = $loan->borrower_id;
            $loan_transaction->transaction_type = "installment_fee";
            $loan_transaction->reversible = 1;
            $loan_transaction->date = $request->disbursed_date;
            $date = explode('-', $request->disbursed_date);
            $loan_transaction->year = $date[0];
            $loan_transaction->month = $date[1];
            $loan_transaction->debit = $fees_installment;
            $loan_transaction->save();
            //add installment to schedules
            foreach (LoanSchedule::where('loan_id', $loan->id)->get() as $key) {
                $schedule = LoanSchedule::find($key->id);
                $schedule->fees = $fees_installment;
                $schedule->save();
            }
        }
        if ($fees_due_date_amount > 0) {
            foreach ($fees_due_date as $key => $value) {
                $due_date = GeneralHelper::determine_due_date($loan->id, $key);
                if (!empty($due_date)) {
                    $schedule = LoanSchedule::where('loan_id', $loan->id)->where('due_date', $due_date)->first();
                    $schedule->fees = $schedule->fees + $value;
                    $schedule->save();
                    $loan_transaction = new LoanTransaction();
                    $loan_transaction->user_id = Sentinel::getUser()->id;
                    $loan_transaction->branch_id = session('branch_id');
                    $loan_transaction->loan_id = $loan->id;
                    $loan_transaction->loan_schedule_id = $schedule->id;
                    $loan_transaction->reversible = 1;
                    $loan_transaction->borrower_id = $loan->borrower_id;
                    $loan_transaction->transaction_type = "specified_due_date_fee";
                    $loan_transaction->date = $due_date;
                    $date = explode('-', $due_date);
                    $loan_transaction->year = $date[0];
                    $loan_transaction->month = $date[1];
                    $loan_transaction->debit = $value;
                    $loan_transaction->save();
                }
            }
        }
        //debit and credit the necessary accounts
        if (!empty($loan->loan_product->chart_fund_source)) {
            $journal = new JournalEntry();
            $journal->user_id = Sentinel::getUser()->id;
            $journal->account_id = $loan->loan_product->chart_fund_source->id;
            $journal->branch_id = $loan->branch_id;
            $journal->date = $request->disbursed_date;
            $journal->year = $date[0];
            $journal->month = $date[1];
            $journal->borrower_id = $loan->borrower_id;
            $journal->transaction_type = 'disbursement';
            $journal->name = "Loan Disbursement";
            $journal->loan_id = $loan->id;
            $journal->credit = $loan->principal;
            $journal->reference = $loan->id;
            $journal->save();
        } else {
            //alert admin that no account has been set
        }
        if (!empty($loan->loan_product->chart_loan_portfolio)) {
            $journal = new JournalEntry();
            $journal->user_id = Sentinel::getUser()->id;
            $journal->account_id = $loan->loan_product->chart_loan_portfolio->id;
            $journal->branch_id = $loan->branch_id;
            $journal->date = $request->disbursed_date;
            $journal->year = $date[0];
            $journal->month = $date[1];
            $journal->borrower_id = $loan->borrower_id;
            $journal->transaction_type = 'disbursement';
            $journal->name = "Loan Disbursement";
            $journal->loan_id = $loan->id;
            $journal->debit = $loan->principal;
            $journal->reference = $loan->id;
            $journal->save();
        } else {
            //alert admin that no account has been set
        }
        if ($loan->loan_product->accounting_rule == "accrual_upfront") {
            //we need to save the accrued interest in journal here
            if (!empty($loan->loan_product->chart_receivable_interest)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_receivable_interest->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->disbursed_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'accrual';
                $journal->name = "Accrued Interest";
                $journal->loan_id = $loan->id;
                $journal->debit = $total_interest;
                $journal->reference = $loan->id;
                $journal->save();
            }
            if (!empty($loan->loan_product->chart_income_interest)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_income_interest->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->disbursed_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'accrual';
                $journal->name = "Accrued Interest";
                $journal->loan_id = $loan->id;
                $journal->credit = $total_interest;
                $journal->reference = $loan->id;
                $journal->save();
            }
        }
        GeneralHelper::audit_trail("Rescheduled loan with id:" . $l->id);
        Flash::success(translate('successfully_saved'));
        return redirect('loan/' . $loan->id . '/show');
    }

    public function undisburse($id)
    {
        if (!Sentinel::hasAccess('loans.disburse')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }

        $loan = Loan::find($id);
        if (Sentinel::getUser()->max_approval < $loan->principal) {
            Flash::warning(translate('max_approval_exceed'));
            return redirect()->back();;
        }

        //delete previously created schedules and payments
        LoanSchedule::where('loan_id', $id)->delete();
        LoanRepayment::where('loan_id', $id)->delete();
        Capital::where('loan_id', $id)->delete();
        $loan->status = 'approved';
        $loan->save();
        //lets reverse all transactions that have been made for this loan
        foreach (LoanTransaction::where('loan_id', $id)->where('reversed', 0)->get() as $key) {
            $loan_transaction = LoanTransaction::find($key->id);
            if ($key->debit > $key->credit) {
                $loan_transaction->credit = $loan_transaction->debit;
            } else {
                $loan_transaction->debit = $loan_transaction->credit;
            }
            $loan_transaction->reversible = 0;
            $loan_transaction->reversed = 1;
            $loan_transaction->reversal_type = 'system';
            $loan_transaction->save();
            //reverse journal transactions
            foreach (JournalEntry::where('reference', $key->id)->where(
                'loan_id',
                $id
            )->get() as $k) {
                $journal = JournalEntry::find($k->id);
                if ($k->debit > $k->credit) {
                    $journal->credit = $journal->debit;
                } else {
                    $journal->debit = $journal->credit;
                }
                $journal->save();
            }
        }
        GeneralHelper::audit_trail("Undisbursed loan with id:" . $loan->id);
        Flash::success(translate('successfully_saved'));
        return redirect('loan/' . $loan->id . '/show');
    }

    public function decline(Request $request, $id)
    {
        if (!Sentinel::hasAccess('loans.approve')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan = Loan::find($id);
        $loan->status = 'declined';
        $loan->declined_date = $request->declined_date;
        $loan->declined_notes = $request->declined_notes;
        $loan->declined_by_id = Sentinel::getUser()->id;
        $loan->save();
        GeneralHelper::audit_trail("Declined loan with id:" . $loan->id);
        Flash::success(translate('successfully_saved'));
        return redirect('loan/' . $id . '/show');
    }

    public function write_off(Request $request, $id)
    {
        if (!Sentinel::hasAccess('loans.writeoff')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan = Loan::find($id);
        $loan->status = 'written_off';
        $loan->written_off_date = $request->written_off_date;
        $loan->written_off_notes = $request->written_off_notes;
        $loan->written_off_by_id = Sentinel::getUser()->id;
        $loan->save();
        $amount = GeneralHelper::loan_due_items($loan->id)["principal"] - GeneralHelper::loan_paid_items($loan->id)["principal"];
        $loan_transaction = new LoanTransaction();
        $loan_transaction->user_id = Sentinel::getUser()->id;
        $loan_transaction->branch_id = session('branch_id');
        $loan_transaction->loan_id = $loan->id;
        $loan_transaction->borrower_id = $loan->borrower_id;
        $loan_transaction->transaction_type = "write_off";
        $loan_transaction->date = $request->written_off_date;
        $loan_transaction->reversible = 1;
        $date = explode('-', $request->written_off_date);
        $loan_transaction->year = $date[0];
        $loan_transaction->month = $date[1];
        $loan_transaction->credit = GeneralHelper::loan_total_balance($loan->id);
        $loan_transaction->notes = $request->written_off_notes;
        $loan_transaction->save();
        //fire payment added event
        //debit and credit the necessary accounts

        //return $allocation;
        //principal

        if (!empty($loan->loan_product->chart_loan_portfolio)) {
            $journal = new JournalEntry();
            $journal->user_id = Sentinel::getUser()->id;
            $journal->account_id = $loan->loan_product->chart_loan_portfolio->id;
            $journal->branch_id = $loan->branch_id;
            $journal->date = $request->collection_date;
            $journal->year = $date[0];
            $journal->month = $date[1];
            $journal->borrower_id = $loan->borrower_id;
            $journal->transaction_type = 'close_write_off';
            $journal->name = "Loan Written Off";
            $journal->loan_id = $loan->id;
            $journal->loan_repayment_id = $loan_transaction->id;
            $journal->credit = $amount;
            $journal->reference = $loan_transaction->id;
            $journal->save();
        }
        if (!empty($loan->loan_product->chart_loans_written_off)) {
            $journal = new JournalEntry();
            $journal->user_id = Sentinel::getUser()->id;
            $journal->account_id = $loan->loan_product->chart_fund_source->id;
            $journal->branch_id = $loan->branch_id;
            $journal->date = $request->collection_date;
            $journal->year = $date[0];
            $journal->month = $date[1];
            $journal->borrower_id = $loan->borrower_id;
            $journal->transaction_type = 'close_write_off';
            $journal->name = "Loan Written Off";
            $journal->loan_id = $loan->id;
            $journal->loan_transaction_id = $loan_transaction->id;
            $journal->debit = $amount;
            $journal->reference = $loan_transaction->id;
            $journal->save();
        }
        GeneralHelper::audit_trail("Write off loan with id:" . $loan->id);
        Flash::success(translate('successfully_saved'));
        return redirect('loan/' . $id . '/show');
    }

    public function withdraw(Request $request, $id)
    {
        if (!Sentinel::hasAccess('loans.withdraw')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan = Loan::find($id);
        $loan->status = 'withdrawn';
        $loan->withdrawn_date = $request->withdrawn_date;
        $loan->withdrawn_notes = $request->withdrawn_notes;
        $loan->withdrawn_by_id = Sentinel::getUser()->id;
        $loan->save();
        GeneralHelper::audit_trail("Withdraw loan with id:" . $loan->id);
        Flash::success(translate('successfully_saved'));
        return redirect('loan/' . $id . '/show');
    }

    public function unwithdraw($id)
    {
        if (!Sentinel::hasAccess('loans.withdraw')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan = Loan::find($id);
        $loan->status = 'disbursed';
        $loan->save();
        GeneralHelper::audit_trail("Unwithdraw loan with id:" . $loan->id);
        Flash::success(translate('successfully_saved'));
        return redirect('loan/' . $id . '/show');
    }

    public function unwrite_off($id)
    {
        if (!Sentinel::hasAccess('loans.writeoff')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan = Loan::find($id);
        $loan->status = 'disbursed';
        $loan->save();
        GeneralHelper::audit_trail("Unwriteoff loan with id:" . $loan->id);
        Flash::success(translate('successfully_saved'));
        return redirect('loan/' . $id . '/show');
    }

    public function edit($loan)
    {
        if (!Sentinel::hasAccess('loans.update')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        if ($loan->status == 'disbursed') {
            Flash::warning(translate('validation_error'));
            return redirect('loan/data');
        }
        $borrowers = array();
        foreach (Borrower::all() as $key) {
            $borrowers[$key->id] = $key->first_name . ' ' . $key->last_name . '(' . $key->unique_number . ')';
        }
        $users = [];
        foreach (User::all() as $key) {
            $users[$key->id] = $key->first_name . ' ' . $key->last_name;
        }
        $loan_products = array();
        foreach (LoanProduct::all() as $key) {
            $loan_products[$key->id] = $key->name;
        }

        $loan_disbursed_by = array();
        foreach (LoanDisbursedBy::all() as $key) {
            $loan_disbursed_by[$key->id] = $key->name;
        }
        $loan_overdue_penalties = array();
        foreach (LoanOverduePenalty::all() as $key) {
            $loan_overdue_penalties[$key->id] = $key->name;
        }
        //get custom fields
        $custom_fields = CustomField::where('category', 'loans')->get();
        $loan_fees = LoanFee::all();
        return view(
            'loan.edit',
            compact(
                'loan',
                'borrowers',
                'loan_disbursed_by',
                'loan_products',
                'custom_fields',
                'loan_fees',
                'loan_overdue_penalties',
                'users'
            )
        );
    }

    /**
     * Update the specified resource in storage.
     *
     * @param \Illuminate\Http\Request $request
     * @param int $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        if (!Sentinel::hasAccess('loans.update')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan = Loan::find($id);
        $loan->principal = $request->principal;
        $loan->applied_amount = $request->principal;
        $loan->interest_method = $request->interest_method;
        $loan->interest_rate = $request->interest_rate;
        $loan->pay_off_interest_rate = $request->pay_off_interest_rate != 0 ? $request->pay_off_interest_rate : $request->interest_rate;

        $loan->interest_period = $request->interest_period;
        $loan->loan_duration = $request->loan_duration;
        $loan->loan_duration_type = $request->loan_duration_type;
        $loan->repayment_cycle = $request->repayment_cycle;
        $loan->decimal_places = $request->decimal_places;
        $loan->override_interest = isset($request->override_interest) ? $request->override_interest : 0;
        $loan->override_interest_amount = isset($request->override_interest_amount) ? $request->override_interest_amount : 0;
        $loan->grace_on_interest_charged = isset($request->grace_on_interest_charged) ? $request->grace_on_interest_charged : 0;
        $loan->borrower_id = $request->borrower_id;
        $loan->loan_product_id = $request->loan_product_id;
        $loan->loan_officer_id = $request->loan_officer_id;
        $loan->release_date = $request->release_date;
        $date = explode('-', $request->release_date);
        $loan->month = $date[1];
        $loan->year = $date[0];
        if (!empty($request->first_payment_date)) {
            $loan->first_payment_date = $request->first_payment_date;
        }

        $loan->description = $request->description;
        $files = unserialize($loan->files);
        $count = count($files);
        if (!empty($request->file('files'))) {
            foreach ($request->file('files') as $key) {
                $count++;
                $file = array('files' => $key);
                $rules = array('files' => 'required|mimes:jpeg,jpg,bmp,png,pdf,docx,xlsx');
                $validator = Validator::make($file, $rules);
                if ($validator->fails()) {
                    Flash::warning(translate('validation_error'));
                    return redirect()->back()->withInput()->withErrors($validator);
                } else {
                    $fname = "loan_" . uniqid() . '.' . $key->guessExtension();
                    $files[$count] = $fname;
                    $key->move(
                        public_path() . '/uploads',
                        $fname
                    );
                }
            }
        }
        $loan->files = serialize($files);
        $loan->save();
        $custom_fields = CustomField::where('category', 'loans')->get();
        foreach ($custom_fields as $key) {
            if (!empty(CustomFieldMeta::where('custom_field_id', $key->id)->where('parent_id', $id)->where(
                'category',
                'loans'
            )->first())) {
                $custom_field = CustomFieldMeta::where('custom_field_id', $key->id)->where(
                    'parent_id',
                    $id
                )->where('category', 'loans')->first();
            } else {
                $custom_field = new CustomFieldMeta();
            }
            $kid = $key->id;
            $custom_field->name = $request->$kid;
            $custom_field->parent_id = $id;
            $custom_field->custom_field_id = $key->id;
            $custom_field->category = "loans";
            $custom_field->save();
        }
        LoanCharge::where('loan_id', $loan->id)->delete();
        if (!empty($request->charges)) {
            //loop through the array
            foreach ($request->charges as $key) {
                $amount = "charge_amount_" . $key;
                $date = "charge_date_" . $key;
                $loan_charge = new LoanCharge();
                $loan_charge->loan_id = $loan->id;
                $loan_charge->user_id = Sentinel::getUser()->id;
                $loan_charge->charge_id = $key;
                $loan_charge->amount = $request->$amount;
                if (!empty($request->$date)) {
                    $loan_charge->date = $request->$date;
                }
                $loan_charge->save();
            }
        }
        GeneralHelper::audit_trail("Updated loan with id:" . $loan->id);
        Flash::success(translate('successfully_saved'));
        return redirect('loan/data');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param int $id
     * @return \Illuminate\Http\Response
     */
    public function delete($id)
    {
        if (!Sentinel::hasAccess('loans.delete')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        Loan::destroy($id);
        LoanSchedule::where('loan_id', $id)->delete();
        LoanRepayment::where('loan_id', $id)->delete();
        Guarantor::where('loan_id', $id)->delete();
        LoanCharge::where('loan_id', $id)->delete();
        GeneralHelper::audit_trail("Deleted loan with id:" . $id);
        Flash::success(translate('successfully_deleted'));
        return redirect('loan/data');
    }

    public function deleteFile(Request $request, $id)
    {
        if (!Sentinel::hasAccess('loans.delete')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan = Loan::find($id);
        $files = unserialize($loan->files);
        @unlink(public_path() . '/uploads/' . $files[$request->id]);
        $files = array_except($files, [$request->id]);
        $loan->files = serialize($files);
        $loan->save();
    }

    public function waiveInterest(Request $request, $loan)
    {
        if (!Sentinel::hasAccess('repayments.update')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $amount = GeneralHelper::loan_total_interest($loan->id) - GeneralHelper::loan_paid_items(
                $loan->id,
                $loan->release_date,
                date("Y-m-d")
            )["interest"];
        if ($request->amount > round($amount, 2)) {
            Flash::warning("Amount is more than the total interest(" . $amount . ')');
            return redirect()->back()->withInput();
        }
        if ($request->date > date("Y-m-d")) {
            Flash::warning(translate('future_date_error'));
            return redirect()->back()->withInput();
        }
        if ($request->date < $loan->disbursed_date) {
            Flash::warning(translate('early_date_error'));
            return redirect()->back()->withInput();
        }
        //add interest transaction
        $loan_transaction = new LoanTransaction();
        $loan_transaction->user_id = Sentinel::getUser()->id;
        $loan_transaction->branch_id = session('branch_id');
        $loan_transaction->loan_id = $loan->id;
        $loan_transaction->borrower_id = $loan->borrower_id;
        $loan_transaction->transaction_type = "waiver";
        $loan_transaction->date = $request->date;
        $loan_transaction->reversible = 0;
        $date = explode('-', $request->date);
        $loan_transaction->year = $date[0];
        $loan_transaction->month = $date[1];
        $loan_transaction->credit = $request->amount;
        $loan_transaction->notes = $request->notes;
        $loan_transaction->save();
        event(new InterestWaived($loan_transaction));
        GeneralHelper::audit_trail("Waived interest for loan with id " . $loan->id);
        Flash::success("Waived interest successfully saved");
        return redirect()->back();
    }

    public function waivePenalty(Request $request, $scheduleId)
    {
        if (!Sentinel::hasAccess('repayments.update')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        // $scheduleId = $request->schedule_id;

        $loanSchedule = LoanSchedule::findOrFail($request->schedule_id);
        $amount = $loanSchedule->penalty;

        if ($request->amount > $amount) {
            Flash::warning("Amount is more than the penalty (" . $amount . ')');
            return redirect()->back()->withInput();
        }
        $loanSchedule->penalty = $loanSchedule->penalty - $request->amount;
        $loanSchedule->penalty_waived = $request->amount;
        // dd($loanSchedule,$request->schedule_id);
        $loanSchedule->save();
        // event(new InterestWaived($loan_transaction));
        GeneralHelper::audit_trail("Waived penalty for loan schedule with id " . $loanSchedule->id);
        Flash::success("Waive Penalty is successfully saved");
        return redirect()->back();
    }

    public function indexRepayment(Request $request)
    {

        if (!Sentinel::hasAccess('repayments')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $date_range = $this->getDateRange($request->date_range);
        $start_date = $date_range->start_date;
        $end_date = $date_range->end_date;
        $data = LoanTransaction::query()
            ->with(['borrower', 'user', 'loan_repayment_method:id,name'])
            ->whereIn('transaction_type', ['repayment', 'pay_off', 'overpay'])
            ->where('reversed', 0)
            ->where('branch_id', session('branch_id'))
        // if($start_date && $end_date){
            ->whereBetween('date',[$start_date, $end_date]);
        // }
        $data = $data->orderBy('id','desc')->paginate(default_paginate());
        return view('loan_repayment.data', compact('data','start_date','end_date'));
    }       

    //loan repayments
    public function createBulkRepayment()
    {
        if (!Sentinel::hasAccess('repayments.create')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loans = array();
        foreach (Loan::all() as $key) {
            $loans[$key->id] = $key->borrower->first_name . ' ' . $key->borrower->last_name . '(' . translate(
                    'loan',
                    1
                ) . '#' . $key->id . ',' . translate(
                    'due',
                    1
                ) . ':' . GeneralHelper::loan_total_balance($key->id) . ')';
        }
        $repayment_methods = array();
        foreach (LoanRepaymentMethod::all() as $key) {
            $repayment_methods[$key->id] = $key->name;
        }
        $custom_fields = CustomField::where('category', 'repayments')->get();
        return view('loan_repayment.bulk', compact('loan', 'repayment_methods', 'custom_fields', 'loans'));
    }

    public function storeBulkRepayment(Request $request)
    {
        if (!Sentinel::hasAccess('repayments.create')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        for ($i = 1; $i <= 20; $i++) {
            $amount = "repayment_amount" . $i;
            $loan_id = "loan_id" . $i;
            $repayment_method = "repayment_method_id" . $i;
            $receipt = "receipt" . $i;
            $collected_date = "repayment_collected_date" . $i;
            $repayment_description = "repayment_description" . $i;
            if (!empty($request->$amount && !empty($request->$loan_id))) {
                $loan = Loan::find($request->$loan_id);
                if ($request->$amount > round(GeneralHelper::loan_total_balance($loan->id), 2)) {
                    Flash::warning("Amount is more than the balance(" . GeneralHelper::loan_total_balance($loan->id) . ')');
                    return redirect()->back()->withInput();
                } else {
                    $repayment = new LoanRepayment();
                    $repayment->user_id = Sentinel::getUser()->id;
                    $repayment->amount = $request->$amount;
                    $repayment->loan_id = $loan->id;
                    $repayment->borrower_id = $loan->borrower_id;
                    $repayment->branch_id = session('branch_id');
                    $repayment->collection_date = $request->$collected_date;
                    $repayment->receipt = $request->$receipt;
                    $repayment->repayment_method_id = $request->$repayment_method;
                    $repayment->notes = $request->$repayment_description;
                    $date = explode('-', $request->$collected_date);
                    $repayment->year = $date[0];
                    $repayment->month = $date[1];
                    //determine which schedule due date the payment applies too
                    $schedule = LoanSchedule::where('due_date', '>=', $request->$collected_date)->where(
                        'loan_id',
                        $loan->id
                    )->orderBy(
                        'due_date',
                        'asc'
                    )->first();
                    if (!empty($schedule)) {
                        $repayment->due_date = $schedule->due_date;
                    } else {
                        $schedule = LoanSchedule::where(
                            'loan_id',
                            $loan->id
                        )->orderBy(
                            'due_date',
                            'desc'
                        )->first();
                        if ($request->$collected_date > $schedule->due_date) {
                            $repayment->due_date = $schedule->due_date;
                        } else {
                            $schedule = LoanSchedule::where(
                                'due_date',
                                '>',
                                $request->$collected_date
                            )->where(
                                'loan_id',
                                $loan->id
                            )->orderBy(
                                'due_date',
                                'asc'
                            )->first();
                            $repayment->due_date = $schedule->due_date;
                        }
                    }
                    $repayment->save();

                    //update loan status if need be
                    if (round(GeneralHelper::loan_total_balance($loan->id), 2) == 0) {
                        $l = Loan::find($loan->id);
                        $l->status = "closed";
                        $l->save();
                    }
                    //check if late repayment is to be applied when adding payment


                }
            }
            //notify borrower


        }
        GeneralHelper::audit_trail("Added  bulk repayment");
        Flash::success("Repayment successfully saved");
        return redirect('repayment/data');
    }

    public function addRepayment()
    {
        if (!Sentinel::hasAccess('repayments.create')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loans = array();
        foreach (Loan::whereIn(
            'status',
            ['disbursed', 'closed', 'written_off']
        )->get() as $key) {

            if (!empty($key->borrower)) {
                $borrower = ' (' . $key->borrower->first_name . ' ' . $key->borrower->last_name . ")";
            } else {
                $borrower = '';
            }
            $loans[$key->id] = "#" . $key->id . $borrower;
        }

        return view('loan_repayment.add', compact('loans'));
    }

    public function createRepayment($loan, $schedule_id)
    {
        if (!Sentinel::hasAccess('repayments.create')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $repayment_methods = array();
        foreach (LoanRepaymentMethod::all() as $key) {
            $repayment_methods[$key->id] = $key->name;
        }
        $schedule = LoanSchedule::findOrFail($schedule_id);
        $custom_fields = CustomField::where('category', 'repayments')->get();
        return view('loan_repayment.create', compact('loan', 'schedule_id', 'schedule', 'repayment_methods', 'custom_fields'));
    }

    public function createPayOff($loan)
    {
        if (!Sentinel::hasAccess('repayments.create')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $repayment_methods = array();
        foreach (LoanRepaymentMethod::all() as $key) {
            $repayment_methods[$key->id] = $key->name;
        }
        $payOffInterestRate = $this->getData($loan, "payOffInterestRate");
        $principal = $this->getData($loan, 'principal');
        $payOffAmount = $this->getData($loan, "payOffAmount");
        $custom_fields = CustomField::where('category', 'repayments')->get();

        return view('loan_repayment.payOff', compact('loan', 'repayment_methods', 'custom_fields', 'payOffAmount', 'payOffInterestRate', 'principal'));
    }

    private function getData($loan, $getType = "payOffAmount")
    {
        // $getType can be "interestToUncharge" or "payOffAmount" or "payOffInterestRate"
        // dd(GeneralHelper::loan_total_balance($loan->id));
        $alreadyPaid = 0;
        $loanTransactions = LoanTransaction::where('loan_id', $loan->id)->whereIn('reversal_type', ['user', 'none'])->where('reversible', true)->get();

        // $loan_total_balance = 0;
        // $amountPaid = 0;
        $repaymentCount = 0;
        // $currentBalance= 0;
        $mainBalanceRest = 0;
        $interestToUncharge = 0;
        $isFirstMonth = true;
        $lastPaymentDate = $loan->first_payment_date;
        foreach ($loanTransactions as $index => $loanTransaction) {
            // $currentBalance = $currentBalance + ($loanTransaction->debit - $loanTransaction->credit);

            if ($loanTransaction->transaction_type == "repayment" && $loanTransaction->credit > 0) {
                $repaymentCount = $repaymentCount + 1;
                $lastPaymentDate = $loanTransaction->date;
                $isFirstMonth = false;
                // $amountPaid = $amountPaid + ($loanTransaction->credit-$loanTransaction->debit);
            } else if ($loanTransaction->transaction_type == "pay_off") {
                $isFirstMonth = false;
                return 0.0;
            }
        }

        if ($loan->interest_method == "interest_only") {
            if ($repaymentCount == 0) {
                $mainBalanceRest = $loan->principal;
                $interestToUncharge = LoanSchedule::where('loan_id', $loan->id)->sum("interest");;
            } else {
                $loanSchedules = LoanSchedule::where('loan_id', $loan->id)->orderBy('due_date', 'asc');

                $mainBalanceRest = $loan->principal;
                $interestToUncharge = $loanSchedules->get()->slice($repaymentCount)->sum("interest");
                // dd($interestToUncharge,$repaymentCount, $mainBalanceRest, $amountPaid);
            }
        } else {
            if ($repaymentCount == 0) {
                $mainBalanceRest = $loan->principal;
                $interestToUncharge = LoanSchedule::where('loan_id', $loan->id)->where("description", "Repayment")->sum("interest");
            } else {
                $loanSchedules = LoanSchedule::where('loan_id', $loan->id)->orderBy('due_date', 'asc');
                $tmp = clone $loanSchedules;
                $mainBalanceRest = $tmp->get()->slice($repaymentCount - 1)->first()->principal_balance;
                $interestToUncharge = $tmp->get()->slice($repaymentCount)->sum("interest");
            }
        }

        //  what we have to know: total paid , Total interest for past duration only, rest amount that borrowed (not include interest) ,
        //  Total PayOffAmount = rest amount that borrow * pay off Rate
        // $interestToUncharge =  ( $loan_total_balance* ($loan->interest_rate/100) * ($loan->loan_duration-$repaymentCount) );
        $today = Carbon::today();
        $dayPassFromLastRepayment = Carbon::parse($lastPaymentDate)->diffInDays($today);

        if ($dayPassFromLastRepayment > 15 || $isFirstMonth) {
            // pay off interest full month
            if ($getType == "payOffAmount") {
                // $mainBalanceRest = $currentBalance-$interestToUncharge;
                return $mainBalanceRest + ($mainBalanceRest * ($loan->pay_off_interest_rate / 100));
            } else if ($getType == "payOffInterestRate") {
                // $mainBalanceRest = $currentBalance;
                return $mainBalanceRest * ($loan->pay_off_interest_rate / 100);
            } else if ($getType == "principal") {
                return $mainBalanceRest;

            } else {
                return $interestToUncharge;
            }
        } else {
            if ($getType == "payOffAmount") {
                // $mainBalanceRest = $currentBalance-$interestToUncharge;
                return $mainBalanceRest + ($mainBalanceRest * ((($loan->pay_off_interest_rate / Carbon::today()->daysInMonth) * $dayPassFromLastRepayment) / 100));
            } else if ($getType == "payOffInterestRate") {
                // $mainBalanceRest = $currentBalance;
                return $mainBalanceRest * ((($loan->pay_off_interest_rate / Carbon::today()->daysInMonth) * $dayPassFromLastRepayment) / 100);

            } else if ($getType == "principal") {
                return $mainBalanceRest;

            } else {
                return $interestToUncharge;
            }
        }
    }

    public function storeRepayment(Request $request, $loan)
    {
        if (!Sentinel::hasAccess('repayments.create')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }

        $amount_to_pay = GeneralHelper::get_total_repayment_amount($request->schedule_id);

        // if (round($request->amount) < round($amount_to_pay)) {
        //     Flash::warning("Amount (" . $request->amount . ") is less than schedule due amount (" . $amount_to_pay . ")");
        //     return redirect()->back()->withInput();
        // }

        if (round($request->amount) != round($amount_to_pay)) {
            Flash::warning("Amount (" . $request->amount . ") is not equal schedule due amount (" . $amount_to_pay . ")");
            return redirect()->back()->withInput();
        } else if ($request->amount == 0) {
            Flash::warning("Amount must be greater than 0");
            return redirect()->back()->withInput();
        }

        // if ($request->collection_date > date("Y-m-d")) {
        //     Flash::warning(translate('future_date_error'));
        //     return redirect()->back()->withInput();
        // }
        // if ($request->collection_date < $loan->disbursed_date) {
        //     Flash::warning(translate('early_date_error'));
        //     return redirect()->back()->withInput();
        // }

        // is over pay?
        // $is_overpay = false;
        // $amt_overpay = 0;
        // if (round($request->amount) > round($amount_to_pay)) {
        //     $amt_overpay = $request->amount - $amount_to_pay;
        //     $is_overpay = true;
        // }

        //add interest transaction
        $loan_transaction = new LoanTransaction();
        $loan_transaction->user_id = Sentinel::getUser()->id;
        $loan_transaction->branch_id = session('branch_id');
        $loan_transaction->loan_id = $loan->id;
        $loan_transaction->loan_schedule_id = $request->schedule_id;
        $loan_transaction->borrower_id = $loan->borrower_id;
        $loan_transaction->transaction_type = "repayment";
        $loan_transaction->receipt = $request->receipt;
        $loan_transaction->date = $request->collection_date;
        $loan_transaction->reversible = 1;
        $loan_transaction->repayment_method_id = $request->repayment_method_id;
        $date = explode('-', $request->collection_date);
        $loan_transaction->year = $date[0];
        $loan_transaction->month = $date[1];
        $loan_transaction->credit = $request->amount; //$amount_to_pay;
        $loan_transaction->notes = $request->notes;
        $loan_transaction->save();
        //fire payment added event
        //debit and credit the necessary accounts

        $allocation = GeneralHelper::loan_allocate_payment($loan_transaction);

        //return $allocation;
        //principal
        // dd($allocation['principal'],$loan->loan_product);
        if ($allocation['principal'] > 0) {
            if (!empty($loan->loan_product->chart_loan_portfolio)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_loan_portfolio->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->transaction_sub_type = 'repayment_principal';
                $journal->name = "Principal Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->credit = $allocation['principal'] + $request->overpay;
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
            if (!empty($loan->loan_product->chart_fund_source)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_fund_source->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->name = "Principal Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->debit = $allocation['principal'] + $request->overpay;
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
        }
        //interest
        if ($allocation['interest'] > 0) {
            if (!empty($loan->loan_product->chart_income_interest)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_income_interest->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->transaction_sub_type = 'repayment_interest';
                $journal->name = "Interest Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->credit = $allocation['interest'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
            if (!empty($loan->loan_product->chart_receivable_interest)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_receivable_interest->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->name = "Interest Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->debit = $allocation['interest'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
        }
        //fees
        if ($allocation['fees'] > 0) {
            if (!empty($loan->loan_product->chart_income_fee)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_income_fee->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->transaction_sub_type = 'repayment_fees';
                $journal->name = "Fees Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->credit = $allocation['fees'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
            if (!empty($loan->loan_product->chart_receivable_fee)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_receivable_fee->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->name = "Fees Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->debit = $allocation['fees'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
        }
        if ($allocation['penalty'] > 0) {
            if (!empty($loan->loan_product->chart_income_penalty)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_income_penalty->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->transaction_sub_type = 'repayment_penalty';
                $journal->name = "Penalty Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->credit = $allocation['penalty'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
            if (!empty($loan->loan_product->chart_receivable_penalty)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_receivable_penalty->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->name = "Penalty Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->debit = $allocation['penalty'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
        }
        //save custom meta
        $custom_fields = CustomField::where('category', 'repayments')->get();
        foreach ($custom_fields as $key) {
            $custom_field = new CustomFieldMeta();
            $id = $key->id;
            $custom_field->name = $request->$id;
            $custom_field->parent_id = $loan_transaction->id;
            $custom_field->custom_field_id = $key->id;
            $custom_field->category = "repayments";
            $custom_field->save();
        }
        //update loan status if need be
        if (round(GeneralHelper::loan_total_balance($loan->id)) <= 0) {
            $l = Loan::find($loan->id);
            $l->status = "closed";
            $l->save();
        }

        if ($request->overpay > 0) {
            $loan_transaction->credit = $request->amount + $request->overpay;
            $loan_transaction->save();

            $loanSchedule = LoanSchedule::where('id', $request->schedule_id)->first();
            $principal_balance = $loanSchedule->principal_balance - $request->overpay;
            $loanTransaction = LoanTransaction::where('loan_id', $loan->id)->where('transaction_type', 'repayment')->where('reversed', 0)->get();

            // $loan_transaction                      = new LoanTransaction();
            // $loan_transaction->user_id             = Sentinel::getUser()->id;
            // $loan_transaction->branch_id           = session('branch_id');
            // $loan_transaction->loan_id             = $loan->id;
            // $loan_transaction->loan_schedule_id    = $request->schedule_id;
            // $loan_transaction->borrower_id         = $loan->borrower_id;
            // $loan_transaction->transaction_type    = "overpay";
            // $loan_transaction->receipt             = $request->receipt;
            // $loan_transaction->date                = $request->collection_date;
            // $loan_transaction->reversible          = 1;
            // $loan_transaction->repayment_method_id = $request->repayment_method_id;
            // $date                                  = explode('-', $request->collection_date);
            // $loan_transaction->year                = $date[0];
            // $loan_transaction->month               = $date[1];
            // $loan_transaction->credit              = $amt_overpay;
            // $loan_transaction->notes               = $request->notes;
            // $loan_transaction->save();

            //TODO: Reschedule
            $re = new Request();
            $re->principal = $principal_balance;
            $re->status = "disbursed";
            $re->interest_method = $loan->interest_method;
            $re->interest_rate = $loan->interest_rate;
            $re->pay_off_interest_rate = $loan->pay_off_interest_rate;
            $re->branch_id = session('branch_id');
            $re->interest_period = $loan->interest_period;
            $re->loan_duration = $loan->loan_duration - count($loanTransaction);
            $re->loan_duration_type = $loan->loan_duration_type;
            $re->repayment_cycle = $loan->repayment_cycle;
            $re->decimal_places = $loan->decimal_places;
            $re->override_interest = $loan->override_interest;
            $re->override_interest_amount = $loan->override_interest_amount;
            $re->grace_on_interest_charged = $loan->grace_on_interest_charged;
            $re->borrower_id = $loan->borrower_id;
            $re->applied_amount = $principal_balance;
            $re->user_id = Sentinel::getUser()->id;
            $re->loan_product_id = $loan->loan_product_id;
            $re->release_date = Carbon::now()->format('Y-m-d');
            $re->first_payment_date = Carbon::createFromFormat('Y-m-d', $loanSchedule->due_date)->addMonth(1)->format('Y-m-d');
            $re->disbursed_date = Carbon::now()->format('Y-m-d'); //$loanSchedule->due_date;
            $re->loan_disbursed_by_id = null;
            $re->disbursed_notes = null;

            $this->rescheduleStore($re, $loan->id);

            // if (!empty($loan->loan_product->chart_income_interest)) {
            //     $journal = new JournalEntry();
            //     $journal->user_id = Sentinel::getUser()->id;
            //     $journal->account_id = $loan->loan_product->chart_income_interest->id;
            //     $journal->branch_id = $loan->branch_id;
            //     $journal->date = $request->collection_date;
            //     $journal->year = $date[0];
            //     $journal->month = $date[1];
            //     $journal->borrower_id = $loan->borrower_id;
            //     $journal->transaction_type = 'repayment';
            //     $journal->transaction_sub_type = 'repayment_interest';
            //     $journal->name = "Interest Repayment";
            //     $journal->loan_id = $loan->id;
            //     $journal->loan_transaction_id = $loan_transaction->id;
            //     $journal->credit = $amt_overpay;
            //     $journal->reference = $loan_transaction->id;
            //     $journal->save();
            // }
            // if (!empty($loan->loan_product->chart_receivable_interest)) {
            //     $journal = new JournalEntry();
            //     $journal->user_id = Sentinel::getUser()->id;
            //     $journal->account_id = $loan->loan_product->chart_receivable_interest->id;
            //     $journal->branch_id = $loan->branch_id;
            //     $journal->date = $request->collection_date;
            //     $journal->year = $date[0];
            //     $journal->month = $date[1];
            //     $journal->borrower_id = $loan->borrower_id;
            //     $journal->transaction_type = 'repayment';
            //     $journal->name = "Interest Repayment";
            //     $journal->loan_id = $loan->id;
            //     $journal->loan_transaction_id = $loan_transaction->id;
            //     $journal->debit = $amt_overpay;
            //     $journal->reference = $loan_transaction->id;
            //     $journal->save();
            // }
        }

        event(new RepaymentCreated($loan_transaction));

        GeneralHelper::audit_trail("Added repayment for loan with id:" . $loan->id);
        Flash::success("Repayment successfully saved");

        return redirect('loan/transaction/' . $loan_transaction->id . '/print_repayment_receipt');
        //redirect('loan/' . $loan->id . '/show');
    }


    public function storePayOff(Request $request, $loan)
    {
        if (!Sentinel::hasAccess('repayments.create')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        //return GeneralHelper::loan_allocate_payment($loan->id, $request->amount)["penalty"];

        if ($request->principal != round($this->getData($loan, 'principal'), 2)) {
            Flash::warning("Amount is more than the balance(" . $this->getData($loan, "payOffAmount") . ')');
            return redirect()->back()->withInput();
        } else if ($request->principal == 0) {
            Flash::warning("Amount must be greater than 0");
            return redirect()->back()->withInput();
        }
        // if ($request->collection_date > date("Y-m-d")) {
        //     Flash::warning(translate('future_date_error'));
        //     return redirect()->back()->withInput();
        // }
        // if ($request->collection_date < $loan->disbursed_date) {
        //     Flash::warning(translate('early_date_error'));
        //     return redirect()->back()->withInput();
        // }


        //add interest transaction (remove interest is because it's pay off)
        $loan_trans = new LoanTransaction();
        $loan_trans->user_id = Sentinel::getUser()->id;
        $loan_trans->branch_id = session('branch_id');
        $loan_trans->loan_id = $loan->id;
        $loan_trans->borrower_id = $loan->borrower_id;
        $loan_trans->transaction_type = "interest";
        $loan_trans->date = $request->collection_date;
        // $date = explode('-', $request->disbursed_date);
        $date = explode('-', $request->collection_date);
        $loan_trans->year = $date[0];
        $loan_trans->month = $date[1];
        $interestToUncharge = $this->getData($loan, "interestToUncharge") * (-1);
        $loan_trans->debit = $interestToUncharge;
        // dd($loan_trans);
        $loan_trans->save();

        //add pay off interest
        $loan_trans = new LoanTransaction();
        $loan_trans->user_id = Sentinel::getUser()->id;
        $loan_trans->branch_id = session('branch_id');
        $loan_trans->loan_id = $loan->id;
        $loan_trans->borrower_id = $loan->borrower_id;
        $loan_trans->transaction_type = "interest";
        $loan_trans->date = $request->collection_date;
        // $date = explode('-', $request->disbursed_date);
        $date = explode('-', $request->collection_date);
        $loan_trans->year = $date[0];
        $loan_trans->month = $date[1];
        $payOffInterestRate = $request->payOffInterestRate;
        $loan_trans->debit = $payOffInterestRate;
        // dd($loan_trans);
        $loan_trans->save();

        //add pay off transaction
        $loan_transaction = new LoanTransaction();
        $loan_transaction->user_id = Sentinel::getUser()->id;
        $loan_transaction->branch_id = session('branch_id');
        $loan_transaction->loan_id = $loan->id;
        $loan_transaction->borrower_id = $loan->borrower_id;
        $loan_transaction->transaction_type = "pay_off";
        $loan_transaction->receipt = $request->receipt;
        $loan_transaction->date = $request->collection_date;
        $loan_transaction->reversible = 1;
        $loan_transaction->repayment_method_id = $request->repayment_method_id;
        $date = explode('-', $request->collection_date);
        $loan_transaction->year = $date[0];
        $loan_transaction->month = $date[1];
        $loan_transaction->credit = $request->principal + $request->payOffInterestRate;
        // $loan_transaction->debit = ($this->getData($loan, "interestToUncharge")- $this->getData($loan, "payOffInterestRate"))*(-1);
        $loan_transaction->notes = $request->notes;
        // dd($loan_transaction);
        $loan_transaction->save();
        //fire payment added event
        //debit and credit the necessary accounts
        GeneralHelper::modify_loan_schedules($loan_transaction, $interestToUncharge + $payOffInterestRate);
        $allocation = GeneralHelper::loan_allocate_payment($loan_transaction);
        //return $allocation;
        //principal
        // if ($allocation['pay_off'] > 0) {
        //     if (!empty($loan->loan_product->chart_loan_portfolio)) {
        //         $journal = new JournalEntry();
        //         $journal->user_id = Sentinel::getUser()->id;
        //         $journal->account_id = $loan->loan_product->chart_loan_portfolio->id;
        //         $journal->branch_id = $loan->branch_id;
        //         $journal->date = $request->collection_date;
        //         $journal->year = $date[0];
        //         $journal->month = $date[1];
        //         $journal->borrower_id = $loan->borrower_id;
        //         $journal->transaction_type = 'pay_off';
        //         $journal->transaction_sub_type = 'pay_off';
        //         $journal->name = "Principal Pay Off";
        //         $journal->loan_id = $loan->id;
        //         $journal->loan_transaction_id = $loan_transaction->id;
        //         $journal->credit = $allocation['principal'];
        //         $journal->reference = $loan_transaction->id;
        //         $journal->save();
        //     }
        //     if (!empty($loan->loan_product->chart_fund_source)) {
        //         $journal = new JournalEntry();
        //         $journal->user_id = Sentinel::getUser()->id;
        //         $journal->account_id = $loan->loan_product->chart_fund_source->id;
        //         $journal->branch_id = $loan->branch_id;
        //         $journal->date = $request->collection_date;
        //         $journal->year = $date[0];
        //         $journal->month = $date[1];
        //         $journal->borrower_id = $loan->borrower_id;
        //         $journal->transaction_type = 'pay_off';
        //         $journal->name = "Principal Pay Off";
        //         $journal->loan_id = $loan->id;
        //         $journal->loan_transaction_id = $loan_transaction->id;
        //         $journal->debit = $allocation['pay_off'];
        //         $journal->reference = $loan_transaction->id;
        //         $journal->save();
        //     }
        // }
        // principal
        if ($allocation['principal'] > 0) {
            if (!empty($loan->loan_product->chart_loan_portfolio)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_loan_portfolio->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->name = "Principal Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->credit = $allocation['principal'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
            if (!empty($loan->loan_product->chart_fund_source)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_fund_source->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->name = "Principal Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->debit = $allocation['principal'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
        }
        //interest
        if ($allocation['interest'] > 0) {
            if (!empty($loan->loan_product->chart_income_interest)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_income_interest->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'pay_off';
                $journal->transaction_sub_type = 'repayment_interest';
                $journal->name = "Interest Pay Off";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->credit = $allocation['interest'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
            if (!empty($loan->loan_product->chart_receivable_interest)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_receivable_interest->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'pay_off';
                $journal->name = "Interest Pay Off";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->debit = $allocation['interest'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
        }
        //save custom meta
        $custom_fields = CustomField::where('category', 'repayments')->get();
        foreach ($custom_fields as $key) {
            $custom_field = new CustomFieldMeta();
            $id = $key->id;
            $custom_field->name = $request->$id;
            $custom_field->parent_id = $loan_transaction->id;
            $custom_field->custom_field_id = $key->id;
            $custom_field->category = "pay_off";
            $custom_field->save();
        }
        //update loan status if need be
        if (round(GeneralHelper::loan_total_balance($loan->id)) <= 0) {
            $l = Loan::find($loan->id);
            $l->status = "closed";
            $l->save();
        }

        event(new RepaymentCreated($loan_transaction));

        GeneralHelper::audit_trail("Added Pay Off for loan with id:" . $loan->id);
        Flash::success("Pay Off successfully saved");
        // return redirect('loan/' . $loan->id . '/show');
        return redirect('loan/transaction/' . $loan_transaction->id . '/print_pay_off_receipt');
    }


    public function reverseRepayment($id)
    {
        if (!Sentinel::hasAccess('repayments.update')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan_transaction = LoanTransaction::find($id);
        $loan_transaction->reversible = 0;
        $loan_transaction->reversed = 1;
        $loan_transaction->reversal_type = "user";
        $loan_transaction->debit = $loan_transaction->credit;
        $loan_transaction->save();
        //reverse journal transactions
        foreach (JournalEntry::where('reference', $id)->where(
            'loan_id',
            $loan_transaction->loan_id
        )->where('transaction_type', 'repayment')->get() as $key) {
            $journal = JournalEntry::find($key->id);
            if ($key->debit > $key->credit) {
                $journal->credit = $journal->debit;
            } else {
                $journal->debit = $journal->credit;
            }
            $journal->reversed = 1;
            $journal->save();
        }
        //trigger transactions refresh
        event(new RepaymentReversed($loan_transaction));
        Flash::success(translate('successfully_saved'));
        return redirect('loan/' . $loan_transaction->loan_id . '/show');
    }

    public function reversePayOff($id)
    {
        if (!Sentinel::hasAccess('repayments.update')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan_transactions = LoanTransaction::whereIn('id', [$id, ($id - 1), ($id - 2)])->get();
        // $id-1 & $Id-2 is transaction created when we pay off
        $loan_id = 0;
        foreach ($loan_transactions as $loan_transaction) {
            $loan_id = $loan_transaction->loan_id;

            $loan_transaction->reversible = 0;
            $loan_transaction->reversed = 1;
            $loan_transaction->reversal_type = "user";
            $loan_transaction->debit = $loan_transaction->credit;
            $loan_transaction->save();
            //reverse journal transactions
            foreach (JournalEntry::where('reference', $id)->where(
                'loan_id',
                $loan_transaction->loan_id
            )->where('transaction_type', 'pay_off')->get() as $key) {
                $journal = JournalEntry::find($key->id);
                if ($key->debit > $key->credit) {
                    $journal->credit = $journal->debit;
                } else {
                    $journal->debit = $journal->credit;
                }
                $journal->reversed = 1;
                $journal->save();
            }
            //trigger transactions refresh
            event(new PayOffReversed($loan_transaction));
        }
        LoanSchedule::where('loan_id', $loan_id)->where('description', 'Pay Off')->first()->delete();

        Flash::success(translate('successfully_saved'));
        return redirect('loan/' . $loan_transaction->loan_id . '/show');
    }


    public function deleteRepayment($loan, $id)
    {
        if (!Sentinel::hasAccess('repayments.delete')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        LoanRepayment::destroy($id);
        if (GeneralHelper::loan_total_balance($loan->id) > 0 && $loan->status == "closed") {
            $l = Loan::find($loan->id);
            $l->status = "disbursed";
            $l->save();
        }
        //remove entries from the journal table
        JournalEntry::where('loan_transaction_id', $id)->delete();
        GeneralHelper::audit_trail("Deleted repayment for loan with id:" . $loan->id);
        Flash::success("Repayment successfully deleted");
        return redirect('loan/' . $loan->id . '/show');
    }

    //    print repayment
    public function pdfRepayment($loan_transaction)
    {
        PDF::AddPage();
        PDF::writeHTML(View::make('loan_repayment.pdf', compact('loan_transaction'))->render());
        PDF::SetAuthor('Tererai Mugova');
        PDF::Output(
            $loan_transaction->borrower->title . ' ' . $loan_transaction->borrower->first_name . ' ' . $loan_transaction->borrower->last_name . " - Repayment Receipt.pdf",
            'D'
        );
    }

    public function printRepayment($loan_transaction)
    {

        return view('loan_repayment.print', compact('loan_transaction'));
    }

    public function editRepayment($loan_transaction)
    {
        if (!Sentinel::hasAccess('repayments.update')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $repayment_methods = array();
        foreach (LoanRepaymentMethod::all() as $key) {
            $repayment_methods[$key->id] = $key->name;
        }
        $custom_fields = CustomField::where('category', 'repayments')->get();
        return view('loan_repayment.edit', compact('loan_transaction', 'repayment_methods', 'custom_fields'));
    }

    public function updateRepayment(Request $request, $id)
    {
        if (!Sentinel::hasAccess('repayments.update')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }

        $loan_transaction = LoanTransaction::find($id);
        if ($request->collection_date > date("Y-m-d")) {
            Flash::warning(translate('future_date_error'));
            return redirect()->back()->withInput();
        }
        if ($request->collection_date < $loan_transaction->loan->first_payment_date) {
            Flash::warning(translate('early_date_error'));
            return redirect()->back()->withInput();
        }
        $loan_transaction->reversible = 0;
        $loan_transaction->reversed = 1;
        $loan_transaction->reversal_type = "user";
        $loan_transaction->debit = $loan_transaction->credit;
        $loan_transaction->save();
        //reverse journal transactions
        foreach (JournalEntry::where('reference', $id)->where(
            'loan_id',
            $loan_transaction->loan_id
        )->where('transaction_type', 'repayment')->get() as $key) {
            $journal = JournalEntry::find($key->id);
            if ($key->debit > $key->credit) {
                $journal->credit = $journal->debit;
            } else {
                $journal->debit = $journal->credit;
            }
            $journal->save();
        }
        //trigger transactions refresh
        event(new RepaymentReversed($loan_transaction));
        //save new loan transaction

        //save custom meta
        $custom_fields = CustomField::where('category', 'repayments')->get();
        foreach ($custom_fields as $key) {
            if (!empty(CustomFieldMeta::where('custom_field_id', $key->id)->where(
                'parent_id',
                $id
            )->where('category', 'repayments')->first())) {
                $custom_field = CustomFieldMeta::where('custom_field_id', $key->id)->where(
                    'parent_id',
                    $id
                )->where('category', 'repayments')->first();
            } else {
                $custom_field = new CustomFieldMeta();
            }
            $kid = $key->id;
            $custom_field->name = $request->$kid;
            $custom_field->parent_id = $id;
            $custom_field->custom_field_id = $key->id;
            $custom_field->category = "repayments";
            $custom_field->save();
        }
        $loan = $loan_transaction->loan;
        //add interest transaction
        $loan_transaction = new LoanTransaction();
        $loan_transaction->user_id = Sentinel::getUser()->id;
        $loan_transaction->branch_id = session('branch_id');
        $loan_transaction->loan_id = $loan->id;
        $loan_transaction->borrower_id = $loan->borrower_id;
        $loan_transaction->transaction_type = "repayment";
        $loan_transaction->receipt = $request->receipt;
        $loan_transaction->date = $request->collection_date;
        $loan_transaction->reversible = 1;
        $loan_transaction->repayment_method_id = $request->repayment_method_id;
        $date = explode('-', $request->collection_date);
        $loan_transaction->year = $date[0];
        $loan_transaction->month = $date[1];
        $loan_transaction->credit = $request->amount;
        $loan_transaction->notes = $request->notes;
        $loan_transaction->save();
        //fire payment added event
        //debit and credit the necessary accounts
        $allocation = GeneralHelper::loan_allocate_payment($loan_transaction);
        //return $allocation;
        //principal
        if ($allocation['principal'] > 0) {
            if (!empty($loan->loan_product->chart_loan_portfolio)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_loan_portfolio->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->name = "Principal Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->credit = $allocation['principal'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
            if (!empty($loan->loan_product->chart_fund_source)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_fund_source->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->name = "Principal Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->debit = $allocation['principal'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
        }
        //interest
        if ($allocation['interest'] > 0) {
            if (!empty($loan->loan_product->chart_income_interest)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_income_interest->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->name = "Interest Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->credit = $allocation['interest'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
            if (!empty($loan->loan_product->chart_receivable_interest)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_receivable_interest->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->name = "Interest Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->debit = $allocation['interest'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
        }
        //fees
        if ($allocation['fees'] > 0) {
            if (!empty($loan->loan_product->chart_income_fee)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_income_fee->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->name = "Fees Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->credit = $allocation['fees'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
            if (!empty($loan->loan_product->chart_receivable_fee)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_receivable_fee->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->name = "Fees Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->debit = $allocation['fees'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
        }
        if ($allocation['penalty'] > 0) {
            if (!empty($loan->loan_product->chart_income_penalty)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_income_penalty->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->name = "Penalty Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->credit = $allocation['penalty'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
            if (!empty($loan->loan_product->chart_receivable_penalty)) {
                $journal = new JournalEntry();
                $journal->user_id = Sentinel::getUser()->id;
                $journal->account_id = $loan->loan_product->chart_receivable_penalty->id;
                $journal->branch_id = $loan->branch_id;
                $journal->date = $request->collection_date;
                $journal->year = $date[0];
                $journal->month = $date[1];
                $journal->borrower_id = $loan->borrower_id;
                $journal->transaction_type = 'repayment';
                $journal->name = "Penalty Repayment";
                $journal->loan_id = $loan->id;
                $journal->loan_transaction_id = $loan_transaction->id;
                $journal->debit = $allocation['penalty'];
                $journal->reference = $loan_transaction->id;
                $journal->save();
            }
        }
        event(new RepaymentUpdated($loan_transaction));

        //update loan status if need be
        if (round(GeneralHelper::loan_total_balance($loan_transaction->loan_id)) <= 0) {
            $l = Loan::find($loan_transaction->loan_id);
            $l->status = "closed";
            $l->save();
        } else {
            $l = Loan::find($loan_transaction->loan_id);
            $l->status = "disbursed";
            $l->save();
        }
        GeneralHelper::audit_trail("Updated repayment for loan with id:" . $loan_transaction->loan_id);
        Flash::success("Repayment successfully saved");
        return redirect('loan/' . $loan_transaction->loan_id . '/show');
    }

    //transactions
    public function showTransaction($loan_transaction)
    {
        $custom_fields = CustomFieldMeta::where('category', 'repayments')->where(
            'parent_id',
            $loan_transaction->id
        )->get();
        return view('loan_transaction.show', compact('loan_transaction', 'custom_fields'));
    }

    public function pdfTransaction($loan_transaction)
    {
        $pdf = \App\Services\Pdf::loadView('loan_transaction.pdf', compact('loan_transaction'));
        return $pdf->download($loan_transaction->borrower->title . ' ' . $loan_transaction->borrower->first_name . ' ' . $loan_transaction->borrower->last_name . " - Repayment Receipt.pdf");
    }

    public function printTransaction($loan_transaction)
    {
        return view('loan_transaction.print', compact('loan_transaction'));
    }

    public function printRepaymentReceipt($loan_transaction)
    {
        return view('loan_transaction.print_repayment_receipt', compact('loan_transaction'));
    }

    public function printPayOffReceipt($loan_transaction)
    {
        return view('loan_transaction.print_pay_off_receipt', compact('loan_transaction'));
    }

    //edit loan schedule
    public function editSchedule($loan)
    {
        if (!Sentinel::hasAccess('loans.update')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $rows = 0;
        $schedules = LoanSchedule::where('loan_id', $loan->id)->orderBy('due_date', 'asc')->get();
        return view('loan.edit_schedule', compact('loan', 'schedules', 'rows'));
    }

    public function updateSchedule(Request $request, $loan)
    {
        if (!Sentinel::hasAccess('loans.update')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        if ($request->submit == 'add_row') {
            $rows = $request->addrows;
            $schedules = LoanSchedule::where('loan_id', $loan->id)->orderBy('due_date', 'asc')->get();
            return view('loan.edit_schedule', compact('loan', 'schedules', 'rows'));
        }
        if ($request->submit == 'submit') {
            //lets delete existing schedules
            LoanSchedule::where('loan_id', $loan->id)->delete();
            for ($count = 0; $count < $request->count; $count++) {
                $schedule = new LoanSchedule();
                if (empty($request->due_date) && empty($request->principal) && empty($request->interest) && empty($request->fees) && empty($request->penalty)) {
                    //do nothing
                } elseif (empty($request->due_date)) {
                    //do nothing
                } else {
                    //all rosy, lets save our data here
                    $schedule->due_date = $request->due_date[$count];
                    $schedule->principal = $request->principal[$count];
                    $schedule->description = $request->description[$count];
                    $schedule->loan_id = $loan->id;
                    $schedule->borrower_id = $loan->borrower_id;
                    $schedule->interest = $request->interest[$count];
                    $schedule->fees = $request->fees[$count];
                    $schedule->penalty = $request->penalty[$count];
                    $date = explode('-', $request->due_date[$count]);
                    $schedule->month = $date[1];
                    $schedule->year = $date[0];
                    $schedule->save();
                }
            }
            GeneralHelper::audit_trail("Updated Schedule for loan with id:" . $loan->id);
            Flash::success("Schedule successfully updated");
            return redirect('loan/' . $loan->id . '/show');
        }
    }

    //charges
    public function addCharge(Request $request, $loan)
    {
        if (!Sentinel::hasAccess('repayments.update')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        if ($request->date < $loan->disbursed_date) {
            Flash::warning(translate('early_date_error'));
            return redirect()->back()->withInput();
        }
        $due_date = GeneralHelper::determine_due_date($loan->id, $request->date);
        $schedule = LoanSchedule::where('due_date', $due_date)->where('loan_id', $loan->id)->first();
        if (!empty($schedule)) {
            //add charge transaction
            $loan_transaction = new LoanTransaction();
            $loan_transaction->user_id = Sentinel::getUser()->id;
            $loan_transaction->branch_id = session('branch_id');
            $loan_transaction->loan_id = $loan->id;
            $loan_transaction->borrower_id = $loan->borrower_id;
            $loan_transaction->transaction_type = "specified_due_date_fee";
            $loan_transaction->date = $due_date;
            $date = explode('-', $due_date);
            $loan_transaction->year = $date[0];
            $loan_transaction->month = $date[1];
            $loan_transaction->debit = $request->amount;
            $loan_transaction->notes = $request->notes;
            $loan_transaction->reversible = 1;
            $loan_transaction->save();
            //update schedule
            $schedule->fees = $schedule->fees + $request->amount;
            $schedule->save();
            GeneralHelper::audit_trail("Added charge for loan with id " . $loan->id);
            //trigger transactions refresh
            event(new LoanTransactionUpdated($loan_transaction));
            Flash::success("Charge successfully saved");
            return redirect()->back();
        } else {
            Flash::warning("An error occurred. No schedule found to apply");
            return redirect()->back()->withInput();
        }
    }

    public function waiveTransaction(Request $request, $id)
    {
        if (!Sentinel::hasAccess('repayments.update')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan_transaction = LoanTransaction::find($id);
        $loan_transaction->reversible = 0;
        $loan_transaction->reversed = 1;
        $loan_transaction->credit = $loan_transaction->debit;
        $loan_transaction->reversal_type = "user";
        $loan_transaction->save();
        $schedule = LoanSchedule::where('due_date', $loan_transaction->date)->where(
            'loan_id',
            $loan_transaction->loan_id
        )->first();
        if (!empty($schedule)) {
            //update schedule
            $schedule->fees = $schedule->fees - $loan_transaction->debit;
            $schedule->save();
            GeneralHelper::audit_trail("Waived charge for loan with id " . $loan_transaction->loan_id);
            //trigger transactions refresh
            event(new InterestWaived($loan_transaction));
            event(new RepaymentReversed($loan_transaction));
            Flash::success("Charge successfully saved");
            return redirect()->back();
        } else {
            Flash::warning("An error occurred. No schedule found to apply");
            return redirect()->back()->withInput();
        }
    }

    public function pdfSchedule($loan)
    {

        $schedules = LoanSchedule::where('loan_id', $loan->id)->orderBy('due_date', 'asc')->get();
        $pdf = Pdf::loadView('loan.pdf_schedule', compact('loan', 'schedules'));
        $pdf->setPaper('A4', 'landscape');
        return $pdf->download($loan->borrower->title . ' ' . $loan->borrower->first_name . ' ' . $loan->borrower->last_name . " - Loan Repayment Schedule.pdf");
    }

    public function printSchedule($loan)
    {
        $schedules = LoanSchedule::where('loan_id', $loan->id)->orderBy('due_date', 'asc')->get();
        return view('loan.print_schedule', compact('loan', 'schedules'));
    }

    public function printContractMotorRental($loan)
    {
        // dd($loan->branch);
        return view('loan.print_contract_motor_rental', compact('loan'));
    }

    public function printContractBorrowMoney($loan)
    {
        // dd($loan->branch);
        return view('loan.print_contract_borrow_money', compact('loan'));
    }

    public function printContractRealEstateMortgage($loan)
    {
        // dd($loan->branch);
        return view('loan.print_real_estate_mortgage', compact('loan'));
    }

    public function printContractBuySellMotor($loan)
    {
        // dd($loan->branch);
        return view('loan.print_contract_buy_sell_motor', compact('loan'));
    }

    public function printCollateralReceipt($loan)
    {
        // dd($loan->branch);
        return view('loan.print_collateral_receipt', compact('loan'));
    }


    public function pdfLoanStatement($loan)
    {
        $payments = LoanRepayment::where('loan_id', $loan->id)->orderBy('collection_date', 'asc')->get();
        $pdf = Pdf::loadView('loan.pdf_loan_statement', compact('loan', 'payments'));
        $pdf->setPaper('A4', 'landscape');
        return $pdf->download($loan->borrower->title . ' ' . $loan->borrower->first_name . ' ' . $loan->borrower->last_name . " - Loan Statement.pdf");
    }

    public function printLoanStatement($loan)
    {
        $payments = LoanRepayment::where('loan_id', $loan->id)->orderBy('collection_date', 'asc')->get();
        return view('loan.print_loan_statement', compact('loan', 'payments'));
    }

    public function pdfBorrowerStatement($borrower)
    {
        $loans = Loan::where('borrower_id', $borrower->id)->orderBy('release_date', 'asc')->get();
        $pdf = \App\Services\Pdf::loadView('loan.pdf_borrower_statement', compact('loans','borrower'));
        $pdf->setPaper('A4', 'landscape');
        return $pdf->download($borrower->title . ' ' . $borrower->first_name . ' ' . $borrower->last_name . " - Client Statement.pdf");
    }

    public function printBorrowerStatement($borrower)
    {
        $loans = Loan::where('borrower_id', $borrower->id)->orderBy('release_date', 'asc')->get();
        return view('loan.print_borrower_statement', compact('loans'));
    }

    public function override(Request $request, $loan)
    {
        if (!Sentinel::hasAccess('loans.update')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        if ($request->isMethod('post')) {
            $l = Loan::find($loan->id);
            $l->balance = $request->balance;
            if (empty($request->override)) {
                $l->override = 0;
            } else {
                $l->override = $request->override;
            }
            $l->save();
            GeneralHelper::audit_trail("Override balance for loan with id:" . $loan->id);
            Flash::success(translate('override_successfully_applied'));
            return redirect('loan/' . $loan->id . '/show');
        }
        return view('loan.override', compact('loan'));
    }

    public function emailBorrowerStatement($borrower)
    {
        if (!empty($borrower->email)) {
            $body = Setting::where(
                'setting_key',
                'borrower_statement_email_template'
            )->first()->setting_value;
            $body = str_replace('{borrowerTitle}', $borrower->title, $body);
            $body = str_replace('{borrowerFirstName}', $borrower->first_name, $body);
            $body = str_replace('{borrowerLastName}', $borrower->last_name, $body);
            $body = str_replace('{borrowerAddress}', $borrower->address, $body);
            $body = str_replace('{borrowerUniqueNumber}', $borrower->unique_number, $body);
            $body = str_replace('{borrowerMobile}', $borrower->mobile, $body);
            $body = str_replace('{borrowerPhone}', $borrower->phone, $body);
            $body = str_replace('{borrowerEmail}', $borrower->email, $body);
            $body = str_replace('{loansPayments}', GeneralHelper::borrower_loans_total_paid($borrower->id), $body);
            $body = str_replace(
                '{loansDue}',
                round(GeneralHelper::borrower_loans_total_due($borrower->id), 2),
                $body
            );
            $body = str_replace(
                '{loansBalance}',
                round((GeneralHelper::borrower_loans_total_due($borrower->id) - GeneralHelper::borrower_loans_total_paid($borrower->id)),
                    2
                ),
                $body
            );
            $body = str_replace(
                '{loanPayments}',
                GeneralHelper::borrower_loans_total_paid($borrower->id),
                $body
            );
            $loans = Loan::where('borrower_id', $borrower->id)->orderBy('release_date', 'asc')->get();
            $file_name = $borrower->title . ' ' . $borrower->first_name . ' ' . $borrower->last_name . " - Client Statement.pdf";
            Mail::raw($body, function ($message) use ($borrower, $file_name, $loans) {
                $message->from(
                    Setting::where('setting_key', 'company_email')->first()->setting_value,
                    Setting::where('setting_key', 'company_name')->first()->setting_value
                );
                $message->to($borrower->email);
                $headers = $message->getHeaders();
                $pdf = Pdf::loadView('loan.pdf_borrower_statement', compact('loans'));
                $message->attachData($pdf->output(), $file_name);
                $message->setContentType('text/html');
                $message->setSubject(Setting::where(
                    'setting_key',
                    'borrower_statement_email_subject'
                )->first()->setting_value);
            });
            $mail = new Email();
            $mail->user_id = Sentinel::getUser()->id;
            $mail->message = $body;
            $mail->subject = Setting::where(
                'setting_key',
                'borrower_statement_email_subject'
            )->first()->setting_value;
            $mail->recipients = 1;
            $mail->send_to = $borrower->first_name . ' ' . $borrower->last_name . '(' . $borrower->unique_number . ')';
            $mail->save();
            Flash::success("Statement successfully sent");
            return redirect('borrower/' . $borrower->id . '/show');
        } else {
            Flash::warning("Borrower has no email set");
            return redirect('borrower/' . $borrower->id . '/show');
        }
    }

    public function emailLoanStatement($loan)
    {
        $borrower = $loan->borrower;
        if (!empty($borrower->email)) {
            $body = Setting::where(
                'setting_key',
                'loan_statement_email_template'
            )->first()->setting_value;
            $body = str_replace('{borrowerTitle}', $borrower->title, $body);
            $body = str_replace('{borrowerFirstName}', $borrower->first_name, $body);
            $body = str_replace('{borrowerLastName}', $borrower->last_name, $body);
            $body = str_replace('{borrowerAddress}', $borrower->address, $body);
            $body = str_replace('{borrowerUniqueNumber}', $borrower->unique_number, $body);
            $body = str_replace('{borrowerMobile}', $borrower->mobile, $body);
            $body = str_replace('{borrowerPhone}', $borrower->phone, $body);
            $body = str_replace('{borrowerEmail}', $borrower->email, $body);
            $body = str_replace('{loanNumber}', $loan->id, $body);
            $body = str_replace('{loanPayments}', GeneralHelper::loan_total_paid($loan->id), $body);
            $body = str_replace(
                '{loanDue}',
                round(GeneralHelper::loan_total_due_amount($loan->id), 2),
                $body
            );
            $body = str_replace(
                '{loanBalance}',
                round((GeneralHelper::loan_total_due_amount($loan->id) - GeneralHelper::loan_total_paid($loan->id)),
                    2
                ),
                $body
            );
            $payments = LoanRepayment::where('loan_id', $loan->id)->orderBy('collection_date', 'asc')->get();
            $file_name = $borrower->title . ' ' . $borrower->first_name . ' ' . $borrower->last_name . " - Loan Statement.pdf";
            Mail::raw($body, function ($message) use ($borrower, $loan, $file_name, $payments) {
                $message->from(
                    Setting::where('setting_key', 'company_email')->first()->setting_value,
                    Setting::where('setting_key', 'company_name')->first()->setting_value
                );
                $message->to($borrower->email);
                $headers = $message->getHeaders();
                $pdf = Pdf::loadView('loan.pdf_loan_statement', compact('loan', 'payments'));
                $message->attachData($pdf->output(), $file_name);
                $message->setContentType('text/html');
                $message->setSubject(Setting::where(
                    'setting_key',
                    'loan_statement_email_subject'
                )->first()->setting_value);
            });
            $mail = new Email();
            $mail->user_id = Sentinel::getUser()->id;
            $mail->message = $body;
            $mail->subject = Setting::where(
                'setting_key',
                'loan_statement_email_subject'
            )->first()->setting_value;
            $mail->recipients = 1;
            $mail->send_to = $borrower->first_name . ' ' . $borrower->last_name . '(' . $borrower->unique_number . ')';
            $mail->save();
            Flash::success("Loan Statement successfully sent");
            return redirect('loan/' . $loan->id . '/show');
        } else {
            Flash::warning("Borrower has no email set");
            return redirect('loan/' . $loan->id . '/show');
        }
    }

    public function emailLoanSchedule($loan)
    {
        $borrower = $loan->borrower;
        if (!empty($borrower->email)) {
            $body = Setting::where(
                'setting_key',
                'loan_schedule_email_template'
            )->first()->setting_value;
            $body = str_replace('{borrowerTitle}', $borrower->title, $body);
            $body = str_replace('{borrowerFirstName}', $borrower->first_name, $body);
            $body = str_replace('{borrowerLastName}', $borrower->last_name, $body);
            $body = str_replace('{borrowerAddress}', $borrower->address, $body);
            $body = str_replace('{borrowerUniqueNumber}', $borrower->unique_number, $body);
            $body = str_replace('{borrowerMobile}', $borrower->mobile, $body);
            $body = str_replace('{borrowerPhone}', $borrower->phone, $body);
            $body = str_replace('{borrowerEmail}', $borrower->email, $body);
            $body = str_replace('{loanNumber}', $loan->id, $body);
            $body = str_replace('{loanPayments}', GeneralHelper::loan_total_paid($loan->id), $body);
            $body = str_replace(
                '{loanDue}',
                round(GeneralHelper::loan_total_due_amount($loan->id), 2),
                $body
            );
            $body = str_replace(
                '{loanBalance}',
                round((GeneralHelper::loan_total_due_amount($loan->id) - GeneralHelper::loan_total_paid($loan->id)),
                    2
                ),
                $body
            );
            $schedules = LoanSchedule::where('loan_id', $loan->id)->orderBy('due_date', 'asc')->get();
            $file_name = $borrower->title . ' ' . $borrower->first_name . ' ' . $borrower->last_name . " - Loan Schedule.pdf";
            Mail::raw($body, function ($message) use ($borrower, $loan, $file_name, $schedules) {
                $message->from(
                    Setting::where('setting_key', 'company_email')->first()->setting_value,
                    Setting::where('setting_key', 'company_name')->first()->setting_value
                );
                $message->to($borrower->email);
                $headers = $message->getHeaders();
                $pdf = Pdf::loadView('loan.pdf_schedule', compact('loan', 'schedules'));
                $message->attachData($pdf->output(), $file_name);
                $message->setContentType('text/html');
                $message->setSubject(Setting::where(
                    'setting_key',
                    'loan_schedule_email_subject'
                )->first()->setting_value);
            });
            $mail = new Email();
            $mail->user_id = Sentinel::getUser()->id;
            $mail->message = $body;
            $mail->subject = Setting::where(
                'setting_key',
                'loan_statement_email_subject'
            )->first()->setting_value;
            $mail->recipients = 1;
            $mail->send_to = $borrower->first_name . ' ' . $borrower->last_name . '(' . $borrower->unique_number . ')';
            $mail->save();
            Flash::success("Loan Statement successfully sent");
            return redirect('loan/' . $loan->id . '/show');
        } else {
            Flash::warning("Borrower has no email set");
            return redirect('loan/' . $loan->id . '/show');
        }
    }

    //loan applications
    public function indexApplication()
    {
        if (!Sentinel::hasAccess('loans')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $data = LoanApplication::where('branch_id', session('branch_id'))->get();

        return view('loan.applications', compact('data'));
    }

    public function declineApplication($id)
    {
        if (!Sentinel::hasAccess('loans')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $application = LoanApplication::find($id);
        $application->status = "declined";
        $application->save();
        GeneralHelper::audit_trail("Declined borrower  loan application with id:" . $id);
        Flash::success(translate('successfully_saved'));
        return redirect('loan/loan_application/data');
    }

    public function deleteApplication($id)
    {
        if (!Sentinel::hasAccess('loans')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        LoanApplication::destroy($id);
        Guarantor::where('loan_application_id', $id)->delete();
        GeneralHelper::audit_trail("Deleted borrower  loan application with id:" . $id);
        Flash::success(translate('successfully_deleted'));
        return redirect('loan/loan_application/data');
    }

    public function approveApplication($id)
    {
        if (!Sentinel::hasAccess('loans')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $application = LoanApplication::find($id);
        //get custom fields
        $custom_fields = CustomField::where('category', 'loans')->get();
        $loan_product = $application->loan_product;
        $charges = array();
        foreach (LoanProductCharge::where('loan_product_id', $loan_product->id)->get() as $key) {
            if (!empty($key->charge)) {
                $charges[$key->id] = $key->charge->name;
            }
        }
        $users = [];
        foreach (User::all() as $key) {
            $users[$key->id] = $key->first_name . ' ' . $key->last_name;
        }
        if (!empty($application->loan_product)) {
            return view(
                'loan.approve_application',
                compact('id', 'application', 'loan_product', 'users', 'custom_fields', 'charges')
            );
        } else {
            Flash::warning(translate('loan_application_approve_error'));
            return redirect('loan/loan_application/data');
        }
    }

    public function storeApproveApplication(Request $request, $id)
    {
        if (!Sentinel::hasAccess('loans')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $application = LoanApplication::find($id);
        $application->status = "approved";
        $application->save();
        //lets save the loan here
        if (!Sentinel::hasAccess('loans.create')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $loan = new Loan();
        $loan->principal = $request->principal;
        $loan->interest_method = $request->interest_method;
        $loan->interest_rate = $request->interest_rate;
        // $loan->pay_off_interest_rate = $request->pay_off_interest_rate;
        $loan->interest_period = $request->interest_period;
        $loan->loan_duration = $request->loan_duration;
        $loan->loan_duration_type = $request->loan_duration_type;
        $loan->repayment_cycle = $request->repayment_cycle;
        $loan->decimal_places = $request->decimal_places;
        $loan->override_interest = $request->override_interest;
        $loan->override_interest_amount = $request->override_interest_amount;
        $loan->grace_on_interest_charged = $request->grace_on_interest_charged;
        $loan->borrower_id = $request->borrower_id;
        $loan->branch_id = $application->branch_id;
        $loan->applied_amount = $request->principal;
        $loan->user_id = Sentinel::getUser()->id;
        $loan->loan_officer_id = $request->loan_officer_id;
        $loan->loan_product_id = $request->loan_product_id;
        $loan->release_date = $request->release_date;
        $date = explode('-', $request->release_date);
        $loan->month = $date[1];
        $loan->year = $date[0];
        if (!empty($request->first_payment_date)) {
            $loan->first_payment_date = $request->first_payment_date;
        }
        $loan->description = $request->description;
        $files = array();
        if (!empty($request->file('files'))) {
            $count = 0;
            foreach ($request->file('files') as $key) {
                $file = array('files' => $key);
                $rules = array('files' => 'required|mimes:jpeg,jpg,bmp,png,pdf,docx,xlsx');
                $validator = Validator::make($file, $rules);
                if ($validator->fails()) {
                    Flash::warning(translate('validation_error'));
                    return redirect()->back()->withInput()->withErrors($validator);
                } else {
                    $files[$count] = $key->getClientOriginalName();
                    $key->move(
                        public_path() . '/uploads',
                        $key->getClientOriginalName()
                    );
                }
                $count++;
            }
        }
        $loan->files = serialize($files);
        $loan->save();
        if (!empty($request->charges)) {
            //loop through the array
            foreach ($request->charges as $key) {
                $amount = "charge_amount_" . $key;
                $date = "charge_date_" . $key;
                $loan_charge = new LoanCharge();
                $loan_charge->loan_id = $loan->id;
                $loan_charge->user_id = Sentinel::getUser()->id;
                $loan_charge->charge_id = $key;
                $loan_charge->amount = $request->$amount;
                if (!empty($request->$date)) {
                    $loan_charge->date = $request->$date;
                }
                $loan_charge->save();
            }
        }
        //save custom meta
        $custom_fields = CustomField::where('category', 'loans')->get();
        foreach ($custom_fields as $key) {
            $custom_field = new CustomFieldMeta();
            $id = $key->id;
            $custom_field->name = $request->$id;
            $custom_field->parent_id = $loan->id;
            $custom_field->custom_field_id = $key->id;
            $custom_field->category = "loans";
            $custom_field->save();
        }

        //lets create schedules here
        //determine interest rate to use

        $interest_rate = GeneralHelper::determine_interest_rate($loan->id);

        $period = GeneralHelper::loan_period($loan->id);
        $loan = Loan::find($loan->id);
        if ($loan->repayment_cycle == 'daily') {
            $repayment_cycle = 'day';
            $loan->maturity_date = date_format(
                date_add(
                    date_create($request->first_payment_date),
                    date_interval_create_from_date_string($period . ' days')
                ),
                'Y-m-d'
            );
        }
        if ($loan->repayment_cycle == 'weekly') {
            $repayment_cycle = 'week';
            $loan->maturity_date = date_format(
                date_add(
                    date_create($request->first_payment_date),
                    date_interval_create_from_date_string($period . ' weeks')
                ),
                'Y-m-d'
            );
        }
        if ($loan->repayment_cycle == 'monthly') {
            $repayment_cycle = 'month';
            $loan->maturity_date = date_format(
                date_add(
                    date_create($request->first_payment_date),
                    date_interval_create_from_date_string($period . ' months')
                ),
                'Y-m-d'
            );
        }
        if ($loan->repayment_cycle == 'bi_monthly') {
            $repayment_cycle = 'month';
            $loan->maturity_date = date_format(
                date_add(
                    date_create($request->first_payment_date),
                    date_interval_create_from_date_string($period . ' months')
                ),
                'Y-m-d'
            );
        }
        if ($loan->repayment_cycle == 'quarterly') {
            $repayment_cycle = 'month';
            $loan->maturity_date = date_format(
                date_add(
                    date_create($request->first_payment_date),
                    date_interval_create_from_date_string($period . ' months')
                ),
                'Y-m-d'
            );
        }
        if ($loan->repayment_cycle == 'semi_annually') {
            $repayment_cycle = 'month';
            $loan->maturity_date = date_format(
                date_add(
                    date_create($request->first_payment_date),
                    date_interval_create_from_date_string($period . ' months')
                ),
                'Y-m-d'
            );
        }
        if ($loan->repayment_cycle == 'yearly') {
            $repayment_cycle = 'year';
            $loan->maturity_date = date_format(
                date_add(
                    date_create($request->first_payment_date),
                    date_interval_create_from_date_string($period . ' years')
                ),
                'Y-m-d'
            );
        }
        $loan->save();

        //generate schedules until period finished
        $next_payment = $request->first_payment_date;
        $balance = $request->principal;
        GeneralHelper::audit_trail("Approved borrower  loan application with id:" . $id);
        Flash::success(translate('successfully_saved'));
        return redirect('loan/loan_application/data');
    }

    //loan calculator
    public function createLoanCalculator(Request $request)
    {
        if (!Sentinel::hasAccess('loans.loan_calculator')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }

        $loan_fees = LoanFee::all();
        return view(
            'loan_calculator/create',
            compact('loan_fees')
        );
    }

    public function showLoanCalculator(Request $request)
    {
        if (!Sentinel::hasAccess('loans.loan_calculator')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }

        return view(
            'loan_calculator/show',
            compact('request')
        );
    }

    public function storeLoanCalculator(Request $request)
    {
        if (!Sentinel::hasAccess('loans.loan_calculator')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        if (!empty($request->pdf)) {
            $pdf = Pdf::loadView('loan_calculator.pdf', compact('request'));
            $pdf->setPaper('A4', 'landscape');
            return $pdf->download("Calculated Schedule.pdf");
        }
        if (!empty($request->print)) {
            return view('loan_calculator.print', compact('request'));
        }
    }

    public function add_guarantor(Request $request, $loan)
    {
        if (!Sentinel::hasAccess('loans.guarantor.create')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        $guarantor = new LoanGuarantor();
        $guarantor->guarantor_id = $request->guarantor_id;
        $guarantor->loan_id = $loan->id;;
        $guarantor->user_id = Sentinel::getUser()->id;
        $guarantor->borrower_id = $loan->borrower_id;
        $guarantor->save();
        GeneralHelper::audit_trail("Added guarantor for loan with id:" . $loan->id);
        Flash::success(translate('successfully_saved'));
        return redirect()->back();
    }

    public function remove_guarantor(Request $request, $id)
    {
        if (!Sentinel::hasAccess('loans.guarantor.delete')) {
            Flash::warning(translate('permission_denied'));
            return redirect()->back();;
        }
        LoanGuarantor::destroy($id);
        GeneralHelper::audit_trail("Removed guarantor for loan with id:" . $id);
        Flash::success(translate('successfully_saved'));
        return redirect()->back();
    }
}

© KUJUNTI.ID