mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Update code for reconciliation.
This commit is contained in:
parent
4b87e5be55
commit
69bb76b6fe
@ -27,7 +27,9 @@ use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Navigation;
|
||||
@ -68,16 +70,38 @@ class ReconcileController extends Controller
|
||||
*/
|
||||
public function overview(Request $request, Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
$startBalance = $request->get('startBalance');
|
||||
$endBalance = $request->get('endBalance');
|
||||
$transactions = $request->get('transactions');
|
||||
$startBalance = $request->get('startBalance');
|
||||
$endBalance = $request->get('endBalance');
|
||||
$transactionIds = $request->get('transactions') ?? [];
|
||||
$clearedIds = $request->get('cleared') ?? [];
|
||||
$amount = '0';
|
||||
$clearedAmount = '0';
|
||||
$route = route('accounts.reconcile.submit', [$account->id, $start->format('Ymd'), $end->format('Ymd')]);
|
||||
// get sum of transaction amounts:
|
||||
/** @var JournalRepositoryInterface $repository */
|
||||
$repository = app(JournalRepositoryInterface::class);
|
||||
$transactions = $repository->getTransactionsById($transactionIds);
|
||||
$cleared = $repository->getTransactionsById($clearedIds);
|
||||
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$amount = bcadd($amount, $transaction->amount);
|
||||
}
|
||||
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($cleared as $transaction) {
|
||||
$clearedAmount = bcadd($clearedAmount, $transaction->amount);
|
||||
}
|
||||
|
||||
$return = [
|
||||
'is_zero' => false,
|
||||
'post_uri' => route('accounts.reconcile.submit', [$account->id, $start->format('Ymd'), $end->format('Ymd')]),
|
||||
'post_uri' => $route,
|
||||
'html' => '',
|
||||
];
|
||||
$return['html'] = view('accounts.reconcile.overview', compact('account', 'start', 'end'))->render();
|
||||
$return['html'] = view(
|
||||
'accounts.reconcile.overview',
|
||||
compact('account', 'start', 'end', 'clearedIds', 'transactionIds', 'clearedAmount', 'startBalance', 'endBalance', 'amount', 'route')
|
||||
)->render();
|
||||
|
||||
return Response::json($return);
|
||||
}
|
||||
@ -175,4 +199,13 @@ class ReconcileController extends Controller
|
||||
|
||||
return Response::json(['html' => $html]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*/
|
||||
public function submit(Request $request, Account $account, Carbon $start, Carbon $end) {
|
||||
var_dump($request->all());
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ class Amount implements ConverterInterface
|
||||
Log::debug(sprintf('No decimal character found. Converted amount from "%s" to "%s".', $oldValue, $value));
|
||||
}
|
||||
|
||||
$number = strval(number_format(round(floatval($value), 12), 12));
|
||||
$number = strval(number_format(round(floatval($value), 12), 12,'',''));
|
||||
return $number;
|
||||
}
|
||||
}
|
||||
|
@ -177,6 +177,23 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
return TransactionType::orderBy('type', 'ASC')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $transactionIds
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getTransactionsById(array $transactionIds): Collection
|
||||
{
|
||||
$set = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->whereIn('transactions.id', $transactionIds)
|
||||
->where('transaction_journals.user_id', $this->user->id)
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->get( ['transactions.*']);
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
|
@ -35,6 +35,15 @@ use Illuminate\Support\MessageBag;
|
||||
*/
|
||||
interface JournalRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param array $transactionIds
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getTransactionsById(array $transactionIds): Collection;
|
||||
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param TransactionType $type
|
||||
|
@ -68,12 +68,19 @@ function storeReconcile() {
|
||||
$.each($('.reconcile_checkbox:checked'), function (i, v) {
|
||||
ids.push($(v).data('id'));
|
||||
});
|
||||
var cleared = [];
|
||||
$.each($('input[class="cleared"]'), function (i, v) {
|
||||
var obj = $(v);
|
||||
cleared.push(obj.data('id'));
|
||||
});
|
||||
|
||||
var variables = {
|
||||
startBalance: parseFloat($('input[name="start_balance"]').val()),
|
||||
endBalance: parseFloat($('input[name="end_balance"]').val()),
|
||||
startDate: $('input[name="start_date"]').val(),
|
||||
startEnd: $('input[name="end_date"]').val(),
|
||||
transactions: ids
|
||||
transactions: ids,
|
||||
cleared: cleared,
|
||||
};
|
||||
var uri = overviewUri.replace('%start%', $('input[name="start_date"]').val()).replace('%end%', $('input[name="end_date"]').val());
|
||||
|
||||
@ -126,11 +133,15 @@ function calculateBalanceDifference() {
|
||||
var startBalance = parseFloat($('input[name="start_balance"]').val());
|
||||
var endBalance = parseFloat($('input[name="end_balance"]').val());
|
||||
balanceDifference = startBalance - endBalance;
|
||||
if (balanceDifference < 0) {
|
||||
balanceDifference = balanceDifference * -1;
|
||||
}
|
||||
//if (balanceDifference < 0) {
|
||||
// balanceDifference = balanceDifference * -1;
|
||||
//}
|
||||
}
|
||||
|
||||
/**
|
||||
* Grab all transactions, update the URL and place the set of transactions in the box.
|
||||
* This more or less resets the reconciliation.
|
||||
*/
|
||||
function getTransactionsForRange() {
|
||||
// clear out the box:
|
||||
$('#transactions_holder').empty().append($('<p>').addClass('text-center').html('<i class="fa fa-fw fa-spin fa-spinner"></i>'));
|
||||
@ -141,12 +152,31 @@ function getTransactionsForRange() {
|
||||
$.getJSON(uri).done(placeTransactions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loop over all transactions that have already been cleared and add this to the selectedAmount.
|
||||
*
|
||||
*/
|
||||
function includeClearedTransactions() {
|
||||
$.each($('input[class="cleared"]'), function (i, v) {
|
||||
var obj = $(v);
|
||||
selectedAmount = selectedAmount - parseFloat(obj.val());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Place the HTML for the transactions within the date range and update the balance difference.
|
||||
* @param data
|
||||
*/
|
||||
function placeTransactions(data) {
|
||||
$('#transactions_holder').empty().html(data.html);
|
||||
|
||||
|
||||
// as long as the dates are equal, changing the balance does not matter.
|
||||
calculateBalanceDifference();
|
||||
|
||||
// any already cleared transactions must be added to / removed from selectedAmount.
|
||||
includeClearedTransactions();
|
||||
|
||||
difference = balanceDifference;
|
||||
updateDifference();
|
||||
|
||||
|
@ -647,6 +647,18 @@ return [
|
||||
'select_more_than_one_budget' => 'Please select more than one budget',
|
||||
'select_more_than_one_tag' => 'Please select more than one tag',
|
||||
'account_default_currency' => 'If you select another currency, new transactions from this account will have this currency pre-selected.',
|
||||
'reconcile_has_more' => 'Your Firefly III ledger has more money in it than your bank claims you should have. There are several options. Please choose what to do. Then, press "Confirm reconciliation".',
|
||||
'reconcile_has_less' => 'Your Firefly III ledger has less money in it than your bank claims you should have. There are several options. Please choose what to do. Then, press "Confirm reconciliation".',
|
||||
'reconcile_is_equal' => 'Your Firefly III ledger and your bank statements match. There is nothing to do. Please press "Confirm reconciliation" to confirm your input.',
|
||||
'create_pos_reconcile_transaction' => 'Clear the selected transactions, and create a correction adding :amount to this asset account.',
|
||||
'create_neg_reconcile_transaction' => 'Clear the selected transactions, and create a correction removing :amount from this asset account.',
|
||||
'reconcile_do_nothing' => 'Clear the selected transactions, but do not correct.',
|
||||
'reconcile_go_back' => 'You can always edit or delete a correction later.',
|
||||
'confirm_reconciliation' => 'Confirm reconciliation',
|
||||
'submitted_start_balance' => 'Submitted start balance',
|
||||
'selected_transactions' => 'Selected transactions (:count)',
|
||||
'already_cleared_transactions' => 'Already cleared transactions (:count)',
|
||||
'submitted_end_balance' => 'Submitted end balance',
|
||||
|
||||
// categories:
|
||||
'new_category' => 'New category',
|
||||
|
@ -7,7 +7,7 @@
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
|
||||
<div class="col-lg-9 col-md-12 col-sm-12 col-xs-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'reconcile_range'|_ }}</h3>
|
||||
@ -89,32 +89,17 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
|
||||
<div class="col-lg-3 col-md-12 col-sm-12 col-xs-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'reconcile_options'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body no-padding">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:50%;">{{ 'difference'|_ }}</th>
|
||||
<th>{{ 'actions'|_ }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<p class="lead" id="difference"></p>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-default store_reconcile" disabled><i class="fa fa-fw fa-check"></i> {{ 'store_reconcile'|_ }}</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="box-body">
|
||||
<p class="lead" id="difference"></p>
|
||||
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-default store_reconcile" disabled><i class="fa fa-fw fa-check"></i> {{ 'store_reconcile'|_ }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span>×</span><span class="sr-only">{{ 'close'|_ }}</span>
|
||||
@ -7,31 +7,90 @@
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
<form style="display: inline;" id="income" action="some route" method="POST">
|
||||
<form style="display: inline;" class="form-horizontal" id="income" action="{{ route }}" method="POST">
|
||||
<div class="modal-body">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
|
||||
<input type="hidden" name="start" value="{{ start.format('Y-m-d') }}"/>
|
||||
<input type="hidden" name="end" value="{{ end.format('Y-m-d') }}"/>
|
||||
<input type="hidden" name="startBalance" value="{{ startBalance }}"/>
|
||||
<input type="hidden" name="endBalance" value="{{ endBalance }}"/>
|
||||
{% for id in transactionIds %}
|
||||
<input type="hidden" name="transactions[]" value="{{ id }}" />
|
||||
{% endfor %}
|
||||
|
||||
You have selected X transactions. Total value X. Difference is zero
|
||||
reconcile will go ahead. (so no popup actually)
|
||||
<table class="table table-striped table-bordered">
|
||||
<tr>
|
||||
<td>{{ 'submitted_start_balance'|_ }} (date)</td>
|
||||
<td>{{ startBalance|formatAmount }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ trans('firefly.selected_transactions', {count: transactionIds|length}) }}</td>
|
||||
<td>{{ amount|formatAmount }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ trans('firefly.already_cleared_transactions', {count: clearedIds|length}) }}</td>
|
||||
<td>{{ clearedAmount|formatAmount }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ 'submitted_end_balance'|_ }} (date)</td>
|
||||
<td>{{ endBalance|formatAmount }}</td>
|
||||
</tr>
|
||||
{% set diff = (startBalance - endBalance) + clearedAmount + amount %}
|
||||
<tr>
|
||||
<td>{{ 'difference'|_ }}</td>
|
||||
<td>{{ diff|formatAmount }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
{% if diff > 0 %}
|
||||
{{ 'reconcile_has_more'|_ }}
|
||||
{% endif %}
|
||||
{% if diff < 0 %}
|
||||
{{ 'reconcile_has_less'|_ }}
|
||||
{% endif %}
|
||||
</p>
|
||||
{% if diff == 0 %}
|
||||
<p>
|
||||
{{ 'reconcile_is_equal'|_ }}
|
||||
</p>
|
||||
<input type="hidden" name="reconcile" value="nothing">
|
||||
{% endif %}
|
||||
{% if diff != 0 %}
|
||||
<div class="form-group">
|
||||
<div class="col-lg-12">
|
||||
<div class="radio">
|
||||
<label>
|
||||
|
||||
Difference is X or -X. X = you have too much money in Firefly III register. -X = you are missing amount X
|
||||
in your Firefly III register.
|
||||
|
||||
Please correct this first, or allow firefly to create a reconcilliation transaction. You can always edit or delete this later:
|
||||
|
||||
[X] Create a reconciling withdrawal for amount X
|
||||
[X] Create a reconciling deposit for amount X.
|
||||
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">{{ getCurrencySymbol()|raw }}</div>
|
||||
<input step="any" class="form-control" id="amount" value="{{ available }}" autocomplete="off" name="amount" type="number"/>
|
||||
<input type="radio" name="reconcile" value="create">
|
||||
{% if diff > 0 %}
|
||||
{{ trans('firefly.create_neg_reconcile_transaction', {amount: (diff*-1)|formatAmount})|raw }}
|
||||
{% endif %}
|
||||
{% if diff < 0 %}
|
||||
{{ trans('firefly.create_pos_reconcile_transaction', {amount: (diff*-1)|formatAmount})|raw }}
|
||||
{% endif %}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-lg-12">
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" checked name="reconcile" value="nothing"> {{ 'reconcile_do_nothing'|_ }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
{{ 'reconcile_go_back'|_ }}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'close'|_ }}</button>
|
||||
<button type="submit" class="btn btn-primary">{{ 'update_amount'|_ }}</button>
|
||||
<button type="submit" class="btn btn-primary">{{ 'confirm_reconciliation'|_ }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -84,6 +84,7 @@
|
||||
<td>
|
||||
{% if transaction.reconciled %}
|
||||
{{ transaction|transactionReconciled }}
|
||||
<input type="hidden" name="cleared[]" class="cleared" data-id="{{ transaction.id }}" value="{{ transaction.transaction_amount }}">
|
||||
{% else %}
|
||||
<input type="checkbox" name="reconciled[]"
|
||||
data-younger="{% if transaction.date > end %}true{% else %}false{% endif %}"
|
||||
|
@ -18,11 +18,7 @@
|
||||
{% for account in accounts %}
|
||||
<tr>
|
||||
<td class="hidden-sm hidden-xs">
|
||||
<div class="btn-group btn-group-xs">
|
||||
<a class="btn btn-default btn-xs" title="{{ 'edit'|_ }}" href="{{ route('accounts.edit',account.id) }}"><i class="fa fa-fw fa-pencil"></i></a>
|
||||
<a class="btn btn-default btn-xs" title="{{ 'reconcile'|_ }}" href="{{ route('accounts.reconcile',account.id) }}"><i class="fa fa-fw fa-check"></i></a>
|
||||
<a class="btn btn-danger btn-xs" title="{{ 'delete'|_ }}" href="{{ route('accounts.delete',account.id) }}"><i class="fa fa-fw fa-trash-o"></i></a>
|
||||
</div>
|
||||
<div class="btn-group btn-group-xs edit_tr_buttons"><a class="btn btn-default btn-xs" title="{{ 'edit'|_ }}" href="{{ route('accounts.edit',account.id) }}"><i class="fa fa-fw fa-pencil"></i></a><a class="btn btn-default btn-xs" title="{{ 'reconcile'|_ }}" href="{{ route('accounts.reconcile',account.id) }}"><i class="fa fa-fw fa-check"></i></a><a class="btn btn-danger btn-xs" title="{{ 'delete'|_ }}" href="{{ route('accounts.delete',account.id) }}"><i class="fa fa-fw fa-trash-o"></i></a></div>
|
||||
</td>
|
||||
<td data-value="{{ account.name }}"><a href="{{ route('accounts.show',account.id) }}">{{ account.name }}</a></td>
|
||||
{% if what == "asset" %}
|
||||
|
Loading…
Reference in New Issue
Block a user