Merge branch 'release/5.3.0-beta.2' into main

This commit is contained in:
James Cole 2020-07-01 19:54:31 +02:00
commit 80de6c78dc
200 changed files with 3619 additions and 1712 deletions

View File

@ -17,7 +17,7 @@ APP_KEY=SomeRandomStringOf32CharsExactly
#
# Firefly III will launch using this language (for new users and unauthenticated visitors)
# For a list of available languages: https://github.com/firefly-iii/firefly-iii/tree/master/resources/lang
# For a list of available languages: https://github.com/firefly-iii/firefly-iii/tree/main/resources/lang
#
# If text is still in English, remember that not everything may have been translated.
DEFAULT_LANGUAGE=en_US

View File

@ -8,7 +8,7 @@ I am always interested in expanding Firefly III's many features. Just open a tic
## Pull requests
When contributing to Firefly III, please first discuss the change you wish to make via issue, email, or any other method. I can only accept pull requests against the `develop` branch, never the `master` branch.
When contributing to Firefly III, please first discuss the change you wish to make via issue, email, or any other method. I can only accept pull requests against the `develop` branch, never the `main` branch.
## Translations :us: :fr: :de:

View File

@ -1,8 +1,9 @@
<!--
Before you create a new PR, please consider the following two considerations.
Before you create a new PR, please consider:
1) Pull request for the MASTER branch will be closed.
1) Pull requests for the MAIN branch will be closed.
2) We cannot accept pull requests to add new currencies.
3) DO NOT include translations in your PR. Only English US sentences.
Thanks.
-->

2
.github/security.md vendored
View File

@ -8,5 +8,5 @@ Only the latest version of Firefly III is supported. If you're not running the l
If you find something that compromises the security of Firefly III, you should [send me a message](mailto:james@firefly-iii.org) as soon as possible. These issues will be fixed immediately. You can also open an issue, but if you feel the issue is sensitive, please drop me a message instead.
You can use my [GPG key](https://keybase.io/jc5) for extra security. My [GitHub commits](https://github.com/firefly-iii/firefly-iii/commits/master) are almost always signed with this key.
You can use my [GPG key](https://keybase.io/jc5) for extra security. My [GitHub commits](https://github.com/firefly-iii/firefly-iii/commits/main) are almost always signed with this key.

View File

@ -3,7 +3,7 @@
"description": "A free and open source personal finances manager",
"repository": "https://github.com/firefly-iii/firefly-iii",
"website": "https://firefly-iii.org/",
"logo": "https://raw.githubusercontent.com/firefly-iii/firefly-iii/master/public/mstile-150x150.png",
"logo": "https://raw.githubusercontent.com/firefly-iii/firefly-iii/main/public/mstile-150x150.png",
"keywords": [
"finance",
"finances",

View File

@ -42,10 +42,8 @@ use Illuminate\Http\JsonResponse;
class AccountController extends Controller
{
use ApiSupport;
/** @var CurrencyRepositoryInterface */
private $currencyRepository;
/** @var AccountRepositoryInterface */
private $repository;
private CurrencyRepositoryInterface $currencyRepository;
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.

View File

@ -241,7 +241,6 @@ class PiggyBankController extends Controller
$this->repository->setCurrentAmount($piggyBank, $data['current_amount']);
}
$manager = $this->getManager();
/** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class);

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* AccountController.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Search;
use FireflyIII\Api\V1\Controllers\Controller;

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* TransactionController.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,45 +20,51 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Search;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Support\Search\SearchInterface;
use FireflyIII\Transformers\TransactionGroupTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection;
/**
* Class TransactionController
*/
class TransactionController extends Controller
{
/** @var string */
public const SEARCH_ALL = 'all';
/** @var string */
public const SEARCH_DESCRIPTION = 'description';
/** @var string */
public const SEARCH_NOTES = 'notes';
/** @var string */
public const SEARCH_ACCOUNTS = 'accounts';
/** @var array */
private $validFields;
public function __construct()
{
parent::__construct();
$this->validFields = [
self::SEARCH_ALL,
self::SEARCH_DESCRIPTION,
self::SEARCH_NOTES,
self::SEARCH_ACCOUNTS,
];
}
/**
* @param Request $request
* @param Request $request
* @param SearchInterface $searcher
*
* @return void
* @return JsonResponse
*/
public function search(Request $request): void
public function search(Request $request, SearchInterface $searcher): JsonResponse
{
die('the route is present but nobody\'s home.');
$manager = $this->getManager();
$fullQuery = (string) $request->get('query');
$page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page');
$searcher->parseQuery($fullQuery);
$searcher->setPage($page);
$searcher->setLimit((int) config('firefly.search_result_limit'));
$groups = $searcher->searchTransactions();
$parameters = ['search' => $fullQuery];
$url = route('api.v1.search.transactions') . '?' . http_build_query($parameters);
$groups->setPath($url);
$transactions = $groups->getCollection();
/** @var TransactionGroupTransformer $transformer */
$transformer = app(TransactionGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Collection($transactions, $transformer, 'transactions');
$resource->setPaginator(new IlluminatePaginatorAdapter($groups));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
}

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* TransferController.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Search;
use FireflyIII\Api\V1\Controllers\Controller;

View File

@ -70,6 +70,7 @@ class BillRequest extends Request
'repeat_freq' => $this->string('repeat_freq'),
'skip' => $this->integer('skip'),
'active' => $active,
'order' => $this->integer('order'),
'notes' => $this->nlString('notes'),
];
}
@ -83,13 +84,13 @@ class BillRequest extends Request
public function rules(): array
{
$rules = [
'name' => 'required|between:1,255|uniqueObjectForUser:bills,name',
'amount_min' => 'required|numeric|more:0',
'amount_max' => 'required|numeric|more:0',
'name' => 'between:1,255|uniqueObjectForUser:bills,name',
'amount_min' => 'numeric|more:0',
'amount_max' => 'numeric|more:0',
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'date' => 'required|date',
'repeat_freq' => 'required|in:weekly,monthly,quarterly,half-year,yearly',
'date' => 'date',
'repeat_freq' => 'in:weekly,monthly,quarterly,half-year,yearly',
'skip' => 'between:0,31',
'active' => [new IsBoolean],
'notes' => 'between:1,65536',

View File

@ -63,6 +63,7 @@ class PiggyBankRequest extends Request
'startdate' => $this->date('start_date'),
'targetdate' => $this->date('target_date'),
'notes' => $this->nlString('notes'),
'order' => $this->integer('order'),
];
}

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* TransferRequest.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Search;
use FireflyIII\Api\V1\Requests\Request;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* CorrectOpeningBalanceCurrencies.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\Account;

View File

@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use DB;
use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Handlers\Events\UpdatedGroupEventHandler;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
/**
* Class FixGroupAccounts
*/
class FixGroupAccounts extends Command
{
/**
* The console command description.
*
* @var string
*/
protected $description = 'Unify the source / destination accounts of split groups.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:unify-group-accounts';
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
// select transaction_group_id, count(transaction_group_id) as the_count from transaction_journals group by transaction_group_id having the_count > 1
$groups = [];
$res = TransactionJournal
::groupBy('transaction_group_id')
->get(['transaction_group_id', DB::raw('COUNT(transaction_group_id) as the_count')]);
foreach ($res as $journal) {
if ((int) $journal->the_count > 1) {
$groups[] = (int) $journal->transaction_group_id;
}
}
$handler = new UpdatedGroupEventHandler;
foreach($groups as $groupId) {
$group = TransactionGroup::find($groupId);
$event = new UpdatedTransactionGroup($group);
$handler->unifyAccounts($event);
}
$this->line('Updated inconsistent transaction groups.');
return 0;
}
}

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* FixLongDescriptions.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\TransactionGroup;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* FixRecurringTransactions.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\Recurrence;

View File

@ -1,6 +1,4 @@
<?php
declare(strict_types=1);
/**
* CreateDatabase.php
@ -22,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands;
use Illuminate\Console\Command;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* ExportData.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Export;
use Carbon\Carbon;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* RestoreOAuthKeys.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Integrity;
use FireflyIII\Support\System\OAuthKeys;

View File

@ -1,5 +1,4 @@
<?php
declare(strict_types=1);
/**
* SetLatestVersion.php
@ -21,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands;
use Illuminate\Console\Command;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* MigrateRecurrenceMeta.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Upgrade;
use FireflyIII\Models\RecurrenceMeta;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* MigrateTagLocations.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Upgrade;
use FireflyIII\Models\Location;

View File

@ -76,7 +76,7 @@ class UpgradeDatabase extends Command
'firefly-iii:migrate-recurrence-meta',
'firefly-iii:migrate-tag-locations',
// there are 16 verify commands.
// there are 15 verify commands.
'firefly-iii:fix-piggies',
'firefly-iii:create-link-types',
'firefly-iii:create-access-tokens',
@ -93,6 +93,7 @@ class UpgradeDatabase extends Command
'firefly-iii:fix-ob-currencies',
'firefly-iii:fix-long-descriptions',
'firefly-iii:fix-recurring-transactions',
'firefly-iii:unify-group-accounts',
// two report commands
'firefly-iii:report-empty-objects',

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* DuplicateTransactionException.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Exceptions;
use Exception;

View File

@ -27,6 +27,7 @@ namespace FireflyIII\Factory;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
use FireflyIII\Services\Internal\Support\BillServiceTrait;
use FireflyIII\User;
use Illuminate\Database\QueryException;
@ -37,7 +38,7 @@ use Log;
*/
class BillFactory
{
use BillServiceTrait;
use BillServiceTrait, CreatesObjectGroups;
/** @var User */
private $user;
@ -97,6 +98,24 @@ class BillFactory
$this->updateNote($bill, $data['notes']);
}
$objectGroupTitle = $data['object_group'] ?? '';
if ('' !== $objectGroupTitle) {
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
if (null !== $objectGroup) {
$bill->objectGroups()->sync([$objectGroup->id]);
$bill->save();
}
}
// try also with ID:
$objectGroupId = (int) ($data['object_group_id'] ?? 0);
if (0 !== $objectGroupId) {
$objectGroup = $this->findObjectGroupById($objectGroupId);
if (null !== $objectGroup) {
$bill->objectGroups()->sync([$objectGroup->id]);
$bill->save();
}
}
return $bill;
}

View File

@ -23,14 +23,58 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\TransactionRules\Engine\RuleEngine;
use Log;
/**
* Class UpdatedGroupEventHandler
*/
class UpdatedGroupEventHandler
{
/**
* This method will make sure all source / destination accounts are the same.
*
* @param UpdatedTransactionGroup $updatedGroupEvent
*/
public function unifyAccounts(UpdatedTransactionGroup $updatedGroupEvent): void
{
$group = $updatedGroupEvent->transactionGroup;
if (1 === $group->transactionJournals->count()) {
return;
}
Log::debug(sprintf('Correct inconsistent accounts in group #%d', $group->id));
// first journal:
/** @var TransactionJournal $first */
$first = $group->transactionJournals()
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->orderBy('transaction_journals.description', 'DESC')
->first();
$all = $group->transactionJournals()->get()->pluck('id')->toArray();
/** @var Account $sourceAccount */
$sourceAccount = $first->transactions()->where('amount', '<', '0')->first()->account;
/** @var Account $destAccount */
$destAccount = $first->transactions()->where('amount', '>', '0')->first()->account;
$type = $first->transactionType->type;
if (TransactionType::TRANSFER === $type || TransactionType::WITHDRAWAL === $type) {
// set all source transactions to source account:
Transaction::whereIn('transaction_journal_id', $all)
->where('amount', '<', 0)->update(['account_id' => $sourceAccount->id]);
}
if (TransactionType::TRANSFER === $type || TransactionType::DEPOSIT === $type) {
// set all destination transactions to destination account:
Transaction::whereIn('transaction_journal_id', $all)
->where('amount', '>', 0)->update(['account_id' => $destAccount->id]);
}
}
/**
* This method will check all the rules when a journal is updated.
*

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* AccountCollection.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Collector\Extensions;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* AmountCollection.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Collector\Extensions;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* CollectorProperties.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Collector\Extensions;
use FireflyIII\User;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* MetaCollection.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Collector\Extensions;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* TimeCollection.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Collector\Extensions;
use Carbon\Carbon;

View File

@ -77,7 +77,7 @@ class Help implements HelpInterface
*/
public function getFromGitHub(string $route, string $language): string
{
$uri = sprintf('https://raw.githubusercontent.com/firefly-iii/help/master/%s/%s.md', $language, $route);
$uri = sprintf('https://raw.githubusercontent.com/firefly-iii/help/main/%s/%s.md', $language, $route);
Log::debug(sprintf('Trying to get %s...', $uri));
$opt = ['headers' => ['User-Agent' => $this->userAgent]];
$content = '';

View File

@ -101,7 +101,7 @@ class IndexController extends Controller
$account->startBalance = $this->isInArray($startBalances, $account->id);
$account->endBalance = $this->isInArray($endBalances, $account->id);
$account->difference = bcsub($account->endBalance, $account->startBalance);
$account->interest = round($this->repository->getMetaValue($account, 'interest'), 6);
$account->interest = number_format((float) $this->repository->getMetaValue($account, 'interest'), 6, '.', '');
$account->interestPeriod = (string) trans(sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period')));
$account->accountTypeString = (string) trans(sprintf('firefly.account_type_%s', $account->accountType->type));
}
@ -155,7 +155,7 @@ class IndexController extends Controller
$account->startBalance = $this->isInArray($startBalances, $account->id);
$account->endBalance = $this->isInArray($endBalances, $account->id);
$account->difference = bcsub($account->endBalance, $account->startBalance);
$account->interest = round($this->repository->getMetaValue($account, 'interest'), 6);
$account->interest = number_format((float) $this->repository->getMetaValue($account, 'interest'), 6, '.', '');
$account->interestPeriod = (string) trans(sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period')));
$account->accountTypeString = (string) trans(sprintf('firefly.account_type_%s', $account->accountType->type));
$account->location = $this->repository->getLocation($account);

View File

@ -129,8 +129,8 @@ class ReconcileController extends Controller
$startDate = clone $start;
$startDate->subDay();
$startBalance = round(app('steam')->balance($account, $startDate), $currency->decimal_places);
$endBalance = round(app('steam')->balance($account, $end), $currency->decimal_places);
$startBalance = number_format((float) app('steam')->balance($account, $startDate), $currency->decimal_places, '.', '');
$endBalance = number_format((float) app('steam')->balance($account, $end), $currency->decimal_places, '.', '');
$subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type));
$subTitle = (string) trans('firefly.reconcile_account', ['account' => $account->name]);

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* TelemetryController.php
* Copyright (c) 2020 thegrumpydictator@gmail.com
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Admin;
use Carbon\Carbon;

View File

@ -1,6 +1,4 @@
<?php
declare(strict_types=1);
/**
* ConfirmPasswordController.php
@ -22,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Auth;
use FireflyIII\Http\Controllers\Controller;

View File

@ -0,0 +1,130 @@
<?php
/**
* CreateController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Bill;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\BillStoreRequest;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
/**
* Class CreateController
*/
class CreateController extends Controller
{
private AttachmentHelperInterface $attachments;
private BillRepositoryInterface $repository;
/**
* BillController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string) trans('firefly.bills'));
app('view')->share('mainTitleIcon', 'fa-calendar-o');
$this->attachments = app(AttachmentHelperInterface::class);
$this->repository = app(BillRepositoryInterface::class);
return $next($request);
}
);
}
/**
* Create a new bill.
*
* @param Request $request
*
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function create(Request $request)
{
$periods = [];
/** @var array $billPeriods */
$billPeriods = config('firefly.bill_periods');
foreach ($billPeriods as $current) {
$periods[$current] = strtolower((string) trans('firefly.repeat_freq_' . $current));
}
$subTitle = (string) trans('firefly.create_new_bill');
$defaultCurrency = app('amount')->getDefaultCurrency();
// put previous url in session if not redirect from store (not "create another").
if (true !== session('bills.create.fromStore')) {
$this->rememberPreviousUri('bills.create.uri');
}
$request->session()->forget('bills.create.fromStore');
return view('bills.create', compact('periods', 'subTitle', 'defaultCurrency'));
}
/**
* Store a new bill.
*
* @param BillStoreRequest $request
*
* @return RedirectResponse
*
*/
public function store(BillStoreRequest $request): RedirectResponse
{
$billData = $request->getBillData();
$billData['active'] = true;
try {
$bill = $this->repository->store($billData);
} catch (FireflyException $e) {
Log::error($e->getMessage());
$request->session()->flash('error', (string) trans('firefly.bill_store_error'));
return redirect(route('bills.create'))->withInput();
}
$request->session()->flash('success', (string) trans('firefly.stored_new_bill', ['name' => $bill->name]));
app('preferences')->mark();
/** @var array $files */
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
if (null !== $files && !auth()->user()->hasRole('demo')) {
$this->attachments->saveAttachmentsForModel($bill, $files);
}
if (null !== $files && auth()->user()->hasRole('demo')) {
session()->flash('info', (string) trans('firefly.no_att_demo_user'));
}
if (count($this->attachments->getMessages()->get('attachments')) > 0) {
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore
}
return redirect(route('rules.create-from-bill', [$bill->id]));
}
}

View File

@ -0,0 +1,99 @@
<?php
/**
* DeleteController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Bill;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\View\View;
/**
* Class DeleteController
*/
class DeleteController extends Controller
{
private BillRepositoryInterface $repository;
/**
* BillController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
app('view')->share('showBudget', true);
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string) trans('firefly.bills'));
app('view')->share('mainTitleIcon', 'fa-calendar-o');
$this->repository = app(BillRepositoryInterface::class);
return $next($request);
}
);
}
/**
* Delete a bill.
*
* @param Bill $bill
*
* @return Factory|View
*/
public function delete(Bill $bill)
{
// put previous url in session
$this->rememberPreviousUri('bills.delete.uri');
$subTitle = (string) trans('firefly.delete_bill', ['name' => $bill->name]);
return view('bills.delete', compact('bill', 'subTitle'));
}
/**
* Destroy a bill.
*
* @param Request $request
* @param Bill $bill
*
* @return RedirectResponse|Redirector
*/
public function destroy(Request $request, Bill $bill)
{
$name = $bill->name;
$this->repository->destroy($bill);
$request->session()->flash('success', (string) trans('firefly.deleted_bill', ['name' => $name]));
app('preferences')->mark();
return redirect($this->getPreviousUri('bills.delete.uri'));
}
}

View File

@ -0,0 +1,155 @@
<?php
/**
* EditController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Bill;
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\BillUpdateRequest;
use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
/**
* Class EditController
*/
class EditController extends Controller
{
private AttachmentHelperInterface $attachments;
private BillRepositoryInterface $repository;
/**
* BillController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string) trans('firefly.bills'));
app('view')->share('mainTitleIcon', 'fa-calendar-o');
$this->attachments = app(AttachmentHelperInterface::class);
$this->repository = app(BillRepositoryInterface::class);
return $next($request);
}
);
}
/**
* Edit a bill.
*
* @param Request $request
* @param Bill $bill
*
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function edit(Request $request, Bill $bill)
{
$periods = [];
/** @var array $billPeriods */
$billPeriods = config('firefly.bill_periods');
foreach ($billPeriods as $current) {
$periods[$current] = (string) trans('firefly.' . $current);
}
$subTitle = (string) trans('firefly.edit_bill', ['name' => $bill->name]);
// put previous url in session if not redirect from store (not "return_to_edit").
if (true !== session('bills.edit.fromUpdate')) {
$this->rememberPreviousUri('bills.edit.uri');
}
$currency = app('amount')->getDefaultCurrency();
$bill->amount_min = round((float) $bill->amount_min, $currency->decimal_places);
$bill->amount_max = round((float) $bill->amount_max, $currency->decimal_places);
$rules = $this->repository->getRulesForBill($bill);
$defaultCurrency = app('amount')->getDefaultCurrency();
// code to handle active-checkboxes
$hasOldInput = null !== $request->old('_token');
$preFilled = [
'notes' => $this->repository->getNoteText($bill),
'transaction_currency_id' => $bill->transaction_currency_id,
'active' => $hasOldInput ? (bool) $request->old('active') : $bill->active,
'object_group' => $bill->objectGroups->first() ? $bill->objectGroups->first()->title : '',
];
$request->session()->flash('preFilled', $preFilled);
$request->session()->forget('bills.edit.fromUpdate');
return view('bills.edit', compact('subTitle', 'periods', 'rules', 'bill', 'defaultCurrency', 'preFilled'));
}
/**
* Update a bill.
*
* @param BillUpdateRequest $request
* @param Bill $bill
*
* @return RedirectResponse
*/
public function update(BillUpdateRequest $request, Bill $bill): RedirectResponse
{
$billData = $request->getBillData();
$bill = $this->repository->update($bill, $billData);
$request->session()->flash('success', (string) trans('firefly.updated_bill', ['name' => $bill->name]));
app('preferences')->mark();
/** @var array $files */
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
if (null !== $files && !auth()->user()->hasRole('demo')) {
$this->attachments->saveAttachmentsForModel($bill, $files);
}
if (null !== $files && auth()->user()->hasRole('demo')) {
session()->flash('info',(string)trans('firefly.no_att_demo_user'));
}
// flash messages
if (count($this->attachments->getMessages()->get('attachments')) > 0) {
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore
}
$redirect = redirect($this->getPreviousUri('bills.edit.uri'));
if (1 === (int) $request->get('return_to_edit')) {
// @codeCoverageIgnoreStart
$request->session()->put('bills.edit.fromUpdate', true);
$redirect = redirect(route('bills.edit', [$bill->id]))->withInput(['return_to_edit' => 1]);
// @codeCoverageIgnoreEnd
}
return $redirect;
}
}

View File

@ -0,0 +1,247 @@
<?php
/**
* IndexController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Bill;
use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\ObjectGroup\OrganisesObjectGroups;
use FireflyIII\Transformers\BillTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Log;
use Symfony\Component\HttpFoundation\ParameterBag;
/**
* Class IndexController
*/
class IndexController extends Controller
{
use OrganisesObjectGroups;
private BillRepositoryInterface $repository;
/**
* BillController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string) trans('firefly.bills'));
app('view')->share('mainTitleIcon', 'fa-calendar-o');
$this->repository = app(BillRepositoryInterface::class);
return $next($request);
}
);
}
/**
* Show all bills.
*/
public function index()
{
$this->cleanupObjectGroups();
$this->repository->correctOrder();
$start = session('start');
$end = session('end');
$collection = $this->repository->getBills();
$total = $collection->count();
$defaultCurrency = app('amount')->getDefaultCurrency();
$parameters = new ParameterBag;
$parameters->set('start', $start);
$parameters->set('end', $end);
/** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class);
$transformer->setParameters($parameters);
// loop all bills, convert to array and add rules and stuff.
$rules = $this->repository->getRulesForBills($collection);
// make bill groups:
$bills = [
0 => [ // the index is the order, not the ID.
'object_group_id' => 0,
'object_group_title' => (string) trans('firefly.default_group_title_name'),
'bills' => [],
],
];
/** @var Bill $bill */
foreach ($collection as $bill) {
$array = $transformer->transform($bill);
$groupOrder = (int) $array['object_group_order'];
// make group array if necessary:
$bills[$groupOrder] = $bills[$groupOrder] ?? [
'object_group_id' => $array['object_group_id'],
'object_group_title' => $array['object_group_title'],
'bills' => [],
];
$nextExpectedMatch = new Carbon($array['next_expected_match']);
$array['next_expected_match_diff'] = $nextExpectedMatch->isToday()
? trans('firefly.today')
: $nextExpectedMatch->diffForHumans(
today(), Carbon::DIFF_RELATIVE_TO_NOW
);
$currency = $bill->transactionCurrency ?? $defaultCurrency;
$array['currency_id'] = $currency->id;
$array['currency_name'] = $currency->name;
$array['currency_symbol'] = $currency->symbol;
$array['currency_code'] = $currency->code;
$array['currency_decimal_places'] = $currency->decimal_places;
$array['attachments'] = $this->repository->getAttachments($bill);
$array['rules'] = $rules[$bill['id']] ?? [];
$bills[$groupOrder]['bills'][] = $array;
}
// order by key
ksort($bills);
// summarise per currency / per group.
$sums = $this->getSums($bills);
return view('bills.index', compact('bills', 'sums', 'total'));
}
/**
* @param array $bills
*
* @return array
*/
private function getSums(array $bills): array
{
$sums = [];
$range = app('preferences')->get('viewRange', '1M')->data;
/** @var array $group */
foreach ($bills as $groupOrder => $group) {
/** @var array $bill */
foreach ($group['bills'] as $bill) {
if (false === $bill['active']) {
continue;
}
/** @var TransactionCurrency $currency */
$currencyId = $bill['currency_id'];
$sums[$groupOrder][$currencyId] = $sums[$groupOrder][$currencyId] ?? [
'currency_id' => $currencyId,
'currency_code' => $bill['currency_code'],
'currency_name' => $bill['currency_name'],
'currency_symbol' => $bill['currency_symbol'],
'currency_decimal_places' => $bill['currency_decimal_places'],
'avg' => '0',
'period' => $range,
'per_period' => '0',
];
// only fill in avg when bill is active.
if (count($bill['pay_dates']) > 0) {
$avg = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2');
$avg = bcmul($avg, (string) count($bill['pay_dates']));
$sums[$groupOrder][$currencyId]['avg'] = bcadd($sums[$groupOrder][$currencyId]['avg'], $avg);
}
// fill in per period regardless:
$sums[$groupOrder][$currencyId]['per_period'] = bcadd($sums[$groupOrder][$currencyId]['per_period'], $this->amountPerPeriod($bill, $range));
}
}
return $sums;
}
/**
* @param array $bill
* @param string $range
*
* @return string
*/
private function amountPerPeriod(array $bill, string $range): string
{
$avg = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2');
Log::debug(sprintf('Amount per period for bill #%d "%s"', $bill['id'], $bill['name']));
Log::debug(sprintf(sprintf('Average is %s', $avg)));
// calculate amount per year:
$multiplies = [
'yearly' => '1',
'half-year' => '2',
'quarterly' => '4',
'monthly' => '12',
'weekly' => '52.17',
];
$yearAmount = bcmul($avg, $multiplies[$bill['repeat_freq']]);
Log::debug(sprintf('Amount per year is %s (%s * %s)', $yearAmount, $avg, $multiplies[$bill['repeat_freq']]));
// per period:
$division = [
'1Y' => '1',
'6M' => '2',
'3M' => '4',
'1M' => '12',
'1W' => '52.16',
'1D' => '365.24',
];
$perPeriod = bcdiv($yearAmount, $division[$range]);
Log::debug(sprintf('Amount per %s is %s (%s / %s)', $range, $perPeriod, $yearAmount, $division[$range]));
return $perPeriod;
}
/**
* Set the order of a bill.
*
* @param Request $request
* @param Bill $bill
*
* @return JsonResponse
*/
public function setOrder(Request $request, Bill $bill): JsonResponse
{
$objectGroupTitle = (string)$request->get('objectGroupTitle');
$newOrder = (int) $request->get('order');
$this->repository->setOrder($bill, $newOrder);
if ('' !== $objectGroupTitle) {
$this->repository->setObjectGroup($bill, $objectGroupTitle);
}
if ('' === $objectGroupTitle) {
$this->repository->removeObjectGroup($bill);
}
return response()->json(['data' => 'OK']);
}
}

View File

@ -0,0 +1,195 @@
<?php
/**
* ShowController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Bill;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Attachment;
use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\TransactionRules\TransactionMatcher;
use FireflyIII\Transformers\AttachmentTransformer;
use FireflyIII\Transformers\BillTransformer;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Collection;
use Illuminate\View\View;
use League\Fractal\Manager;
use League\Fractal\Resource\Item;
use League\Fractal\Serializer\DataArraySerializer;
use Symfony\Component\HttpFoundation\ParameterBag;
/**
* Class ShowController
*/
class ShowController extends Controller
{
private BillRepositoryInterface $repository;
/**
* BillController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
app('view')->share('showBudget', true);
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string) trans('firefly.bills'));
app('view')->share('mainTitleIcon', 'fa-calendar-o');
$this->repository = app(BillRepositoryInterface::class);
return $next($request);
}
);
}
/**
* Rescan bills for transactions.
*
* @param Request $request
* @param Bill $bill
*
* @throws FireflyException
* @return RedirectResponse|Redirector
*/
public function rescan(Request $request, Bill $bill)
{
$total = 0;
if (false === $bill->active) {
$request->session()->flash('warning', (string) trans('firefly.cannot_scan_inactive_bill'));
return redirect(route('bills.show', [$bill->id]));
}
$set = new Collection;
if (true === $bill->active) {
$set = $this->repository->getRulesForBill($bill);
$total = 0;
}
if (0 === $set->count()) {
$request->session()->flash('error', (string) trans('firefly.no_rules_for_bill'));
return redirect(route('bills.show', [$bill->id]));
}
// unlink all journals:
$this->repository->unlinkAll($bill);
foreach ($set as $rule) {
// simply fire off all rules?
/** @var TransactionMatcher $matcher */
$matcher = app(TransactionMatcher::class);
$matcher->setSearchLimit(100000); // large upper limit
$matcher->setTriggeredLimit(100000); // large upper limit
$matcher->setRule($rule);
$matchingTransactions = $matcher->findTransactionsByRule();
$total += count($matchingTransactions);
$this->repository->linkCollectionToBill($bill, $matchingTransactions);
}
$request->session()->flash('success', (string) trans_choice('firefly.rescanned_bill', $total));
app('preferences')->mark();
return redirect(route('bills.show', [$bill->id]));
}
/**
* Show a bill.
*
* @param Request $request
* @param Bill $bill
*
* @return Factory|View
*/
public function show(Request $request, Bill $bill)
{
// add info about rules:
$rules = $this->repository->getRulesForBill($bill);
$subTitle = $bill->name;
/** @var Carbon $start */
$start = session('start');
/** @var Carbon $end */
$end = session('end');
$year = $start->year;
$page = (int) $request->get('page');
$pageSize = (int) app('preferences')->get('listPageSize', 50)->data;
$yearAverage = $this->repository->getYearAverage($bill, $start);
$overallAverage = $this->repository->getOverallAverage($bill);
$manager = new Manager();
$manager->setSerializer(new DataArraySerializer());
$manager->parseIncludes(['attachments', 'notes']);
// Make a resource out of the data and
$parameters = new ParameterBag();
$parameters->set('start', $start);
$parameters->set('end', $end);
/** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class);
$transformer->setParameters($parameters);
$resource = new Item($bill, $transformer, 'bill');
$object = $manager->createData($resource)->toArray();
$object['data']['currency'] = $bill->transactionCurrency;
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setBill($bill)->setLimit($pageSize)->setPage($page)->withBudgetInformation()
->withCategoryInformation()->withAccountInformation();
$groups = $collector->getPaginatedGroups();
$groups->setPath(route('bills.show', [$bill->id]));
// transform any attachments as well.
$collection = $this->repository->getAttachments($bill);
$attachments = new Collection;
// @codeCoverageIgnoreStart
if ($collection->count() > 0) {
/** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class);
$attachments = $collection->each(
static function (Attachment $attachment) use ($transformer) {
return $transformer->transform($attachment);
}
);
}
// @codeCoverageIgnoreEnd
return view('bills.show', compact('attachments', 'groups', 'rules', 'yearAverage', 'overallAverage', 'year', 'object', 'bill', 'subTitle'));
}
}

View File

@ -1,483 +0,0 @@
<?php
/**
* BillController.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Http\Requests\BillFormRequest;
use FireflyIII\Models\Attachment;
use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\TransactionRules\TransactionMatcher;
use FireflyIII\Transformers\AttachmentTransformer;
use FireflyIII\Transformers\BillTransformer;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Collection;
use Illuminate\View\View;
use League\Fractal\Manager;
use League\Fractal\Resource\Item;
use League\Fractal\Serializer\DataArraySerializer;
use Log;
use Symfony\Component\HttpFoundation\ParameterBag;
/**
* Class BillController.
*
*/
class BillController extends Controller
{
/** @var AttachmentHelperInterface Helper for attachments. */
private $attachments;
/** @var BillRepositoryInterface Bill repository */
private $billRepository;
/**
* BillController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
app('view')->share('showBudget', true);
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string) trans('firefly.bills'));
app('view')->share('mainTitleIcon', 'fa-calendar-o');
$this->attachments = app(AttachmentHelperInterface::class);
$this->billRepository = app(BillRepositoryInterface::class);
return $next($request);
}
);
}
/**
* Create a new bill.
*
* @param Request $request
*
* @return Factory|View
*/
public function create(Request $request)
{
$periods = [];
/** @var array $billPeriods */
$billPeriods = config('firefly.bill_periods');
foreach ($billPeriods as $current) {
$periods[$current] = strtolower((string) trans('firefly.repeat_freq_' . $current));
}
$subTitle = (string) trans('firefly.create_new_bill');
$defaultCurrency = app('amount')->getDefaultCurrency();
// put previous url in session if not redirect from store (not "create another").
if (true !== session('bills.create.fromStore')) {
$this->rememberPreviousUri('bills.create.uri');
}
$request->session()->forget('bills.create.fromStore');
return view('bills.create', compact('periods', 'subTitle', 'defaultCurrency'));
}
/**
* Delete a bill.
*
* @param Bill $bill
*
* @return Factory|View
*/
public function delete(Bill $bill)
{
// put previous url in session
$this->rememberPreviousUri('bills.delete.uri');
$subTitle = (string) trans('firefly.delete_bill', ['name' => $bill->name]);
return view('bills.delete', compact('bill', 'subTitle'));
}
/**
* Destroy a bill.
*
* @param Request $request
* @param Bill $bill
*
* @return RedirectResponse|Redirector
*/
public function destroy(Request $request, Bill $bill)
{
$name = $bill->name;
$this->billRepository->destroy($bill);
$request->session()->flash('success', (string) trans('firefly.deleted_bill', ['name' => $name]));
app('preferences')->mark();
return redirect($this->getPreviousUri('bills.delete.uri'));
}
/**
* Edit a bill.
*
* @param Request $request
* @param Bill $bill
*
* @return Factory|View
*/
public function edit(Request $request, Bill $bill)
{
$periods = [];
/** @var array $billPeriods */
$billPeriods = config('firefly.bill_periods');
foreach ($billPeriods as $current) {
$periods[$current] = (string) trans('firefly.' . $current);
}
$subTitle = (string) trans('firefly.edit_bill', ['name' => $bill->name]);
// put previous url in session if not redirect from store (not "return_to_edit").
if (true !== session('bills.edit.fromUpdate')) {
$this->rememberPreviousUri('bills.edit.uri');
}
$currency = app('amount')->getDefaultCurrency();
$bill->amount_min = round((float) $bill->amount_min, $currency->decimal_places);
$bill->amount_max = round((float) $bill->amount_max, $currency->decimal_places);
$rules = $this->billRepository->getRulesForBill($bill);
$defaultCurrency = app('amount')->getDefaultCurrency();
// code to handle active-checkboxes
$hasOldInput = null !== $request->old('_token');
$preFilled = [
'notes' => $this->billRepository->getNoteText($bill),
'transaction_currency_id' => $bill->transaction_currency_id,
'active' => $hasOldInput ? (bool) $request->old('active') : $bill->active,
];
$request->session()->flash('preFilled', $preFilled);
$request->session()->forget('bills.edit.fromUpdate');
return view('bills.edit', compact('subTitle', 'periods', 'rules', 'bill', 'defaultCurrency', 'preFilled'));
}
/**
* Show all bills.
*
* @return Factory|View
*/
public function index()
{
$start = session('start');
$end = session('end');
$unfiltered = $this->billRepository->getBills();
$defaultCurrency = app('amount')->getDefaultCurrency();
$parameters = new ParameterBag();
$parameters->set('start', $start);
$parameters->set('end', $end);
/** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class);
$transformer->setParameters($parameters);
/** @var Collection $bills */
$bills = $unfiltered->map(
function (Bill $bill) use ($transformer, $defaultCurrency) {
$return = $transformer->transform($bill);
$nextExpectedMatch = new Carbon($return['next_expected_match']);
$return['next_expected_match_diff'] = $nextExpectedMatch->isToday()
? trans('firefly.today')
: $nextExpectedMatch->diffForHumans(
today(), Carbon::DIFF_RELATIVE_TO_NOW
);
$currency = $bill->transactionCurrency ?? $defaultCurrency;
$return['currency_id'] = $currency->id;
$return['currency_name'] = $currency->name;
$return['currency_symbol'] = $currency->symbol;
$return['currency_code'] = $currency->code;
$return['currency_decimal_places'] = $currency->decimal_places;
$return['attachments'] = $this->billRepository->getAttachments($bill);
return $return;
}
);
// add info about rules:
$rules = $this->billRepository->getRulesForBills($unfiltered);
$bills = $bills->map(
static function (array $bill) use ($rules) {
$bill['rules'] = $rules[$bill['id']] ?? [];
return $bill;
}
);
// summarise per currency:
$sums = $this->getSums($bills);
return view('bills.index', compact('bills', 'sums'));
}
/**
* Rescan bills for transactions.
*
* @param Request $request
* @param Bill $bill
*
* @throws FireflyException
* @return RedirectResponse|Redirector
*/
public function rescan(Request $request, Bill $bill)
{
$total = 0;
if (false === $bill->active) {
$request->session()->flash('warning', (string) trans('firefly.cannot_scan_inactive_bill'));
return redirect(route('bills.show', [$bill->id]));
}
$set = new Collection;
if (true === $bill->active) {
$set = $this->billRepository->getRulesForBill($bill);
$total = 0;
}
if (0 === $set->count()) {
$request->session()->flash('error', (string) trans('firefly.no_rules_for_bill'));
return redirect(route('bills.show', [$bill->id]));
}
// unlink all journals:
$this->billRepository->unlinkAll($bill);
foreach ($set as $rule) {
// simply fire off all rules?
/** @var TransactionMatcher $matcher */
$matcher = app(TransactionMatcher::class);
$matcher->setSearchLimit(100000); // large upper limit
$matcher->setTriggeredLimit(100000); // large upper limit
$matcher->setRule($rule);
$matchingTransactions = $matcher->findTransactionsByRule();
$total += count($matchingTransactions);
$this->billRepository->linkCollectionToBill($bill, $matchingTransactions);
}
$request->session()->flash('success', (string) trans_choice('firefly.rescanned_bill', $total));
app('preferences')->mark();
return redirect(route('bills.show', [$bill->id]));
}
/**
* Show a bill.
*
* @param Request $request
* @param Bill $bill
*
* @return Factory|View
*/
public function show(Request $request, Bill $bill)
{
// add info about rules:
$rules = $this->billRepository->getRulesForBill($bill);
$subTitle = $bill->name;
/** @var Carbon $start */
$start = session('start');
/** @var Carbon $end */
$end = session('end');
$year = $start->year;
$page = (int) $request->get('page');
$pageSize = (int) app('preferences')->get('listPageSize', 50)->data;
$yearAverage = $this->billRepository->getYearAverage($bill, $start);
$overallAverage = $this->billRepository->getOverallAverage($bill);
$manager = new Manager();
$manager->setSerializer(new DataArraySerializer());
$manager->parseIncludes(['attachments', 'notes']);
// Make a resource out of the data and
$parameters = new ParameterBag();
$parameters->set('start', $start);
$parameters->set('end', $end);
/** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class);
$transformer->setParameters($parameters);
$resource = new Item($bill, $transformer, 'bill');
$object = $manager->createData($resource)->toArray();
$object['data']['currency'] = $bill->transactionCurrency;
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setBill($bill)->setLimit($pageSize)->setPage($page)->withBudgetInformation()
->withCategoryInformation()->withAccountInformation();
$groups = $collector->getPaginatedGroups();
$groups->setPath(route('bills.show', [$bill->id]));
// transform any attachments as well.
$collection = $this->billRepository->getAttachments($bill);
$attachments = new Collection;
// @codeCoverageIgnoreStart
if ($collection->count() > 0) {
/** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class);
$attachments = $collection->each(
static function (Attachment $attachment) use ($transformer) {
return $transformer->transform($attachment);
}
);
}
// @codeCoverageIgnoreEnd
return view('bills.show', compact('attachments', 'groups', 'rules', 'yearAverage', 'overallAverage', 'year', 'object', 'bill', 'subTitle'));
}
/**
* Store a new bill.
*
* @param BillFormRequest $request
*
* @return RedirectResponse
*
*/
public function store(BillFormRequest $request): RedirectResponse
{
$billData = $request->getBillData();
$billData['active'] = true;
try {
$bill = $this->billRepository->store($billData);
} catch (FireflyException $e) {
Log::error($e->getMessage());
$request->session()->flash('error', (string) trans('firefly.bill_store_error'));
return redirect(route('bills.create'))->withInput();
}
$request->session()->flash('success', (string) trans('firefly.stored_new_bill', ['name' => $bill->name]));
app('preferences')->mark();
/** @var array $files */
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
if (null !== $files && !auth()->user()->hasRole('demo')) {
$this->attachments->saveAttachmentsForModel($bill, $files);
}
if (null !== $files && auth()->user()->hasRole('demo')) {
session()->flash('info',(string)trans('firefly.no_att_demo_user'));
}
if (count($this->attachments->getMessages()->get('attachments')) > 0) {
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore
}
return redirect(route('rules.create-from-bill', [$bill->id]));
}
/**
* Update a bill.
*
* @param BillFormRequest $request
* @param Bill $bill
*
* @return RedirectResponse
*/
public function update(BillFormRequest $request, Bill $bill): RedirectResponse
{
$billData = $request->getBillData();
$bill = $this->billRepository->update($bill, $billData);
$request->session()->flash('success', (string) trans('firefly.updated_bill', ['name' => $bill->name]));
app('preferences')->mark();
/** @var array $files */
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
if (null !== $files && !auth()->user()->hasRole('demo')) {
$this->attachments->saveAttachmentsForModel($bill, $files);
}
if (null !== $files && auth()->user()->hasRole('demo')) {
session()->flash('info',(string)trans('firefly.no_att_demo_user'));
}
// flash messages
if (count($this->attachments->getMessages()->get('attachments')) > 0) {
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore
}
$redirect = redirect($this->getPreviousUri('bills.edit.uri'));
if (1 === (int) $request->get('return_to_edit')) {
// @codeCoverageIgnoreStart
$request->session()->put('bills.edit.fromUpdate', true);
$redirect = redirect(route('bills.edit', [$bill->id]))->withInput(['return_to_edit' => 1]);
// @codeCoverageIgnoreEnd
}
return $redirect;
}
/**
* @param Collection $bills
*
* @return array
*/
private function getSums(Collection $bills): array
{
$sums = [];
/** @var array $bill */
foreach ($bills as $bill) {
if (false === $bill['active']) {
continue;
}
if (0 === count($bill['pay_dates'])) {
continue;
}
/** @var TransactionCurrency $currency */
$currencyId = $bill['currency_id'];
$sums[$currencyId] = $sums[$currencyId] ?? [
'currency_id' => $currencyId,
'currency_code' => $bill['currency_code'],
'currency_name' => $bill['currency_name'],
'currency_symbol' => $bill['currency_symbol'],
'currency_decimal_places' => $bill['currency_decimal_places'],
'avg' => '0',
];
$avg = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2');
$avg = bcmul($avg, (string) count($bill['pay_dates']));
$sums[$currencyId]['avg'] = bcadd($sums[$currencyId]['avg'], $avg);
}
return $sums;
}
}

View File

@ -157,7 +157,7 @@ class AvailableBudgetController extends Controller
*/
public function edit(AvailableBudget $availableBudget, Carbon $start, Carbon $end)
{
$availableBudget->amount = round($availableBudget->amount, $availableBudget->transactionCurrency->decimal_places);
$availableBudget->amount = number_format((float) $availableBudget->amount, $availableBudget->transactionCurrency->decimal_places, '.', '');
return view('budgets.available-budgets.edit', compact('availableBudget', 'start', 'end'));
}

View File

@ -213,7 +213,7 @@ class BudgetLimitController extends Controller
$array['left_per_day'] = bcdiv(bcadd($array['spent'], $array['amount']), $array['days_left']);
// left per day formatted.
$array['amount'] = round($limit['amount'], $limit->transactionCurrency->decimal_places);
$array['amount'] = number_format((float) $limit['amount'], $limit->transactionCurrency->decimal_places, '.', '');
$array['left_per_day_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, $array['left_per_day']);
return response()->json($array);

View File

@ -174,7 +174,7 @@ class IndexController extends Controller
$currency = $limit->transactionCurrency ?? $defaultCurrency;
$array['budgeted'][] = [
'id' => $limit->id,
'amount' => round($limit->amount, $currency->decimal_places),
'amount' => number_format((float) $limit->amount, $currency->decimal_places, '.', ''),
'start_date' => $limit->start_date->formatLocalized($this->monthAndDayFormat),
'end_date' => $limit->end_date->formatLocalized($this->monthAndDayFormat),
'in_range' => $limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end),

View File

@ -84,8 +84,6 @@ class ShowController extends Controller
*/
public function noBudget(Request $request, Carbon $start = null, Carbon $end = null)
{
/** @var Carbon $start */
$start = $start ?? session('start');
/** @var Carbon $end */
@ -211,7 +209,7 @@ class ShowController extends Controller
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setRange($budgetLimit->start_date, $budgetLimit->end_date)
$collector->setRange($budgetLimit->start_date, $budgetLimit->end_date)->withAccountInformation()
->setBudget($budget)->setLimit($pageSize)->setPage($page)->withBudgetInformation()->withCategoryInformation();
$groups = $collector->getPaginatedGroups();
$groups->setPath(route('budgets.show', [$budget->id, $budgetLimit->id]));

View File

@ -216,7 +216,6 @@ class BudgetController extends Controller
$cache->addProperty($budget->id);
$cache->addProperty($budgetLimitId);
$cache->addProperty('chart.budget.expense-asset');
$collector->setRange(session()->get('start'), session()->get('end'));
$start = session()->get('start');
$end = session()->get('end');
if (null !== $budgetLimit) {
@ -230,6 +229,7 @@ class BudgetController extends Controller
if ($cache->has()) {
return response()->json($cache->get()); // @codeCoverageIgnore
}
$collector->setRange($start, $end);
$collector->setBudget($budget);
$journals = $collector->getExtractedJournals();
$result = [];
@ -282,13 +282,12 @@ class BudgetController extends Controller
$cache->addProperty($budget->id);
$cache->addProperty($budgetLimitId);
$cache->addProperty('chart.budget.expense-category');
$collector->setRange(session()->get('start'), session()->get('end'));
$start = session()->get('start');
$end = session()->get('end');
if (null !== $budgetLimit) {
$start = $budgetLimit->start_date;
$end = $budgetLimit->end_date;
$collector->setRange($budgetLimit->start_date, $budgetLimit->end_date)->setCurrency($budgetLimit->transactionCurrency);
$collector->setCurrency($budgetLimit->transactionCurrency);
}
$cache->addProperty($start);
$cache->addProperty($end);
@ -296,6 +295,7 @@ class BudgetController extends Controller
if ($cache->has()) {
return response()->json($cache->get()); // @codeCoverageIgnore
}
$collector->setRange($start, $end);
$collector->setBudget($budget)->withCategoryInformation();
$journals = $collector->getExtractedJournals();
$result = [];
@ -345,7 +345,6 @@ class BudgetController extends Controller
$cache->addProperty($budget->id);
$cache->addProperty($budgetLimitId);
$cache->addProperty('chart.budget.expense-expense');
$collector->setRange(session()->get('start'), session()->get('end'));
$start = session()->get('start');
$end = session()->get('end');
if (null !== $budgetLimit) {
@ -359,7 +358,7 @@ class BudgetController extends Controller
if ($cache->has()) {
return response()->json($cache->get()); // @codeCoverageIgnore
}
$collector->setRange($start, $end);
$collector->setTypes([TransactionType::WITHDRAWAL])->setBudget($budget)->withAccountInformation();
$journals = $collector->getExtractedJournals();
$result = [];

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* TransactionController.php
* Copyright (c) 2020 thegrumpydictator@gmail.com
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon;

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* IndexController.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Export;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* BudgetController.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Json;

View File

@ -1,4 +1,25 @@
<?php
/**
* DeleteController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\ObjectGroup;

View File

@ -1,4 +1,25 @@
<?php
/**
* EditController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\ObjectGroup;

View File

@ -1,4 +1,25 @@
<?php
/**
* IndexController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\ObjectGroup;
@ -43,6 +64,7 @@ class IndexController extends Controller
*/
public function index()
{
$this->repository->deleteEmpty();
$this->repository->sort();
$subTitle = (string) trans('firefly.object_groups_index');
$objectGroups = $this->repository->get();

View File

@ -1,4 +1,25 @@
<?php
/**
* AmountController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\PiggyBank;
@ -155,8 +176,7 @@ class AmountController extends Controller
return redirect(route('piggy-banks.index'));
}
$amount = (string) round($request->get('amount'), 12);
$amount = number_format((float) $request->get('amount'), 12, '.', '');
session()->flash(
'error',

View File

@ -1,4 +1,25 @@
<?php
/**
* CreateController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\PiggyBank;
@ -7,7 +28,7 @@ namespace FireflyIII\Http\Controllers\PiggyBank;
use Carbon\Carbon;
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\PiggyBankFormRequest;
use FireflyIII\Http\Requests\PiggyBankStoreRequest;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
@ -67,11 +88,11 @@ class CreateController extends Controller
/**
* Store a new piggy bank.
*
* @param PiggyBankFormRequest $request
* @param PiggyBankStoreRequest $request
*
* @return RedirectResponse|Redirector
*/
public function store(PiggyBankFormRequest $request)
public function store(PiggyBankStoreRequest $request)
{
$data = $request->getPiggyBankData();
if (null === $data['startdate']) {

View File

@ -1,4 +1,25 @@
<?php
/**
* DeleteController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\PiggyBank;

View File

@ -1,4 +1,25 @@
<?php
/**
* EditController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\PiggyBank;
@ -6,7 +27,7 @@ namespace FireflyIII\Http\Controllers\PiggyBank;
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\PiggyBankFormRequest;
use FireflyIII\Http\Requests\PiggyBankUpdateRequest;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use Illuminate\Contracts\View\Factory;
@ -89,12 +110,12 @@ class EditController extends Controller
/**
* Update a piggy bank.
*
* @param PiggyBankFormRequest $request
* @param PiggyBankUpdateRequest $request
* @param PiggyBank $piggyBank
*
* @return RedirectResponse|Redirector
*/
public function update(PiggyBankFormRequest $request, PiggyBank $piggyBank)
public function update(PiggyBankUpdateRequest $request, PiggyBank $piggyBank)
{
$data = $request->getPiggyBankData();
$piggyBank = $this->piggyRepos->update($piggyBank, $data);

View File

@ -1,4 +1,25 @@
<?php
/**
* IndexController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\PiggyBank;
@ -174,7 +195,7 @@ class IndexController extends Controller
*/
public function setOrder(Request $request, PiggyBank $piggyBank): JsonResponse
{
$objectGroupTitle = $request->get('objectGroupTitle');
$objectGroupTitle = (string) $request->get('objectGroupTitle');
$newOrder = (int) $request->get('order');
$this->piggyRepos->setOrder($piggyBank, $newOrder);
if ('' !== $objectGroupTitle) {

View File

@ -1,4 +1,25 @@
<?php
/**
* ShowController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\PiggyBank;

View File

@ -67,7 +67,8 @@ class PreferencesController extends Controller
public function index(AccountRepositoryInterface $repository)
{
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]);
$isDocker = env('IS_DOCKER', false);
// group accounts
$groupedAccounts = [];
/** @var Account $account */
@ -122,6 +123,7 @@ class PreferencesController extends Controller
compact(
'language',
'groupedAccounts',
'isDocker',
'frontPageAccounts',
'languages',
'locales',

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* DataController.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Profile;
use FireflyIII\Http\Controllers\Controller;

View File

@ -31,9 +31,7 @@ use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Controllers\GetConfigurationData;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Arr;
use Laravel\Passport\Passport;
use Log;
@ -106,6 +104,7 @@ class InstallController extends Controller
'firefly-iii:fix-ob-currencies' => [],
'firefly-iii:fix-long-descriptions' => [],
'firefly-iii:fix-recurring-transactions' => [],
'firefly-iii:unify-group-accounts' => [],
// final command to set latest version in DB
'firefly-iii:set-latest-version' => ['--james-is-cool' => true],

View File

@ -285,7 +285,7 @@ class TagController extends Controller
$periods = [];
$subTitle = (string) trans('firefly.all_journals_for_tag', ['tag' => $tag->tag]);
$start = $this->repository->firstUseDate($tag) ?? new Carbon;
$end = new Carbon;
$end = $this->repository->lastUseDate($tag) ?? new Carbon;
$attachments = $this->repository->getAttachments($tag);
$path = route('tags.show', [$tag->id, 'all']);
$location = $this->repository->getLocation($tag);

View File

@ -0,0 +1,81 @@
<?php
/**
* BillStoreRequest.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Requests;
/**
* Class BillStoreRequest.
*/
class BillStoreRequest extends Request
{
/**
* Verify the request.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow logged in users
return auth()->check();
}
/**
* Returns the data required by the controller.
*
* @return array
*/
public function getBillData(): array
{
return [
'name' => $this->string('name'),
'amount_min' => $this->string('amount_min'),
'currency_id' => $this->integer('transaction_currency_id'),
'currency_code' => '',
'amount_max' => $this->string('amount_max'),
'date' => $this->date('date'),
'repeat_freq' => $this->string('repeat_freq'),
'skip' => $this->integer('skip'),
'notes' => $this->nlString('notes'),
'active' => $this->boolean('active'),
'object_group' => $this->string('object_group'),
];
}
/**
* Rules for this request.
*
* @return array
*/
public function rules(): array
{
return [
'name' => 'required|between:1,255|uniqueObjectForUser:bills,name',
'amount_min' => 'required|numeric|more:0|max:1000000000',
'amount_max' => 'required|numeric|more:0|max:1000000000',
'transaction_currency_id' => 'required|exists:transaction_currencies,id',
'date' => 'required|date',
'repeat_freq' => 'required|in:weekly,monthly,quarterly,half-year,yearly',
'skip' => 'required|between:0,31',
'active' => 'boolean',
];
}
}

View File

@ -1,6 +1,6 @@
<?php
/**
* BillFormRequest.php
* BillUpdateRequest.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@ -25,9 +25,9 @@ namespace FireflyIII\Http\Requests;
use FireflyIII\Models\Bill;
/**
* Class BillFormRequest.
* Class BillUpdateRequest.
*/
class BillFormRequest extends Request
class BillUpdateRequest extends Request
{
/**
* Verify the request.
@ -58,6 +58,7 @@ class BillFormRequest extends Request
'skip' => $this->integer('skip'),
'notes' => $this->nlString('notes'),
'active' => $this->boolean('active'),
'object_group' => $this->string('object_group'),
];
}
@ -68,15 +69,11 @@ class BillFormRequest extends Request
*/
public function rules(): array
{
$nameRule = 'required|between:1,255|uniqueObjectForUser:bills,name';
/** @var Bill $bill */
$bill = $this->route()->parameter('bill');
if (null !== $bill) {
$nameRule = 'required|between:1,255|uniqueObjectForUser:bills,name,' . $bill->id;
}
// is OK
$rules = [
'name' => $nameRule,
return [
'name' => sprintf('required|between:1,255|uniqueObjectForUser:bills,name,%d', $bill->id),
'amount_min' => 'required|numeric|more:0|max:1000000000',
'amount_max' => 'required|numeric|more:0|max:1000000000',
'transaction_currency_id' => 'required|exists:transaction_currencies,id',
@ -85,7 +82,5 @@ class BillFormRequest extends Request
'skip' => 'required|between:0,31',
'active' => 'boolean',
];
return $rules;
}
}

View File

@ -0,0 +1,76 @@
<?php
/**
* PiggyBankStoreRequest.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Requests;
/**
* Class PiggyBankStoreRequest.
*/
class PiggyBankStoreRequest extends Request
{
/**
* Verify the request.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow logged in users
return auth()->check();
}
/**
* Returns the data required by the controller.
*
* @return array
*/
public function getPiggyBankData(): array
{
return [
'name' => $this->string('name'),
'startdate' => $this->date('startdate'),
'account_id' => $this->integer('account_id'),
'targetamount' => $this->string('targetamount'),
'targetdate' => $this->date('targetdate'),
'notes' => $this->nlString('notes'),
'object_group' => $this->string('object_group'),
];
}
/**
* Rules for this request.
*
* @return array
*/
public function rules(): array
{
return [
'name' => 'required|between:1,255|uniquePiggyBankForUser',
'account_id' => 'required|belongsToUser:accounts',
'targetamount' => 'required|numeric|gte:0.01|max:1000000000',
'startdate' => 'date',
'targetdate' => 'date|nullable',
'order' => 'integer|min:1',
'object_group' => 'min:0|max:255',
];
}
}

View File

@ -1,6 +1,6 @@
<?php
/**
* PiggyBankFormRequest.php
* PiggyBankUpdateRequest.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@ -27,7 +27,7 @@ use FireflyIII\Models\PiggyBank;
/**
* Class PiggyBankFormRequest.
*/
class PiggyBankFormRequest extends Request
class PiggyBankUpdateRequest extends Request
{
/**
* Verify the request.
@ -65,24 +65,17 @@ class PiggyBankFormRequest extends Request
*/
public function rules(): array
{
$nameRule = 'required|between:1,255|uniquePiggyBankForUser';
/** @var PiggyBank $piggy */
$piggy = $this->route()->parameter('piggyBank');
if (null !== $piggy) {
$nameRule = 'required|between:1,255|uniquePiggyBankForUser:' . $piggy->id;
}
$rules = [
'name' => $nameRule,
return [
'name' => sprintf('required|between:1,255|uniquePiggyBankForUser:%d', $piggy->id),
'account_id' => 'required|belongsToUser:accounts',
'targetamount' => 'required|numeric|gte:0.01|max:1000000000',
'startdate' => 'date',
'targetdate' => 'date|nullable',
'order' => 'integer|min:1',
'object_group' => 'min:0|max:255',
];
return $rules;
}
}

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* CreateAutoBudgetLimits.php
* Copyright (c) 2020 thegrumpydictator@gmail.com
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Jobs;
use Carbon\Carbon;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* SubmitTelemetryData.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Jobs;

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* AutoBudget.php
* Copyright (c) 2020 thegrumpydictator@gmail.com
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Models;
use Eloquent;

View File

@ -161,6 +161,14 @@ class Bill extends Model
return $this->morphMany(Note::class, 'noteable');
}
/**
* Get all of the tags for the post.
*/
public function objectGroups()
{
return $this->morphToMany(ObjectGroup::class, 'object_groupable');
}
/**
* @codeCoverageIgnore
*

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* Location.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Models;

View File

@ -1,4 +1,25 @@
<?php
/**
* ObjectGroup.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Models;
@ -56,6 +77,14 @@ class ObjectGroup extends Model
return $this->morphedByMany(PiggyBank::class, 'object_groupable');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
*/
public function bills()
{
return $this->morphedByMany(Bill::class, 'object_groupable');
}
/**
* Route binder. Converts the key in the URL to the specified object (or throw 404).
*

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* Telemetry.php
* Copyright (c) 2020 thegrumpydictator@gmail.com
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Models;

View File

@ -94,6 +94,7 @@ class EventServiceProvider extends ServiceProvider
],
// is a Transaction Journal related event.
UpdatedTransactionGroup::class => [
'FireflyIII\Handlers\Events\UpdatedGroupEventHandler@unifyAccounts',
'FireflyIII\Handlers\Events\UpdatedGroupEventHandler@processRules',
],
// API related events:

View File

@ -32,6 +32,7 @@ use FireflyIII\Models\Note;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
use FireflyIII\Services\Internal\Destroy\BillDestroyService;
use FireflyIII\Services\Internal\Update\BillUpdateService;
use FireflyIII\Support\CacheProperties;
@ -48,6 +49,7 @@ use Storage;
*/
class BillRepository implements BillRepositoryInterface
{
use CreatesObjectGroups;
/** @var User */
private $user;
@ -190,7 +192,10 @@ class BillRepository implements BillRepositoryInterface
public function getBills(): Collection
{
/** @var Collection $set */
return $this->user->bills()->orderBy('active', 'DESC')->orderBy('name', 'ASC')->get();
return $this->user->bills()
->orderBy('order', 'ASC')
->orderBy('active', 'DESC')
->orderBy('name', 'ASC')->get();
}
/**
@ -711,4 +716,52 @@ class BillRepository implements BillRepositoryInterface
{
$this->user->transactionJournals()->where('bill_id', $bill->id)->update(['bill_id' => null]);
}
/**
* Correct order of piggies in case of issues.
*/
public function correctOrder(): void
{
$set = $this->user->bills()->orderBy('order', 'ASC')->get();
$current = 1;
foreach ($set as $bill) {
if ((int) $bill->order !== $current) {
$bill->order = $current;
$bill->save();
}
$current++;
}
}
/**
* @inheritDoc
*/
public function setObjectGroup(Bill $bill, string $objectGroupTitle): Bill
{
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
if (null !== $objectGroup) {
$bill->objectGroups()->sync([$objectGroup->id]);
}
return $bill;
}
/**
* @inheritDoc
*/
public function removeObjectGroup(Bill $bill): Bill
{
$bill->objectGroups()->sync([]);
return $bill;
}
/**
* @inheritDoc
*/
public function setOrder(Bill $bill, int $order): void
{
$bill->order = $order;
$bill->save();
}
}

View File

@ -35,11 +35,39 @@ use Illuminate\Support\Collection;
interface BillRepositoryInterface
{
/**
* @param Bill $bill
* @param string $objectGroupTitle
*
* @return Bill
*/
public function setObjectGroup(Bill $bill, string $objectGroupTitle): Bill;
/**
* @param Bill $bill
*
* @return Bill
*/
public function removeObjectGroup(Bill $bill): Bill;
/**
* @param Bill $bill
*/
public function unlinkAll(Bill $bill): void;
/**
* Add correct order to bills.
*/
public function correctOrder(): void;
/**
* Set specific piggy bank to specific order.
*
* @param Bill $bill
* @param int $order
*/
public function setOrder(Bill $bill, int $order): void;
/**
* @param Bill $bill
*

View File

@ -1,4 +1,25 @@
<?php
/**
* CreatesObjectGroups.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Repositories\ObjectGroup;

View File

@ -1,4 +1,25 @@
<?php
/**
* ObjectGroupRepository.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Repositories\ObjectGroup;
@ -33,7 +54,9 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface
*/
public function get(): Collection
{
return $this->user->objectGroups()->orderBy('order', 'ASC')->orderBy('title', 'ASC')->get();
return $this->user->objectGroups()
->with(['piggyBanks', 'bills'])
->orderBy('order', 'ASC')->orderBy('title', 'ASC')->get();
}
/**

View File

@ -1,4 +1,25 @@
<?php
/**
* ObjectGroupRepositoryInterface.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Repositories\ObjectGroup;

View File

@ -1,4 +1,25 @@
<?php
/**
* OrganisesObjectGroups.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Repositories\ObjectGroup;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* ModifiesPiggyBanks.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,10 +20,13 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Repositories\PiggyBank;
use Carbon\Carbon;
use DB;
use Exception;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Note;
@ -32,6 +35,7 @@ use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
use FireflyIII\User;
use Illuminate\Database\QueryException;
use Log;
@ -349,6 +353,14 @@ trait ModifiesPiggyBanks
$this->updateNote($piggyBank, $data['notes'] ?? '');
// update the order of the piggy bank:
$oldOrder = (int) $piggyBank->order;
$newOrder = (int) ($data['order'] ?? $oldOrder);
if ($oldOrder !== $newOrder) {
$this->updateOrder($piggyBank, $oldOrder, $newOrder);
}
// if the piggy bank is now smaller than the current relevant rep,
// remove money from the rep.
$repetition = $this->getRepetition($piggyBank);
@ -360,6 +372,7 @@ trait ModifiesPiggyBanks
$repetition->save();
}
// update using name:
$objectGroupTitle = $data['object_group'] ?? '';
if ('' !== $objectGroupTitle) {
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
@ -368,6 +381,15 @@ trait ModifiesPiggyBanks
$piggyBank->save();
}
}
// try also with ID:
$objectGroupId = (int) ($data['object_group_id'] ?? 0);
if (0 !== $objectGroupId) {
$objectGroup = $this->findObjectGroupById($objectGroupId);
if (null !== $objectGroup) {
$piggyBank->objectGroups()->sync([$objectGroup->id]);
$piggyBank->save();
}
}
return $piggyBank;
}
@ -403,4 +425,38 @@ trait ModifiesPiggyBanks
return true;
}
/**
* @param PiggyBank $piggyBank
* @param int $oldOrder
* @param int $newOrder
*/
private function updateOrder(PiggyBank $piggyBank, int $oldOrder, int $newOrder): void
{
if ($newOrder > $oldOrder) {
// Iedereen [7 en lager] [hoger dan 3] behalve piggy zelf, puntje er af:
//piggy zelf naar 7
/** @var User $user */
$user = $this->user;
$user->piggyBanks()->where('order', '<=', $newOrder)->where('order', '>', $oldOrder)
->where('piggy_banks.id', '!=', $piggyBank->id)
->update(['order' => DB::raw('piggy_banks.order-1')]);
$piggyBank->order = $newOrder;
$piggyBank->save();
}
if ($newOrder < $oldOrder) {
//
//Van 8 naar 2
// iedereen [2 of hoger] en [kleiner dan 8] puntje er bij.
// 8 naar 2
/** @var User $user */
$user = $this->user;
$user->piggyBanks()->where('order', '>=', $newOrder)->where('order', '<', $oldOrder)
->where('piggy_banks.id', '!=', $piggyBank->id)
->update(['order' => DB::raw('piggy_banks.order+1')]);
$piggyBank->order = $newOrder;
$piggyBank->save();
}
}
}

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* TelemetryRepository.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Repositories\Telemetry;
use FireflyIII\Models\Telemetry;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* TelemetryRepositoryInterface.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Repositories\Telemetry;

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* IsTransferAccount.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Rules;

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* LessThanPiggyTarget.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,9 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Rules;
use Illuminate\Contracts\Validation\Rule;

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* UpdateRequest.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\FireflyIIIOrg\Update;
use Carbon\Carbon;

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* UpdateRequestInterface.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\FireflyIIIOrg\Update;
use FireflyIII\Exceptions\FireflyException;

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* LocationServiceTrait.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Internal\Support;
use FireflyIII\Models\Location;

View File

@ -23,13 +23,16 @@ declare(strict_types=1);
namespace FireflyIII\Services\Internal\Update;
use DB;
use FireflyIII\Factory\TransactionCurrencyFactory;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Rule;
use FireflyIII\Models\RuleTrigger;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
use FireflyIII\Services\Internal\Support\BillServiceTrait;
use FireflyIII\User;
use Illuminate\Support\Collection;
use Log;
@ -39,7 +42,9 @@ use Log;
*/
class BillUpdateService
{
use BillServiceTrait;
use BillServiceTrait, CreatesObjectGroups;
protected $user;
/**
* Constructor.
@ -59,6 +64,7 @@ class BillUpdateService
*/
public function update(Bill $bill, array $data): Bill
{
$this->user = $bill->user;
/** @var TransactionCurrencyFactory $factory */
$factory = app(TransactionCurrencyFactory::class);
/** @var TransactionCurrency $currency */
@ -82,16 +88,33 @@ class BillUpdateService
];
// new values
$data['transaction_currency_name'] = $currency->name;
$bill->name = $data['name'];
$bill->match = $data['match'] ?? $bill->match;
$bill->amount_min = $data['amount_min'];
$bill->amount_max = $data['amount_max'];
$bill->date = $data['date'];
$bill->transaction_currency_id = $currency->id;
$bill->repeat_freq = $data['repeat_freq'];
$bill->skip = $data['skip'];
$bill->automatch = true;
$bill->active = $data['active'] ?? true;
if (isset($data['name']) && '' !== (string) $data['name']) {
$bill->name = $data['name'];
}
if (isset($data['amount_min']) && '' !== (string) $data['amount_min']) {
$bill->amount_min = $data['amount_min'];
}
if (isset($data['amount_max']) && '' !== (string) $data['amount_max']) {
$bill->amount_max = $data['amount_max'];
}
if (isset($data['date']) && '' !== (string) $data['date']) {
$bill->date = $data['date'];
}
if (isset($data['repeat_freq']) && '' !== (string) $data['repeat_freq']) {
$bill->repeat_freq = $data['repeat_freq'];
}
if (isset($data['skip']) && '' !== (string) $data['skip']) {
$bill->skip = $data['skip'];
}
if (isset($data['active']) && '' !== (string) $data['active']) {
$bill->active = $data['active'];
}
$bill->transaction_currency_id = $currency->id;
$bill->match = 'EMPTY';
$bill->automatch = true;
$bill->save();
// update note:
@ -99,10 +122,37 @@ class BillUpdateService
$this->updateNote($bill, (string) $data['notes']);
}
// update order.
// update the order of the piggy bank:
$oldOrder = (int) $bill->order;
$newOrder = (int) ($data['order'] ?? $oldOrder);
if ($oldOrder !== $newOrder) {
$this->updateOrder($bill, $oldOrder, $newOrder);
}
// update rule actions.
$this->updateBillActions($bill, $oldData['name'], $data['name']);
$this->updateBillTriggers($bill, $oldData, $data);
// update using name:
$objectGroupTitle = $data['object_group'] ?? '';
if ('' !== $objectGroupTitle) {
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
if (null !== $objectGroup) {
$bill->objectGroups()->sync([$objectGroup->id]);
$bill->save();
}
}
// try also with ID:
$objectGroupId = (int) ($data['object_group_id'] ?? 0);
if (0 !== $objectGroupId) {
$objectGroup = $this->findObjectGroupById($objectGroupId);
if (null !== $objectGroup) {
$bill->objectGroups()->sync([$objectGroup->id]);
$bill->save();
}
}
return $bill;
}
@ -177,4 +227,32 @@ class BillUpdateService
{
return $rule->ruleTriggers()->where('trigger_type', $key)->first();
}
/**
* @param Bill $bill
* @param int $oldOrder
* @param int $newOrder
*/
private function updateOrder(Bill $bill, int $oldOrder, int $newOrder): void
{
if ($newOrder > $oldOrder) {
/** @var User $user */
$user = $this->user;
$user->bills()->where('order', '<=', $newOrder)->where('order', '>', $oldOrder)
->where('bills.id', '!=', $bill->id)
->update(['order' => DB::raw('bills.order-1')]);
$bill->order = $newOrder;
$bill->save();
}
if ($newOrder < $oldOrder) {
/** @var User $user */
$user = $this->user;
$user->bills()->where('order', '>=', $newOrder)->where('order', '<', $oldOrder)
->where('bills.id', '!=', $bill->id)
->update(['order' => DB::raw('bills.order+1')]);
$bill->order = $newOrder;
$bill->save();
}
}
}

View File

@ -1,4 +1,25 @@
<?php
/**
* RemoteUserGuard.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Support\Authentication;

View File

@ -1,4 +1,25 @@
<?php
/**
* RemoteUserProvider.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Support\Authentication;

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* FrontpageChartGenerator.php
* Copyright (c) 2020 thegrumpydictator@gmail.com
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Support\Chart\Category;
use Carbon\Carbon;

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* AutoBudgetCronjob.php
* Copyright (c) 2020 thegrumpydictator@gmail.com
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Support\Cronjobs;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* TelemetryCronjob.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Support\Cronjobs;
use Carbon\Carbon;

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* ExportDataGenerator.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Support\Export;
use Carbon\Carbon;

View File

@ -1,4 +1,25 @@
<?php
/**
* ParseDateString.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* AccountSearch.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Support\Search;

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* GenericSearchInterface.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Support\Search;

Some files were not shown because too many files have changed in this diff Show More