Path : /var/www/html/thb_loan_system/app/Http/Controllers/ |
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(); } }