Files
firefly-iii/app/Http/Controllers/Account/ReconcileController.php

227 lines
8.6 KiB
PHP
Raw Normal View History

2017-11-15 06:29:49 +01:00
<?php
/**
* ReconcileController.php
* 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
2017-12-17 14:41:58 +01:00
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
2017-11-15 06:29:49 +01:00
*/
2018-07-08 12:08:53 +02:00
/** @noinspection CallableParameterUseCaseInTypeContextInspection */
2017-11-15 06:29:49 +01:00
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Account;
use Carbon\Carbon;
2019-06-22 13:09:11 +02:00
use Exception;
2019-06-23 05:53:01 +02:00
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\TransactionGroupFactory;
2017-11-15 06:29:49 +01:00
use FireflyIII\Http\Controllers\Controller;
2018-02-23 15:13:01 +01:00
use FireflyIII\Http\Requests\ReconciliationStoreRequest;
2017-11-15 06:29:49 +01:00
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
2019-06-23 05:53:01 +02:00
use FireflyIII\Models\TransactionType;
2017-11-22 17:49:06 +01:00
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
2017-11-15 06:29:49 +01:00
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
2017-11-22 16:54:49 +01:00
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Support\Http\Controllers\UserNavigation;
2019-06-23 05:53:01 +02:00
use FireflyIII\User;
2018-02-23 15:13:01 +01:00
use Log;
2017-11-15 06:29:49 +01:00
/**
2017-11-15 12:25:49 +01:00
* Class ReconcileController.
2017-11-15 06:29:49 +01:00
*/
class ReconcileController extends Controller
{
use UserNavigation;
/** @var AccountRepositoryInterface The account repository */
2018-07-15 15:45:45 +02:00
private $accountRepos;
/** @var CurrencyRepositoryInterface The currency repository */
2018-03-25 09:01:43 +02:00
private $currencyRepos;
/** @var JournalRepositoryInterface Journals and transactions overview */
private $repository;
2017-11-15 06:29:49 +01:00
/**
* ReconcileController constructor.
2019-06-22 13:09:11 +02:00
* @codeCoverageIgnore
2017-11-15 06:29:49 +01:00
*/
public function __construct()
{
parent::__construct();
// translations:
$this->middleware(
function ($request, $next) {
2017-12-16 19:46:36 +01:00
app('view')->share('mainTitleIcon', 'fa-credit-card');
2018-07-15 09:38:49 +02:00
app('view')->share('title', (string)trans('firefly.accounts'));
2018-03-25 09:01:43 +02:00
$this->repository = app(JournalRepositoryInterface::class);
$this->accountRepos = app(AccountRepositoryInterface::class);
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
2017-11-15 06:29:49 +01:00
return $next($request);
}
);
}
/**
* Reconciliation overview.
*
2019-06-22 13:09:11 +02:00
* @param Account $account
2017-11-15 06:29:49 +01:00
* @param Carbon|null $start
* @param Carbon|null $end
*
2017-11-25 15:20:53 +01:00
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
2019-06-22 13:09:11 +02:00
* @throws Exception
2017-11-15 06:29:49 +01:00
*/
public function reconcile(Account $account, Carbon $start = null, Carbon $end = null)
{
2017-11-22 17:49:06 +01:00
if (AccountType::ASSET !== $account->accountType->type) {
2019-06-23 05:53:01 +02:00
// @codeCoverageIgnoreStart
2018-07-15 09:38:49 +02:00
session()->flash('error', (string)trans('firefly.must_be_asset_account'));
2017-11-22 17:49:06 +01:00
2019-06-22 13:09:11 +02:00
return redirect(route('accounts.index', [config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type))]));
2019-06-23 05:53:01 +02:00
// @codeCoverageIgnoreEnd
2017-11-15 06:29:49 +01:00
}
2019-06-22 13:09:11 +02:00
$currency = $this->accountRepos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency();
2017-11-15 06:29:49 +01:00
// no start or end:
$range = app('preferences')->get('viewRange', '1M')->data;
2017-11-15 06:29:49 +01:00
// get start and end
2019-06-23 05:53:01 +02:00
// @codeCoverageIgnoreStart
2017-11-15 12:25:49 +01:00
if (null === $start && null === $end) {
2019-06-23 05:53:01 +02:00
2018-07-27 04:46:21 +02:00
/** @var Carbon $start */
$start = clone session('start', app('navigation')->startOfPeriod(new Carbon, $range));
2018-07-27 04:46:21 +02:00
/** @var Carbon $end */
2018-08-06 19:14:30 +02:00
$end = clone session('end', app('navigation')->endOfPeriod(new Carbon, $range));
2019-06-23 05:53:01 +02:00
2017-11-15 06:29:49 +01:00
}
2017-11-15 12:25:49 +01:00
if (null === $end) {
2018-07-27 04:46:21 +02:00
/** @var Carbon $end */
$end = app('navigation')->endOfPeriod($start, $range);
2017-11-15 06:29:49 +01:00
}
2019-06-23 05:53:01 +02:00
// @codeCoverageIgnoreEnd
2017-11-15 06:29:49 +01:00
$startDate = clone $start;
2019-06-22 13:09:11 +02:00
$startDate->subDay();
2017-11-15 06:29:49 +01:00
$startBalance = round(app('steam')->balance($account, $startDate), $currency->decimal_places);
2019-08-02 16:31:36 +02:00
2017-11-15 06:29:49 +01:00
$endBalance = round(app('steam')->balance($account, $end), $currency->decimal_places);
2019-06-22 13:09:11 +02:00
$subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type));
2018-07-15 09:38:49 +02:00
$subTitle = (string)trans('firefly.reconcile_account', ['account' => $account->name]);
2017-11-15 06:29:49 +01:00
// 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%']);
2019-06-22 13:09:11 +02:00
$objectType = 'asset';
2018-04-24 19:26:16 +02:00
2019-06-22 13:09:11 +02:00
return view('accounts.reconcile.index',
compact('account', 'currency', 'objectType',
'subTitleIcon', 'start', 'end', 'subTitle', 'startBalance', 'endBalance',
'transactionsUri', 'overviewUri', 'indexUri'));
2017-11-15 06:29:49 +01:00
}
2017-11-22 17:49:06 +01:00
/**
* Submit a new reconciliation.
*
2018-02-23 15:13:01 +01:00
* @param ReconciliationStoreRequest $request
2019-06-22 13:09:11 +02:00
* @param Account $account
* @param Carbon $start
* @param Carbon $end
2017-11-25 15:20:53 +01:00
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
2017-11-22 17:49:06 +01:00
*/
2018-07-08 12:08:53 +02:00
public function submit(ReconciliationStoreRequest $request, Account $account, Carbon $start, Carbon $end)
2017-11-22 17:49:06 +01:00
{
2018-02-23 15:13:01 +01:00
Log::debug('In ReconcileController::submit()');
$data = $request->getAll();
2019-06-23 05:53:01 +02:00
/** @var string $journalId */
foreach ($data['journals'] as $journalId) {
$this->repository->reconcileById((int)$journalId);
2017-11-22 17:49:06 +01:00
}
2018-02-23 15:13:01 +01:00
Log::debug('Reconciled all transactions.');
2017-11-22 17:49:06 +01:00
// create reconciliation transaction (if necessary):
2019-06-23 05:53:01 +02:00
$result = '';
2018-02-23 15:13:01 +01:00
if ('create' === $data['reconcile']) {
2019-06-23 05:53:01 +02:00
$result = $this->createReconciliation($account, $start, $end, $data['difference']);
2017-11-22 17:49:06 +01:00
}
2018-02-23 15:13:01 +01:00
Log::debug('End of routine.');
2018-07-08 12:08:53 +02:00
app('preferences')->mark();
2019-06-23 05:53:01 +02:00
if ('' === $result) {
session()->flash('success', (string)trans('firefly.reconciliation_stored'));
}
if ('' !== $result) {
session()->flash('error', (string)trans('firefly.reconciliation_error', ['error' => $result]));
}
2017-11-22 17:49:06 +01:00
return redirect(route('accounts.show', [$account->id]));
}
2019-06-23 05:53:01 +02:00
/**
* Creates a reconciliation group.
* @return string
*/
private function createReconciliation(Account $account, Carbon $start, Carbon $end, string $difference): string
{
$reconciliation = $this->accountRepos->getReconciliation($account);
$currency = $this->accountRepos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency();
$source = $reconciliation;
$destination = $account;
if (1 === bccomp($difference, '0')) {
$source = $account;
$destination = $reconciliation;
}
// title:
$description = trans('firefly.reconciliation_transaction_title',
['from' => $start->formatLocalized($this->monthAndDayFormat), 'to' => $end->formatLocalized($this->monthAndDayFormat)]);
$submission = [
'user' => auth()->user()->id,
'group_title' => null,
'transactions' => [
[
'user' => auth()->user()->id,
'type' => strtolower(TransactionType::RECONCILIATION),
'date' => $end,
'order' => 0,
'currency_id' => $currency->id,
'foreign_currency_id' => null,
'amount' => $difference,
'foreign_amount' => null,
'description' => $description,
'source_id' => $source->id,
'destination_id' => $destination->id,
'reconciled' => true,
],
],
];
/** @var TransactionGroupFactory $factory */
$factory = app(TransactionGroupFactory::class);
/** @var User $user */
$user = auth()->user();
$factory->setUser($user);
try {
$factory->create($submission);
} catch (FireflyException $e) {
return $e->getMessage();
}
return '';
}
2017-11-15 10:52:29 +01:00
}