Merge pull request #288 from denisdulici/customer-vendor-show

Customer/Vendor show page
This commit is contained in:
Denis Duliçi 2018-04-07 17:20:23 +03:00 committed by GitHub
commit 696a635c26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 507 additions and 3 deletions

View File

@ -4,10 +4,16 @@ namespace App\Http\Controllers\Expenses;
use App\Http\Controllers\Controller;
use App\Http\Requests\Expense\Vendor as Request;
use App\Models\Expense\Bill;
use App\Models\Expense\Payment;
use App\Models\Expense\Vendor;
use App\Models\Setting\Currency;
use App\Traits\Uploads;
use App\Utilities\ImportFile;
use Date;
use Illuminate\Pagination\Paginator;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
class Vendors extends Controller
{
@ -25,6 +31,80 @@ class Vendors extends Controller
return view('expenses.vendors.index', compact('vendors'));
}
/**
* Show the form for viewing the specified resource.
*
* @param Vendor $vendor
*
* @return Response
*/
public function show(Vendor $vendor)
{
$amounts = [
'paid' => 0,
'open' => 0,
'overdue' => 0,
];
$counts = [
'bills' => 0,
'payments' => 0,
];
// Handle bills
$bills = Bill::with(['status', 'payments'])->where('vendor_id', $vendor->id)->get();
$counts['bills'] = $bills->count();
$bill_payments = [];
$today = Date::today()->toDateString();
foreach ($bills as $item) {
$payments = 0;
foreach ($item->payments as $payment) {
$payment->category = new \stdClass();
$payment->category->id = 0;
$payment->category->name = trans_choice('general.bills', 2);
$bill_payments[] = $payment;
$amount = $payment->getConvertedAmount();
$amounts['paid'] += $amount;
$payments += $amount;
}
if ($item->bill_status_code == 'paid') {
continue;
}
// Check if it's open or overdue invoice
if ($item->due_at > $today) {
$amounts['open'] += $item->getConvertedAmount() - $payments;
} else {
$amounts['overdue'] += $item->getConvertedAmount() - $payments;
}
}
// Handle payments
$payments = Payment::with(['account', 'category'])->where('vendor_id', $vendor->id)->get();
$counts['payments'] = $payments->count();
// Prepare data
$items = collect($payments)->each(function ($item) use (&$amounts) {
$amounts['paid'] += $item->getConvertedAmount();
});
$limit = request('limit', setting('general.list_limit', '25'));
$transactions = $this->paginate($items->merge($bill_payments)->sortByDesc('paid_at'), $limit);
return view('expenses.vendors.show', compact('vendor', 'counts', 'amounts', 'transactions'));
}
/**
* Show the form for creating a new resource.
*
@ -206,4 +286,23 @@ class Vendors extends Controller
return response()->json($vendor);
}
/**
* Generate a pagination collection.
*
* @param array|Collection $items
* @param int $perPage
* @param int $page
* @param array $options
*
* @return LengthAwarePaginator
*/
public function paginate($items, $perPage = 15, $page = null, $options = [])
{
$page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
$items = $items instanceof Collection ? $items : Collection::make($items);
return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
}
}

View File

@ -4,11 +4,17 @@ namespace App\Http\Controllers\Incomes;
use App\Http\Controllers\Controller;
use App\Http\Requests\Income\Customer as Request;
use Illuminate\Http\Request as FRequest;
use App\Models\Auth\User;
use App\Models\Income\Customer;
use App\Models\Income\Invoice;
use App\Models\Income\Revenue;
use App\Models\Setting\Currency;
use App\Utilities\ImportFile;
use Date;
use Illuminate\Http\Request as FRequest;
use Illuminate\Pagination\Paginator;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
class Customers extends Controller
{
@ -25,6 +31,80 @@ class Customers extends Controller
return view('incomes.customers.index', compact('customers', 'emails'));
}
/**
* Show the form for viewing the specified resource.
*
* @param Customer $customer
*
* @return Response
*/
public function show(Customer $customer)
{
$amounts = [
'paid' => 0,
'open' => 0,
'overdue' => 0,
];
$counts = [
'invoices' => 0,
'revenues' => 0,
];
// Handle invoices
$invoices = Invoice::with(['status', 'payments'])->where('customer_id', $customer->id)->get();
$counts['invoices'] = $invoices->count();
$invoice_payments = [];
$today = Date::today()->toDateString();
foreach ($invoices as $item) {
$payments = 0;
foreach ($item->payments as $payment) {
$payment->category = new \stdClass();
$payment->category->id = 0;
$payment->category->name = trans_choice('general.invoices', 2);
$invoice_payments[] = $payment;
$amount = $payment->getConvertedAmount();
$amounts['paid'] += $amount;
$payments += $amount;
}
if ($item->invoice_status_code == 'paid') {
continue;
}
// Check if it's open or overdue invoice
if ($item->due_at > $today) {
$amounts['open'] += $item->getConvertedAmount() - $payments;
} else {
$amounts['overdue'] += $item->getConvertedAmount() - $payments;
}
}
// Handle revenues
$revenues = Revenue::with(['account', 'category'])->where('customer_id', $customer->id)->get();
$counts['revenues'] = $revenues->count();
// Prepare data
$items = collect($revenues)->each(function ($item) use (&$amounts) {
$amounts['paid'] += $item->getConvertedAmount();
});
$limit = request('limit', setting('general.list_limit', '25'));
$transactions = $this->paginate($items->merge($invoice_payments)->sortByDesc('paid_at'), $limit);
return view('incomes.customers.show', compact('customer', 'counts', 'amounts', 'transactions'));
}
/**
* Show the form for creating a new resource.
*
@ -266,4 +346,23 @@ class Customers extends Controller
return response()->json($json);
}
/**
* Generate a pagination collection.
*
* @param array|Collection $items
* @param int $perPage
* @param int $page
* @param array $options
*
* @return LengthAwarePaginator
*/
public function paginate($items, $perPage = 15, $page = null, $options = [])
{
$page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
$items = $items instanceof Collection ? $items : Collection::make($items);
return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
}
}

View File

@ -42,7 +42,7 @@
<tbody>
@foreach($vendors as $item)
<tr>
<td><a href="{{ url('expenses/vendors/' . $item->id . '/edit') }}">{{ $item->name }}</a></td>
<td><a href="{{ url('expenses/vendors/' . $item->id) }}">{{ $item->name }}</a></td>
<td class="hidden-xs">{{ !empty($item->email) ? $item->email : trans('general.na') }}</td>
<td>{{ $item->phone }}</td>
<td class="hidden-xs">
@ -58,6 +58,7 @@
<i class="fa fa-ellipsis-h"></i>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{{ url('expenses/vendors/' . $item->id) }}">{{ trans('general.show') }}</a></li>
<li><a href="{{ url('expenses/vendors/' . $item->id . '/edit') }}">{{ trans('general.edit') }}</a></li>
<li class="divider"></li>
@permission('create-expenses-vendors')

View File

@ -0,0 +1,152 @@
@extends('layouts.admin')
@section('title', $vendor->name)
@section('content')
<div class="row">
<div class="col-md-3">
<!-- Stats -->
<div class="box box-success">
<div class="box-body box-profile">
<ul class="list-group list-group-unbordered">
<li class="list-group-item" style="border-top: 0;">
<b>{{ trans_choice('general.bills', 2) }}</b> <a class="pull-right">{{ $counts['bills'] }}</a>
</li>
<li class="list-group-item">
<b>{{ trans_choice('general.payments', 2) }}</b> <a class="pull-right">{{ $counts['payments'] }}</a>
</li>
</ul>
</div>
<!-- /.box-body -->
</div>
<!-- Profile -->
<div class="box box-success">
<div class="box-header with-border">
<h3 class="box-title">{{ trans('auth.profile') }}</h3>
</div>
<div class="box-body box-profile">
<ul class="list-group list-group-unbordered">
<li class="list-group-item" style="border-top: 0;">
<b>{{ trans('general.email') }}</b> <a class="pull-right">{{ $vendor->email }}</a>
</li>
<li class="list-group-item">
<b>{{ trans('general.phone') }}</b> <a class="pull-right">{{ $vendor->phone }}</a>
</li>
<li class="list-group-item">
<b>{{ trans('general.website') }}</b> <a class="pull-right">{{ $vendor->website }}</a>
</li>
<li class="list-group-item">
<b>{{ trans('general.tax_number') }}</b> <a class="pull-right">{{ $vendor->tax_number }}</a>
</li>
</ul>
</div>
<!-- /.box-body -->
</div>
<!-- Address Box -->
<div class="box box-success">
<div class="box-header with-border">
<h3 class="box-title">{{ trans('general.address') }}</h3>
</div>
<!-- /.box-header -->
<div class="box-body">
<p class="text-muted">
{{ $vendor->address }}
</p>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
<!-- Edit -->
<div>
<a href="{{ url('expenses/vendors/' . $vendor->id . '/edit') }}" class="btn btn-primary btn-block"><b>{{ trans('general.edit') }}</b></a>
<!-- /.box-body -->
</div>
</div>
<!-- /.col -->
<div class="col-md-9">
<div class="row">
<div class="col-md-4 col-sm-8 col-xs-12">
<div class="info-box">
<span class="info-box-icon bg-green"><i class="fa fa-shopping-cart"></i></span>
<div class="info-box-content">
<span class="info-box-text">{{ trans('general.paid') }}</span>
<span class="info-box-number">@money($amounts['paid'], setting('general.default_currency'), true)</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<div class="col-md-4 col-sm-8 col-xs-12">
<div class="info-box">
<span class="info-box-icon bg-yellow"><i class="fa fa-paper-plane-o"></i></span>
<div class="info-box-content">
<span class="info-box-text">{{ trans('dashboard.open_bills') }}</span>
<span class="info-box-number">@money($amounts['open'], setting('general.default_currency'), true)</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<div class="col-md-4 col-sm-8 col-xs-12">
<div class="info-box">
<span class="info-box-icon bg-red"><i class="fa fa-warning"></i></span>
<div class="info-box-content">
<span class="info-box-text">{{ trans('dashboard.overdue_bills') }}</span>
<span class="info-box-number">@money($amounts['overdue'], setting('general.default_currency'), true)</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
</div>
<div class="box box-success">
<div class="box-header with-border">
<h3 class="box-title">{{ trans_choice('general.transactions', 2) }}</h3>
</div>
<!-- /.box-header -->
<div class="box-body">
<div class="table table-responsive">
<table class="table table-striped table-hover" id="tbl-transactions">
<thead>
<tr>
<th class="col-md-3">{{ trans('general.date') }}</th>
<th class="col-md-2 text-right amount-space">{{ trans('general.amount') }}</th>
<th class="col-md-4 hidden-xs">{{ trans_choice('general.categories', 1) }}</th>
<th class="col-md-3 hidden-xs">{{ trans_choice('general.accounts', 1) }}</th>
</tr>
</thead>
<tbody>
@foreach($transactions as $item)
<tr>
<td>{{ Date::parse($item->paid_at)->format($date_format) }}</td>
<td class="text-right amount-space">@money($item->amount, $item->currency_code, true)</td>
<td class="hidden-xs">{{ $item->category->name }}</td>
<td class="hidden-xs">{{ $item->account->name }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
@include('partials.admin.pagination', ['items' => $transactions, 'type' => 'transactions'])
</div>
<!-- /.box-footer -->
</div>
<!-- /.box -->
</div>
</div>
@endsection

View File

@ -42,7 +42,7 @@
<tbody>
@foreach($customers as $item)
<tr>
<td><a href="{{ url('incomes/customers/' . $item->id . '/edit') }}">{{ $item->name }}</a></td>
<td><a href="{{ url('incomes/customers/' . $item->id) }}">{{ $item->name }}</a></td>
<td class="hidden-xs">{{ !empty($item->email) ? $item->email : trans('general.na') }}</td>
<td>{{ $item->phone }}</td>
<td class="hidden-xs">
@ -58,6 +58,7 @@
<i class="fa fa-ellipsis-h"></i>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{{ url('incomes/customers/' . $item->id) }}">{{ trans('general.show') }}</a></li>
<li><a href="{{ url('incomes/customers/' . $item->id . '/edit') }}">{{ trans('general.edit') }}</a></li>
<li class="divider"></li>
@permission('create-incomes-customers')

View File

@ -0,0 +1,152 @@
@extends('layouts.admin')
@section('title', $customer->name)
@section('content')
<div class="row">
<div class="col-md-3">
<!-- Stats -->
<div class="box box-success">
<div class="box-body box-profile">
<ul class="list-group list-group-unbordered">
<li class="list-group-item" style="border-top: 0;">
<b>{{ trans_choice('general.invoices', 2) }}</b> <a class="pull-right">{{ $counts['invoices'] }}</a>
</li>
<li class="list-group-item">
<b>{{ trans_choice('general.revenues', 2) }}</b> <a class="pull-right">{{ $counts['revenues'] }}</a>
</li>
</ul>
</div>
<!-- /.box-body -->
</div>
<!-- Profile -->
<div class="box box-success">
<div class="box-header with-border">
<h3 class="box-title">{{ trans('auth.profile') }}</h3>
</div>
<div class="box-body box-profile">
<ul class="list-group list-group-unbordered">
<li class="list-group-item" style="border-top: 0;">
<b>{{ trans('general.email') }}</b> <a class="pull-right">{{ $customer->email }}</a>
</li>
<li class="list-group-item">
<b>{{ trans('general.phone') }}</b> <a class="pull-right">{{ $customer->phone }}</a>
</li>
<li class="list-group-item">
<b>{{ trans('general.website') }}</b> <a class="pull-right">{{ $customer->website }}</a>
</li>
<li class="list-group-item">
<b>{{ trans('general.tax_number') }}</b> <a class="pull-right">{{ $customer->tax_number }}</a>
</li>
</ul>
</div>
<!-- /.box-body -->
</div>
<!-- Address Box -->
<div class="box box-success">
<div class="box-header with-border">
<h3 class="box-title">{{ trans('general.address') }}</h3>
</div>
<!-- /.box-header -->
<div class="box-body">
<p class="text-muted">
{{ $customer->address }}
</p>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
<!-- Edit -->
<div>
<a href="{{ url('incomes/customers/' . $customer->id . '/edit') }}" class="btn btn-primary btn-block"><b>{{ trans('general.edit') }}</b></a>
<!-- /.box-body -->
</div>
</div>
<!-- /.col -->
<div class="col-md-9">
<div class="row">
<div class="col-md-4 col-sm-8 col-xs-12">
<div class="info-box">
<span class="info-box-icon bg-green"><i class="fa fa-money"></i></span>
<div class="info-box-content">
<span class="info-box-text">{{ trans('general.paid') }}</span>
<span class="info-box-number">@money($amounts['paid'], setting('general.default_currency'), true)</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<div class="col-md-4 col-sm-8 col-xs-12">
<div class="info-box">
<span class="info-box-icon bg-yellow"><i class="fa fa-paper-plane-o"></i></span>
<div class="info-box-content">
<span class="info-box-text">{{ trans('dashboard.open_invoices') }}</span>
<span class="info-box-number">@money($amounts['open'], setting('general.default_currency'), true)</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<div class="col-md-4 col-sm-8 col-xs-12">
<div class="info-box">
<span class="info-box-icon bg-red"><i class="fa fa-warning"></i></span>
<div class="info-box-content">
<span class="info-box-text">{{ trans('dashboard.overdue_invoices') }}</span>
<span class="info-box-number">@money($amounts['overdue'], setting('general.default_currency'), true)</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
</div>
<div class="box box-success">
<div class="box-header with-border">
<h3 class="box-title">{{ trans_choice('general.transactions', 2) }}</h3>
</div>
<!-- /.box-header -->
<div class="box-body">
<div class="table table-responsive">
<table class="table table-striped table-hover" id="tbl-transactions">
<thead>
<tr>
<th class="col-md-3">{{ trans('general.date') }}</th>
<th class="col-md-2 text-right amount-space">{{ trans('general.amount') }}</th>
<th class="col-md-4 hidden-xs">{{ trans_choice('general.categories', 1) }}</th>
<th class="col-md-3 hidden-xs">{{ trans_choice('general.accounts', 1) }}</th>
</tr>
</thead>
<tbody>
@foreach($transactions as $item)
<tr>
<td>{{ Date::parse($item->paid_at)->format($date_format) }}</td>
<td class="text-right amount-space">@money($item->amount, $item->currency_code, true)</td>
<td class="hidden-xs">{{ $item->category->name }}</td>
<td class="hidden-xs">{{ $item->account->name }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
@include('partials.admin.pagination', ['items' => $transactions, 'type' => 'transactions'])
</div>
<!-- /.box-footer -->
</div>
<!-- /.box -->
</div>
</div>
@endsection