Merge pull request #2218 from cuneytsenturk/account-show-page

Account show page
This commit is contained in:
Cüneyt Şentürk 2021-08-07 17:33:07 +03:00 committed by GitHub
commit 19b7993387
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 455 additions and 15 deletions

View File

@ -8,6 +8,9 @@ use App\Jobs\Banking\CreateAccount;
use App\Jobs\Banking\DeleteAccount;
use App\Jobs\Banking\UpdateAccount;
use App\Models\Banking\Account;
use App\Models\Banking\Transaction;
use App\Models\Banking\Transfer;
use App\Utilities\Reports as Utility;
use App\Models\Setting\Currency;
class Accounts extends Controller
@ -29,11 +32,28 @@ class Accounts extends Controller
*
* @return Response
*/
public function show()
public function show(Account $account)
{
return redirect()->route('accounts.index');
}
$limit = (int) request('limit', setting('default.list_limit', '25'));
// Handle transactions
$transactions = Transaction::with('account', 'category')->where('account_id', $account->id)->collect('paid_at');
$transfers = Transfer::with('transaction')->all()->filter(function ($transfer) use($account) {
if ($transfer->expense_account->id == $account->id || $transfer->income_account->id == $account->id) {
return true;
}
return false;
})->sortByDesc(function ($transfer) {
return $transfer->expense_transaction->paid_at;
});
$limit = (int) request('limit', setting('default.list_limit', '25'));
$transfers = $this->paginate($transfers, $limit);
return view('banking.accounts.show', compact('account', 'transactions', 'transfers'));
}
/**
* Show the form for creating a new resource.
*
@ -60,7 +80,7 @@ class Accounts extends Controller
$response = $this->ajaxDispatch(new CreateAccount($request));
if ($response['success']) {
$response['redirect'] = route('accounts.index');
$response['redirect'] = route('accounts.show', $response['data']->id);
$message = trans('messages.success.added', ['type' => trans_choice('general.accounts', 1)]);
@ -76,6 +96,24 @@ class Accounts extends Controller
return response()->json($response);
}
/**
* Duplicate the specified resource.
*
* @param Account $account
*
* @return Response
*/
public function duplicate(Account $account)
{
$clone = $account->duplicate();
$message = trans('messages.success.duplicated', ['type' => trans_choice('general.accounts', 1)]);
flash($message)->success();
return redirect()->route('accounts.edit', $clone->id);
}
/**
* Show the form for editing the specified resource.
*
@ -107,7 +145,7 @@ class Accounts extends Controller
$response = $this->ajaxDispatch(new UpdateAccount($account, $request));
if ($response['success']) {
$response['redirect'] = route('accounts.index');
$response['redirect'] = route('accounts.show', $account->id);
$message = trans('messages.success.updated', ['type' => $account->name]);
@ -185,6 +223,44 @@ class Accounts extends Controller
return response()->json($response);
}
public function createRevenue(Account $account)
{
$data['account_id'] = $account->id;
return redirect()->route('revenues.create')->withInput($data);
}
public function createPayment(Account $account)
{
$data['account_id'] = $account->id;
return redirect()->route('payments.create')->withInput($data);
}
public function createTransfer(Account $account)
{
$data['from_account_id'] = $account->id;
return redirect()->route('transfers.create')->withInput($data);
}
public function seePerformance(Account $account)
{
$data['account_id'] = $account->id;
$report = Utility::getClassInstance('App\Reports\IncomeExpenseSummary');
if (empty($report) || empty($report->model)) {
$message = trans('accounts.create_report');
flash($message)->warning()->important();
return redirect()->route('reports.create');
}
return redirect()->route('reports.show', $report->model->id)->withInput($data);
}
public function currency()
{
$account_id = (int) request('account_id');

View File

@ -109,7 +109,7 @@ class Search extends Component
'name' => $account->name,
'type' => trans_choice('general.accounts', 1),
'color' => '#55588b',
'href' => route('accounts.edit', $account->id),
'href' => route('accounts.show', $account->id),
];
}
}

View File

@ -27,6 +27,35 @@ class AddSearchString extends Listener
return;
}
$old = old();
$request = request()->all();
if ($old || $request) {
$input = request('search');
$filters = [];
if ($input) {
$filters = explode(' ', $input);
}
foreach ($old as $key => $value) {
$filters[] = $key . ':' . $value;
}
foreach ($request as $key => $value) {
if ($key == 'search') {
continue;
}
$filters[] = $key . ':' . $value;
}
request()->merge([
'search' => implode(' ', $filters)
]);
}
// Apply search string
$this->applySearchStringFilter($event);
}

View File

@ -5,10 +5,11 @@ namespace App\Models\Banking;
use App\Abstracts\Model;
use App\Traits\Transactions;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Bkwld\Cloner\Cloneable;
class Account extends Model
{
use HasFactory, Transactions;
use Cloneable, HasFactory, Transactions;
protected $table = 'accounts';
@ -92,6 +93,41 @@ class Account extends Model
return $total;
}
/**
* Get the current balance.
*
* @return string
*/
public function getIncomeBalanceAttribute()
{
// Opening Balance
//$total = $this->opening_balance;
$total = 0;
// Sum Incomes
$total += $this->income_transactions->sum('amount');
return $total;
}
/**
* Get the current balance.
*
* @return string
*/
public function getExpenseBalanceAttribute()
{
// Opening Balance
//$total = $this->opening_balance;
$total = 0;
// Subtract Expenses
$total += $this->expense_transactions->sum('amount');
return $total;
}
/**
* Create a new factory instance for the model.
*

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
{"/livewire.js":"/livewire.js?id=936e5d0fb0b76b631ba7"}
{"/livewire.js":"/livewire.js?id=d9e06c155e467adb5de2"}

View File

@ -19,7 +19,7 @@ import BulkAction from './../../plugins/bulk-action';
Vue.use(DashboardPlugin);
const app = new Vue({
el: '#app',
el: '#main-body',
mixins: [
Global
@ -28,8 +28,7 @@ const app = new Vue({
data: function () {
return {
form: new Form('account'),
bulk_action: new BulkAction('accounts')
bulk_action: new BulkAction('accounts'),
}
},
});

View File

@ -10,5 +10,9 @@ return [
'bank_phone' => 'Bank Phone',
'bank_address' => 'Bank Address',
'default_account' => 'Default Account',
'incoming' => 'Incoming',
'outgoing' => 'Outgoing',
'see_performance' => 'See Performance',
'create_report' => 'If you want to see account performance. You can create Income vs Expense report instance.',
];

View File

@ -73,6 +73,7 @@ return [
'add_new' => 'Add New',
'add_income' => 'Add Income',
'add_expense' => 'Add Expense',
'add_transfer' => 'Add Transfer',
'show' => 'Show',
'edit' => 'Edit',
'delete' => 'Delete',

View File

@ -44,7 +44,7 @@
<td class="col-sm-2 col-md-1 col-lg-1 col-xl-1 d-none d-sm-block">
{{ Form::bulkActionGroup($item->id, $item->name) }}
</td>
<td class="col-xs-4 col-sm-4 col-md-4 col-lg-4 col-xl-3 long-texts"><a href="{{ route('accounts.edit', $item->id) }}">{{ $item->name }}</a></td>
<td class="col-xs-4 col-sm-4 col-md-4 col-lg-4 col-xl-3 long-texts"><a href="{{ route('accounts.show', $item->id) }}">{{ $item->name }}</a></td>
<td class="col-md-2 col-lg-2 col-xl-2 d-none d-md-block text-left">{{ $item->number }}</td>
<td class="col-sm-2 col-md-2 col-lg-2 col-xl-4 d-none d-sm-block text-right">@money($item->balance, $item->currency_code, true)</td>
<td class="col-xs-4 col-sm-2 col-md-1 col-lg-2 col-xl-1">

View File

@ -0,0 +1,281 @@
@extends('layouts.admin')
@section('title', $account->name)
@section('new_button')
<div class="dropup header-drop-top">
<button type="button" class="btn btn-white btn-sm" data-toggle="dropdown" aria-expanded="false">
<i class="fa fa-chevron-down"></i>&nbsp; {{ trans('general.more_actions') }}
</button>
<div class="dropdown-menu" role="menu">
@stack('button_dropdown_start')
@stack('duplicate_button_start')
@can('create-banking-accounts')
<a class="dropdown-item" href="{{ route('accounts.duplicate', $account->id) }}">
{{ trans('general.duplicate') }}
</a>
@endcan
@stack('duplicate_button_end')
<div class="dropdown-divider"></div>
@stack('revenue_button_start')
@can('create-sales-revenues')
<a class="dropdown-item" href="{{ route('accounts.create-revenue', $account->id) }}">
{{ trans('general.add_income')}}
</a>
@endcan
@stack('revenue_button_end')
@stack('payment_button_start')
@can('create-purchases-payments')
<a class="dropdown-item" href="{{ route('accounts.create-payment', $account->id) }}">
{{ trans('general.add_expense') }}
</a>
@endcan
@stack('payment_button_end')
@stack('transfer_button_start')
@can('create-banking-transfers')
<a class="dropdown-item" href="{{ route('accounts.create-transfer', $account->id) }}">
{{ trans('general.add_transfer') }}
</a>
@endcan
@stack('transfer_button_end')
<div class="dropdown-divider"></div>
@stack('performance_button_start')
@can('read-banking-accounts')
<a class="dropdown-item" href="{{ route('accounts.see-performance', $account->id) }}">
{{ trans('accounts.see_performance') }}
</a>
@endcan
@stack('performance_button_end')
<div class="dropdown-divider"></div>
@stack('delete_button_start')
@can('delete-sales-customers')
{!! Form::deleteLink($account, 'accounts.destroy') !!}
@endcan
@stack('delete_button_end')
@stack('button_dropdown_end')
</div>
@stack('edit_button_start')
@can('update-sales-customers')
<a href="{{ route('accounts.edit', $account->id) }}" class="btn btn-white btn-sm">
{{ trans('general.edit') }}
</a>
@endcan
@stack('edit_button_end')
</div>
@endsection
@section('content')
<div class="row">
<div class="col-xl-3">
<ul class="list-group mb-4">
@stack('account_number_start')
<li class="list-group-item d-flex justify-content-between align-items-center border-0 font-weight-600">
{{ trans_choice('general.accounts', 1) }} {{ trans_choice('accounts.number', 2) }}
<small class="long-texts">{{ $account -> number}}</small>
</li>
@stack('account_number_end')
@stack('account_currency_start')
<li class="list-group-item d-flex justify-content-between align-items-center border-0 border-top-1 font-weight-600">
{{ trans_choice('general.currencies', 2) }}
<small class="long-texts"> {{ $account -> currency -> name}} </small>
</li>
@stack('account_currency_end')
@stack('account_starting_balance_start')
<li class="list-group-item d-flex justify-content-between align-items-center border-0 border-top-1 font-weight-600">
{{ trans_choice('accounts.opening_balance', 2) }}
<small class="long-texts"> @money($account -> opening_balance, $account -> currency -> currency_code, true) </small>
</li>
@stack('account_starting_balance_end')
</ul>
<ul class="list-group mb-4">
@stack('bank_name_start')
<li class="list-group-item border-0">
<div class="font-weight-600">{{ trans('accounts.bank_name') }}</div>
<div><small class="long-texts" title="{{ $account->bank_name }}">{{ $account->bank_name }}</small></div>
</li>
@stack('bank_name_end')
@stack('account_phone_start')
<li class="list-group-item border-0 border-top-1">
<div class="font-weight-600">{{ trans('accounts.bank_phone') }}</div>
<div><small class="long-texts" title="{{ $account->bank_phone }}">{{ $account->bank_phone }}</small></div>
</li>
@stack('account_phone_end')
@stack('account_address_start')
<li class="list-group-item border-0 border-top-1">
<div class="font-weight-600">{{ trans('accounts.bank_address') }}</div>
<div><small class="long-texts" title="{{ $account->bank_address }}">{{ $account->bank_address }}</small></div>
</li>
@stack('account_address_end')
</ul>
</div>
<div class="col-xl-9">
<div class="row mb--3">
@stack('account_incoming_card_start')
<div class="col-md-4">
<div class="card bg-gradient-info border-0">
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="text-uppercase text-muted mb-0 text-white">{{ trans('accounts.incoming') }}</h5>
<div class="dropdown-divider"></div>
<span class="h2 font-weight-bold mb-0 text-white">@money($account->income_balance, $account->currency_code, true)</span>
</div>
</div>
</div>
</div>
</div>
@stack('account_incoming_card_end')
@stack('account_outgoing_card_start')
<div class="col-md-4">
<div class="card bg-gradient-danger border-0">
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="text-uppercase text-muted mb-0 text-white">{{ trans('accounts.outgoing') }}</h5>
<div class="dropdown-divider"></div>
<span class="h2 font-weight-bold mb-0 text-white">@money($account->expense_balance, $account->currency_code, true)</span>
</div>
</div>
</div>
</div>
</div>
@stack('account_outgoing_card_end')
@stack('account_balance_card_start')
<div class="col-md-4">
<div class="card bg-gradient-success border-0">
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="text-uppercase text-muted mb-0 text-white">{{ trans('widgets.account_balance') }}</h5>
<div class="dropdown-divider"></div>
<span class="h2 font-weight-bold mb-0 text-white">@money($account->balance, $account->currency_code, true)</span>
</div>
</div>
</div>
</div>
</div>
@stack('account_balance_card_end')
</div>
<div class="row">
<div class="col-md-12">
<div class="nav-wrapper">
<ul class="nav nav-pills nav-fill flex-column flex-md-row" id="tabs-icons-text" role="tablist">
@stack('account_transactions_tab_start')
<li class="nav-item">
<a class="nav-link mb-sm-3 mb-md-0 active" id="transactions-tab" data-toggle="tab" href="#transactions-content" role="tab" aria-controls="transactions-content" aria-selected="true">
{{ trans_choice('general.transactions', 2) }}
</a>
</li>
@stack('account_transactions_tab_end')
@stack('account_transfers_tab_start')
<li class="nav-item">
<a class="nav-link mb-sm-3 mb-md-0" id="transfers-tab" data-toggle="tab" href="#transfers-content" role="tab" aria-controls="transfers-content" aria-selected="false">
{{ trans_choice('general.transfers', 2) }}
</a>
</li>
@stack('account_transfers_tab_end')
</ul>
</div>
<div class="card">
<div class="tab-content" id="account-tab-content">
@stack('account_transactions_content_start')
<div class="tab-pane fade show active" id="transactions-content" role="tabpanel" aria-labelledby="transactions-tab">
<div class="table-responsive">
<table class="table table-flush table-hover" id="tbl-transactions">
<thead class="thead-light">
<tr class="row table-head-line">
<th class="col-sm-3">{{ trans_choice('general.date', 1) }}</th>
<th class="col-sm-3">{{ trans('general.amount') }}</th>
<th class="col-sm-3">{{ trans_choice('general.types', 1) }}</th>
<th class="col-sm-3">{{ trans_choice('general.categories', 1) }}</th>
</tr>
</thead>
<tbody>
@foreach($transactions as $item)
<tr class="row align-items-center border-top-1 tr-py">
<td class="col-sm-3"><a href="{{ route($item->route_name, $item->route_id) }}">@date($item->issued_at)</a></td>
<td class="col-sm-3">@money($item->amount, $item->currency_code, true)</td>
<td class="col-sm-3">{{ $item->type_title }}</td>
<td class="col-sm-3">{{ $item->category->name }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="card-footer py-4 table-action">
<div class="row">
@include('partials.admin.pagination', ['items' => $transactions, 'type' => 'transactions'])
</div>
</div>
</div>
@stack('account_transactions_content_end')
@stack('account_transfers_content_start')
<div class="tab-pane fade" id="transfers-content" role="tabpanel" aria-labelledby="transfers-tab">
<div class="table-responsive">
<table class="table table-flush table-hover" id="tbl-transfers">
<thead class="thead-light">
<tr class="row table-head-line">
<th class="col-sm-3">{{ trans('general.date') }}</th>
<th class="col-sm-3">{{ trans('general.amount') }}</th>
<th class="col-sm-3">{{ trans_choice('transfers.from_account', 1) }}</th>
<th class="col-sm-3">{{ trans_choice('transfers.to_account', 1) }}</th>
</tr>
</thead>
<tbody>
@foreach($transfers as $item)
<tr class="row align-items-center border-top-1 tr-py">
<td class="col-sm-3"><a href="{{ route('transfers.show', $item->id) }}">@date($item->expense_transaction->paid_at)</a></td>
<td class="col-sm-3">@money($item->expense_transaction->amount, $item->expense_transaction->currency_code, true)</td>
<td class="col-sm-3">{{ $item->expense_transaction->account->name }}</td>
<td class="col-sm-3">{{ $item->income_transaction->account->name }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="card-footer py-4 table-action">
<div class="row">
@include('partials.admin.pagination', ['items' => $transfers, 'type' => 'transfers'])
</div>
</div>
</div>
@stack('account_transfers_content_end')
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@push('scripts_start')
<script src="{{ asset('public/js/banking/accounts.js?v=' . version('short')) }}"></script>
@endpush

View File

@ -73,6 +73,14 @@
'value' => \Date::now()->year,
];
}
if (old($key) || request()->get($key)) {
$filtered[] = [
'option' => $key,
'operator' => '=',
'value' => old($key, request()->get($key)),
];
}
}
@endphp

View File

@ -128,14 +128,20 @@ Route::group(['prefix' => 'purchases'], function () {
Route::group(['prefix' => 'banking'], function () {
Route::get('accounts/currency', 'Banking\Accounts@currency')->name('accounts.currency');
Route::get('accounts/{account}/create-revenue', 'Banking\Accounts@createRevenue')->name('accounts.create-revenue');
Route::get('accounts/{account}/create-payment', 'Banking\Accounts@createPayment')->name('accounts.create-payment');
Route::get('accounts/{account}/create-transfer', 'Banking\Accounts@createTransfer')->name('accounts.create-transfer');
Route::get('accounts/{account}/see-performance', 'Banking\Accounts@seePerformance')->name('accounts.see-performance');
Route::get('accounts/{account}/enable', 'Banking\Accounts@enable')->name('accounts.enable');
Route::get('accounts/{account}/disable', 'Banking\Accounts@disable')->name('accounts.disable');
Route::get('accounts/{account}/duplicate', 'Banking\Accounts@duplicate')->name('accounts.duplicate');
Route::resource('accounts', 'Banking\Accounts', ['middleware' => ['date.format', 'money']]);
Route::post('transactions/import', 'Banking\Transactions@import')->name('transactions.import');
Route::get('transactions/export', 'Banking\Transactions@export')->name('transactions.export');
Route::resource('transactions', 'Banking\Transactions');
Route::resource('transactions', 'Banking\Transactions');
Route::get('transfers/{transfer}/print', 'Banking\Transfers@printTransfer')->name('transfers.print');
Route::get('transfers/{transfer}/pdf', 'Banking\Transfers@pdfTransfer')->name('transfers.pdf');
Route::get('transfers/{transfer}/duplicate', 'Banking\Transfers@duplicate')->name('transfers.duplicate');