diff --git a/app/Http/Controllers/Account/ReconcileController.php b/app/Http/Controllers/Account/ReconcileController.php
new file mode 100644
index 0000000000..2ef5905eeb
--- /dev/null
+++ b/app/Http/Controllers/Account/ReconcileController.php
@@ -0,0 +1,173 @@
+.
+ */
+
+declare(strict_types=1);
+
+namespace FireflyIII\Http\Controllers\Account;
+
+
+use Carbon\Carbon;
+use FireflyIII\Helpers\Collector\JournalCollectorInterface;
+use FireflyIII\Http\Controllers\Controller;
+use FireflyIII\Models\Account;
+use FireflyIII\Models\AccountType;
+use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
+use Illuminate\Http\Request;
+use Illuminate\Support\Collection;
+use Navigation;
+use Preferences;
+use Response;
+use View;
+
+/**
+ * Class ReconcileController
+ *
+ * @package FireflyIII\Http\Controllers\Account
+ */
+class ReconcileController extends Controller
+{
+ /**
+ *
+ */
+ public function __construct()
+ {
+ parent::__construct();
+
+ // translations:
+ $this->middleware(
+ function ($request, $next) {
+ View::share('mainTitleIcon', 'fa-credit-card');
+ View::share('title', trans('firefly.accounts'));
+
+ return $next($request);
+ }
+ );
+ }
+
+ /**
+ * @param Request $request
+ * @param Account $account
+ * @param Carbon $start
+ * @param Carbon $end
+ *
+ * @return \Illuminate\Http\JsonResponse
+ */
+ public function overview(Request $request, Account $account, Carbon $start, Carbon $end)
+ {
+ $startBalance = $request->get('startBalance');
+ $endBalance = $request->get('endBalance');
+ $transactions = $request->get('transactions');
+
+ $return = [
+ 'is_zero' => false,
+ 'post_uri' => route('accounts.reconcile.submit', [$account->id, $start->format('Ymd'), $end->format('Ymd')]),
+ 'html' => '',
+ ];
+ $return['html'] = view('accounts.reconcile.overview', compact('account', 'start', 'end'))->render();
+
+ return Response::json($return);
+
+ }
+
+ /**
+ * @param Account $account
+ * @param Carbon|null $start
+ * @param Carbon|null $end
+ *
+ * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
+ */
+ public function reconcile(Account $account, Carbon $start = null, Carbon $end = null)
+ {
+ if ($account->accountType->type === AccountType::INITIAL_BALANCE) {
+ return $this->redirectToOriginalAccount($account);
+ }
+ /** @var CurrencyRepositoryInterface $currencyRepos */
+ $currencyRepos = app(CurrencyRepositoryInterface::class);
+ $currencyId = intval($account->getMeta('currency_id'));
+ $currency = $currencyRepos->find($currencyId);
+ if ($currencyId === 0) {
+ $currency = app('amount')->getDefaultCurrency();
+ }
+
+ // no start or end:
+ $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));
+ $end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
+ }
+ 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);
+ $subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
+ $subTitle = trans('firefly.reconcile_account', ['account' => $account->name]);
+
+ // various links
+ $transactionsUri = route('accounts.reconcile.transactions', [$account->id, '%start%', '%end%']);
+ $overviewUri = route('accounts.reconcile.overview', [$account->id, '%start%', '%end%']);
+ $indexUri = route('accounts.reconcile', [$account->id, '%start%', '%end%']);
+
+ return view(
+ 'accounts.reconcile.index', compact(
+ 'account', 'currency', 'subTitleIcon', 'start', 'end', 'subTitle', 'startBalance', 'endBalance', 'transactionsUri',
+ 'selectionStart', 'selectionEnd', 'overviewUri', 'indexUri'
+ )
+ );
+ }
+
+ /**
+ * @param Account $account
+ * @param Carbon $start
+ * @param Carbon $end
+ *
+ * @return mixed
+ */
+ public function transactions(Account $account, Carbon $start, Carbon $end)
+ {
+ if ($account->accountType->type === AccountType::INITIAL_BALANCE) {
+ return $this->redirectToOriginalAccount($account);
+ }
+
+ // get the transactions
+ $selectionStart = clone $start;
+ $selectionStart->subDays(3);
+ $selectionEnd = clone $end;
+ $selectionEnd->addDays(3);
+
+
+ // grab transactions:
+ /** @var JournalCollectorInterface $collector */
+ $collector = app(JournalCollectorInterface::class);
+ $collector->setAccounts(new Collection([$account]))
+ ->setRange($selectionStart, $selectionEnd)->withBudgetInformation()->withOpposingAccount()->withCategoryInformation();
+ $transactions = $collector->getJournals();
+ $html = view('accounts.reconcile.transactions', compact('account', 'transactions', 'start', 'end', 'selectionStart', 'selectionEnd'))->render();
+
+ return Response::json(['html' => $html]);
+ }
+
+}
\ No newline at end of file
diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php
index 1181029657..ecd68c0b91 100644
--- a/app/Http/Controllers/AccountController.php
+++ b/app/Http/Controllers/AccountController.php
@@ -250,74 +250,6 @@ class AccountController extends Controller
return view('accounts.index', compact('what', 'subTitleIcon', 'subTitle', 'accounts'));
}
- /**
- * @param Request $request
- * @param Account $account
- * @param string $moment
- *
- * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
- */
- public function reconcile(Request $request, Account $account, Carbon $start = null, Carbon $end = null)
- {
- if ($account->accountType->type === AccountType::INITIAL_BALANCE) {
- return $this->redirectToOriginalAccount($account);
- }
- /** @var CurrencyRepositoryInterface $currencyRepos */
- $currencyRepos = app(CurrencyRepositoryInterface::class);
- $currencyId = intval($account->getMeta('currency_id'));
- $currency = $currencyRepos->find($currencyId);
- if ($currencyId === 0) {
- $currency = app('amount')->getDefaultCurrency();
- }
-
- // no start or end:
- $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));
- $end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
- }
- 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);
- $subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
- $subTitle = trans('firefly.reconcile_account', ['account' => $account->name]);
-
- // get the transactions
- $selectionStart = clone $start;
- $selectionStart->subDays(7);
- $selectionEnd = clone $end;
- $selectionEnd->addDays(5);
-
- // 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.
- if (strlen($moment) > 0 && $moment !== 'all') {
- $start = new Carbon($moment);
- $end = Navigation::endOfPeriod($start, $range);
- }
-
-
-
- return view(
- 'accounts.show',
- compact('account', 'currency', 'moment', 'periods', 'subTitleIcon', 'transactions', 'subTitle', 'start', 'end', 'chartUri')
- );
- }
-
/**
* Show an account.
*
diff --git a/public/js/ff/accounts/reconcile.js b/public/js/ff/accounts/reconcile.js
index c19b64d482..8611b24f74 100644
--- a/public/js/ff/accounts/reconcile.js
+++ b/public/js/ff/accounts/reconcile.js
@@ -18,20 +18,178 @@
* along with Firefly III. If not, see
').addClass('text-center').html('')); + var uri = transactionsUri.replace('%start%', $('input[name="start_date"]').val()).replace('%end%', $('input[name="end_date"]').val()); + var index = indexUri.replace('%start%', $('input[name="start_date"]').val()).replace('%end%', $('input[name="end_date"]').val()); + window.history.pushState('object or string', "Reconcile account", index); + + $.getJSON(uri).done(placeTransactions); +} + +function placeTransactions(data) { + $('#transactions_holder').empty().html(data.html); + + + // as long as the dates are equal, changing the balance does not matter. + calculateBalanceDifference(); + difference = balanceDifference; + updateDifference(); + + // enable the check buttons: + $('.reconcile_checkbox').prop('disabled', false).unbind('change').change(checkReconciledBox); + + // show the other instruction: + $('.select_transactions_instruction').show(); +} + +/** + * + * @returns {boolean} + */ +function startReconcile() { + + reconcileStarted = true; + + // hide the start button. + $('.start_reconcile').hide(); + + // hide the start instructions: + $('.update_balance_instruction').hide(); + + // hide date-change warning + $('.date_change_warning').hide(); + + // hide update button + $('.change_date_button').hide(); + + getTransactionsForRange(); + + return false; } + +function updateDifference() { + var addClass = 'text-info'; + if (difference > 0) { + addClass = 'text-success'; + } + if (difference < 0) { + addClass = 'text-danger'; + } + $('#difference').addClass(addClass).text(accounting.formatMoney(difference)); +} \ No newline at end of file diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index c6b211e967..d387359f22 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -619,8 +619,19 @@ return [ 'cash_accounts' => 'Cash accounts', 'Cash account' => 'Cash account', 'reconcile_account' => 'Reconcile account ":account"', - 'end_of_reconcile_period' => 'End of reconcile period: :period', - 'start_of_reconcile_period' => 'Start of reconcile period: :period', + 'end_of_reconcile_period' => 'End of reconcile period: :period', + 'start_of_reconcile_period' => 'Start of reconcile period: :period', + 'start_balance' => 'Start balance', + 'end_balance' => 'End balance', + 'update_balance_dates_instruction' => 'Match the amounts and dates above to your bank statement, and press "Start reconciling"', + 'select_transactions_instruction' => 'Select the transactions that appear on your bank statement.', + 'select_range_and_balance' => 'First verify the date-range and balances. Then press "Start reconciling"', + 'date_change_instruction' => 'If you change the date range now, any progress will be lost.', + 'update_selection' => 'Update selection', + 'store_reconcile' => 'Store reconciliation', + 'reconcile_options' => 'Reconciliation options', + 'reconcile_range' => 'Reconciliation range', + 'start_reconcile' => 'Start reconciling', 'cash' => 'cash', 'account_type' => 'Account type', 'save_transactions_by_moving' => 'Save these transaction(s) by moving them to another account:', diff --git a/resources/views/accounts/reconcile/index.twig b/resources/views/accounts/reconcile/index.twig index e111c69190..a5aade3415 100644 --- a/resources/views/accounts/reconcile/index.twig +++ b/resources/views/accounts/reconcile/index.twig @@ -75,9 +75,13 @@
+- | {{ trans('list.description') }} | -{{ trans('list.amount') }} | - - - - - -- | - | |||||
---|---|---|---|---|---|---|---|---|---|
- - | -- - {{ trans('firefly.start_of_reconcile_period', {period: start.formatLocalized(monthAndDayFormat) }) }} - - | -- - | -|||||||
- - | -- - {{ trans('firefly.end_of_reconcile_period', {period: end.formatLocalized(monthAndDayFormat) }) }} - - | -- - | -|||||||
- - | - {# icon #} -- {{ transaction|transactionIcon }} - | - - {# description #} -- - {{ transaction|transactionDescription }} - - {# is a split journal #} - {{ transaction|transactionIsSplit }} - - {# count attachments #} - {{ transaction|transactionHasAtt }} - - - | -{{ transaction|transactionAmount }} | -- {% if transaction.reconciled %} - {{ transaction|transactionReconciled }} - {% else %} - - {% endif %} - | - - - -- {{ transaction|transactionBudgets }} - | -- {{ transaction|transactionCategories }} - | -
{{ 'select_range_and_balance'|_ }}
++ | {{ trans('list.description') }} | +{{ trans('list.amount') }} | + + + + + ++ | + | |||||
---|---|---|---|---|---|---|---|---|---|
+ + | ++ + {{ trans('firefly.start_of_reconcile_period', {period: start.formatLocalized(monthAndDayFormat) }) }} + + | ++ + | +|||||||
+ + | ++ + {{ trans('firefly.end_of_reconcile_period', {period: end.formatLocalized(monthAndDayFormat) }) }} + + | ++ + | +|||||||
+ + | + {# icon #} ++ {{ transaction|transactionIcon }} + | + + {# description #} ++ + {{ transaction|transactionDescription }} + + {# is a split journal #} + {{ transaction|transactionIsSplit }} + + {# count attachments #} + {{ transaction|transactionHasAtt }} + + + | +{{ transaction|transactionAmount }} | ++ {% if transaction.reconciled %} + {{ transaction|transactionReconciled }} + {% else %} + + {% endif %} + | + + + ++ {{ transaction|transactionBudgets }} + | ++ {{ transaction|transactionCategories }} + | +|||
+ + | ++ + {{ trans('firefly.start_of_reconcile_period', {period: start.formatLocalized(monthAndDayFormat) }) }} + + | ++ + | +