Merge branch 'release/v6.0.25'

This commit is contained in:
James Cole
2023-09-23 08:29:47 +02:00
398 changed files with 6467 additions and 2968 deletions

View File

@@ -226,16 +226,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.26.1",
"version": "v3.28.0",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "d023ba6684055f6ea1da1352d8a02baca0426983"
"reference": "113e09fea3d2306319ffaa2423fe3de768b28cff"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/d023ba6684055f6ea1da1352d8a02baca0426983",
"reference": "d023ba6684055f6ea1da1352d8a02baca0426983",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/113e09fea3d2306319ffaa2423fe3de768b28cff",
"reference": "113e09fea3d2306319ffaa2423fe3de768b28cff",
"shasum": ""
},
"require": {
@@ -309,7 +309,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.26.1"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.28.0"
},
"funding": [
{
@@ -317,7 +317,7 @@
"type": "github"
}
],
"time": "2023-09-08T19:09:07+00:00"
"time": "2023-09-22T20:43:40+00:00"
},
{
"name": "psr/container",

View File

@@ -8,7 +8,5 @@
# To hide directory listing
Options All -Indexes
# To prevent access to .env and other files
<Files .*>
Deny from all
</Files>
# To prevent access any file
Deny from all

View File

@@ -80,7 +80,7 @@ class ShowController extends Controller
->setPage($this->parameters->get('page'))
// set types of transactions to return.
->setTypes($types);
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
if (null !== $this->parameters->get('start') || null !== $this->parameters->get('end')) {
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
}
$paginator = $collector->getPaginatedGroups();

View File

@@ -30,7 +30,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Administration\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface;
use FireflyIII\Support\Http\Api\AccountFilter;
use Illuminate\Http\JsonResponse;
@@ -67,9 +67,9 @@ class AccountController extends Controller
* TODO list of checks
* 1. use dates from ParameterBag
* 2. Request validates dates
* 3. Request includes user_group_id as administration_id
* 3. Request includes user_group_id
* 4. Endpoint is documented.
* 5. Collector uses administration_id
* 5. Collector uses user_group_id
*
* @param AutocompleteRequest $request
*
@@ -79,6 +79,7 @@ class AccountController extends Controller
*/
public function accounts(AutocompleteRequest $request): JsonResponse
{
throw new FireflyException('uses old administration ID check, needs to be updated. 1');
$data = $request->getData();
$types = $data['types'];
$query = $data['query'];

View File

@@ -31,8 +31,9 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Administration\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use Illuminate\Http\JsonResponse;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
@@ -43,6 +44,7 @@ use Psr\Container\NotFoundExceptionInterface;
class AccountController extends Controller
{
use CleansChartData;
use ValidatesUserGroupTrait;
private AccountRepositoryInterface $repository;
@@ -55,7 +57,11 @@ class AccountController extends Controller
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
$this->repository->setAdministrationId(auth()->user()->user_group_id);
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
return $next($request);
}
);
@@ -70,7 +76,7 @@ class AccountController extends Controller
* If a transaction has foreign currency = native currency, the foreign amount will be used, no conversion
* will take place.
*
* TODO validate and set administration_id from request
* TODO validate and set user_group_id from request
*
* @param DateRequest $request
*

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* BalanceController.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,6 +21,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Chart;
use Carbon\Carbon;
@@ -30,7 +32,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Administration\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Http\JsonResponse;
@@ -69,7 +71,7 @@ class BalanceController extends Controller
* If the transaction being processed is already in native currency OR if the
* foreign amount is in the native currency, the amount will not be converted.
*
* TODO validate and set administration_id
* TODO validate and set user_group_id
* TODO collector set group, not user
*
* @param BalanceChartRequest $request

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* BudgetController.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,6 +21,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Chart;
use Carbon\Carbon;
@@ -30,11 +32,12 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Administration\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Administration\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
@@ -45,6 +48,7 @@ use Illuminate\Support\Collection;
class BudgetController extends Controller
{
use CleansChartData;
use ValidatesUserGroupTrait;
protected OperationsRepositoryInterface $opsRepository;
private BudgetLimitRepositoryInterface $blRepository;
@@ -61,6 +65,13 @@ class BudgetController extends Controller
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
$this->opsRepository = app(OperationsRepositoryInterface::class);
$this->currency = app('amount')->getDefaultCurrency();
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
$this->opsRepository->setUserGroup($userGroup);
}
return $next($request);
}
);
@@ -76,14 +87,6 @@ class BudgetController extends Controller
*/
public function dashboard(DateRequest $request): JsonResponse
{
// get user.
/** @var User $user */
$user = auth()->user();
// group ID
$administrationId = $user->getAdministrationId();
$this->repository->setAdministrationId($administrationId);
$this->opsRepository->setAdministrationId($administrationId);
$params = $request->getAll();
/** @var Carbon $start */
$start = $params['start'];

View File

@@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/*
* BudgetController.php
* CategoryController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@@ -21,6 +21,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Chart;
use Carbon\Carbon;
@@ -30,10 +32,11 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Administration\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use Illuminate\Http\JsonResponse;
/**
@@ -42,6 +45,7 @@ use Illuminate\Http\JsonResponse;
class CategoryController extends Controller
{
use CleansChartData;
use ValidatesUserGroupTrait;
private AccountRepositoryInterface $accountRepos;
private CurrencyRepositoryInterface $currencyRepos;
@@ -53,7 +57,10 @@ class CategoryController extends Controller
function ($request, $next) {
$this->accountRepos = app(AccountRepositoryInterface::class);
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
$this->accountRepos->setAdministrationId(auth()->user()->user_group_id);
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->accountRepos->setUserGroup($userGroup);
}
return $next($request);
}
);

View File

@@ -171,7 +171,7 @@ class Controller extends BaseController
*
* @return array
*/
final protected function jsonApiObject(string $key, Model $object, AbstractTransformer $transformer): array
final protected function jsonApiObject(string $key, array | Model $object, AbstractTransformer $transformer): array
{
// create some objects:
$manager = new Manager();

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* ShowController.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,11 +21,15 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\Bill;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Administration\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Bill\BillRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\V2\AccountTransformer;
use FireflyIII\Transformers\V2\BillTransformer;
use Illuminate\Http\JsonResponse;
@@ -37,6 +41,8 @@ use Illuminate\Pagination\LengthAwarePaginator;
*/
class ShowController extends Controller
{
use ValidatesUserGroupTrait;
private BillRepositoryInterface $repository;
public function __construct()
@@ -45,7 +51,13 @@ class ShowController extends Controller
$this->middleware(
function ($request, $next) {
$this->repository = app(BillRepositoryInterface::class);
$this->repository->setAdministrationId(auth()->user()->user_group_id);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
return $next($request);
}
);

View File

@@ -26,7 +26,8 @@ namespace FireflyIII\Api\V2\Controllers\Model\Bill;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\DateRequest;
use FireflyIII\Repositories\Administration\Bill\BillRepositoryInterface;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\UserGroups\Bill\BillRepositoryInterface;
use Illuminate\Http\JsonResponse;
/**
@@ -63,6 +64,7 @@ class SumController extends Controller
*/
public function paid(DateRequest $request): JsonResponse
{
throw new FireflyException('uses old administration ID check, needs to be updated.6');
$this->repository->setAdministrationId(auth()->user()->user_group_id);
$result = $this->repository->sumPaidInRange($this->parameters->get('start'), $this->parameters->get('end'));
@@ -82,6 +84,7 @@ class SumController extends Controller
*/
public function unpaid(DateRequest $request): JsonResponse
{
throw new FireflyException('uses old administration ID check, needs to be updated.7');
$this->repository->setAdministrationId(auth()->user()->user_group_id);
$result = $this->repository->sumUnpaidInRange($this->parameters->get('start'), $this->parameters->get('end'));

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V2\Controllers\Model\Budget;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\DateRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Illuminate\Http\JsonResponse;
@@ -60,7 +61,7 @@ class ShowController extends Controller
*/
public function budgeted(DateRequest $request, Budget $budget): JsonResponse
{
die('deprecated use of thing.');
throw new FireflyException('deprecated use of thing.');
$data = $request->getAll();
$result = $this->repository->budgetedInPeriodForBudget($budget, $data['start'], $data['end']);
$converted = $this->cerSum(array_values($result));
@@ -75,7 +76,7 @@ class ShowController extends Controller
*/
public function spent(DateRequest $request, Budget $budget): JsonResponse
{
die('deprecated use of thing.');
throw new FireflyException('deprecated use of thing.');
$data = $request->getAll();
$result = $this->repository->spentInPeriodForBudget($budget, $data['start'], $data['end']);
$converted = $this->cerSum(array_values($result));

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V2\Controllers\Model\Budget;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\DateRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Illuminate\Http\JsonResponse;
@@ -61,7 +62,7 @@ class SumController extends Controller
*/
public function budgeted(DateRequest $request): JsonResponse
{
die('deprecated use of thing.');
throw new FireflyException('deprecated use of thing.');
$data = $request->getAll();
$result = $this->repository->budgetedInPeriod($data['start'], $data['end']);
$converted = $this->cerSum(array_values($result));
@@ -79,7 +80,7 @@ class SumController extends Controller
*/
public function spent(DateRequest $request): JsonResponse
{
die('deprecated use of thing.');
throw new FireflyException('deprecated use of thing.');
$data = $request->getAll();
$result = $this->repository->spentInPeriod($data['start'], $data['end']);
$converted = $this->cerSum(array_values($result));

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* ShowController.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,10 +21,14 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\PiggyBank;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Repositories\Administration\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\UserGroups\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\V2\PiggyBankTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -35,6 +39,8 @@ use Illuminate\Pagination\LengthAwarePaginator;
*/
class ShowController extends Controller
{
use ValidatesUserGroupTrait;
private PiggyBankRepositoryInterface $repository;
public function __construct()
@@ -43,7 +49,12 @@ class ShowController extends Controller
$this->middleware(
function ($request, $next) {
$this->repository = app(PiggyBankRepositoryInterface::class);
$this->repository->setAdministrationId(auth()->user()->user_group_id);
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
return $next($request);
}
);

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* StoreController.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,24 +21,107 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\Transaction;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\Transaction\StoreRequest;
use FireflyIII\Events\StoredTransactionGroup;
use FireflyIII\Exceptions\DuplicateTransactionException;
use FireflyIII\Exceptions\FireflyException;
use Illuminate\Validation\ValidationException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
use FireflyIII\Rules\IsDuplicateTransaction;
use FireflyIII\Transformers\V2\TransactionGroupTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Validator;
/**
* Class StoreController
*/
class StoreController extends Controller
{
private TransactionGroupRepositoryInterface $groupRepository;
/**
* @return JsonResponse
* TransactionController constructor.
*/
public function post(): JsonResponse
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->groupRepository = app(TransactionGroupRepositoryInterface::class);
return $next($request);
}
);
}
/**
* TODO this method is practically the same as the V1 method and borrows as much code as possible.
*
* @return JsonResponse
* @throws FireflyException
* @throws ValidationException
*/
public function post(StoreRequest $request): JsonResponse
{
return response()->json([]);
app('log')->debug('Now in API v2 StoreController::store()');
$data = $request->getAll();
$userGroup = $request->getUserGroup();
$data['user_group'] = $userGroup;
// overrule user group and see where we end up.
// what happens when we refer to a budget that is not in this user group?
app('log')->channel('audit')->info('Store new transaction over API.', $data);
try {
$transactionGroup = $this->groupRepository->store($data);
} catch (DuplicateTransactionException $e) {
app('log')->warning('Caught a duplicate transaction. Return error message.');
$validator = Validator::make(
['transactions' => [['description' => $e->getMessage()]]],
['transactions.0.description' => new IsDuplicateTransaction()]
);
throw new ValidationException($validator, 0, $e);
} catch (FireflyException $e) {
app('log')->warning('Caught an exception. Return error message.');
app('log')->error($e->getMessage());
$message = sprintf('Internal exception: %s', $e->getMessage());
$validator = Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
throw new ValidationException($validator, 0, $e);
}
app('preferences')->mark();
$applyRules = $data['apply_rules'] ?? true;
$fireWebhooks = $data['fire_webhooks'] ?? true;
event(new StoredTransactionGroup($transactionGroup, $applyRules, $fireWebhooks));
/** @var User $admin */
$admin = auth()->user();
// use new group collector:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector
->setUser($admin)
// filter on transaction group.
->setTransactionGroup($transactionGroup);
$selectedGroup = $collector->getGroups()->first();
if (null === $selectedGroup) {
throw new FireflyException('200032: Cannot find transaction. Possibly, a rule deleted this transaction after its creation.');
}
$transformer = new TransactionGroupTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject('transactions', $selectedGroup, $transformer))
->header('Content-Type', self::CONTENT_TYPE);
}

View File

@@ -36,13 +36,14 @@ use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionType;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\Administration\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Administration\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Administration\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Repositories\Administration\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Administration\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
@@ -51,6 +52,8 @@ use Illuminate\Http\JsonResponse;
*/
class BasicController extends Controller
{
use ValidatesUserGroupTrait;
private AvailableBudgetRepositoryInterface $abRepository;
private AccountRepositoryInterface $accountRepository;
private BillRepositoryInterface $billRepository;
@@ -68,8 +71,6 @@ class BasicController extends Controller
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->abRepository = app(AvailableBudgetRepositoryInterface::class);
$this->accountRepository = app(AccountRepositoryInterface::class);
$this->billRepository = app(BillRepositoryInterface::class);
@@ -77,12 +78,14 @@ class BasicController extends Controller
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
$this->opsRepository = app(OperationsRepositoryInterface::class);
$this->abRepository->setAdministrationId($user->user_group_id);
$this->accountRepository->setAdministrationId($user->user_group_id);
$this->billRepository->setAdministrationId($user->user_group_id);
$this->budgetRepository->setAdministrationId($user->user_group_id);
$this->currencyRepos->setUser($user);
$this->opsRepository->setAdministrationId($user->user_group_id);
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->abRepository->setUserGroup($userGroup);
$this->accountRepository->setUserGroup($userGroup);
$this->billRepository->setUserGroup($userGroup);
$this->budgetRepository->setUserGroup($userGroup);
$this->opsRepository->setUserGroup($userGroup);
}
return $next($request);
}

View File

@@ -2,7 +2,7 @@
/*
* NetWorthController.php
* Copyright (c) 2022 james@firefly-iii.org
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -22,10 +22,13 @@
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers;
namespace FireflyIII\Api\V2\Controllers\Summary;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\SingleDateRequest;
use FireflyIII\Helpers\Report\NetWorthInterface;
use FireflyIII\Support\Http\Api\ConvertsExchangeRates;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use Illuminate\Http\JsonResponse;
/**
@@ -33,6 +36,9 @@ use Illuminate\Http\JsonResponse;
*/
class NetWorthController extends Controller
{
use ValidatesUserGroupTrait;
use ConvertsExchangeRates;
private NetWorthInterface $netWorth;
/**
@@ -44,7 +50,12 @@ class NetWorthController extends Controller
$this->middleware(
function ($request, $next) {
$this->netWorth = app(NetWorthInterface::class);
$this->netWorth->setUser(auth()->user());
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->netWorth->setUserGroup($userGroup);
}
return $next($request);
}
@@ -61,7 +72,6 @@ class NetWorthController extends Controller
*/
public function get(SingleDateRequest $request): JsonResponse
{
die('deprecated use of thing.');
$date = $request->getDate();
$result = $this->netWorth->sumNetWorthByCurrency($date);
$converted = $this->cerSum($result);

View File

@@ -2,7 +2,7 @@
/*
* VersionUpdateController.php
* Copyright (c) 2022 james@firefly-iii.org
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -22,7 +22,9 @@
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers;
namespace FireflyIII\Api\V2\Controllers\System;
use FireflyIII\Api\V2\Controllers\Controller;
/**
* Class VersionUpdateController

View File

@@ -2,7 +2,7 @@
/*
* AccountController.php
* Copyright (c) 2022 james@firefly-iii.org
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Transaction\List;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Transaction\ListRequest;
use FireflyIII\Api\V2\Request\Model\Transaction\ListRequest;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Account;
use FireflyIII\Support\Http\Api\TransactionFilter;

View File

@@ -1,6 +1,4 @@
<?php
declare(strict_types=1);
/*
* TransactionController.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,10 +19,12 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Transaction\List;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Transaction\ListRequest;
use FireflyIII\Api\V2\Request\Model\Transaction\ListRequest;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Transformers\V2\TransactionGroupTransformer;
use Illuminate\Http\JsonResponse;

View File

@@ -2,7 +2,7 @@
/*
* BillController.php
* Copyright (c) 2022 james@firefly-iii.org
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*

View File

@@ -0,0 +1,77 @@
<?php
/*
* DestroyController.php
* Copyright (c) 2023 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\Api\V2\Controllers\UserGroup;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Class DestroyController
*/
class DestroyController extends Controller
{
private UserGroupRepositoryInterface $repository;
/**
*
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(UserGroupRepositoryInterface::class);
return $next($request);
}
);
}
/**
* @param Request $request
* @param UserGroup $userGroup
*
* @return JsonResponse
*/
public function destroy(Request $request, UserGroup $userGroup): JsonResponse
{
/** @var User $user */
$user = auth()->user();
// need owner role or system owner role to delete user group.
$access = $user->hasRoleInGroup($userGroup, UserRoleEnum::OWNER, false, true);
if (false === $access) {
throw new NotFoundHttpException();
}
$this->repository->destroy($userGroup);
return response()->json([], 204);
}
}

View File

@@ -0,0 +1,101 @@
<?php
/*
* ShowController.php
* Copyright (c) 2023 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\Api\V2\Controllers\UserGroup;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\Transformers\V2\UserGroupTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
/**
* Class ShowController
*/
class ShowController extends Controller
{
private UserGroupRepositoryInterface $repository;
/**
*
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(UserGroupRepositoryInterface::class);
return $next($request);
}
);
}
/**
* @param Request $request
*
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
$collection = new Collection();
// if the user has the system owner role, get all. Otherwise, get only the users' groups.
if (!auth()->user()->hasRole('owner')) {
$collection = $this->repository->get();
}
if (auth()->user()->hasRole('owner')) {
$collection = $this->repository->getAll();
}
$count = $collection->count();
$userGroups = $collection->slice(($this->parameters->get('page') - 1) * $this->pageSize, $this->pageSize);
$paginator = new LengthAwarePaginator($userGroups, $count, $this->pageSize, $this->parameters->get('page'));
$transformer = new UserGroupTransformer();
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList('user-groups', $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE);
}
/**
* @param Request $request
* @param UserGroup $userGroup
*
* @return JsonResponse
*/
public function show(Request $request, UserGroup $userGroup): JsonResponse
{
$transformer = new UserGroupTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject('user-groups', $userGroup, $transformer))
->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@@ -0,0 +1,73 @@
<?php
/*
* StoreController.php
* Copyright (c) 2023 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\Api\V2\Controllers\UserGroup;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\UserGroup\StoreRequest;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\Transformers\V2\UserGroupTransformer;
use Illuminate\Http\JsonResponse;
/**
* Class StoreController
*/
class StoreController extends Controller
{
private UserGroupRepositoryInterface $repository;
/**
*
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(UserGroupRepositoryInterface::class);
return $next($request);
}
);
}
/**
* @param StoreRequest $request
*
* @return JsonResponse
*/
public function store(StoreRequest $request): JsonResponse
{
$all = $request->getAll();
$userGroup = $this->repository->store($all);
$transformer = new UserGroupTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject('user-groups', $userGroup, $transformer))
->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@@ -0,0 +1,96 @@
<?php
/*
* UpdateController.php
* Copyright (c) 2023 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\Api\V2\Controllers\UserGroup;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\UserGroup\UpdateMembershipRequest;
use FireflyIII\Api\V2\Request\UserGroup\UpdateRequest;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\Transformers\V2\UserGroupTransformer;
use Illuminate\Http\JsonResponse;
/**
* Class UpdateController
*/
class UpdateController extends Controller
{
// basic update van group
// add user, add rights, remove user, remove rights.
private UserGroupRepositoryInterface $repository;
/**
*
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(UserGroupRepositoryInterface::class);
return $next($request);
}
);
}
/**
* @param UpdateRequest $request
* @param UserGroup $userGroup
*
* @return JsonResponse
*/
public function update(UpdateRequest $request, UserGroup $userGroup): JsonResponse
{
$all = $request->getAll();
$userGroup = $this->repository->update($userGroup, $all);
$transformer = new UserGroupTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject('user-groups', $userGroup, $transformer))
->header('Content-Type', self::CONTENT_TYPE);
}
/**
* @param UpdateMembershipRequest $request
* @param UserGroup $userGroup
*
* @return JsonResponse
*/
public function updateMembership(UpdateMembershipRequest $request, UserGroup $userGroup): JsonResponse
{
$all = $request->getAll();
$userGroup = $this->repository->updateMembership($userGroup, $all);
$transformer = new UserGroupTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject('user-groups', $userGroup, $transformer))
->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@@ -23,13 +23,11 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Autocomplete;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\UserRole;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\User;
use FireflyIII\Validation\Administration\ValidatesAdministrationAccess;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
@@ -40,11 +38,10 @@ class AutocompleteRequest extends FormRequest
{
use ConvertsDataTypes;
use ChecksLogin;
use ValidatesAdministrationAccess;
protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS];
/**
* @return array
* @throws FireflyException
*/
public function getData(): array
{
@@ -62,11 +59,10 @@ class AutocompleteRequest extends FormRequest
$user = auth()->user();
return [
'types' => $array,
'query' => $this->convertString('query'),
'date' => $this->getCarbonDate('date'),
'limit' => $limit,
'administration_id' => (int)($this->get('administration_id', null) ?? $user->getAdministrationId()),
'types' => $array,
'query' => $this->convertString('query'),
'date' => $this->getCarbonDate('date'),
'limit' => $limit,
];
}
@@ -92,7 +88,7 @@ class AutocompleteRequest extends FormRequest
$validator->after(
function (Validator $validator) {
// validate if the account can access this administration
$this->validateAdministration($validator, [UserRole::CHANGE_TRANSACTIONS]);
$this->validateAdministration($validator, [UserRoleEnum::MANAGE_TRANSACTIONS]);
}
);
}

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* BalanceChartRequest.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,6 +21,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Chart;
use FireflyIII\Support\Request\ChecksLogin;
@@ -28,6 +30,9 @@ use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
/**
* Class BalanceChartRequest
*/
class BalanceChartRequest extends FormRequest
{
use ConvertsDataTypes;

View File

@@ -2,7 +2,7 @@
/*
* ListRequest.php
* Copyright (c) 2022 james@firefly-iii.org
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -22,7 +22,7 @@
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Transaction;
namespace FireflyIII\Api\V2\Request\Model\Transaction;
use Carbon\Carbon;
use FireflyIII\Support\Http\Api\TransactionFilter;

View File

@@ -0,0 +1,317 @@
<?php
/*
* StoreRequest.php
* Copyright (c) 2023 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\Api\V2\Request\Model\Transaction;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\UserGroup;
use FireflyIII\Rules\BelongsUserGroup;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsDateOrTime;
use FireflyIII\Support\NullArrayObject;
use FireflyIII\Support\Request\AppendsLocationData;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\User;
use FireflyIII\Validation\CurrencyValidation;
use FireflyIII\Validation\GroupValidation;
use FireflyIII\Validation\TransactionValidation;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
/**
* Class StoreRequest
*
* TODO this class is basically the same as the v1 request. However, it does not accept
* TODO models, objects and references that are NOT part of the designated user group (aka administration).
* TODO this distinction is already made in the CheckLogin trait, where there is also a convenient function
* TODO to grab the current UserGroup. This code is slightly different from other v2 apis that use
* TODO the "administration_id", those will have to be updated later on.
*/
class StoreRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
use TransactionValidation;
use GroupValidation;
use CurrencyValidation;
use AppendsLocationData;
protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS];
/**
* Get all data.
*
* @return array
*/
public function getAll(): array
{
app('log')->debug('V2: Get all data in TransactionStoreRequest');
return [
'group_title' => $this->convertString('group_title'),
'error_if_duplicate_hash' => $this->boolean('error_if_duplicate_hash'),
'apply_rules' => $this->boolean('apply_rules', true),
'fire_webhooks' => $this->boolean('fire_webhooks', true),
'transactions' => $this->getTransactionData(),
];
// TODO include location and ability to process it.
}
/**
* Get transaction data.
*
* @return array
*/
private function getTransactionData(): array
{
$return = [];
/**
* @var array $transaction
*/
foreach ($this->get('transactions') as $transaction) {
$object = new NullArrayObject($transaction);
$return[] = [
'type' => $this->clearString($object['type'], false),
'date' => $this->dateFromValue($object['date']),
'order' => $this->integerFromValue((string)$object['order']),
'currency_id' => $this->integerFromValue((string)$object['currency_id']),
'currency_code' => $this->clearString((string)$object['currency_code'], false),
// foreign currency info:
'foreign_currency_id' => $this->integerFromValue((string)$object['foreign_currency_id']),
'foreign_currency_code' => $this->clearString((string)$object['foreign_currency_code'], false),
// amount and foreign amount. Cannot be 0.
'amount' => $this->clearString((string)$object['amount'], false),
'foreign_amount' => $this->clearString((string)$object['foreign_amount'], false),
// description.
'description' => $this->clearString($object['description'], false),
// source of transaction. If everything is null, assume cash account.
'source_id' => $this->integerFromValue((string)$object['source_id']),
'source_name' => $this->clearString((string)$object['source_name'], false),
'source_iban' => $this->clearString((string)$object['source_iban'], false),
'source_number' => $this->clearString((string)$object['source_number'], false),
'source_bic' => $this->clearString((string)$object['source_bic'], false),
// destination of transaction. If everything is null, assume cash account.
'destination_id' => $this->integerFromValue((string)$object['destination_id']),
'destination_name' => $this->clearString((string)$object['destination_name'], false),
'destination_iban' => $this->clearString((string)$object['destination_iban'], false),
'destination_number' => $this->clearString((string)$object['destination_number'], false),
'destination_bic' => $this->clearString((string)$object['destination_bic'], false),
// budget info
'budget_id' => $this->integerFromValue((string)$object['budget_id']),
'budget_name' => $this->clearString((string)$object['budget_name'], false),
// category info
'category_id' => $this->integerFromValue((string)$object['category_id']),
'category_name' => $this->clearString((string)$object['category_name'], false),
// journal bill reference. Optional. Will only work for withdrawals
'bill_id' => $this->integerFromValue((string)$object['bill_id']),
'bill_name' => $this->clearString((string)$object['bill_name'], false),
// piggy bank reference. Optional. Will only work for transfers
'piggy_bank_id' => $this->integerFromValue((string)$object['piggy_bank_id']),
'piggy_bank_name' => $this->clearString((string)$object['piggy_bank_name'], false),
// some other interesting properties
'reconciled' => $this->convertBoolean((string)$object['reconciled']),
'notes' => $this->clearString((string)$object['notes']),
'tags' => $this->arrayFromValue($object['tags']),
// all custom fields:
'internal_reference' => $this->clearString((string)$object['internal_reference'], false),
'external_id' => $this->clearString((string)$object['external_id'], false),
'original_source' => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')),
'recurrence_id' => $this->integerFromValue($object['recurrence_id']),
'bunq_payment_id' => $this->clearString((string)$object['bunq_payment_id'], false),
'external_url' => $this->clearString((string)$object['external_url'], false),
'sepa_cc' => $this->clearString((string)$object['sepa_cc'], false),
'sepa_ct_op' => $this->clearString((string)$object['sepa_ct_op'], false),
'sepa_ct_id' => $this->clearString((string)$object['sepa_ct_id'], false),
'sepa_db' => $this->clearString((string)$object['sepa_db'], false),
'sepa_country' => $this->clearString((string)$object['sepa_country'], false),
'sepa_ep' => $this->clearString((string)$object['sepa_ep'], false),
'sepa_ci' => $this->clearString((string)$object['sepa_ci'], false),
'sepa_batch_id' => $this->clearString((string)$object['sepa_batch_id'], false),
// custom date fields. Must be Carbon objects. Presence is optional.
'interest_date' => $this->dateFromValue($object['interest_date']),
'book_date' => $this->dateFromValue($object['book_date']),
'process_date' => $this->dateFromValue($object['process_date']),
'due_date' => $this->dateFromValue($object['due_date']),
'payment_date' => $this->dateFromValue($object['payment_date']),
'invoice_date' => $this->dateFromValue($object['invoice_date']),
];
}
return $return;
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
app('log')->debug('V2: Collect rules of TransactionStoreRequest');
// at this point the userGroup can't be NULL because the
// authorize() method will complain. Loudly.
/** @var UserGroup $userGroup */
$userGroup = $this->getUserGroup();
return [
// basic fields for group:
'group_title' => 'between:1,1000|nullable',
'error_if_duplicate_hash' => [new IsBoolean()],
'apply_rules' => [new IsBoolean()],
// transaction rules (in array for splits):
'transactions.*.type' => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation',
'transactions.*.date' => ['required', new IsDateOrTime()],
'transactions.*.order' => 'numeric|min:0',
// currency info
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|nullable',
'transactions.*.currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id|nullable',
'transactions.*.foreign_currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
// amount
'transactions.*.amount' => 'required|numeric|gt:0',
'transactions.*.foreign_amount' => 'numeric',
// description
'transactions.*.description' => 'nullable|between:1,1000',
// source of transaction
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUserGroup($userGroup)],
'transactions.*.source_name' => 'between:1,255|nullable',
'transactions.*.source_iban' => 'between:1,255|nullable|iban',
'transactions.*.source_number' => 'between:1,255|nullable',
'transactions.*.source_bic' => 'between:1,255|nullable|bic',
// destination of transaction
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUserGroup($userGroup)],
'transactions.*.destination_name' => 'between:1,255|nullable',
'transactions.*.destination_iban' => 'between:1,255|nullable|iban',
'transactions.*.destination_number' => 'between:1,255|nullable',
'transactions.*.destination_bic' => 'between:1,255|nullable|bic',
// budget, category, bill and piggy
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUserGroup($userGroup)],
'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUserGroup($userGroup)],
'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUserGroup($userGroup), 'nullable'],
'transactions.*.category_name' => 'between:1,255|nullable',
'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUserGroup($userGroup)],
'transactions.*.bill_name' => ['between:1,255', 'nullable', new BelongsUserGroup($userGroup)],
'transactions.*.piggy_bank_id' => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUserGroup($userGroup)],
'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUserGroup($userGroup)],
// other interesting fields
'transactions.*.reconciled' => [new IsBoolean()],
'transactions.*.notes' => 'min:1|max:50000|nullable',
'transactions.*.tags' => 'between:0,255',
// meta info fields
'transactions.*.internal_reference' => 'min:1|max:255|nullable',
'transactions.*.external_id' => 'min:1|max:255|nullable',
'transactions.*.recurrence_id' => 'min:1|max:255|nullable',
'transactions.*.bunq_payment_id' => 'min:1|max:255|nullable',
'transactions.*.external_url' => 'min:1|max:255|nullable|url',
// SEPA fields:
'transactions.*.sepa_cc' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_op' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_id' => 'min:1|max:255|nullable',
'transactions.*.sepa_db' => 'min:1|max:255|nullable',
'transactions.*.sepa_country' => 'min:1|max:255|nullable',
'transactions.*.sepa_ep' => 'min:1|max:255|nullable',
'transactions.*.sepa_ci' => 'min:1|max:255|nullable',
'transactions.*.sepa_batch_id' => 'min:1|max:255|nullable',
// dates
'transactions.*.interest_date' => 'date|nullable',
'transactions.*.book_date' => 'date|nullable',
'transactions.*.process_date' => 'date|nullable',
'transactions.*.due_date' => 'date|nullable',
'transactions.*.payment_date' => 'date|nullable',
'transactions.*.invoice_date' => 'date|nullable',
];
}
/**
* Configure the validator instance.
*
* @param Validator $validator
*
* @return void
*/
public function withValidator(Validator $validator): void
{
/** @var User $user */
$user = auth()->user();
/** @var UserGroup $userGroup */
$userGroup = $this->getUserGroup();
$validator->after(
function (Validator $validator) use ($user, $userGroup) {
// must be valid array.
$this->validateTransactionArray($validator); // does not need group validation.
// must submit at least one transaction.
app('log')->debug('Now going to validateOneTransaction');
$this->validateOneTransaction($validator); // does not need group validation.
app('log')->debug('Now done with validateOneTransaction');
// all journals must have a description
$this->validateDescriptions($validator); // does not need group validation.
// all transaction types must be equal:
$this->validateTransactionTypes($validator); // does not need group validation.
// validate foreign currency info
$this->validateForeignCurrencyInformation($validator); // does not need group validation.
// validate all account info
$this->validateAccountInformation($validator, $user, $userGroup);
// validate source/destination is equal, depending on the transaction journal type.
$this->validateEqualAccounts($validator);
// the group must have a description if > 1 journal.
$this->validateGroupDescription($validator);
}
);
}
}

View File

@@ -0,0 +1,61 @@
<?php
/*
* StoreRequest.php
* Copyright (c) 2023 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\Api\V2\Request\UserGroup;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class StoreRequest
*/
class StoreRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
protected array $acceptedRoles = [UserRoleEnum::OWNER, UserRoleEnum::FULL];
/**
* @return array
*/
public function getAll(): array
{
return [
'title' => $this->convertString('title'),
];
}
/**
* @return array
*/
public function rules(): array
{
return [
'title' => 'unique:user_groups,title|required|min:2|max:255',
];
}
}

View File

@@ -0,0 +1,69 @@
<?php
/*
* StoreRequest.php
* Copyright (c) 2023 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\Api\V2\Request\UserGroup;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class StoreRequest
*/
class UpdateMembershipRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
protected array $acceptedRoles = [UserRoleEnum::OWNER, UserRoleEnum::FULL];
/**
* @return array
*/
public function getAll(): array
{
return [
'id' => $this->convertInteger('id'),
'email' => $this->convertString('email'),
'roles' => $this->get('roles') ?? [],
];
}
/**
* @return array
*/
public function rules(): array
{
$validRoles = [];
foreach (UserRoleEnum::cases() as $role) {
$validRoles[] = $role->value;
}
return [
'id' => 'exists:users,id|required_without:email',
'email' => 'exists:users,email|required_without:id',
'roles.*' => 'required|in:' . join(',', $validRoles),
];
}
}

View File

@@ -0,0 +1,64 @@
<?php
/*
* StoreRequest.php
* Copyright (c) 2023 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\Api\V2\Request\UserGroup;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\UserGroup;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class StoreRequest
*/
class UpdateRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
protected array $acceptedRoles = [UserRoleEnum::OWNER, UserRoleEnum::FULL];
/**
* @return array
*/
public function getAll(): array
{
return [
'title' => $this->convertString('title'),
];
}
/**
* @return array
*/
public function rules(): array
{
/** @var UserGroup $userGroup */
$userGroup = $this->route()->parameter('userGroup');
return [
'title' => sprintf('required|min:2|max:255|unique:user_groups,title,%d', $userGroup->id),
];
}
}

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Integrity;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\GroupMembership;
use FireflyIII\Models\UserGroup;
@@ -85,7 +86,7 @@ class CreateGroupMemberships extends Command
$userGroup = UserGroup::create(['title' => $user->email]);
}
$userRole = UserRole::where('title', UserRole::OWNER)->first();
$userRole = UserRole::where('title', UserRoleEnum::OWNER->value)->first();
if (null === $userRole) {
throw new FireflyException('Firefly III could not find a user role. Please make sure all migrations have run.');

View File

@@ -126,7 +126,7 @@ class UpdateGroupInformation extends Command
return;
}
if (0 !== $result) {
$this->friendlyPositive(sprintf('Moved %d %s objects to the correct group.', $result, str_replace('FireflyIII\\Models\\', '', $className)));
$this->friendlyPositive(sprintf('User #%d: Moved %d %s objects to the correct group.', $user->id, $result, str_replace('FireflyIII\\Models\\', '', $className)));
}
}
}

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* OutputVersion.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,25 +21,29 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\System;
use Illuminate\Console\Command;
/**
* Class OutputVersion
*/
class OutputVersion extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:output-version';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Outputs the Firefly III version';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:output-version';
/**
* Execute the console command.

View File

@@ -29,12 +29,34 @@ namespace FireflyIII\Enums;
*/
enum UserRoleEnum: string
{
case CHANGE_PIGGY_BANKS = 'change_piggies';
case CHANGE_REPETITIONS = 'change_reps';
case CHANGE_RULES = 'change_rules';
case CHANGE_TRANSACTIONS = 'change_tx';
case FULL = 'full';
case OWNER = 'owner';
case READ_ONLY = 'ro';
case VIEW_REPORTS = 'view_reports';
// most basic rights, cannot see other members, can see everything else.
case READ_ONLY = 'ro';
// required to even USE the group properly (in this order)
case MANAGE_TRANSACTIONS = 'mng_trx';
// required to edit, add or change categories/tags/object-groups
case MANAGE_META = 'mng_meta';
// manage other financial objects:
case MANAGE_BUDGETS = 'mng_budgets';
case MANAGE_PIGGY_BANKS = 'mng_piggies';
case MANAGE_REPETITIONS = 'mng_reps';
case MANAGE_SUBSCRIPTIONS = 'mng_subscriptions';
case MANAGE_RULES = 'mng_rules';
case MANAGE_RECURRING = 'mng_recurring';
case MANAGE_WEBHOOKS = 'mng_webhooks';
case MANAGE_CURRENCIES = 'mng_currencies';
// view and generate reports
case VIEW_REPORTS = 'view_reports';
// view memberships. needs FULL to manage them.
case VIEW_MEMBERSHIPS = 'view_memberships';
// everything the creator can, except remove/change original creator and delete group
case FULL = 'full';
// reserved for original creator
case OWNER = 'owner';
}

View File

@@ -22,8 +22,9 @@
declare(strict_types=1);
namespace FireflyIII\Events;
namespace FireflyIII\Events\Model\PiggyBank;
use FireflyIII\Events\Event;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
@@ -31,9 +32,9 @@ use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
/**
* Class ChangedPiggyBankAmount
* Class ChangedAmount
*/
class ChangedPiggyBankAmount extends Event
class ChangedAmount extends Event
{
use SerializesModels;

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* RuleActionFailedOnArray.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,6 +21,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Events\Model\Rule;
use FireflyIII\Models\RuleAction;

View File

@@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/*
* RuleActionFailedOnArray.php
* RuleActionFailedOnObject.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@@ -21,6 +21,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Events\Model\Rule;
use FireflyIII\Models\RuleAction;

View File

@@ -81,7 +81,7 @@ class TransactionGroupFactory
$group = new TransactionGroup();
$group->user()->associate($this->user);
$group->userGroup()->associate($this->user->userGroup);
$group->userGroup()->associate($data['user_group'] ?? $this->user->userGroup);
$group->title = $title;
$group->save();

View File

@@ -0,0 +1,66 @@
<?php
/*
* UserGroupFactory.php
* Copyright (c) 2023 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\Factory;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\GroupMembership;
use FireflyIII\Models\UserGroup;
use FireflyIII\Models\UserRole;
/**
* Class UserGroupFactory
*/
class UserGroupFactory
{
/**
* @param array $data
*
* @return UserGroup
* @throws FireflyException
*/
public function create(array $data): UserGroup
{
$userGroup = new UserGroup();
$userGroup->title = $data['title'];
$userGroup->save();
// grab the OWNER role:
$role = UserRole::whereTitle(UserRoleEnum::OWNER->value)->first();
if (null === $role) {
throw new FireflyException('Role "owner" does not exist.');
}
// make user member:
$groupMembership = new GroupMembership();
$groupMembership->user_group_id = $userGroup->id;
$groupMembership->user_id = $data['user']->id;
$groupMembership->user_role_id = $role->id;
$groupMembership->save();
return $userGroup;
}
}

View File

@@ -48,18 +48,23 @@ class AutomationHandler
public function reportJournals(RequestedReportOnJournals $event): void
{
Log::debug('In reportJournals.');
$sendReport = config('firefly.send_report_journals');
if (false === $sendReport) {
return;
}
/** @var UserRepositoryInterface $repository */
$repository = app(UserRepositoryInterface::class);
$user = $repository->find($event->userId);
if (null === $user || 0 === $event->groups->count()) {
$sendReport = app('preferences')->getForUser($user, 'notification_transaction_creation', false)->data;
if (false === $sendReport) {
Log::debug('Not sending report, because config says so.');
return;
}
if (null === $user || 0 === $event->groups->count()) {
Log::debug('No transaction groups in event, nothing to email about.');
return;
}
Log::debug('Continue with message!');
// transform groups into array:
/** @var TransactionGroupTransformer $transformer */
$transformer = app(TransactionGroupTransformer::class);
@@ -83,5 +88,6 @@ class AutomationHandler
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
}
Log::debug('If there is no error above this line, message was sent.');
}
}

View File

@@ -22,9 +22,9 @@
declare(strict_types=1);
namespace FireflyIII\Handlers\Events;
namespace FireflyIII\Handlers\Events\Model;
use FireflyIII\Events\ChangedPiggyBankAmount;
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
use FireflyIII\Models\PiggyBankEvent;
use Illuminate\Support\Facades\Log;
@@ -34,11 +34,11 @@ use Illuminate\Support\Facades\Log;
class PiggyBankEventHandler
{
/**
* @param ChangedPiggyBankAmount $event
* @param ChangedAmount $event
*
* @return void
*/
public function changePiggyAmount(ChangedPiggyBankAmount $event): void
public function changePiggyAmount(ChangedAmount $event): void
{
// find journal if group is present.
$journal = $event->transactionJournal;

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* RuleHandler.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,6 +21,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Handlers\Events\Model;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Handlers\Events;
use Carbon\Carbon;
use Database\Seeders\ExchangeRateSeeder;
use Exception;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Events\ActuallyLoggedIn;
use FireflyIII\Events\Admin\InvitationCreated;
use FireflyIII\Events\DetectedNewIPAddress;
@@ -144,7 +145,7 @@ class UserEventHandler
}
}
/** @var UserRole|null $role */
$role = UserRole::where('title', UserRole::OWNER)->first();
$role = UserRole::where('title', UserRoleEnum::OWNER->value)->first();
if (null === $role) {
throw new FireflyException('The user role is unexpectedly empty. Did you run all migrations?');
}

View File

@@ -0,0 +1,58 @@
<?php
/*
* AccountObserver.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\Account;
/**
* Class AccountObserver
*/
class AccountObserver
{
/**
* Also delete related objects.
*
* @param Account $account
*
* @return void
*/
public function deleting(Account $account): void
{
app('log')->debug('Observe "deleting" of an account.');
$account->accountMeta()->delete();
foreach ($account->piggyBanks()->get() as $piggy) {
$piggy->delete();
}
foreach ($account->attachments()->get() as $attachment) {
$attachment->delete();
}
foreach ($account->transactions()->get() as $transaction) {
$transaction->delete();
}
$account->notes()->delete();
$account->locations()->delete();
}
}

View File

@@ -0,0 +1,38 @@
<?php
/*
* AttachmentObserver.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\Attachment;
/**
* Class AttachmentObserver
*/
class AttachmentObserver
{
public function deleting(Attachment $attachment): void
{
app('log')->debug('Observe "deleting" of an attachment.');
$attachment->notes()->delete();
}
}

View File

@@ -0,0 +1,47 @@
<?php
/*
* BillObserver.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\Bill;
/**
* Class BillObserver
*/
class BillObserver
{
/**
* @param Bill $bill
*
* @return void
*/
public function deleting(Bill $bill): void
{
app('log')->debug('Observe "deleting" of a bill.');
foreach ($bill->attachments()->get() as $attachment) {
$attachment->delete();
}
$bill->notes()->delete();
}
}

View File

@@ -0,0 +1,51 @@
<?php
/*
* BudgetObserver.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\Budget;
/**
* Class BudgetObserver
*/
class BudgetObserver
{
/**
* @param Budget $budget
*
* @return void
*/
public function deleting(Budget $budget): void
{
app('log')->debug('Observe "deleting" of a budget.');
foreach ($budget->attachments()->get() as $attachment) {
$attachment->delete();
}
$budget->budgetlimits()->delete();
$budget->notes()->delete();
$budget->autoBudgets()->delete();
}
}

View File

@@ -0,0 +1,47 @@
<?php
/*
* CategoryObserver.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\Category;
/**
* Class CategoryObserver
*/
class CategoryObserver
{
/**
* @param Category $category
*
* @return void
*/
public function deleting(Category $category): void
{
app('log')->debug('Observe "deleting" of a category.');
foreach ($category->attachments()->get() as $attachment) {
$attachment->delete();
}
$category->notes()->delete();
}
}

View File

@@ -0,0 +1,71 @@
<?php
/*
* PiggyBankObserver.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankRepetition;
/**
* Class PiggyBankObserver
*/
class PiggyBankObserver
{
/**
* @param PiggyBank $piggyBank
*
* @return void
*/
public function created(PiggyBank $piggyBank): void
{
app('log')->debug('Observe "created" of a piggy bank.');
$repetition = new PiggyBankRepetition();
$repetition->piggyBank()->associate($piggyBank);
$repetition->startdate = $piggyBank->startdate;
$repetition->targetdate = $piggyBank->targetdate;
$repetition->currentamount = 0;
$repetition->save();
}
/**
* Also delete related objects.
*
* @param PiggyBank $piggyBank
*
* @return void
*/
public function deleting(PiggyBank $piggyBank): void
{
app('log')->debug('Observe "deleting" of a piggy bank.');
foreach ($piggyBank->attachments()->get() as $attachment) {
$attachment->delete();
}
$piggyBank->piggyBankEvents()->delete();
$piggyBank->piggyBankRepetitions()->delete();
$piggyBank->notes()->delete();
}
}

View File

@@ -0,0 +1,54 @@
<?php
/*
* RecurrenceObserver.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\Recurrence;
/**
* Class RecurrenceObserver
*/
class RecurrenceObserver
{
/**
* @param Recurrence $recurrence
*
* @return void
*/
public function deleting(Recurrence $recurrence): void
{
app('log')->debug('Observe "deleting" of a recurrence.');
foreach ($recurrence->attachments()->get() as $attachment) {
$attachment->delete();
}
$recurrence->recurrenceRepetitions()->delete();
$recurrence->recurrenceMeta()->delete();
foreach ($recurrence->recurrenceTransactions()->get() as $transaction) {
$transaction->delete();
}
$recurrence->notes()->delete();
}
}

View File

@@ -0,0 +1,44 @@
<?php
/*
* RecurrenceTransactionObserver.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\RecurrenceTransaction;
/**
* Class RecurrenceTransactionObserver
*/
class RecurrenceTransactionObserver
{
/**
* @param RecurrenceTransaction $transaction
*
* @return void
*/
public function deleting(RecurrenceTransaction $transaction): void
{
app('log')->debug('Observe "deleting" of a recurrence transaction.');
$transaction->recurrenceTransactionMeta()->delete();
}
}

View File

@@ -0,0 +1,47 @@
<?php
/*
* RuleGroupObserver.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\RuleGroup;
/**
* Class RuleGroupObserver
*/
class RuleGroupObserver
{
/**
* @param RuleGroup $ruleGroup
*
* @return void
*/
public function deleting(RuleGroup $ruleGroup): void
{
app('log')->debug('Observe "deleting" of a rule group.');
foreach ($ruleGroup->rules()->get() as $rule) {
$rule->delete();
}
}
}

View File

@@ -0,0 +1,45 @@
<?php
/*
* RuleObserver.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\Rule;
/**
* Class RuleObserver
*/
class RuleObserver
{
/**
* @param Rule $rule
*
* @return void
*/
public function deleting(Rule $rule): void
{
app('log')->debug('Observe "deleting" of a rule.');
$rule->ruleActions()->delete();
$rule->ruleTriggers()->delete();
}
}

View File

@@ -0,0 +1,50 @@
<?php
/*
* TagObserver.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\Tag;
/**
* Class TagObserver
*/
class TagObserver
{
/**
* @param Tag $tag
*
* @return void
*/
public function deleting(Tag $tag): void
{
app('log')->debug('Observe "deleting" of a tag.');
foreach ($tag->attachments()->get() as $attachment) {
$attachment->delete();
}
$tag->locations()->delete();
}
}

View File

@@ -0,0 +1,41 @@
<?php
/*
* TransactionGroup.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\TransactionGroup;
/**
* Class TransactionGroup
*/
class TransactionGroupObserver
{
public function deleting(TransactionGroup $transactionGroup): void
{
app('log')->debug('Observe "deleting" of a transaction group.');
foreach ($transactionGroup->transactionJournals()->get() as $journal) {
$journal->delete();
}
}
}

View File

@@ -0,0 +1,57 @@
<?php
/*
* TransactionJournalObserver.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\TransactionJournal;
/**
* Class TransactionJournalObserver
*/
class TransactionJournalObserver
{
/**
* @param TransactionJournal $transactionJournal
*
* @return void
*/
public function deleting(TransactionJournal $transactionJournal): void
{
app('log')->debug('Observe "deleting" of a transaction journal.');
// to make sure the listener doesn't get back to use and loop
TransactionJournal::withoutEvents(function () use ($transactionJournal) {
foreach ($transactionJournal->transactions()->get() as $transaction) {
$transaction->delete();
}
});
foreach ($transactionJournal->attachments()->get() as $attachment) {
$attachment->delete();
}
$transactionJournal->locations()->delete();
$transactionJournal->sourceJournalLinks()->delete();
$transactionJournal->destJournalLinks()->delete();
$transactionJournal->auditLogEntries()->delete();
}
}

View File

@@ -0,0 +1,39 @@
<?php
/*
* TransactionObserver.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\Transaction;
/**
* Class TransactionObserver
*/
class TransactionObserver
{
public function deleting(Transaction $transaction): void
{
app('log')->debug('Observe "deleting" of a transaction.');
$transaction?->transactionJournal?->delete();
}
}

View File

@@ -0,0 +1,43 @@
<?php
/*
* WebhookMessageObserver.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\WebhookMessage;
/**
* Class WebhookMessageObserver
*/
class WebhookMessageObserver
{
/**
* @param WebhookMessage $webhookMessage
*
* @return void
*/
public function deleting(WebhookMessage $webhookMessage): void
{
app('log')->debug('Observe "deleting" of a webhook message.');
$webhookMessage->webhookAttempts()->delete();
}
}

View File

@@ -0,0 +1,46 @@
<?php
/*
* WebhookObserver.php
* Copyright (c) 2023 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\Handlers\Observer;
use FireflyIII\Models\Webhook;
/**
* Class WebhookObserver
*/
class WebhookObserver
{
/**
* @param Webhook $webhook
*
* @return void
*/
public function deleting(Webhook $webhook): void
{
app('log')->debug('Observe "deleting" of a webhook.');
foreach ($webhook->webhookMessages() as $message) {
$message->delete();
}
}
}

View File

@@ -819,22 +819,28 @@ trait TimeCollection
/**
* Set the start and end time of the results to return.
*
* @param Carbon $start
* @param Carbon $end
* Can either or both be NULL
*
* @param Carbon|null $start
* @param Carbon|null $end
*
* @return GroupCollectorInterface
*/
public function setRange(Carbon $start, Carbon $end): GroupCollectorInterface
public function setRange(?Carbon $start, ?Carbon $end): GroupCollectorInterface
{
if ($end < $start) {
if (null !== $start && null !== $end && $end < $start) {
[$start, $end] = [$end, $start];
}
// always got to end of day / start of day for ranges.
$startStr = $start->format('Y-m-d 00:00:00');
$endStr = $end->format('Y-m-d 23:59:59');
$startStr = $start?->format('Y-m-d 00:00:00');
$endStr = $end?->format('Y-m-d 23:59:59');
$this->query->where('transaction_journals.date', '>=', $startStr);
$this->query->where('transaction_journals.date', '<=', $endStr);
if (null !== $start) {
$this->query->where('transaction_journals.date', '>=', $startStr);
}
if (null !== $end) {
$this->query->where('transaction_journals.date', '<=', $endStr);
}
return $this;
}

View File

@@ -29,8 +29,8 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Administration\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\User;
@@ -39,6 +39,8 @@ use Illuminate\Support\Collection;
use JsonException;
/**
* This class can handle both request with and without a user group and will return the appropriate repository when
* necessary.
*
* Class NetWorth
*/
@@ -49,7 +51,7 @@ class NetWorth implements NetWorthInterface
private CurrencyRepositoryInterface $currencyRepos;
private User $user;
private UserGroup $userGroup;
private null | UserGroup $userGroup;
/**
* @param Collection $accounts
@@ -67,7 +69,7 @@ class NetWorth implements NetWorthInterface
$cache->addProperty('net-worth-by-accounts');
$cache->addProperty($ids);
if ($cache->has()) {
//return $cache->get();
return $cache->get();
}
app('log')->debug(sprintf('Now in byAccounts("%s", "%s")', $ids, $date->format('Y-m-d')));
@@ -96,7 +98,7 @@ class NetWorth implements NetWorthInterface
/** @var Account $account */
foreach ($accounts as $account) {
app('log')->debug(sprintf('Now at account #%d ("%s")', $account->id, $account->name));
$currency = $this->adminAccountRepository->getAccountCurrency($account);
$currency = $this->getRepository()->getAccountCurrency($account);
$currencyId = (int)$currency->id;
$balance = '0';
$nativeBalance = '0';
@@ -137,6 +139,17 @@ class NetWorth implements NetWorthInterface
return $netWorth;
}
/**
* @return AdminAccountRepositoryInterface|AccountRepositoryInterface
*/
private function getRepository(): AdminAccountRepositoryInterface | AccountRepositoryInterface
{
if (null === $this->userGroup) {
return $this->accountRepository;
}
return $this->adminAccountRepository;
}
/**
* Returns the user's net worth in an array with the following layout:
*
@@ -181,7 +194,7 @@ class NetWorth implements NetWorthInterface
/** @var Account $account */
foreach ($accounts as $account) {
// Log::debug(sprintf('Now at account #%d: "%s"', $account->id, $account->name));
$currencyId = (int)$this->accountRepository->getMetaValue($account, 'currency_id');
$currencyId = (int)$this->getRepository()->getMetaValue($account, 'currency_id');
$currencyId = 0 === $currencyId ? $default->id : $currencyId;
// Log::debug(sprintf('Currency ID is #%d', $currencyId));
@@ -227,7 +240,8 @@ class NetWorth implements NetWorthInterface
if (null === $user) {
return;
}
$this->user = $user;
$this->user = $user;
$this->userGroup = null;
// make repository:
$this->accountRepository = app(AccountRepositoryInterface::class);
@@ -239,13 +253,12 @@ class NetWorth implements NetWorthInterface
/**
* @inheritDoc
* @throws FireflyException
*/
public function setUserGroup(UserGroup $userGroup): void
{
$this->userGroup = $userGroup;
$this->adminAccountRepository = app(AdminAccountRepositoryInterface::class);
$this->adminAccountRepository->setAdministrationId($userGroup->id);
$this->adminAccountRepository->setUserGroup($userGroup);
}
/**
@@ -260,7 +273,7 @@ class NetWorth implements NetWorthInterface
$return = [];
$balances = app('steam')->balancesByAccounts($accounts, $date);
foreach ($accounts as $account) {
$currency = $this->accountRepository->getAccountCurrency($account);
$currency = $this->getRepository()->getAccountCurrency($account);
$balance = $balances[$account->id] ?? '0';
// always subtract virtual balance.
@@ -288,13 +301,13 @@ class NetWorth implements NetWorthInterface
*/
private function getAccounts(): Collection
{
$accounts = $this->accountRepository->getAccountsByType(
$accounts = $this->getRepository()->getAccountsByType(
[AccountType::ASSET, AccountType::DEFAULT, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]
);
$filtered = new Collection();
/** @var Account $account */
foreach ($accounts as $account) {
if (1 === (int)$this->accountRepository->getMetaValue($account, 'include_net_worth')) {
if (1 === (int)$this->getRepository()->getMetaValue($account, 'include_net_worth')) {
$filtered->push($account);
}
}

View File

@@ -22,25 +22,6 @@
*/
declare(strict_types=1);
/*
* TriggerController.php
* Copyright (c) 2022 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/>.
*/
namespace FireflyIII\Http\Controllers\Recurring;

View File

@@ -23,16 +23,14 @@ declare(strict_types=1);
namespace FireflyIII\Http\Requests;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\Account;
use FireflyIII\Models\Location;
use FireflyIII\Models\UserRole;
use FireflyIII\Rules\UniqueIban;
use FireflyIII\Support\Request\AppendsLocationData;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Validation\Administration\ValidatesAdministrationAccess;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
/**
* Class AccountFormRequest.
@@ -42,7 +40,7 @@ class AccountFormRequest extends FormRequest
use ConvertsDataTypes;
use AppendsLocationData;
use ChecksLogin;
use ValidatesAdministrationAccess;
protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS];
/**
* Get all data.
@@ -52,7 +50,6 @@ class AccountFormRequest extends FormRequest
public function getAccountData(): array
{
$data = [
'administration_id' => $this->convertInteger('administration_id'),
'name' => $this->convertString('name'),
'active' => $this->boolean('active'),
'account_type_name' => $this->convertString('objectType'),
@@ -72,9 +69,6 @@ class AccountFormRequest extends FormRequest
'include_net_worth' => '1',
'liability_direction' => $this->convertString('liability_direction'),
];
if (0 === $data['administration_id']) {
$data['administration_id'] = auth()->user()->getAdministrationId();
}
$data = $this->appendLocationData($data, 'location');
if (false === $this->boolean('include_net_worth')) {
@@ -109,7 +103,6 @@ class AccountFormRequest extends FormRequest
$types = implode(',', array_keys(config('firefly.subTitlesByIdentifier')));
$ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes')));
$rules = [
'administration_id' => 'min:1|max:16777216|numeric',
'name' => 'required|max:1024|min:1|uniqueAccountForUser',
'opening_balance' => 'numeric|nullable|max:1000000000',
'opening_balance_date' => 'date|required_with:opening_balance|nullable',
@@ -139,21 +132,4 @@ class AccountFormRequest extends FormRequest
return $rules;
}
/**
* Configure the validator instance with special rules for after the basic validation rules.
*
* @param Validator $validator
*
* @return void
*/
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator) {
// validate if the account can access this administration
$this->validateAdministration($validator, [UserRole::CHANGE_TRANSACTIONS]);
}
);
}
}

View File

@@ -460,16 +460,18 @@ class CreateRecurringTransactions implements ShouldQueue
$total = $this->repository->totalTransactions($recurrence, $repetition);
$count = $this->repository->getJournalCount($recurrence) + 1;
$transactions = $recurrence->recurrenceTransactions()->get();
$return = [];
/** @var RecurrenceTransaction $first */
$first = $transactions->first();
$return = [];
/** @var RecurrenceTransaction $transaction */
foreach ($transactions as $index => $transaction) {
$single = [
'type' => strtolower($recurrence->transactionType->type),
'type' => null === $first->transactionType ? strtolower($recurrence->transactionType->type) : strtolower($first->transactionType->type),
'date' => $date,
'user' => $recurrence->user_id,
'currency_id' => (int)$transaction->transaction_currency_id,
'currency_code' => null,
'description' => $transactions->first()->description,
'description' => $first->description,
'amount' => $transaction->amount,
'budget_id' => $this->repository->getBudget($transaction),
'budget_name' => null,

View File

@@ -154,7 +154,7 @@ class Attachment extends Model
}
/**
* Get all of the notes.
* Get all the notes.
*/
public function notes(): MorphMany
{

View File

@@ -29,6 +29,7 @@ use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Carbon;
/**
@@ -66,6 +67,8 @@ use Illuminate\Support\Carbon;
*/
class CurrencyExchangeRate extends Model
{
use SoftDeletes;
/** @var array Convert these fields to other data types */
protected $casts
= [

View File

@@ -97,7 +97,7 @@ class Location extends Model
}
/**
* Get all of the accounts.
* Get all the accounts.
*/
public function accounts(): MorphMany
{
@@ -105,7 +105,7 @@ class Location extends Model
}
/**
* Get all of the owning attachable models.
* Get all the owning attachable models.
*
*
* @return MorphTo

View File

@@ -76,7 +76,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static Builder|Rule withoutTrashed()
* @property int|null $user_group_id
* @method static \Illuminate\Database\Eloquent\Builder|Rule whereUserGroupId($value)
* @property-read \FireflyIII\Models\UserGroup|null $userGroup
* @property-read UserGroup|null $userGroup
* @mixin Eloquent
*/
class Rule extends Model
@@ -125,14 +125,6 @@ class Rule extends Model
throw new NotFoundHttpException();
}
/**
* @return BelongsTo
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
/**
* @return HasMany
*/
@@ -167,6 +159,14 @@ class Rule extends Model
$this->attributes['description'] = e($value);
}
/**
* @return BelongsTo
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
/**
* @return BelongsTo
*/

View File

@@ -90,7 +90,7 @@ class RuleGroup extends Model
];
/** @var array Fields that can be filled */
protected $fillable = ['user_id', 'stop_processing', 'order', 'title', 'description', 'active'];
protected $fillable = ['user_id', 'user_group_id', 'stop_processing', 'order', 'title', 'description', 'active'];
/**
* Route binder. Converts the key in the URL to the specified object (or throw 404).

View File

@@ -61,7 +61,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static Builder|TransactionGroup withoutTrashed()
* @property int|null $user_group_id
* @method static \Illuminate\Database\Eloquent\Builder|TransactionGroup whereUserGroupId($value)
* @property-read \FireflyIII\Models\UserGroup|null $userGroup
* @property-read UserGroup|null $userGroup
* @mixin Eloquent
*/
class TransactionGroup extends Model
@@ -84,7 +84,7 @@ class TransactionGroup extends Model
];
/** @var array Fields that can be filled */
protected $fillable = ['user_id', 'title'];
protected $fillable = ['user_id', 'user_group_id', 'title'];
/**
* Route binder. Converts the key in the URL to the specified object (or throw 404).

View File

@@ -201,6 +201,14 @@ class TransactionJournal extends Model
return $this->morphMany(Attachment::class, 'attachable');
}
/**
* @return MorphMany
*/
public function auditLogEntries(): MorphMany
{
return $this->morphMany(AuditLogEntry::class, 'auditable');
}
/**
* @return BelongsTo
*/
@@ -254,7 +262,7 @@ class TransactionJournal extends Model
}
/**
* Get all of the notes.
* Get all the notes.
*/
public function notes(): MorphMany
{

View File

@@ -25,23 +25,26 @@ declare(strict_types=1);
namespace FireflyIII\Models;
use Eloquent;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Support\Carbon;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Class UserGroup
*
* @property int $id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property string|null $deleted_at
* @property string $title
* @property-read Collection|GroupMembership[] $groupMemberships
* @property-read int|null $group_memberships_count
* @property int $id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property string|null $deleted_at
* @property string $title
* @property-read Collection|GroupMembership[] $groupMemberships
* @property-read int|null $group_memberships_count
* @method static Builder|UserGroup newModelQuery()
* @method static Builder|UserGroup newQuery()
* @method static Builder|UserGroup query()
@@ -50,24 +53,52 @@ use Illuminate\Support\Carbon;
* @method static Builder|UserGroup whereId($value)
* @method static Builder|UserGroup whereTitle($value)
* @method static Builder|UserGroup whereUpdatedAt($value)
* @property-read Collection<int, Account> $accounts
* @property-read int|null $accounts_count
* @property-read Collection<int, \FireflyIII\Models\AvailableBudget> $availableBudgets
* @property-read int|null $available_budgets_count
* @property-read Collection<int, \FireflyIII\Models\Bill> $bills
* @property-read int|null $bills_count
* @property-read Collection<int, \FireflyIII\Models\Budget> $budgets
* @property-read int|null $budgets_count
* @property-read Collection<int, \FireflyIII\Models\PiggyBank> $piggyBanks
* @property-read int|null $piggy_banks_count
* @property-read Collection<int, \FireflyIII\Models\TransactionJournal> $transactionJournals
* @property-read int|null $transaction_journals_count
* @property-read Collection<int, Account> $accounts
* @property-read int|null $accounts_count
* @property-read Collection<int, AvailableBudget> $availableBudgets
* @property-read int|null $available_budgets_count
* @property-read Collection<int, Bill> $bills
* @property-read int|null $bills_count
* @property-read Collection<int, Budget> $budgets
* @property-read int|null $budgets_count
* @property-read Collection<int, PiggyBank> $piggyBanks
* @property-read int|null $piggy_banks_count
* @property-read Collection<int, TransactionJournal> $transactionJournals
* @property-read int|null $transaction_journals_count
* @mixin Eloquent
*/
class UserGroup extends Model
{
protected $fillable = ['title'];
/**
* Route binder. Converts the key in the URL to the specified object (or throw 404).
*
* @param string $value
*
* @return UserGroup
* @throws NotFoundHttpException
*/
public static function routeBinder(string $value): UserGroup
{
if (auth()->check()) {
$userGroupId = (int)$value;
/** @var User $user */
$user = auth()->user();
/** @var UserGroup $userGroup */
$userGroup = UserGroup::find($userGroupId);
if (null === $userGroup) {
throw new NotFoundHttpException();
}
// need at least ready only to be aware of the user group's existence,
// but owner/full role (in the group) or global owner role may overrule this.
if ($user->hasRoleInGroup($userGroup, UserRoleEnum::READ_ONLY, true, true)) {
return $userGroup;
}
}
throw new NotFoundHttpException();
}
/**
* Link to accounts.
*
@@ -78,6 +109,16 @@ class UserGroup extends Model
return $this->hasMany(Account::class);
}
/**
* Link to attachments.
*
* @return HasMany
*/
public function attachments(): HasMany
{
return $this->hasMany(Attachment::class);
}
/**
* Link to bills.
*
@@ -108,6 +149,26 @@ class UserGroup extends Model
return $this->hasMany(Budget::class);
}
/**
* Link to categories.
*
* @return HasMany
*/
public function categories(): HasMany
{
return $this->hasMany(Category::class);
}
/**
* Link to exchange rates.
*
* @return HasMany
*/
public function currencyExchangeRates(): HasMany
{
return $this->hasMany(CurrencyExchangeRate::class);
}
/**
*
* @return HasMany
@@ -117,6 +178,14 @@ class UserGroup extends Model
return $this->hasMany(GroupMembership::class);
}
/**
* @return HasMany
*/
public function objectGroups(): HasMany
{
return $this->hasMany(ObjectGroup::class);
}
/**
* Link to piggy banks.
*
@@ -127,6 +196,46 @@ class UserGroup extends Model
return $this->hasManyThrough(PiggyBank::class, Account::class);
}
/**
* @return HasMany
*/
public function recurrences(): HasMany
{
return $this->hasMany(Recurrence::class);
}
/**
* @return HasMany
*/
public function ruleGroups(): HasMany
{
return $this->hasMany(RuleGroup::class);
}
/**
* @return HasMany
*/
public function rules(): HasMany
{
return $this->hasMany(Rule::class);
}
/**
* @return HasMany
*/
public function tags(): HasMany
{
return $this->hasMany(Tag::class);
}
/**
* @return HasMany
*/
public function transactionGroups(): HasMany
{
return $this->hasMany(TransactionGroup::class);
}
/**
* Link to transaction journals.
*
@@ -136,4 +245,12 @@ class UserGroup extends Model
{
return $this->hasMany(TransactionJournal::class);
}
/**
* @return HasMany
*/
public function webhooks(): HasMany
{
return $this->hasMany(Webhook::class);
}
}

View File

@@ -53,18 +53,6 @@ use Illuminate\Support\Carbon;
*/
class UserRole extends Model
{
public const CHANGE_PIGGY_BANKS = 'change_piggies';
public const CHANGE_REPETITIONS = 'change_reps';
public const CHANGE_RULES = 'change_rules';
public const CHANGE_TRANSACTIONS = 'change_tx';
public const FULL = 'full';
public const MANAGE_CURRENCIES = 'manage_currencies';
public const MANAGE_WEBHOOKS = 'manage_webhooks';
public const OWNER = 'owner';
public const READ_ONLY = 'ro';
public const VIEW_REPORTS = 'view_reports';
protected $fillable = ['title'];
/**

View File

@@ -99,9 +99,7 @@ class TestNotification extends Notification
*/
public function via($notifiable)
{
/** @var User|null $user */
$user = auth()->user();
$slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data;
$slackUrl = app('fireflyconfig')->get('slack_webhook_url', '')->data;
if (UrlValidator::isValidWebhookURL($slackUrl)) {
return ['mail', 'slack'];
}

View File

@@ -102,9 +102,7 @@ class UserInvitation extends Notification
*/
public function via($notifiable)
{
/** @var User|null $user */
$user = auth()->user();
$slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data;
$slackUrl = app('fireflyconfig')->get('slack_webhook_url', '')->data;
if (UrlValidator::isValidWebhookURL($slackUrl)) {
return ['mail', 'slack'];
}

View File

@@ -99,9 +99,7 @@ class UserRegistration extends Notification
*/
public function via($notifiable)
{
/** @var User|null $user */
$user = auth()->user();
$slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data;
$slackUrl = app('fireflyconfig')->get('slack_webhook_url', '')->data;
if (UrlValidator::isValidWebhookURL($slackUrl)) {
return ['mail', 'slack'];
}

View File

@@ -103,9 +103,7 @@ class VersionCheckResult extends Notification
*/
public function via($notifiable)
{
/** @var User|null $user */
$user = auth()->user();
$slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data;
$slackUrl = app('fireflyconfig')->get('slack_webhook_url', '')->data;
if (UrlValidator::isValidWebhookURL($slackUrl)) {
return ['mail', 'slack'];
}

View File

@@ -29,8 +29,8 @@ use FireflyIII\Repositories\Account\AccountTasker;
use FireflyIII\Repositories\Account\AccountTaskerInterface;
use FireflyIII\Repositories\Account\OperationsRepository;
use FireflyIII\Repositories\Account\OperationsRepositoryInterface;
use FireflyIII\Repositories\Administration\Account\AccountRepository as AdminAccountRepository;
use FireflyIII\Repositories\Administration\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Account\AccountRepository as AdminAccountRepository;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;
@@ -84,7 +84,6 @@ class AccountServiceProvider extends ServiceProvider
// phpstan thinks auth does not exist.
if ($app->auth->check()) { // @phpstan-ignore-line
$repository->setUser(auth()->user());
$repository->setAdministrationId((int)auth()->user()->user_group_id);
}
return $repository;

View File

@@ -25,8 +25,8 @@ namespace FireflyIII\Providers;
use FireflyIII\Repositories\Bill\BillRepository;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Administration\Bill\BillRepository as AdminBillRepository;
use FireflyIII\Repositories\Administration\Bill\BillRepositoryInterface as AdminBillRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Bill\BillRepository as AdminBillRepository;
use FireflyIII\Repositories\UserGroups\Bill\BillRepositoryInterface as AdminBillRepositoryInterface;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;

View File

@@ -25,20 +25,20 @@ namespace FireflyIII\Providers;
use FireflyIII\Repositories\Budget\AvailableBudgetRepository;
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Repositories\Administration\Budget\AvailableBudgetRepository as AdminAbRepository;
use FireflyIII\Repositories\Administration\Budget\AvailableBudgetRepositoryInterface as AdminAbRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetLimitRepository;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepository;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Administration\Budget\BudgetRepository as AdminBudgetRepository;
use FireflyIII\Repositories\Administration\Budget\BudgetRepositoryInterface as AdminBudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\NoBudgetRepository;
use FireflyIII\Repositories\Budget\NoBudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepository;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\Administration\Budget\OperationsRepository as AdminOperationsRepository;
use FireflyIII\Repositories\Administration\Budget\OperationsRepositoryInterface as AdminOperationsRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Budget\AvailableBudgetRepository as AdminAbRepository;
use FireflyIII\Repositories\UserGroups\Budget\AvailableBudgetRepositoryInterface as AdminAbRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Budget\BudgetRepository as AdminBudgetRepository;
use FireflyIII\Repositories\UserGroups\Budget\BudgetRepositoryInterface as AdminBudgetRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Budget\OperationsRepository as AdminOperationsRepository;
use FireflyIII\Repositories\UserGroups\Budget\OperationsRepositoryInterface as AdminOperationsRepositoryInterface;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;
@@ -80,7 +80,6 @@ class BudgetServiceProvider extends ServiceProvider
$repository = app(AdminBudgetRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line
$repository->setUser(auth()->user());
$repository->setAdministrationId(auth()->user()->user_group_id);
}
return $repository;
@@ -109,7 +108,6 @@ class BudgetServiceProvider extends ServiceProvider
$repository = app(AdminAbRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line
$repository->setUser(auth()->user());
$repository->setAdministrationId(auth()->user()->user_group_id);
}
return $repository;
@@ -164,7 +162,6 @@ class BudgetServiceProvider extends ServiceProvider
$repository = app(AdminOperationsRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line
$repository->setUser(auth()->user());
$repository->setAdministrationId(auth()->user()->user_group_id);
}
return $repository;

View File

@@ -26,12 +26,13 @@ namespace FireflyIII\Providers;
use FireflyIII\Events\ActuallyLoggedIn;
use FireflyIII\Events\Admin\InvitationCreated;
use FireflyIII\Events\AdminRequestedTestMessage;
use FireflyIII\Events\ChangedPiggyBankAmount;
use FireflyIII\Events\DestroyedTransactionGroup;
use FireflyIII\Events\DetectedNewIPAddress;
use FireflyIII\Events\Model\BudgetLimit\Created;
use FireflyIII\Events\Model\BudgetLimit\Deleted;
use FireflyIII\Events\Model\BudgetLimit\Updated;
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
use FireflyIII\Events\Model\PiggyBank\ChangedPiggyBankAmount;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject;
use FireflyIII\Events\NewVersionAvailable;
@@ -47,8 +48,38 @@ use FireflyIII\Events\UpdatedAccount;
use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Events\UserChangedEmail;
use FireflyIII\Events\WarnUserAboutBill;
use FireflyIII\Handlers\Observer\AccountObserver;
use FireflyIII\Handlers\Observer\AttachmentObserver;
use FireflyIII\Handlers\Observer\BillObserver;
use FireflyIII\Handlers\Observer\BudgetObserver;
use FireflyIII\Handlers\Observer\CategoryObserver;
use FireflyIII\Handlers\Observer\PiggyBankObserver;
use FireflyIII\Handlers\Observer\RecurrenceObserver;
use FireflyIII\Handlers\Observer\RecurrenceTransactionObserver;
use FireflyIII\Handlers\Observer\RuleGroupObserver;
use FireflyIII\Handlers\Observer\RuleObserver;
use FireflyIII\Handlers\Observer\TagObserver;
use FireflyIII\Handlers\Observer\TransactionGroupObserver;
use FireflyIII\Handlers\Observer\TransactionJournalObserver;
use FireflyIII\Handlers\Observer\TransactionObserver;
use FireflyIII\Handlers\Observer\WebhookMessageObserver;
use FireflyIII\Handlers\Observer\WebhookObserver;
use FireflyIII\Models\Account;
use FireflyIII\Models\Attachment;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\Recurrence;
use FireflyIII\Models\RecurrenceTransaction;
use FireflyIII\Models\Rule;
use FireflyIII\Models\RuleGroup;
use FireflyIII\Models\Tag;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\Webhook;
use FireflyIII\Models\WebhookMessage;
use Illuminate\Auth\Events\Login;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Laravel\Passport\Events\AccessTokenCreated;
@@ -158,9 +189,10 @@ class EventServiceProvider extends ServiceProvider
'FireflyIII\Handlers\Events\AuditEventHandler@storeAuditEvent',
],
// piggy bank related events:
ChangedPiggyBankAmount::class => [
'FireflyIII\Handlers\Events\PiggyBankEventHandler@changePiggyAmount',
ChangedAmount::class => [
'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changePiggyAmount',
],
// budget related events: CRUD budget limit
Created::class => [
'FireflyIII\Handlers\Events\Model\BudgetLimitHandler@created',
@@ -187,24 +219,30 @@ class EventServiceProvider extends ServiceProvider
*/
public function boot(): void
{
parent::boot();
$this->registerCreateEvents();
$this->registerObservers();
}
/**
* TODO needs a dedicated (static) method.
* @return void
*/
protected function registerCreateEvents(): void
private function registerObservers(): void
{
PiggyBank::created(
static function (PiggyBank $piggyBank) {
$repetition = new PiggyBankRepetition();
$repetition->piggyBank()->associate($piggyBank);
$repetition->startdate = $piggyBank->startdate;
$repetition->targetdate = $piggyBank->targetdate;
$repetition->currentamount = 0;
$repetition->save();
}
);
app('log')->debug('Register observers');
Attachment::observe(new AttachmentObserver());
PiggyBank::observe(new PiggyBankObserver());
Account::observe(new AccountObserver());
Bill::observe(new BillObserver());
Budget::observe(new BudgetObserver());
Category::observe(new CategoryObserver());
Recurrence::observe(new RecurrenceObserver());
RecurrenceTransaction::observe(new RecurrenceTransactionObserver());
Rule::observe(new RuleObserver());
RuleGroup::observe(new RuleGroupObserver());
Tag::observe(new TagObserver());
Transaction::observe(new TransactionObserver());
TransactionJournal::observe(new TransactionJournalObserver());
TransactionGroup::observe(new TransactionGroupObserver());
Webhook::observe(new WebhookObserver());
WebhookMessage::observe(new WebhookMessageObserver());
}
}

View File

@@ -47,6 +47,8 @@ use FireflyIII\Repositories\TransactionType\TransactionTypeRepository;
use FireflyIII\Repositories\TransactionType\TransactionTypeRepositoryInterface;
use FireflyIII\Repositories\User\UserRepository;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Repositories\UserGroup\UserGroupRepository;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\Repositories\Webhook\WebhookRepository;
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
use FireflyIII\Services\FireflyIIIOrg\Update\UpdateRequest;
@@ -212,6 +214,19 @@ class FireflyServiceProvider extends ServiceProvider
}
);
$this->app->bind(
UserGroupRepositoryInterface::class,
static function (Application $app) {
/** @var UserGroupRepository $repository */
$repository = app(UserGroupRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
$repository->setUser(auth()->user());
}
return $repository;
}
);
// more generators:
$this->app->bind(PopupReportInterface::class, PopupReport::class);
$this->app->bind(ReportHelperInterface::class, ReportHelper::class);

View File

@@ -26,8 +26,8 @@ namespace FireflyIII\Providers;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepository;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Repositories\Administration\PiggyBank\PiggyBankRepository as AdminPiggyBankRepository;
use FireflyIII\Repositories\Administration\PiggyBank\PiggyBankRepositoryInterface as AdminPiggyBankRepositoryInterface;
use FireflyIII\Repositories\UserGroups\PiggyBank\PiggyBankRepository as AdminPiggyBankRepository;
use FireflyIII\Repositories\UserGroups\PiggyBank\PiggyBankRepositoryInterface as AdminPiggyBankRepositoryInterface;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;

View File

@@ -25,7 +25,8 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\PiggyBank;
use Exception;
use FireflyIII\Events\ChangedPiggyBankAmount;
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
use FireflyIII\Events\Model\PiggyBank\ChangedPiggyBankAmount;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Note;
use FireflyIII\Models\PiggyBank;
@@ -80,7 +81,7 @@ trait ModifiesPiggyBanks
$repetition->save();
Log::debug('addAmount [a]: Trigger change for negative amount.');
event(new ChangedPiggyBankAmount($piggyBank, bcmul($amount, '-1'), $journal, null));
event(new ChangedAmount($piggyBank, bcmul($amount, '-1'), $journal, null));
return true;
}
@@ -103,7 +104,7 @@ trait ModifiesPiggyBanks
$repetition->save();
Log::debug('addAmount [b]: Trigger change for positive amount.');
event(new ChangedPiggyBankAmount($piggyBank, $amount, $journal, null));
event(new ChangedAmount($piggyBank, $amount, $journal, null));
return true;
}
@@ -202,11 +203,11 @@ trait ModifiesPiggyBanks
if (-1 === bccomp($difference, '0')) {
Log::debug('addAmount [c]: Trigger change for negative amount.');
event(new ChangedPiggyBankAmount($piggyBank, $difference, null, null));
event(new ChangedAmount($piggyBank, $difference, null, null));
}
if (1 === bccomp($difference, '0')) {
Log::debug('addAmount [d]: Trigger change for positive amount.');
event(new ChangedPiggyBankAmount($piggyBank, $difference, null, null));
event(new ChangedAmount($piggyBank, $difference, null, null));
}
return $piggyBank;
@@ -386,7 +387,7 @@ trait ModifiesPiggyBanks
$difference = bcsub($piggyBank->targetamount, $repetition->currentamount);
// an amount will be removed, create "negative" event:
event(new ChangedPiggyBankAmount($piggyBank, $difference, null, null));
event(new ChangedAmount($piggyBank, $difference, null, null));
$repetition->currentamount = $piggyBank->targetamount;
$repetition->save();

View File

@@ -462,11 +462,12 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface
{
$newRuleGroup = new RuleGroup(
[
'user_id' => $this->user->id,
'title' => $data['title'],
'description' => $data['description'],
'order' => 31337,
'active' => array_key_exists('active', $data) ? $data['active'] : true,
'user_id' => $this->user->id,
'user_group_id' => $this->user->user_group_id,
'title' => $data['title'],
'description' => $data['description'],
'order' => 31337,
'active' => array_key_exists('active', $data) ? $data['active'] : true,
]
);
$newRuleGroup->save();

View File

@@ -0,0 +1,285 @@
<?php
/*
* UserGroupRepository.php
* Copyright (c) 2023 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\UserGroup;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\UserGroupFactory;
use FireflyIII\Models\GroupMembership;
use FireflyIII\Models\UserGroup;
use FireflyIII\Models\UserRole;
use FireflyIII\User;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Support\Collection;
use ValueError;
/**
* Class UserGroupRepository
*/
class UserGroupRepository implements UserGroupRepositoryInterface
{
private User $user;
/**
* @inheritDoc
*/
public function destroy(UserGroup $userGroup): void
{
app('log')->debug(sprintf('Going to destroy user group #%d ("%s").', $userGroup->id, $userGroup->title));
$memberships = $userGroup->groupMemberships()->get();
/** @var GroupMembership $membership */
foreach ($memberships as $membership) {
/** @var User $user */
$user = $membership->user()->first();
if (null === $user) {
continue;
}
app('log')->debug(sprintf('Processing membership #%d (user #%d "%s")', $membership->id, $user->id, $user->email));
// user has memberships of other groups?
$count = $user->groupMemberships()->where('user_group_id', '!=', $userGroup->id)->count();
if (0 === $count) {
app('log')->debug('User has no other memberships and needs a new user group.');
$newUserGroup = $this->createNewUserGroup($user);
$user->user_group_id = $newUserGroup->id;
$user->save();
app('log')->debug(sprintf('Make new group #%d ("%s")', $newUserGroup->id, $newUserGroup->title));
}
// user has other memberships, select one at random and assign it to the user.
if ($count > 0) {
app('log')->debug('User has other memberships and will be assigned a new administration.');
/** @var GroupMembership $first */
$first = $user->groupMemberships()->where('user_group_id', '!=', $userGroup->id)->inRandomOrder()->first();
$user->user_group_id = $first->id;
$user->save();
}
// delete membership so group is empty after this for-loop.
$membership->delete();
}
// all users are now moved away from user group.
// time to DESTROY all objects.
// we have to do this one by one to trigger the necessary observers :(
$objects = ['availableBudgets', 'bills', 'budgets', 'categories', 'currencyExchangeRates', 'objectGroups',
'recurrences', 'rules', 'ruleGroups', 'tags', 'transactionGroups', 'transactionJournals', 'piggyBanks', 'accounts', 'webhooks',
];
foreach ($objects as $object) {
foreach ($userGroup->$object()->get() as $item) {
$item->delete();
}
}
$userGroup->delete();
app('log')->debug('Done!');
}
/**
* Returns all groups the user is member in.
*
* @inheritDoc
*/
public function get(): Collection
{
$collection = new Collection();
$memberships = $this->user->groupMemberships()->get();
/** @var GroupMembership $membership */
foreach ($memberships as $membership) {
/** @var UserGroup $group */
$group = $membership->userGroup()->first();
if (null !== $group) {
$collection->push($group);
}
}
return $collection;
}
/**
* Because there is the chance that a group with this name already exists,
* Firefly III runs a little loop of combinations to make sure the group name is unique.
*
* @param User $user
*
* @return UserGroup
*/
private function createNewUserGroup(User $user): UserGroup
{
$loop = 0;
$groupName = $user->email;
$exists = true;
$existingGroup = null;
while ($exists && $loop < 10) {
$existingGroup = $this->findByName($groupName);
if (null === $existingGroup) {
$exists = false;
$existingGroup = $this->store(['user' => $user, 'title' => $groupName]);
}
if (null !== $existingGroup) {
// group already exists
$groupName = sprintf('%s-%s', $user->email, substr(sha1((string)(rand(1000, 9999) . microtime())), 0, 4));
}
$loop++;
}
return $existingGroup;
}
/**
* @param string $title
*
* @return UserGroup|null
*/
public function findByName(string $title): ?UserGroup
{
return UserGroup::whereTitle($title)->first();
}
/**
* @param array $data
*
* @return UserGroup
* @throws FireflyException
*/
public function store(array $data): UserGroup
{
$data['user'] = $this->user;
/** @var UserGroupFactory $factory */
$factory = app(UserGroupFactory::class);
return $factory->create($data);
}
/**
* Returns all groups.
*
* @inheritDoc
*/
public function getAll(): Collection
{
return UserGroup::all();
}
/**
* @inheritDoc
*/
public function setUser(Authenticatable | User | null $user): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
if (null !== $user) {
$this->user = $user;
}
}
/**
* @inheritDoc
*/
public function update(UserGroup $userGroup, array $data): UserGroup
{
$userGroup->title = $data['title'];
$userGroup->save();
return $userGroup;
}
/**
* @inheritDoc
* @throws FireflyException
*/
public function updateMembership(UserGroup $userGroup, array $data): UserGroup
{
$owner = UserRole::whereTitle(UserRoleEnum::OWNER)->first();
app('log')->debug('in update membership');
$user = null;
if (array_key_exists('id', $data)) {
$user = User::find($data['id']);
app('log')->debug('Found user by ID');
}
if (array_key_exists('email', $data) && '' !== (string)$data['email']) {
$user = User::whereEmail($data['email'])->first();
app('log')->debug('Found user by email');
}
if (null === $user) {
// should throw error, but validator already catches this.
app('log')->debug('No user found');
return $userGroup;
}
// count the number of members in the group right now:
$membershipCount = $userGroup->groupMemberships()->distinct()->get(['group_memberships.user_id'])->count();
// if it's 1:
if (1 === $membershipCount) {
$lastUserId = (int)$userGroup->groupMemberships()->distinct()->first(['group_memberships.user_id'])->user_id;
// if this is also the user we're editing right now, and we remove all of their roles:
if ($lastUserId === (int)$user->id && 0 === count($data['roles'])) {
app('log')->debug('User is last in this group, refuse to act');
throw new FireflyException('You cannot remove the last member from this user group. Delete the user group instead.');
}
// if this is also the user we're editing right now, and do not grant them the owner role:
if ($lastUserId === (int)$user->id && count($data['roles']) > 0 && !in_array(UserRoleEnum::OWNER->value, $data['roles'], true)) {
app('log')->debug('User needs to have owner role in this group, refuse to act');
throw new FireflyException('The last member in this user group must get or keep the "owner" role.');
}
}
if ($membershipCount > 1) {
// group has multiple members. How many are owner, except the user we're editing now?
$ownerCount = $userGroup->groupMemberships()
->where('user_role_id', $owner->id)
->where('user_id', '!=', $user->id)->count();
// if there are no other owners and the current users does not get or keep the owner role, refuse.
if (0 === $ownerCount && (0 === count($data['roles']) || (count($data['roles']) > 0 && !in_array(UserRoleEnum::OWNER->value, $data['roles'], true)))) {
app('log')->debug('User needs to keep owner role in this group, refuse to act');
throw new FireflyException('The last owner in this user group must keep the "owner" role.');
}
}
// simplify the list of roles:
$rolesSimplified = $this->simplifyListByName($data['roles']);
// delete all existing roles for user:
$user->groupMemberships()->where('user_group_id', $userGroup->id)->delete();
foreach ($rolesSimplified as $role) {
try {
$enum = UserRoleEnum::from($role);
} catch (ValueError $e) {
// TODO error message
continue;
}
$userRole = UserRole::whereTitle($enum->value)->first();
$user->groupMemberships()->create(['user_group_id' => $userGroup->id, 'user_role_id' => $userRole->id]);
}
return $userGroup;
}
/**
* @param array $roles
*
* @return array
*/
private function simplifyListByName(array $roles): array
{
if (in_array(UserRoleEnum::OWNER->value, $roles, true)) {
app('log')->debug(sprintf('List of roles is [%1$s] but this includes "%2$s", so return [%2$s]', join(',', $roles), UserRoleEnum::OWNER->value));
return [UserRoleEnum::OWNER->value];
}
if (in_array(UserRoleEnum::FULL->value, $roles, true)) {
app('log')->debug(sprintf('List of roles is [%1$s] but this includes "%2$s", so return [%2$s]', join(',', $roles), UserRoleEnum::FULL->value));
return [UserRoleEnum::FULL->value];
}
return $roles;
}
}

View File

@@ -0,0 +1,84 @@
<?php
/*
* UserGroupRepositoryInterface.php
* Copyright (c) 2023 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\UserGroup;
use FireflyIII\Models\UserGroup;
use FireflyIII\User;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Support\Collection;
/**
* Interface UserGroupRepositoryInterface
*/
interface UserGroupRepositoryInterface
{
/**
* @param UserGroup $userGroup
*
* @return void
*/
public function destroy(UserGroup $userGroup): void;
/**
* @return Collection
*/
public function get(): Collection;
/**
* @return Collection
*/
public function getAll(): Collection;
/**
* @param User|Authenticatable|null $user
*
* @return void
*/
public function setUser(User | Authenticatable | null $user): void;
/**
* @param array $data
*
* @return UserGroup
*/
public function store(array $data): UserGroup;
/**
* @param UserGroup $userGroup
* @param array $data
*
* @return UserGroup
*/
public function update(UserGroup $userGroup, array $data): UserGroup;
/**
* @param UserGroup $userGroup
* @param array $data
*
* @return UserGroup
*/
public function updateMembership(UserGroup $userGroup, array $data): UserGroup;
}

View File

@@ -23,22 +23,49 @@
declare(strict_types=1);
namespace FireflyIII\Repositories\Administration\Account;
namespace FireflyIII\Repositories\UserGroups\Account;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountMeta;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Support\Repositories\Administration\AdministrationTrait;
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
/**
* Class AccountRepository
*/
class AccountRepository implements AccountRepositoryInterface
{
use AdministrationTrait;
use UserGroupTrait;
/**
* @inheritDoc
*/
public function findByName(string $name, array $types): ?Account
{
$query = $this->userGroup->accounts();
if (0 !== count($types)) {
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
$query->whereIn('account_types.type', $types);
}
Log::debug(sprintf('Searching for account named "%s" (of user #%d) of the following type(s)', $name, $this->user->id), ['types' => $types]);
$query->where('accounts.name', $name);
/** @var Account $account */
$account = $query->first(['accounts.*']);
if (null === $account) {
Log::debug(sprintf('There is no account with name "%s" of types', $name), $types);
return null;
}
Log::debug(sprintf('Found #%d (%s) with type id %d', $account->id, $account->name, $account->account_type_id));
return $account;
}
/**
* @param Account $account

View File

@@ -23,7 +23,7 @@
declare(strict_types=1);
namespace FireflyIII\Repositories\Administration\Account;
namespace FireflyIII\Repositories\UserGroups\Account;
use FireflyIII\Models\Account;
use FireflyIII\Models\TransactionCurrency;
@@ -41,6 +41,14 @@ interface AccountRepositoryInterface
*/
public function find(int $accountId): ?Account;
/**
* @param string $name
* @param array $types
*
* @return Account|null
*/
public function findByName(string $name, array $types): ?Account;
/**
* @param Account $account
*
@@ -89,4 +97,5 @@ interface AccountRepositoryInterface
*/
public function searchAccount(string $query, array $types, int $limit): Collection;
}

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* BillRepository.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,7 +21,9 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Repositories\Administration\Bill;
declare(strict_types=1);
namespace FireflyIII\Repositories\UserGroups\Bill;
use Carbon\Carbon;
use FireflyIII\Models\Bill;
@@ -29,7 +31,7 @@ use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Support\CacheProperties;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Repositories\Administration\AdministrationTrait;
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
use Illuminate\Support\Collection;
/**
@@ -37,7 +39,7 @@ use Illuminate\Support\Collection;
*/
class BillRepository implements BillRepositoryInterface
{
use AdministrationTrait;
use UserGroupTrait;
/**
* Correct order of piggies in case of issues.

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* BillRepositoryInterface.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,7 +21,9 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Repositories\Administration\Bill;
declare(strict_types=1);
namespace FireflyIII\Repositories\UserGroups\Bill;
use Carbon\Carbon;
use FireflyIII\Models\Bill;

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* AvailableBudgetRepository.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,19 +21,21 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Repositories\Administration\Budget;
declare(strict_types=1);
namespace FireflyIII\Repositories\UserGroups\Budget;
use Carbon\Carbon;
use FireflyIII\Models\AvailableBudget;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Repositories\Administration\AdministrationTrait;
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
/**
* Class AvailableBudgetRepository
*/
class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface
{
use AdministrationTrait;
use UserGroupTrait;
/**
* @param Carbon $start

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* AvailableBudgetRepositoryInterface.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,7 +21,9 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Repositories\Administration\Budget;
declare(strict_types=1);
namespace FireflyIII\Repositories\UserGroups\Budget;
use Carbon\Carbon;

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* BudgetRepository.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,9 +21,11 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Repositories\Administration\Budget;
declare(strict_types=1);
use FireflyIII\Support\Repositories\Administration\AdministrationTrait;
namespace FireflyIII\Repositories\UserGroups\Budget;
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
use Illuminate\Support\Collection;
/**
@@ -31,7 +33,7 @@ use Illuminate\Support\Collection;
*/
class BudgetRepository implements BudgetRepositoryInterface
{
use AdministrationTrait;
use UserGroupTrait;
/**
* @inheritDoc

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* BudgetRepositoryInterface.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,7 +21,9 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Repositories\Administration\Budget;
declare(strict_types=1);
namespace FireflyIII\Repositories\UserGroups\Budget;
use Illuminate\Support\Collection;

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* OperationsRepository.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,13 +21,15 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Repositories\Administration\Budget;
declare(strict_types=1);
namespace FireflyIII\Repositories\UserGroups\Budget;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\TransactionType;
use FireflyIII\Support\Repositories\Administration\AdministrationTrait;
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
use Illuminate\Support\Collection;
/**
@@ -35,7 +37,7 @@ use Illuminate\Support\Collection;
*/
class OperationsRepository implements OperationsRepositoryInterface
{
use AdministrationTrait;
use UserGroupTrait;
/**
* @inheritDoc
@@ -130,6 +132,7 @@ class OperationsRepository implements OperationsRepositoryInterface
{
/** @var BudgetRepositoryInterface $repos */
$repos = app(BudgetRepositoryInterface::class);
throw new FireflyException('uses old administration ID check, needs to be updated.F');
$repos->setAdministrationId($this->getAdministrationId());
return $repos->getActiveBudgets();

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* OperationsRepositoryInterface.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,7 +21,9 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Repositories\Administration\Budget;
declare(strict_types=1);
namespace FireflyIII\Repositories\UserGroups\Budget;
use Carbon\Carbon;
use Illuminate\Support\Collection;
@@ -36,8 +38,8 @@ interface OperationsRepositoryInterface
* which have the specified budget set to them. It's grouped per currency, with as few details in the array
* as possible. Amounts are always negative.
*
* @param Carbon $start
* @param Carbon $end
* @param Carbon $start
* @param Carbon $end
* @param Collection|null $accounts
* @param Collection|null $budgets
*

View File

@@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
/*
* PiggyBankRepository.php
* Copyright (c) 2023 james@firefly-iii.org
@@ -21,9 +21,11 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Repositories\Administration\PiggyBank;
declare(strict_types=1);
use FireflyIII\Support\Repositories\Administration\AdministrationTrait;
namespace FireflyIII\Repositories\UserGroups\PiggyBank;
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
use Illuminate\Support\Collection;
/**
@@ -31,7 +33,7 @@ use Illuminate\Support\Collection;
*/
class PiggyBankRepository implements PiggyBankRepositoryInterface
{
use AdministrationTrait;
use UserGroupTrait;
/**
* @inheritDoc

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