mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Basic reconcile view for #736
This commit is contained in:
parent
b899628dbe
commit
f0e195f33b
@ -257,7 +257,7 @@ class AccountController extends Controller
|
|||||||
*
|
*
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
*/
|
*/
|
||||||
public function reconcile(Request $request, Account $account, string $moment = '')
|
public function reconcile(Request $request, Account $account, Carbon $start = null, Carbon $end = null)
|
||||||
{
|
{
|
||||||
if ($account->accountType->type === AccountType::INITIAL_BALANCE) {
|
if ($account->accountType->type === AccountType::INITIAL_BALANCE) {
|
||||||
return $this->redirectToOriginalAccount($account);
|
return $this->redirectToOriginalAccount($account);
|
||||||
@ -270,21 +270,39 @@ class AccountController extends Controller
|
|||||||
$currency = app('amount')->getDefaultCurrency();
|
$currency = app('amount')->getDefaultCurrency();
|
||||||
}
|
}
|
||||||
|
|
||||||
// get start and end
|
// no start or end:
|
||||||
$range = Preferences::get('viewRange', '1M')->data;
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
|
|
||||||
|
// get start and end
|
||||||
|
if(is_null($start) && is_null($end)) {
|
||||||
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
|
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||||
$end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
|
$end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||||
$startBalance = round(app('steam')->balance($account, $start), $currency->decimal_places);
|
}
|
||||||
|
if(is_null($end)) {
|
||||||
|
$end = Navigation::endOfPeriod($start, $range);
|
||||||
|
}
|
||||||
|
|
||||||
|
$startDate = clone $start;
|
||||||
|
$startDate->subDays(1);
|
||||||
|
$startBalance = round(app('steam')->balance($account, $startDate), $currency->decimal_places);
|
||||||
$endBalance = round(app('steam')->balance($account, $end), $currency->decimal_places);
|
$endBalance = round(app('steam')->balance($account, $end), $currency->decimal_places);
|
||||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
|
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
|
||||||
$subTitle = trans('firefly.reconcile_account', ['account' => $account->name]);
|
$subTitle = trans('firefly.reconcile_account', ['account' => $account->name]);
|
||||||
|
|
||||||
if(strlen($moment) > 0 && $moment !== 'all') {
|
// get the transactions
|
||||||
$start = new Carbon($moment);
|
$selectionStart = clone $start;
|
||||||
$end = Navigation::endOfPeriod($start, $range);
|
$selectionStart->subDays(7);
|
||||||
}
|
$selectionEnd = clone $end;
|
||||||
|
$selectionEnd->addDays(5);
|
||||||
|
|
||||||
return view('accounts.reconcile', compact('account', 'currency', 'subTitleIcon', 'start', 'end', 'subTitle', 'startBalance', 'endBalance'));
|
// grab transactions:
|
||||||
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class);
|
||||||
|
$collector->setAccounts(new Collection([$account]))
|
||||||
|
->setRange($selectionStart, $selectionEnd)->withBudgetInformation()->withOpposingAccount()->withCategoryInformation();
|
||||||
|
$transactions = $collector->getJournals();
|
||||||
|
|
||||||
|
return view('accounts.reconcile', compact('account', 'currency', 'subTitleIcon', 'start', 'end', 'subTitle', 'startBalance', 'endBalance','transactions','selectionStart','selectionEnd'));
|
||||||
|
|
||||||
// prep for "specific date" view.
|
// prep for "specific date" view.
|
||||||
if (strlen($moment) > 0 && $moment !== 'all') {
|
if (strlen($moment) > 0 && $moment !== 'all') {
|
||||||
@ -292,14 +310,7 @@ class AccountController extends Controller
|
|||||||
$end = Navigation::endOfPeriod($start, $range);
|
$end = Navigation::endOfPeriod($start, $range);
|
||||||
}
|
}
|
||||||
|
|
||||||
// grab journals:
|
|
||||||
$collector = app(JournalCollectorInterface::class);
|
|
||||||
$collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page);
|
|
||||||
if (!is_null($start)) {
|
|
||||||
$collector->setRange($start, $end);
|
|
||||||
}
|
|
||||||
$transactions = $collector->getPaginatedJournals();
|
|
||||||
$transactions->setPath(route('accounts.show', [$account->id, $moment]));
|
|
||||||
|
|
||||||
return view(
|
return view(
|
||||||
'accounts.show',
|
'accounts.show',
|
||||||
|
37
public/js/ff/accounts/reconcile.js
vendored
Normal file
37
public/js/ff/accounts/reconcile.js
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* reconcile.js
|
||||||
|
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III.
|
||||||
|
*
|
||||||
|
* Firefly III is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Firefly III is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
"use strict";
|
||||||
|
$('input[type="date"]').on('change', showUpdateButton);
|
||||||
|
$('.update_view').on('click', updateView);
|
||||||
|
});
|
||||||
|
|
||||||
|
function showUpdateButton() {
|
||||||
|
$('.update_date_button').show();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateView() {
|
||||||
|
var startDate = $('input[name="start_date"]').val();
|
||||||
|
var endDate = $('input[name="end_date"]').val();
|
||||||
|
window.location = '/accounts/reconcile/2/' + startDate + '/' + endDate;
|
||||||
|
return false;
|
||||||
|
}
|
@ -619,6 +619,8 @@ return [
|
|||||||
'cash_accounts' => 'Cash accounts',
|
'cash_accounts' => 'Cash accounts',
|
||||||
'Cash account' => 'Cash account',
|
'Cash account' => 'Cash account',
|
||||||
'reconcile_account' => 'Reconcile account ":account"',
|
'reconcile_account' => 'Reconcile account ":account"',
|
||||||
|
'end_of_reconcile_period' => 'End of reconcile period: :period',
|
||||||
|
'start_of_reconcile_period' => 'Start of reconcile period: :period',
|
||||||
'cash' => 'cash',
|
'cash' => 'cash',
|
||||||
'account_type' => 'Account type',
|
'account_type' => 'Account type',
|
||||||
'save_transactions_by_moving' => 'Save these transaction(s) by moving them to another account:',
|
'save_transactions_by_moving' => 'Save these transaction(s) by moving them to another account:',
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<h3 class="box-title">{{ 'reconcile_range'|_ }}</h3>
|
<h3 class="box-title">{{ 'reconcile_range'|_ }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body no-padding">
|
<div class="box-body no-padding">
|
||||||
<table class="table">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="2" style="width:50%;">{{ 'start_balance'|_ }}</th>
|
<th colspan="2" style="width:50%;">{{ 'start_balance'|_ }}</th>
|
||||||
@ -67,11 +67,12 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr class="update_date_button" style="display:none;">
|
||||||
<td colspan="4">
|
<td colspan="4">
|
||||||
<a href="#" class="btn btn-default">
|
<a href="#" class="btn btn-default update_view">
|
||||||
{{ 'update'|_ }}
|
{{ 'update_view'|_ }}
|
||||||
</a>
|
</a>
|
||||||
|
<span class="text-muted">(unsaved progress will be lost!)</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
@ -84,8 +85,28 @@
|
|||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title">{{ 'reconcile_options'|_ }}</h3>
|
<h3 class="box-title">{{ 'reconcile_options'|_ }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body no-padding">
|
||||||
Do something
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width:50%;">{{ 'difference'|_ }}</th>
|
||||||
|
<th>{{ 'actions'|_ }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span id="difference"></span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="btn-group">
|
||||||
|
<a href="#" class="btn btn-default">Reconcile</a>
|
||||||
|
<a href="#" class="btn btn-default">Reconcile with transaction</a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -99,6 +120,111 @@
|
|||||||
<h3 class="box-title">{{ 'transactions'|_ }}</h3>
|
<h3 class="box-title">{{ 'transactions'|_ }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
|
<table class="table table-striped table-condensed">
|
||||||
|
<thead>
|
||||||
|
<tr class="ignore">
|
||||||
|
<th class="hidden-xs" colspan="2"> </th>
|
||||||
|
<th>{{ trans('list.description') }}</th>
|
||||||
|
<th style="text-align:right;">{{ trans('list.amount') }}</th>
|
||||||
|
<th class="hidden-xs hidden-sm hidden-md">{{ trans('list.reconcile') }}</th>
|
||||||
|
<th class="hidden-xs hidden-sm">{{ trans('list.date') }}</th>
|
||||||
|
<th class="hidden-xs hidden-sm hidden-md">{{ trans('list.from') }}</th>
|
||||||
|
<th class="hidden-xs hidden-sm hidden-md">{{ trans('list.to') }}</th>
|
||||||
|
|
||||||
|
<th class="hidden-xs"><i class="fa fa-tasks fa-fw" title="{{ trans('list.budget') }}"></i></th>
|
||||||
|
<th class="hidden-xs"><i class="fa fa-bar-chart fa-fw" title="{{ trans('list.category') }}"></i></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{# data for previous/next markers #}
|
||||||
|
{% set endSet = false %}
|
||||||
|
{% set startSet = false %}
|
||||||
|
{% for transaction in transactions %}
|
||||||
|
{# start marker #}
|
||||||
|
{% if transaction.date < start and startSet == false %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="5">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td colspan="3">
|
||||||
|
<span class="label label-default">
|
||||||
|
{{ trans('firefly.start_of_reconcile_period', {period: start.formatLocalized(monthAndDayFormat) }) }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td colspan="2">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% set startSet = true %}
|
||||||
|
{% endif %}
|
||||||
|
<tr data-date="{{ transaction.date.format('Y-m-d') }}" data-id="{{ transaction.journal_id }}"
|
||||||
|
data-transaction-id="{{ transaction.id }}">
|
||||||
|
<td class="hidden-xs">
|
||||||
|
<div class="btn-group btn-group-xs">
|
||||||
|
<a href="{{ route('transactions.edit',transaction.journal_id) }}" class="btn btn-xs btn-default"><i
|
||||||
|
class="fa fa-fw fa-pencil"></i></a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
{# icon #}
|
||||||
|
<td class="hidden-xs">
|
||||||
|
{{ transaction|transactionIcon }}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{# description #}
|
||||||
|
<td>
|
||||||
|
<a href="{{ route('transactions.show',transaction.journal_id) }}">
|
||||||
|
{{ transaction|transactionDescription }}
|
||||||
|
</a>
|
||||||
|
{# is a split journal #}
|
||||||
|
{{ transaction|transactionIsSplit }}
|
||||||
|
|
||||||
|
{# count attachments #}
|
||||||
|
{{ transaction|transactionHasAtt }}
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td style="text-align: right;"><span style="margin-right:5px;">{{ transaction|transactionAmount }}</span></td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="reconciled[]" value="{{ transaction.amount }}" class="reconcile_checkbox">
|
||||||
|
</td>
|
||||||
|
<td class="hidden-sm hidden-xs">
|
||||||
|
{{ transaction.date.formatLocalized(monthAndDayFormat) }}
|
||||||
|
</td>
|
||||||
|
<td class="hidden-xs hidden-sm hidden-md">
|
||||||
|
{# all source accounts #}
|
||||||
|
{{ transaction|transactionSourceAccount }}
|
||||||
|
</td>
|
||||||
|
<td class="hidden-xs hidden-sm hidden-md">
|
||||||
|
{# all destination accounts #}
|
||||||
|
{{ transaction|transactionDestinationAccount }}
|
||||||
|
</td>
|
||||||
|
<td class="hidden-xs">
|
||||||
|
{{ transaction|transactionBudgets }}
|
||||||
|
</td>
|
||||||
|
<td class="hidden-xs">
|
||||||
|
{{ transaction|transactionCategories }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{# end marker #}
|
||||||
|
{% if transaction.date <= end and endSet == false %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="5">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td colspan="3">
|
||||||
|
<span class="label label-default">
|
||||||
|
{{ trans('firefly.end_of_reconcile_period', {period: end.formatLocalized(monthAndDayFormat) }) }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td colspan="2">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% set endSet = true %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -112,6 +238,8 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
currencySymbol = "{{ currency.symbol }}";
|
currencySymbol = "{{ currency.symbol }}";
|
||||||
var accountID = {{ account.id }};
|
var accountID = {{ account.id }};
|
||||||
|
var startBalance = {{ startBalance }};
|
||||||
|
var endBalance = {{ endBalance }};
|
||||||
</script>
|
</script>
|
||||||
<script src="js/ff/accounts/reconcile.js?v={{ FF_VERSION }}" type="text/javascript"></script>
|
<script src="js/ff/accounts/reconcile.js?v={{ FF_VERSION }}" type="text/javascript"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -48,7 +48,11 @@
|
|||||||
<a href="#" class="btn btn-default mass_stop_select" style="display:none;"><i class="fa faw-fw fa-square-o"
|
<a href="#" class="btn btn-default mass_stop_select" style="display:none;"><i class="fa faw-fw fa-square-o"
|
||||||
></i> {{ 'stop_selection'|_ }}</a>
|
></i> {{ 'stop_selection'|_ }}</a>
|
||||||
{% if showReconcile == true %}
|
{% if showReconcile == true %}
|
||||||
<a href="{{ route('accounts.reconcile', [account.id, moment]) }}" class="btn btn-info mass_reconcile"><i class="fa fa-fw fa-check"></i> {{ 'reconcile_this_account'|_ }}</a>
|
{% if moment == 'all' %}
|
||||||
|
<a href="{{ route('accounts.reconcile', [account.id, start.format('Ymd')]) }}" class="btn btn-info mass_reconcile"><i class="fa fa-fw fa-check"></i> {{ 'reconcile_this_account'|_ }}</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ route('accounts.reconcile', [account.id, start.format('Ymd'), end.format('Ymd')]) }}" class="btn btn-info mass_reconcile"><i class="fa fa-fw fa-check"></i> {{ 'reconcile_this_account'|_ }}</a>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -90,7 +90,7 @@ Route::group(
|
|||||||
Route::get('{what}', ['uses' => 'AccountController@index', 'as' => 'index'])->where('what', 'revenue|asset|expense');
|
Route::get('{what}', ['uses' => 'AccountController@index', 'as' => 'index'])->where('what', 'revenue|asset|expense');
|
||||||
Route::get('create/{what}', ['uses' => 'AccountController@create', 'as' => 'create'])->where('what', 'revenue|asset|expense');
|
Route::get('create/{what}', ['uses' => 'AccountController@create', 'as' => 'create'])->where('what', 'revenue|asset|expense');
|
||||||
Route::get('edit/{account}', ['uses' => 'AccountController@edit', 'as' => 'edit']);
|
Route::get('edit/{account}', ['uses' => 'AccountController@edit', 'as' => 'edit']);
|
||||||
Route::get('reconcile/{account}/{moment?}', ['uses' => 'AccountController@reconcile', 'as' => 'reconcile']);
|
Route::get('reconcile/{account}/{start_date?}/{end_date?}', ['uses' => 'AccountController@reconcile', 'as' => 'reconcile']);
|
||||||
Route::get('delete/{account}', ['uses' => 'AccountController@delete', 'as' => 'delete']);
|
Route::get('delete/{account}', ['uses' => 'AccountController@delete', 'as' => 'delete']);
|
||||||
Route::get('show/{account}/{moment?}', ['uses' => 'AccountController@show', 'as' => 'show']);
|
Route::get('show/{account}/{moment?}', ['uses' => 'AccountController@show', 'as' => 'show']);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user