v2 first commit
This commit is contained in:
209
app/Http/Controllers/Portal/Dashboard.php
Normal file
209
app/Http/Controllers/Portal/Dashboard.php
Normal file
@ -0,0 +1,209 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Portal;
|
||||
|
||||
use App\Abstracts\Http\Controller;
|
||||
use App\Models\Income\Invoice;
|
||||
use App\Utilities\Chartjs;
|
||||
use Date;
|
||||
|
||||
class Dashboard extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$contact = user()->contact;
|
||||
|
||||
$invoices = Invoice::with('status')->accrued()->where('contact_id', $contact->id)->get();
|
||||
|
||||
$start = Date::parse(request('start', Date::today()->startOfYear()->format('Y-m-d')));
|
||||
$end = Date::parse(request('end', Date::today()->endOfYear()->format('Y-m-d')));
|
||||
|
||||
$start_month = $start->month;
|
||||
$end_month = $end->month;
|
||||
|
||||
// Monthly
|
||||
$labels = [];
|
||||
|
||||
$s = clone $start;
|
||||
|
||||
for ($j = $end_month; $j >= $start_month; $j--) {
|
||||
$labels[$end_month - $j] = $s->format('M Y');
|
||||
|
||||
$s->addMonth();
|
||||
}
|
||||
|
||||
$unpaid = $paid = $overdue = $partial_paid = [];
|
||||
|
||||
foreach ($invoices as $invoice) {
|
||||
switch ($invoice->invoice_status_code) {
|
||||
case 'paid':
|
||||
$paid[] = $invoice;
|
||||
break;
|
||||
case 'partial':
|
||||
$partial_paid[] = $invoice;
|
||||
break;
|
||||
case 'sent':
|
||||
default:
|
||||
if (Date::today()->format('Y-m-d') > $invoice->due_at->format('Y-m-d')) {
|
||||
$overdue[] = $invoice;
|
||||
} else {
|
||||
$unpaid[] = $invoice;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$total = count($unpaid) + count($paid) + count($partial_paid) + count($overdue);
|
||||
|
||||
$progress = [
|
||||
'unpaid' => count($unpaid),
|
||||
'paid' => count($paid),
|
||||
'overdue' => count($overdue),
|
||||
'partially_paid' => count($partial_paid),
|
||||
'total' => $total,
|
||||
];
|
||||
|
||||
$unpaid = $this->calculateTotals($unpaid, $start, $end, 'unpaid');
|
||||
$paid = $this->calculateTotals($paid, $start, $end, 'paid');
|
||||
$partial_paid = $this->calculateTotals($partial_paid, $start, $end, 'partial');
|
||||
$overdue = $this->calculateTotals($overdue, $start, $end, 'overdue');
|
||||
|
||||
$options = [
|
||||
'tooltips' => [
|
||||
'backgroundColor' => '#f5f5f5',
|
||||
'titleFontColor' => '#333',
|
||||
'bodyFontColor' => '#666',
|
||||
'bodySpacing' => 4,
|
||||
'YrPadding' => 12,
|
||||
'mode' => 'nearest',
|
||||
'intersect' => 0,
|
||||
'position' => 'nearest'
|
||||
],
|
||||
'responsive' => true,
|
||||
'scales' => [
|
||||
|
||||
'yAxes' => [
|
||||
[
|
||||
'barPercentage' => 1.6,
|
||||
'gridLines' => [
|
||||
'drawBorder' => false,
|
||||
'color' => 'rgba(29,140,248,0.1)',
|
||||
'zeroLineColor' => 'transparent',
|
||||
'borderDash' => [2],
|
||||
'borderDashOffset' => [2],
|
||||
],
|
||||
'ticks' => [
|
||||
'padding' => 10,
|
||||
'fontColor' => '#9e9e9e'
|
||||
]
|
||||
]
|
||||
],
|
||||
|
||||
'xAxes' => [
|
||||
[
|
||||
'barPercentage' => 1.6,
|
||||
'gridLines' => [
|
||||
'drawBorder' => false,
|
||||
'color' => 'rgba(29,140,248,0.0)',
|
||||
'zeroLineColor' => 'transparent'
|
||||
],
|
||||
'ticks' => [
|
||||
'suggestedMin' => 60,
|
||||
'suggestedMax' => 125,
|
||||
'padding' => 20,
|
||||
'fontColor' => '#9e9e9e'
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
]
|
||||
];
|
||||
|
||||
$chart = new Chartjs();
|
||||
$chart->type('line')
|
||||
->width(0)
|
||||
->height(300)
|
||||
->options($options)
|
||||
->labels($labels);
|
||||
|
||||
$chart->dataset(trans('general.unpaid'), 'line', array_values($unpaid))
|
||||
->backgroundColor('#ef3232')
|
||||
->color('#ef3232')
|
||||
->options([
|
||||
'borderWidth' => 4,
|
||||
'pointStyle' => 'line',
|
||||
])
|
||||
->fill(false);
|
||||
|
||||
$chart->dataset(trans('general.paid'), 'line', array_values($paid))
|
||||
->backgroundColor('#6da252')
|
||||
->color('#6da252')
|
||||
->options([
|
||||
'borderWidth' => 4,
|
||||
'pointStyle' => 'line',
|
||||
])
|
||||
->fill(false);
|
||||
|
||||
$chart->dataset(trans('general.overdue'), 'line', array_values($overdue))
|
||||
->backgroundColor('#efad32')
|
||||
->color('#efad32')
|
||||
->options([
|
||||
'borderWidth' => 4,
|
||||
'pointStyle' => 'line',
|
||||
])
|
||||
->fill(false);
|
||||
|
||||
$chart->dataset(trans('general.partially_paid'), 'line', array_values($partial_paid))
|
||||
->backgroundColor('#328aef')
|
||||
->color('#328aef')
|
||||
->options([
|
||||
'borderWidth' => 4,
|
||||
'pointStyle' => 'line',
|
||||
])
|
||||
->fill(false);
|
||||
|
||||
|
||||
return view('portal.dashboard.index', compact('contact', 'invoices', 'progress', 'chart'));
|
||||
}
|
||||
|
||||
private function calculateTotals($items, $start, $end, $type)
|
||||
{
|
||||
$totals = [];
|
||||
|
||||
$date_format = 'Y-m';
|
||||
|
||||
$n = 1;
|
||||
$start_date = $start->format($date_format);
|
||||
$end_date = $end->format($date_format);
|
||||
$next_date = $start_date;
|
||||
|
||||
$s = clone $start;
|
||||
|
||||
while ($next_date <= $end_date) {
|
||||
$totals[$next_date] = 0;
|
||||
|
||||
$next_date = $s->addMonths($n)->format($date_format);
|
||||
}
|
||||
|
||||
$this->setTotals($totals, $items, $date_format, $type);
|
||||
|
||||
return $totals;
|
||||
}
|
||||
|
||||
private function setTotals(&$totals, $items, $date_format, $type)
|
||||
{
|
||||
foreach ($items as $item) {
|
||||
if ($type == 'partial') {
|
||||
$item->amount = $item->payments()->paid();
|
||||
}
|
||||
|
||||
$i = Date::parse($item->paid_at)->format($date_format);
|
||||
|
||||
$totals[$i] += $item->getAmountConvertedToDefault();
|
||||
}
|
||||
}
|
||||
}
|
185
app/Http/Controllers/Portal/Invoices.php
Normal file
185
app/Http/Controllers/Portal/Invoices.php
Normal file
@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Portal;
|
||||
|
||||
use App\Abstracts\Http\Controller;
|
||||
use App\Models\Banking\Account;
|
||||
use App\Models\Common\Contact;
|
||||
use App\Models\Income\Invoice;
|
||||
use App\Models\Income\InvoiceStatus;
|
||||
use App\Models\Setting\Category;
|
||||
use App\Models\Setting\Currency;
|
||||
use App\Traits\Currencies;
|
||||
use App\Traits\DateTime;
|
||||
use App\Traits\Uploads;
|
||||
use App\Utilities\Modules;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
|
||||
class Invoices extends Controller
|
||||
{
|
||||
use DateTime, Currencies, Uploads;
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$invoices = Invoice::with(['contact', 'status', 'items', 'payments', 'histories'])
|
||||
->accrued()->where('contact_id', user()->contact->id)
|
||||
->collect(['invoice_number'=> 'desc']);
|
||||
|
||||
$categories = collect(Category::type('income')->enabled()->orderBy('name')->pluck('name', 'id'));
|
||||
|
||||
$statuses = collect(InvoiceStatus::get()->each(function ($item) {
|
||||
$item->name = trans('invoices.status.' . $item->code);
|
||||
return $item;
|
||||
})->pluck('name', 'code'));
|
||||
|
||||
return view('portal.invoices.index', compact('invoices', 'categories', 'statuses'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for viewing the specified resource.
|
||||
*
|
||||
* @param Invoice $invoice
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function show(Invoice $invoice)
|
||||
{
|
||||
$accounts = Account::enabled()->orderBy('name')->pluck('name', 'id');
|
||||
|
||||
$currencies = Currency::enabled()->orderBy('name')->pluck('name', 'code')->toArray();
|
||||
|
||||
$account_currency_code = Account::where('id', setting('default.account'))->pluck('currency_code')->first();
|
||||
|
||||
$customers = Contact::type('customer')->enabled()->orderBy('name')->pluck('name', 'id');
|
||||
|
||||
$categories = Category::type('income')->enabled()->orderBy('name')->pluck('name', 'id');
|
||||
|
||||
$payment_methods = Modules::getPaymentMethods();
|
||||
|
||||
event(new \App\Events\Income\InvoiceViewed($invoice));
|
||||
|
||||
return view('portal.invoices.show', compact('invoice', 'accounts', 'currencies', 'account_currency_code', 'customers', 'categories', 'payment_methods'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for viewing the specified resource.
|
||||
*
|
||||
* @param Invoice $invoice
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function printInvoice(Invoice $invoice)
|
||||
{
|
||||
$invoice = $this->prepareInvoice($invoice);
|
||||
|
||||
return view($invoice->template_path, compact('invoice'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for viewing the specified resource.
|
||||
*
|
||||
* @param Invoice $invoice
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function pdfInvoice(Invoice $invoice)
|
||||
{
|
||||
$invoice = $this->prepareInvoice($invoice);
|
||||
|
||||
$currency_style = true;
|
||||
|
||||
$view = view($invoice->template_path, compact('invoice', 'currency_style'))->render();
|
||||
$html = mb_convert_encoding($view, 'HTML-ENTITIES');
|
||||
|
||||
$pdf = \App::make('dompdf.wrapper');
|
||||
$pdf->loadHTML($html);
|
||||
|
||||
//$pdf->setPaper('A4', 'portrait');
|
||||
|
||||
$file_name = 'invoice_' . time() . '.pdf';
|
||||
|
||||
return $pdf->download($file_name);
|
||||
}
|
||||
|
||||
protected function prepareInvoice(Invoice $invoice)
|
||||
{
|
||||
$paid = 0;
|
||||
|
||||
foreach ($invoice->payments as $item) {
|
||||
$amount = $item->amount;
|
||||
|
||||
if ($invoice->currency_code != $item->currency_code) {
|
||||
$item->default_currency_code = $invoice->currency_code;
|
||||
|
||||
$amount = $item->getAmountConvertedFromCustomDefault();
|
||||
}
|
||||
|
||||
$paid += $amount;
|
||||
}
|
||||
|
||||
$invoice->paid = $paid;
|
||||
|
||||
$invoice->template_path = 'incomes.invoices.invoice';
|
||||
|
||||
event(new \App\Events\Income\InvoicePrinting($invoice));
|
||||
|
||||
return $invoice;
|
||||
}
|
||||
|
||||
public function signed(Invoice $invoice)
|
||||
{
|
||||
if (empty($invoice)) {
|
||||
redirect()->route('login');
|
||||
}
|
||||
|
||||
$paid = 0;
|
||||
|
||||
foreach ($invoice->payments as $item) {
|
||||
$amount = $item->amount;
|
||||
|
||||
if ($invoice->currency_code != $item->currency_code) {
|
||||
$item->default_currency_code = $invoice->currency_code;
|
||||
|
||||
$amount = $item->getAmountConvertedFromCustomDefault();
|
||||
}
|
||||
|
||||
$paid += $amount;
|
||||
}
|
||||
|
||||
$invoice->paid = $paid;
|
||||
|
||||
$accounts = Account::enabled()->pluck('name', 'id');
|
||||
|
||||
$currencies = Currency::enabled()->pluck('name', 'code')->toArray();
|
||||
|
||||
$account_currency_code = Account::where('id', setting('default.account'))->pluck('currency_code')->first();
|
||||
|
||||
$customers = Contact::type('customer')->enabled()->pluck('name', 'id');
|
||||
|
||||
$categories = Category::type('income')->enabled()->pluck('name', 'id');
|
||||
|
||||
$payment_methods = Modules::getPaymentMethods();
|
||||
|
||||
$payment_actions = [];
|
||||
|
||||
foreach ($payment_methods as $payment_method_key => $payment_method_value) {
|
||||
$codes = explode('.', $payment_method_key);
|
||||
|
||||
if (!isset($payment_actions[$codes[0]])) {
|
||||
$payment_actions[$codes[0]] = URL::signedRoute('signed.invoices.' . $codes[0] . '.show', [$invoice->id, 'company_id' => session('company_id')]);
|
||||
}
|
||||
}
|
||||
|
||||
$print_action = URL::signedRoute('signed.invoices.print', [$invoice->id, 'company_id' => session('company_id')]);
|
||||
$pdf_action = URL::signedRoute('signed.invoices.pdf', [$invoice->id, 'company_id' => session('company_id')]);
|
||||
|
||||
event(new \App\Events\Income\InvoiceViewed($invoice));
|
||||
|
||||
return view('portal.invoices.signed', compact('invoice', 'accounts', 'currencies', 'account_currency_code', 'customers', 'categories', 'payment_methods', 'payment_actions', 'print_action', 'pdf_action'));
|
||||
}
|
||||
}
|
47
app/Http/Controllers/Portal/Payments.php
Normal file
47
app/Http/Controllers/Portal/Payments.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\portal;
|
||||
|
||||
use App\Abstracts\Http\Controller;
|
||||
use App\Models\Banking\Account;
|
||||
use App\Models\Banking\Transaction;
|
||||
use App\Models\Setting\Category;
|
||||
use App\Utilities\Modules;
|
||||
|
||||
class Payments extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$payments = Transaction::type('income')->with(['account', 'category'])->where('contact_id', '=', user()->contact->id)->paginate();
|
||||
|
||||
$payment_methods = Modules::getPaymentMethods('all');
|
||||
|
||||
$categories = collect(Category::type('income')->enabled()->pluck('name', 'id'))
|
||||
->prepend(trans('general.all_type', ['type' => trans_choice('general.categories', 2)]), '');
|
||||
|
||||
$accounts = collect(Account::enabled()->pluck('name', 'id'))
|
||||
->prepend(trans('general.all_type', ['type' => trans_choice('general.accounts', 2)]), '');
|
||||
|
||||
return view('portal.payments.index', compact('payments', 'payment_methods', 'categories', 'accounts'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for viewing the specified resource.
|
||||
*
|
||||
* @param Transaction $payment
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function show(Transaction $payment)
|
||||
{
|
||||
$payment_methods = Modules::getPaymentMethods('all');
|
||||
|
||||
return view('portal.payments.show', compact('payment', 'payment_methods'));
|
||||
}
|
||||
}
|
95
app/Http/Controllers/Portal/Profile.php
Normal file
95
app/Http/Controllers/Portal/Profile.php
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Portal;
|
||||
|
||||
use App\Abstracts\Http\Controller;
|
||||
use App\Http\Requests\Portal\Profile as Request;
|
||||
use App\Models\Auth\User;
|
||||
use App\Traits\Uploads;
|
||||
|
||||
class Profile extends Controller
|
||||
{
|
||||
use Uploads;
|
||||
|
||||
public function index()
|
||||
{
|
||||
return $this->edit();
|
||||
}
|
||||
|
||||
public function show()
|
||||
{
|
||||
return $this->edit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$user = user();
|
||||
|
||||
return view('portal.profile.edit', compact('user'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function update(Request $request)
|
||||
{
|
||||
$user = user();
|
||||
|
||||
// Do not reset password if not entered/changed
|
||||
if (empty($request['password'])) {
|
||||
unset($request['password']);
|
||||
unset($request['password_confirmation']);
|
||||
}
|
||||
|
||||
// Update user
|
||||
$user->update($request->input());
|
||||
|
||||
// Upload picture
|
||||
if ($request->file('picture')) {
|
||||
$media = $this->getMedia($request->file('picture'), 'users');
|
||||
|
||||
$user->attachMedia($media, 'picture');
|
||||
}
|
||||
|
||||
// Update customer
|
||||
$user->customer->update($request->input());
|
||||
|
||||
$message = trans('messages.success.updated', ['type' => trans('auth.profile')]);
|
||||
|
||||
flash($message)->success();
|
||||
|
||||
return redirect()->route('portal.profile.edit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark overdue invoices notifications are read and redirect to invoices page.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function readOverdueInvoices()
|
||||
{
|
||||
$user = user();
|
||||
|
||||
// Mark invoice notifications as read
|
||||
foreach ($user->unreadNotifications as $notification) {
|
||||
// Not an invoice notification
|
||||
if ($notification->getAttribute('type') != 'App\Notifications\Income\Invoice') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$notification->markAsRead();
|
||||
}
|
||||
|
||||
// Redirect to invoices
|
||||
return redirect()->route('portal.invoices.index');
|
||||
}
|
||||
}
|
23
app/Http/Controllers/Portal/Transactions.php
Normal file
23
app/Http/Controllers/Portal/Transactions.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Portal;
|
||||
|
||||
use App\Abstracts\Http\Controller;
|
||||
use App\Models\Banking\Transaction;
|
||||
use Auth;
|
||||
|
||||
class Transactions extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$transactions = Transaction::type('income')->where('contact_id', user()->contact->id)->get();
|
||||
|
||||
return view('portal.transactions.index', compact('transactions'));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user