diff --git a/app/Api/V2/Controllers/Autocomplete/AccountController.php b/app/Api/V2/Controllers/Autocomplete/AccountController.php deleted file mode 100644 index ce4483329b..0000000000 --- a/app/Api/V2/Controllers/Autocomplete/AccountController.php +++ /dev/null @@ -1,140 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Autocomplete; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Api\V2\Request\Autocomplete\AutocompleteRequest; -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Models\Account; -use FireflyIII\Models\AccountBalance; -use FireflyIII\Models\TransactionCurrency; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\Support\Http\Api\ExchangeRateConverter; -use Illuminate\Http\JsonResponse; -use Illuminate\Support\Facades\Log; - -/** - * Class AccountController - */ -class AccountController extends Controller -{ - private ExchangeRateConverter $converter; - private TransactionCurrency $default; - private AccountRepositoryInterface $repository; - - /** - * AccountController constructor. - */ - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $userGroup = $this->validateUserGroup($request); - $this->repository = app(AccountRepositoryInterface::class); - $this->repository->setUserGroup($userGroup); - $this->default = app('amount')->getPrimaryCurrency(); - $this->converter = app(ExchangeRateConverter::class); - - return $next($request); - } - ); - } - - /** - * Documentation: https://api-docs.firefly-iii.org/?urls.primaryName=2.1.0%20(v2)#/autocomplete/getAccountsAC - */ - public function accounts(AutocompleteRequest $request): JsonResponse - { - $params = $request->getParameters(); - $result = $this->repository->searchAccount($params['query'], $params['account_types'], $params['size']); - $return = []; - - /** @var Account $account */ - foreach ($result as $account) { - $return[] = $this->parseAccount($account); - } - - return response()->json($return); - } - - private function parseAccount(Account $account): array - { - $currency = $this->repository->getAccountCurrency($account); - - return [ - 'id' => (string) $account->id, - 'title' => $account->name, - 'meta' => [ - 'type' => $account->accountType->type, - // TODO is multi currency property. - 'currency_id' => $currency instanceof TransactionCurrency ? (string) $currency->id : null, - 'currency_code' => $currency?->code, - 'currency_symbol' => $currency?->symbol, - 'currency_decimal_places' => $currency?->decimal_places, - 'account_balances' => $this->getAccountBalances($account), - ], - ]; - } - - private function getAccountBalances(Account $account): array - { - $return = []; - $balances = $this->repository->getAccountBalances($account); - - /** @var AccountBalance $balance */ - foreach ($balances as $balance) { - try { - $return[] = $this->parseAccountBalance($balance); - } catch (FireflyException $e) { - Log::error(sprintf('Could not parse convert account balance: %s', $e->getMessage())); - } - } - - return $return; - } - - /** - * @throws FireflyException - */ - private function parseAccountBalance(AccountBalance $balance): array - { - $currency = $balance->transactionCurrency; - - return [ - 'title' => $balance->title, - 'native_amount' => $this->converter->convert($currency, $this->default, today(), $balance->balance), - 'amount' => app('steam')->bcround($balance->balance, $currency->decimal_places), - 'currency_id' => (string) $currency->id, - 'currency_code' => $currency->code, - 'currency_symbol' => $currency->symbol, - 'currency_decimal_places' => $currency->decimal_places, - 'native_currency_id' => (string) $this->default->id, - 'native_currency_code' => $this->default->code, - 'native_currency_symbol' => $this->default->symbol, - 'native_currency_decimal_places' => $this->default->decimal_places, - ]; - } -} diff --git a/app/Api/V2/Controllers/Autocomplete/CategoryController.php b/app/Api/V2/Controllers/Autocomplete/CategoryController.php deleted file mode 100644 index ea3635be5f..0000000000 --- a/app/Api/V2/Controllers/Autocomplete/CategoryController.php +++ /dev/null @@ -1,73 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Autocomplete; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Api\V2\Request\Autocomplete\AutocompleteRequest; -use FireflyIII\Models\Category; -use FireflyIII\Repositories\Category\CategoryRepositoryInterface; -use Illuminate\Http\JsonResponse; - -/** - * Class CategoryController - */ -class CategoryController extends Controller -{ - private CategoryRepositoryInterface $repository; - - /** - * AccountController constructor. - */ - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(CategoryRepositoryInterface::class); - $this->repository->setUserGroup($this->validateUserGroup($request)); - - return $next($request); - } - ); - } - - /** - * Documentation: https://api-docs.firefly-iii.org/?urls.primaryName=2.1.0%20(v2)#/autocomplete/getCategoriesAC - */ - public function categories(AutocompleteRequest $request): JsonResponse - { - $queryParameters = $request->getParameters(); - $result = $this->repository->searchCategory($queryParameters['query'], $queryParameters['size']); - $filtered = $result->map( - static fn (Category $item) => [ - 'id' => (string) $item->id, - 'title' => $item->name, - 'meta' => [], - ] - ); - - return response()->json($filtered); - } -} diff --git a/app/Api/V2/Controllers/Autocomplete/TagController.php b/app/Api/V2/Controllers/Autocomplete/TagController.php deleted file mode 100644 index 92a620bcdd..0000000000 --- a/app/Api/V2/Controllers/Autocomplete/TagController.php +++ /dev/null @@ -1,75 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Autocomplete; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Api\V2\Request\Autocomplete\AutocompleteRequest; -use FireflyIII\Models\Tag; -use FireflyIII\Repositories\Tag\TagRepositoryInterface; -use Illuminate\Http\JsonResponse; - -/** - * Class TagController - */ -class TagController extends Controller -{ - private TagRepositoryInterface $repository; - - /** - * AccountController constructor. - */ - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(TagRepositoryInterface::class); - $this->repository->setUserGroup($this->validateUserGroup($request)); - - return $next($request); - } - ); - } - - /** - * Documentation: https://api-docs.firefly-iii.org/?urls.primaryName=2.1.0%20(v2)#/autocomplete/getTagsAC - */ - public function tags(AutocompleteRequest $request): JsonResponse - { - $queryParameters = $request->getParameters(); - $result = $this->repository->searchTag($queryParameters['query']); - $filtered = $result->map( - static fn (Tag $item) => [ - 'id' => (string) $item->id, - 'title' => $item->tag, - 'value' => (string) $item->id, - 'label' => $item->tag, - 'meta' => [], - ] - ); - - return response()->json($filtered); - } -} diff --git a/app/Api/V2/Controllers/Autocomplete/TransactionController.php b/app/Api/V2/Controllers/Autocomplete/TransactionController.php deleted file mode 100644 index 3ff8780201..0000000000 --- a/app/Api/V2/Controllers/Autocomplete/TransactionController.php +++ /dev/null @@ -1,81 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Autocomplete; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Api\V2\Request\Autocomplete\AutocompleteRequest; -use FireflyIII\Models\TransactionJournal; -use FireflyIII\Repositories\Journal\JournalRepositoryInterface; -use Illuminate\Http\JsonResponse; - -/** - * Class TransactionController - */ -class TransactionController extends Controller -{ - private JournalRepositoryInterface $repository; - - /** - * AccountController constructor. - */ - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(JournalRepositoryInterface::class); - $this->repository->setUserGroup($this->validateUserGroup($request)); - - return $next($request); - } - ); - } - - /** - * Documentation: https://api-docs.firefly-iii.org/?urls.primaryName=2.1.0%20(v2)#/autocomplete/getTransactionsAC - */ - public function transactionDescriptions(AutocompleteRequest $request): JsonResponse - { - $queryParameters = $request->getParameters(); - $result = $this->repository->searchJournalDescriptions($queryParameters['query'], $queryParameters['size']); - - // limit and unique - $filtered = $result->unique('description'); - $array = []; - - /** @var TransactionJournal $journal */ - foreach ($filtered as $journal) { - $array[] = [ - 'id' => (string) $journal->id, - 'title' => $journal->description, - 'meta' => [ - 'transaction_group_id' => (string) $journal->transaction_group_id, - ], - ]; - } - - return response()->json($array); - } -} diff --git a/app/Api/V2/Controllers/Chart/AccountController.php b/app/Api/V2/Controllers/Chart/AccountController.php deleted file mode 100644 index 9765ae30c5..0000000000 --- a/app/Api/V2/Controllers/Chart/AccountController.php +++ /dev/null @@ -1,140 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Chart; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Api\V2\Request\Chart\ChartRequest; -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Models\Account; -use FireflyIII\Models\TransactionCurrency; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\Support\Chart\ChartData; -use FireflyIII\Support\Facades\Steam; -use FireflyIII\Support\Http\Api\CleansChartData; -use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter; -use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; -use Illuminate\Http\JsonResponse; - -/** - * Class AccountController - */ -class AccountController extends Controller -{ - use CleansChartData; - use CollectsAccountsFromFilter; - use ValidatesUserGroupTrait; - - private ChartData $chartData; - private TransactionCurrency $default; - private AccountRepositoryInterface $repository; - - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(AccountRepositoryInterface::class); - $this->repository->setUserGroup($this->validateUserGroup($request)); - $this->chartData = new ChartData(); - $this->default = app('amount')->getPrimaryCurrency(); - - return $next($request); - } - ); - } - - /** - * TODO fix documentation - * - * @throws FireflyException - */ - public function dashboard(ChartRequest $request): JsonResponse - { - $queryParameters = $request->getParameters(); - $accounts = $this->getAccountList($queryParameters); - - // move date to end of day - $queryParameters['start']->startOfDay(); - $queryParameters['end']->endOfDay(); - - // loop each account, and collect info: - /** @var Account $account */ - foreach ($accounts as $account) { - $this->renderAccountData($queryParameters, $account); - } - - return response()->json($this->chartData->render()); - } - - /** - * @throws FireflyException - */ - private function renderAccountData(array $params, Account $account): void - { - $currency = $this->repository->getAccountCurrency($account); - if (!$currency instanceof TransactionCurrency) { - $currency = $this->default; - } - $currentSet = [ - 'label' => $account->name, - - // the currency that belongs to the account. - 'currency_id' => (string) $currency->id, - 'currency_code' => $currency->code, - 'currency_symbol' => $currency->symbol, - 'currency_decimal_places' => $currency->decimal_places, - - // the default currency of the user (could be the same!) - 'native_currency_id' => (string) $this->default->id, - 'native_currency_code' => $this->default->code, - 'native_currency_symbol' => $this->default->symbol, - 'native_currency_decimal_places' => $this->default->decimal_places, - 'date' => $params['start']->toAtomString(), - 'start' => $params['start']->toAtomString(), - 'end' => $params['end']->toAtomString(), - 'period' => '1D', - 'entries' => [], - 'native_entries' => [], - ]; - $currentStart = clone $params['start']; - $range = Steam::finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToNative); - - $previous = array_values($range)[0]['balance']; - $previousNative = array_values($range)[0]['native_balance']; - while ($currentStart <= $params['end']) { - $format = $currentStart->format('Y-m-d'); - $label = $currentStart->toAtomString(); - $balance = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous; - $balanceNative = array_key_exists($format, $range) ? $range[$format]['balance_native'] : $previousNative; - $previous = $balance; - $previousNative = $balanceNative; - - $currentStart->addDay(); - $currentSet['entries'][$label] = $balance; - $currentSet['native_entries'][$label] = $balanceNative; - } - $this->chartData->add($currentSet); - } -} diff --git a/app/Api/V2/Controllers/Chart/BalanceController.php b/app/Api/V2/Controllers/Chart/BalanceController.php deleted file mode 100644 index 32d489e88c..0000000000 --- a/app/Api/V2/Controllers/Chart/BalanceController.php +++ /dev/null @@ -1,116 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Chart; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Api\V2\Request\Chart\ChartRequest; -use FireflyIII\Enums\TransactionTypeEnum; -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Helpers\Collector\GroupCollectorInterface; -use FireflyIII\Models\TransactionCurrency; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\Support\Chart\ChartData; -use FireflyIII\Support\Http\Api\AccountBalanceGrouped; -use FireflyIII\Support\Http\Api\CleansChartData; -use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter; -use Illuminate\Http\JsonResponse; - -/** - * Class BalanceController - */ -class BalanceController extends Controller -{ - use CleansChartData; - use CollectsAccountsFromFilter; - - private ChartData $chartData; - private GroupCollectorInterface $collector; - private AccountRepositoryInterface $repository; - - // private TransactionCurrency $default; - - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(AccountRepositoryInterface::class); - $this->collector = app(GroupCollectorInterface::class); - $userGroup = $this->validateUserGroup($request); - $this->repository->setUserGroup($userGroup); - $this->collector->setUserGroup($userGroup); - $this->chartData = new ChartData(); - // $this->default = app('amount')->getPrimaryCurrency(); - - return $next($request); - } - ); - } - - /** - * The code is practically a duplicate of ReportController::operations. - * - * Currency is up to the account/transactions in question, but conversion to the default - * currency is possible. - * - * 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. - * - * @throws FireflyException - */ - public function balance(ChartRequest $request): JsonResponse - { - $queryParameters = $request->getParameters(); - $accounts = $this->getAccountList($queryParameters); - - // prepare for currency conversion and data collection: - /** @var TransactionCurrency $default */ - $default = app('amount')->getPrimaryCurrency(); - - // get journals for entire period: - - $this->collector->setRange($queryParameters['start'], $queryParameters['end']) - ->withAccountInformation() - ->setXorAccounts($accounts) - ->setTypes([TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::DEPOSIT->value, TransactionTypeEnum::RECONCILIATION->value, TransactionTypeEnum::TRANSFER->value]) - ; - $journals = $this->collector->getExtractedJournals(); - - $object = new AccountBalanceGrouped(); - $object->setPreferredRange($queryParameters['period']); - $object->setDefault($default); - $object->setAccounts($accounts); - $object->setJournals($journals); - $object->setStart($queryParameters['start']); - $object->setEnd($queryParameters['end']); - $object->groupByCurrencyAndPeriod(); - $data = $object->convertToChartData(); - foreach ($data as $entry) { - $this->chartData->add($entry); - } - - return response()->json($this->chartData->render()); - } -} diff --git a/app/Api/V2/Controllers/Chart/BudgetController.php b/app/Api/V2/Controllers/Chart/BudgetController.php deleted file mode 100644 index 148524157f..0000000000 --- a/app/Api/V2/Controllers/Chart/BudgetController.php +++ /dev/null @@ -1,293 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Chart; - -use Carbon\Carbon; -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Api\V2\Request\Generic\DateRequest; -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Models\Budget; -use FireflyIII\Models\BudgetLimit; -use FireflyIII\Models\TransactionCurrency; -use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; -use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; -use FireflyIII\Repositories\Budget\OperationsRepositoryInterface; -use FireflyIII\Support\Http\Api\CleansChartData; -use FireflyIII\Support\Http\Api\ExchangeRateConverter; -use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; -use Illuminate\Http\JsonResponse; -use Illuminate\Support\Collection; -use Illuminate\Support\Facades\Log; - -/** - * Class BudgetController - */ -class BudgetController extends Controller -{ - use CleansChartData; - use ValidatesUserGroupTrait; - - protected OperationsRepositoryInterface $opsRepository; - private BudgetLimitRepositoryInterface $blRepository; - private array $currencies = []; - private TransactionCurrency $currency; - private BudgetRepositoryInterface $repository; - - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(BudgetRepositoryInterface::class); - $this->blRepository = app(BudgetLimitRepositoryInterface::class); - $this->opsRepository = app(OperationsRepositoryInterface::class); - $this->currency = app('amount')->getPrimaryCurrency(); - $userGroup = $this->validateUserGroup($request); - $this->repository->setUserGroup($userGroup); - $this->opsRepository->setUserGroup($userGroup); - - return $next($request); - } - ); - } - - /** - * TODO see autocomplete/accountcontroller - */ - public function dashboard(DateRequest $request): JsonResponse - { - $params = $request->getAll(); - - /** @var Carbon $start */ - $start = $params['start']; - - /** @var Carbon $end */ - $end = $params['end']; - - // code from FrontpageChartGenerator, but not in separate class - $budgets = $this->repository->getActiveBudgets(); - $data = []; - - /** @var Budget $budget */ - foreach ($budgets as $budget) { - // could return multiple arrays, so merge. - $data = array_merge($data, $this->processBudget($budget, $start, $end)); - } - - return response()->json($this->clean($data)); - } - - /** - * @throws FireflyException - */ - private function processBudget(Budget $budget, Carbon $start, Carbon $end): array - { - // get all limits: - $limits = $this->blRepository->getBudgetLimits($budget, $start, $end); - $rows = []; - - // if no limits - if (0 === $limits->count()) { - // return as a single item in an array - $rows = $this->noBudgetLimits($budget, $start, $end); - } - if ($limits->count() > 0) { - $rows = $this->budgetLimits($budget, $limits); - } - // is always an array - $return = []; - foreach ($rows as $row) { - $current = [ - 'label' => $budget->name, - 'currency_id' => (string) $row['currency_id'], - 'currency_code' => $row['currency_code'], - 'currency_name' => $row['currency_name'], - 'currency_decimal_places' => $row['currency_decimal_places'], - 'native_currency_id' => (string) $row['native_currency_id'], - 'native_currency_code' => $row['native_currency_code'], - 'native_currency_name' => $row['native_currency_name'], - 'native_currency_decimal_places' => $row['native_currency_decimal_places'], - 'period' => null, - 'start' => $row['start'], - 'end' => $row['end'], - 'entries' => [ - 'spent' => $row['spent'], - 'left' => $row['left'], - 'overspent' => $row['overspent'], - ], - 'native_entries' => [ - 'spent' => $row['native_spent'], - 'left' => $row['native_left'], - 'overspent' => $row['native_overspent'], - ], - ]; - $return[] = $current; - } - - return $return; - } - - /** - * When no budget limits are present, the expenses of the whole period are collected and grouped. - * This is grouped per currency. Because there is no limit set, "left to spend" and "overspent" are empty. - * - * @throws FireflyException - */ - private function noBudgetLimits(Budget $budget, Carbon $start, Carbon $end): array - { - $spent = $this->opsRepository->listExpenses($start, $end, null, new Collection([$budget])); - - return $this->processExpenses($budget->id, $spent, $start, $end); - } - - /** - * Shared between the "noBudgetLimits" function and "processLimit". Will take a single set of expenses and return - * its info. - * - * @param array> $array - * - * @throws FireflyException - */ - private function processExpenses(int $budgetId, array $array, Carbon $start, Carbon $end): array - { - Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__)); - $converter = new ExchangeRateConverter(); - $return = []; - - /** - * This array contains the expenses in this budget. Grouped per currency. - * The grouping is on the main currency only. - * - * @var int $currencyId - * @var array $block - */ - foreach ($array as $currencyId => $block) { - $this->currencies[$currencyId] ??= TransactionCurrency::find($currencyId); - $return[$currencyId] ??= [ - 'currency_id' => (string) $currencyId, - 'currency_code' => $block['currency_code'], - 'currency_name' => $block['currency_name'], - 'currency_symbol' => $block['currency_symbol'], - 'currency_decimal_places' => (int) $block['currency_decimal_places'], - 'native_currency_id' => (string) $this->currency->id, - 'native_currency_code' => $this->currency->code, - 'native_currency_name' => $this->currency->name, - 'native_currency_symbol' => $this->currency->symbol, - 'native_currency_decimal_places' => $this->currency->decimal_places, - 'start' => $start->toAtomString(), - 'end' => $end->toAtomString(), - 'spent' => '0', - 'native_spent' => '0', - 'left' => '0', - 'native_left' => '0', - 'overspent' => '0', - 'native_overspent' => '0', - ]; - $currentBudgetArray = $block['budgets'][$budgetId]; - - // var_dump($return); - /** @var array $journal */ - foreach ($currentBudgetArray['transaction_journals'] as $journal) { - // convert the amount to the native currency. - $rate = $converter->getCurrencyRate($this->currencies[$currencyId], $this->currency, $journal['date']); - $convertedAmount = bcmul((string) $journal['amount'], $rate); - if ($journal['foreign_currency_id'] === $this->currency->id) { - $convertedAmount = $journal['foreign_amount']; - } - - $return[$currencyId]['spent'] = bcadd($return[$currencyId]['spent'], (string) $journal['amount']); - $return[$currencyId]['native_spent'] = bcadd($return[$currencyId]['native_spent'], (string) $convertedAmount); - } - } - $converter->summarize(); - - return $return; - } - - /** - * Function that processes each budget limit (per budget). - * - * If you have a budget limit in EUR, only transactions in EUR will be considered. - * If you have a budget limit in GBP, only transactions in GBP will be considered. - * - * If you have a budget limit in EUR, and a transaction in GBP, it will not be considered for the EUR budget limit. - * - * @throws FireflyException - */ - private function budgetLimits(Budget $budget, Collection $limits): array - { - app('log')->debug(sprintf('Now in budgetLimits(#%d)', $budget->id)); - $data = []; - - /** @var BudgetLimit $limit */ - foreach ($limits as $limit) { - $data = array_merge($data, $this->processLimit($budget, $limit)); - } - - return $data; - } - - /** - * @throws FireflyException - */ - private function processLimit(Budget $budget, BudgetLimit $limit): array - { - Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__)); - $end = clone $limit->end_date; - $end->endOfDay(); - $spent = $this->opsRepository->listExpenses($limit->start_date, $end, null, new Collection([$budget])); - $limitCurrencyId = $limit->transaction_currency_id; - $limitCurrency = $limit->transactionCurrency; - $converter = new ExchangeRateConverter(); - $filtered = []; - $rate = $converter->getCurrencyRate($limitCurrency, $this->currency, $limit->start_date); - $convertedLimitAmount = bcmul($limit->amount, $rate); - - /** @var array $entry */ - foreach ($spent as $currencyId => $entry) { - // only spent the entry where the entry's currency matches the budget limit's currency - // so $filtered will only have 1 or 0 entries - if ($entry['currency_id'] === $limitCurrencyId) { - $filtered[$currencyId] = $entry; - } - } - $result = $this->processExpenses($budget->id, $filtered, $limit->start_date, $end); - if (1 === count($result)) { - $compare = bccomp($limit->amount, (string) app('steam')->positive($result[$limitCurrencyId]['spent'])); - if (1 === $compare) { - // convert this amount into the native currency: - $result[$limitCurrencyId]['left'] = bcadd($limit->amount, (string) $result[$limitCurrencyId]['spent']); - $result[$limitCurrencyId]['native_left'] = bcadd($convertedLimitAmount, (string) $result[$limitCurrencyId]['native_spent']); - } - if ($compare <= 0) { - $result[$limitCurrencyId]['overspent'] = app('steam')->positive(bcadd($limit->amount, (string) $result[$limitCurrencyId]['spent'])); - $result[$limitCurrencyId]['native_overspent'] = app('steam')->positive(bcadd($convertedLimitAmount, (string) $result[$limitCurrencyId]['native_spent'])); - } - } - $converter->summarize(); - - return $result; - } -} diff --git a/app/Api/V2/Controllers/Chart/CategoryController.php b/app/Api/V2/Controllers/Chart/CategoryController.php deleted file mode 100644 index 9a1372935b..0000000000 --- a/app/Api/V2/Controllers/Chart/CategoryController.php +++ /dev/null @@ -1,142 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Chart; - -use Carbon\Carbon; -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Api\V2\Request\Generic\DateRequest; -use FireflyIII\Enums\AccountTypeEnum; -use FireflyIII\Enums\TransactionTypeEnum; -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Helpers\Collector\GroupCollectorInterface; -use FireflyIII\Repositories\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; -use Illuminate\Support\Facades\Log; - -/** - * Class BudgetController - */ -class CategoryController extends Controller -{ - use CleansChartData; - use ValidatesUserGroupTrait; - - private AccountRepositoryInterface $accountRepos; - private CurrencyRepositoryInterface $currencyRepos; - - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->accountRepos = app(AccountRepositoryInterface::class); - $this->currencyRepos = app(CurrencyRepositoryInterface::class); - $this->accountRepos->setUserGroup($this->validateUserGroup($request)); - - return $next($request); - } - ); - } - - /** - * TODO may be worth to move to a handler but the data is simple enough. - * TODO see autoComplete/account controller - * - * @throws FireflyException - * - * @SuppressWarnings("PHPMD.UnusedFormalParameter") - */ - public function dashboard(DateRequest $request): JsonResponse - { - Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__)); - - /** @var Carbon $start */ - $start = $this->parameters->get('start'); - - /** @var Carbon $end */ - $end = $this->parameters->get('end'); - $accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value]); - $default = app('amount')->getPrimaryCurrency(); - $converter = new ExchangeRateConverter(); - $currencies = []; - $return = []; - - // get journals for entire period: - /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); - $collector->setRange($start, $end)->withAccountInformation(); - $collector->setXorAccounts($accounts)->withCategoryInformation(); - $collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::RECONCILIATION->value]); - $journals = $collector->getExtractedJournals(); - - /** @var array $journal */ - foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; - $currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId); - $currencies[$currencyId] = $currency; - $categoryName = $journal['category_name'] ?? (string) trans('firefly.no_category'); - $amount = app('steam')->positive($journal['amount']); - $nativeAmount = $converter->convert($default, $currency, $journal['date'], $amount); - $key = sprintf('%s-%s', $categoryName, $currency->code); - if ((int) $journal['foreign_currency_id'] === $default->id) { - $nativeAmount = app('steam')->positive($journal['foreign_amount']); - } - // create arrays - $return[$key] ??= [ - 'label' => $categoryName, - 'currency_id' => (string) $currency->id, - 'currency_code' => $currency->code, - 'currency_name' => $currency->name, - 'currency_symbol' => $currency->symbol, - 'currency_decimal_places' => $currency->decimal_places, - 'native_currency_id' => (string) $default->id, - 'native_currency_code' => $default->code, - 'native_currency_name' => $default->name, - 'native_currency_symbol' => $default->symbol, - 'native_currency_decimal_places' => $default->decimal_places, - 'period' => null, - 'start' => $start->toAtomString(), - 'end' => $end->toAtomString(), - 'amount' => '0', - 'native_amount' => '0', - ]; - - // add monies - $return[$key]['amount'] = bcadd($return[$key]['amount'], (string) $amount); - $return[$key]['native_amount'] = bcadd($return[$key]['native_amount'], (string) $nativeAmount); - } - $return = array_values($return); - - // order by native amount - usort($return, static fn (array $a, array $b) => (float) $a['native_amount'] < (float) $b['native_amount'] ? 1 : -1); - $converter->summarize(); - - return response()->json($this->clean($return)); - } -} diff --git a/app/Api/V2/Controllers/Controller.php b/app/Api/V2/Controllers/Controller.php deleted file mode 100644 index 6117197914..0000000000 --- a/app/Api/V2/Controllers/Controller.php +++ /dev/null @@ -1,195 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers; - -use Carbon\Carbon; -use Carbon\Exceptions\InvalidDateException; -use Carbon\Exceptions\InvalidFormatException; -use FireflyIII\Enums\UserRoleEnum; -use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; -use FireflyIII\Transformers\AbstractTransformer; -use Illuminate\Database\Eloquent\Model; -use Illuminate\Pagination\LengthAwarePaginator; -use Illuminate\Routing\Controller as BaseController; -use League\Fractal\Manager; -use League\Fractal\Pagination\IlluminatePaginatorAdapter; -use League\Fractal\Resource\Collection as FractalCollection; -use League\Fractal\Resource\Item; -use League\Fractal\Serializer\JsonApiSerializer; -use Psr\Container\ContainerExceptionInterface; -use Symfony\Component\HttpFoundation\Exception\BadRequestException; -use Symfony\Component\HttpFoundation\ParameterBag; - -/** - * Class Controller - * - * @SuppressWarnings("PHPMD.CouplingBetweenObjects") - * @SuppressWarnings("PHPMD.NumberOfChildren") - */ -class Controller extends BaseController -{ - use ValidatesUserGroupTrait; - - protected const string CONTENT_TYPE = 'application/vnd.api+json'; - protected array $acceptedRoles = [UserRoleEnum::READ_ONLY]; - protected bool $convertToNative = false; - protected ParameterBag $parameters; - - public function __construct() - { - $this->middleware( - function ($request, $next) { - $this->parameters = $this->getParameters(); - - return $next($request); - } - ); - } - - /** - * TODO duplicate from V1 controller - * Method to grab all parameters from the URL. - * - * @SuppressWarnings("PHPMD.NPathComplexity") - */ - private function getParameters(): ParameterBag - { - $bag = new ParameterBag(); - $bag->set('limit', 50); - - try { - $page = (int) request()->get('page'); - } catch (ContainerExceptionInterface) { - $page = 1; - } - - $integers = ['limit', 'administration']; - $dates = ['start', 'end', 'date']; - - if ($page < 1) { - $page = 1; - } - if ($page > 2 ** 16) { - $page = 2 ** 16; - } - $bag->set('page', $page); - - // some date fields: - foreach ($dates as $field) { - $date = null; - $obj = null; - - try { - $date = request()->query->get($field); - } catch (BadRequestException $e) { - app('log')->error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $field)); - app('log')->error($e->getMessage()); - app('log')->error($e->getTraceAsString()); - } - if (null !== $date) { - try { - $obj = Carbon::parse((string) $date, config('app.timezone')); - } catch (InvalidDateException|InvalidFormatException $e) { - // don't care - app('log')->warning(sprintf('Ignored invalid date "%s" in API v2 controller parameter check: %s', substr((string) $date, 0, 20), $e->getMessage())); - } - // out of range? set to null. - if ($obj instanceof Carbon && ($obj->year <= 1970 || $obj->year > 2038)) { - app('log')->warning(sprintf('Refuse to use date "%s" in API v2 controller parameter check: %s', $field, $obj->toAtomString())); - $obj = null; - } - } - if (null !== $date && 'end' === $field) { - $obj->endOfDay(); - } - $bag->set($field, $obj); - } - - // integer fields: - foreach ($integers as $integer) { - try { - $value = request()->query->get($integer); - } catch (BadRequestException $e) { - app('log')->error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $integer)); - app('log')->error($e->getMessage()); - $value = null; - } - if (null !== $value) { - $bag->set($integer, (int) $value); - } - if (null === $value && 'limit' === $integer && auth()->check()) { - // set default for user: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; - $bag->set($integer, $pageSize); - } - } - - // sort fields: - // return $this->getSortParameters($bag); - - return $bag; - } - - final protected function jsonApiList(string $key, LengthAwarePaginator $paginator, AbstractTransformer $transformer): array - { - $manager = new Manager(); - $baseUrl = request()->getSchemeAndHttpHost().'/api/v2'; - - // TODO add stuff to path? - - $manager->setSerializer(new JsonApiSerializer($baseUrl)); - - $objects = $paginator->getCollection(); - - // the transformer, at this point, needs to collect information that ALL items in the collection - // require, like meta-data and stuff like that, and save it for later. - // $objects = $transformer->collectMetaData($objects); - $paginator->setCollection($objects); - - $resource = new FractalCollection($objects, $transformer, $key); - $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); - - return $manager->createData($resource)->toArray(); - } - - /** - * Returns a JSON API object and returns it. - * - * @param array|Model $object - */ - final protected function jsonApiObject(string $key, array|Model $object, AbstractTransformer $transformer): array - { - // create some objects: - $manager = new Manager(); - $baseUrl = request()->getSchemeAndHttpHost().'/api/v2'; - $manager->setSerializer(new JsonApiSerializer($baseUrl)); - - // $transformer->collectMetaData(new Collection([$object])); - - $resource = new Item($object, $transformer, $key); - - return $manager->createData($resource)->toArray(); - } -} diff --git a/app/Api/V2/Controllers/Data/Bulk/AccountController.php b/app/Api/V2/Controllers/Data/Bulk/AccountController.php deleted file mode 100644 index 3dbfd0343d..0000000000 --- a/app/Api/V2/Controllers/Data/Bulk/AccountController.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Data\Bulk; - -use FireflyIII\Api\V2\Controllers\Controller; - -/** - * Class AccountController - */ -class AccountController extends Controller {} diff --git a/app/Api/V2/Controllers/Data/Export/AccountController.php b/app/Api/V2/Controllers/Data/Export/AccountController.php deleted file mode 100644 index 4526f0f399..0000000000 --- a/app/Api/V2/Controllers/Data/Export/AccountController.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Data\Export; - -use FireflyIII\Api\V2\Controllers\Controller; - -/** - * Class AccountController - */ -class AccountController extends Controller {} diff --git a/app/Api/V2/Controllers/Data/MassDestroy/AccountController.php b/app/Api/V2/Controllers/Data/MassDestroy/AccountController.php deleted file mode 100644 index 6d11f3473e..0000000000 --- a/app/Api/V2/Controllers/Data/MassDestroy/AccountController.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Data\MassDestroy; - -use FireflyIII\Api\V2\Controllers\Controller; - -/** - * Class AccountController - */ -class AccountController extends Controller {} diff --git a/app/Api/V2/Controllers/Model/Account/IndexController.php b/app/Api/V2/Controllers/Model/Account/IndexController.php deleted file mode 100644 index a2960e6673..0000000000 --- a/app/Api/V2/Controllers/Model/Account/IndexController.php +++ /dev/null @@ -1,97 +0,0 @@ -middleware( - function ($request, $next) { - $this->repository = app(AccountRepositoryInterface::class); - // new way of user group validation - $userGroup = $this->validateUserGroup($request); - $this->repository->setUserGroup($userGroup); - - return $next($request); - } - ); - } - - /** - * TODO the sort instructions need proper repeatable documentation. - * TODO see autocomplete/account controller for list. - */ - public function index(IndexRequest $request): JsonResponse - { - $this->repository->resetAccountOrder(); - $types = $request->getAccountTypes(); - $sorting = $request->getSortInstructions('accounts'); - $filters = $request->getFilterInstructions('accounts'); - $accounts = $this->repository->getAccountsByType($types, $sorting); - $pageSize = $this->parameters->get('limit'); - $count = $accounts->count(); - - // depending on the sort parameters, this list must not be split, because the - // order is calculated in the account transformer and by that time it's too late. - $first = array_key_first($sorting); - $disablePagination = in_array($first, ['last_activity', 'balance', 'balance_difference'], true); - Log::debug(sprintf('Will disable pagination in account index v2? %s', var_export($disablePagination, true))); - if (!$disablePagination) { - $accounts = $accounts->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); - } - $paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page')); - $transformer = new AccountTransformer(); - - $this->parameters->set('disablePagination', $disablePagination); - $this->parameters->set('pageSize', $pageSize); - $this->parameters->set('sort', $sorting); - - $this->parameters->set('filters', $filters); - $transformer->setParameters($this->parameters); // give params to transformer - - return response() - ->json($this->jsonApiList('accounts', $paginator, $transformer)) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } -} diff --git a/app/Api/V2/Controllers/Model/Account/ShowController.php b/app/Api/V2/Controllers/Model/Account/ShowController.php deleted file mode 100644 index 13d1f0cd8e..0000000000 --- a/app/Api/V2/Controllers/Model/Account/ShowController.php +++ /dev/null @@ -1,76 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Model\Account; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Enums\UserRoleEnum; -use FireflyIII\Models\Account; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\Transformers\AccountTransformer; -use Illuminate\Http\JsonResponse; - -/** - * Show = show a single account. - * Index = show all accounts - * Class ShowController - */ -class ShowController extends Controller -{ - public const string RESOURCE_KEY = 'accounts'; - protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS]; - private AccountRepositoryInterface $repository; - - /** - * AccountController constructor. - */ - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(AccountRepositoryInterface::class); - // new way of user group validation - $userGroup = $this->validateUserGroup($request); - $this->repository->setUserGroup($userGroup); - - return $next($request); - } - ); - } - - /** - * TODO this endpoint is not yet reachable. - */ - public function show(Account $account): JsonResponse - { - $transformer = new AccountTransformer(); - $transformer->setParameters($this->parameters); - - return response() - ->api($this->jsonApiObject('accounts', $account, $transformer)) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } -} diff --git a/app/Api/V2/Controllers/Model/Account/UpdateController.php b/app/Api/V2/Controllers/Model/Account/UpdateController.php deleted file mode 100644 index 49c0f8d5b9..0000000000 --- a/app/Api/V2/Controllers/Model/Account/UpdateController.php +++ /dev/null @@ -1,76 +0,0 @@ -middleware( - function ($request, $next) { - $this->repository = app(AccountRepositoryInterface::class); - $this->repository->setUserGroup($this->validateUserGroup($request)); - - return $next($request); - } - ); - } - - /** - * TODO this endpoint is not yet reachable. - */ - public function update(UpdateRequest $request, Account $account): JsonResponse - { - app('log')->debug(sprintf('Now in %s', __METHOD__)); - $data = $request->getUpdateData(); - $data['type'] = config('firefly.shortNamesByFullName.'.$account->accountType->type); - $account = $this->repository->update($account, $data); - $account->refresh(); - app('preferences')->mark(); - - $transformer = new AccountTransformer(); - $transformer->setParameters($this->parameters); - - return response() - ->api($this->jsonApiObject('accounts', $account, $transformer)) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } -} diff --git a/app/Api/V2/Controllers/Model/Bill/IndexController.php b/app/Api/V2/Controllers/Model/Bill/IndexController.php deleted file mode 100644 index bf09a6360b..0000000000 --- a/app/Api/V2/Controllers/Model/Bill/IndexController.php +++ /dev/null @@ -1,75 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Model\Bill; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Repositories\Bill\BillRepositoryInterface; -use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; -use FireflyIII\Transformers\BillTransformer; -use Illuminate\Http\JsonResponse; -use Illuminate\Pagination\LengthAwarePaginator; - -/** - * Class ShowController - */ -class IndexController extends Controller -{ - use ValidatesUserGroupTrait; - - private BillRepositoryInterface $repository; - - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(BillRepositoryInterface::class); - $this->repository->setUserGroup($this->validateUserGroup($request)); - - return $next($request); - } - ); - } - - /** - * TODO see autocomplete/accountcontroller for list. - */ - public function index(): JsonResponse - { - $this->repository->correctOrder(); - $bills = $this->repository->getBills(); - $pageSize = $this->parameters->get('limit'); - $count = $bills->count(); - $bills = $bills->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); - $paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page')); - $transformer = new BillTransformer(); - $transformer->setParameters($this->parameters); // give params to transformer - - return response() - ->json($this->jsonApiList('subscriptions', $paginator, $transformer)) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } -} diff --git a/app/Api/V2/Controllers/Model/Bill/ShowController.php b/app/Api/V2/Controllers/Model/Bill/ShowController.php deleted file mode 100644 index 16327e3f02..0000000000 --- a/app/Api/V2/Controllers/Model/Bill/ShowController.php +++ /dev/null @@ -1,69 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Model\Bill; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Models\Bill; -use FireflyIII\Repositories\Bill\BillRepositoryInterface; -use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; -use FireflyIII\Transformers\BillTransformer; -use Illuminate\Http\JsonResponse; - -/** - * Class ShowController - */ -class ShowController extends Controller -{ - use ValidatesUserGroupTrait; - - private BillRepositoryInterface $repository; - - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(BillRepositoryInterface::class); - $this->repository->setUserGroup($this->validateUserGroup($request)); - - return $next($request); - } - ); - } - - /** - * TODO this endpoint is not documented - */ - public function show(Bill $bill): JsonResponse - { - $transformer = new BillTransformer(); - $transformer->setParameters($this->parameters); - - return response() - ->api($this->jsonApiObject('subscriptions', $bill, $transformer)) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } -} diff --git a/app/Api/V2/Controllers/Model/Bill/SumController.php b/app/Api/V2/Controllers/Model/Bill/SumController.php deleted file mode 100644 index 69b0dcc7aa..0000000000 --- a/app/Api/V2/Controllers/Model/Bill/SumController.php +++ /dev/null @@ -1,86 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Model\Bill; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Api\V2\Request\Generic\DateRequest; -use FireflyIII\Repositories\Bill\BillRepositoryInterface; -use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; -use Illuminate\Http\JsonResponse; - -/** - * Class SumController - */ -class SumController extends Controller -{ - use ValidatesUserGroupTrait; - - private BillRepositoryInterface $repository; - - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(BillRepositoryInterface::class); - $this->repository->setUserGroup($this->validateUserGroup($request)); - - return $next($request); - } - ); - } - - /** - * This endpoint is documented at: - * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/transactions-sum/getBillsPaidTrSum - * - * TODO see autocomplete/accountcontroller for list. - * - * @SuppressWarnings("PHPMD.UnusedFormalParameter") - */ - public function paid(DateRequest $request): JsonResponse - { - $result = $this->repository->sumPaidInRange($this->parameters->get('start'), $this->parameters->get('end')); - - // convert to JSON response: - return response()->api(array_values($result)); - } - - /** - * This endpoint is documented at: - * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/transactions-sum/getBillsUnpaidTrSum - * - * TODO see autocomplete/accountcontroller for list. - * - * @SuppressWarnings("PHPMD.UnusedFormalParameter") - */ - public function unpaid(DateRequest $request): JsonResponse - { - $result = $this->repository->sumUnpaidInRange($this->parameters->get('start'), $this->parameters->get('end')); - - // convert to JSON response: - return response()->api(array_values($result)); - } -} diff --git a/app/Api/V2/Controllers/Model/Budget/IndexController.php b/app/Api/V2/Controllers/Model/Budget/IndexController.php deleted file mode 100644 index d2a8eb6e6e..0000000000 --- a/app/Api/V2/Controllers/Model/Budget/IndexController.php +++ /dev/null @@ -1,71 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Model\Budget; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; -use FireflyIII\Transformers\BudgetTransformer; -use Illuminate\Http\JsonResponse; -use Illuminate\Pagination\LengthAwarePaginator; - -/** - * Class IndexController - */ -class IndexController extends Controller -{ - private BudgetRepositoryInterface $repository; - - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(BudgetRepositoryInterface::class); - - return $next($request); - } - ); - } - - /** - * This endpoint is documented at: - * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/budgets/listBudgets - */ - public function index(): JsonResponse - { - $pageSize = $this->parameters->get('limit'); - $collection = $this->repository->getActiveBudgets(); - $total = $collection->count(); - $collection->slice($pageSize * $this->parameters->get('page'), $pageSize); - - $paginator = new LengthAwarePaginator($collection, $total, $pageSize, $this->parameters->get('page')); - $transformer = new BudgetTransformer(); - - return response() - ->api($this->jsonApiList('budgets', $paginator, $transformer)) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } -} diff --git a/app/Api/V2/Controllers/Model/Budget/ShowController.php b/app/Api/V2/Controllers/Model/Budget/ShowController.php deleted file mode 100644 index 566cc992f9..0000000000 --- a/app/Api/V2/Controllers/Model/Budget/ShowController.php +++ /dev/null @@ -1,94 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Model\Budget; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Api\V2\Request\Generic\DateRequest; -use FireflyIII\Models\Budget; -use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; -use FireflyIII\Transformers\BudgetTransformer; -use Illuminate\Http\JsonResponse; - -/** - * Class ShowController - * TODO lots of deprecated code here. - */ -class ShowController extends Controller -{ - private BudgetRepositoryInterface $repository; - - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(BudgetRepositoryInterface::class); - - return $next($request); - } - ); - } - - /** - * 2023-10-29 removed the cerSum reference, not sure where this is used atm - * so removed from api.php. Also applies to "spent" method. - * - * This endpoint is documented at: - * TODO add URL - */ - public function budgeted(DateRequest $request, Budget $budget): JsonResponse - { - $data = $request->getAll(); - $result = $this->repository->budgetedInPeriodForBudget($budget, $data['start'], $data['end']); - - return response()->json($result); - } - - /** - * Show a budget. - */ - public function show(Budget $budget): JsonResponse - { - $transformer = new BudgetTransformer(); - $transformer->setParameters($this->parameters); - - return response() - ->api($this->jsonApiObject('budgets', $budget, $transformer)) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } - - /** - * This endpoint is documented at: - * TODO add URL - */ - public function spent(DateRequest $request, Budget $budget): JsonResponse - { - $data = $request->getAll(); - $result = $this->repository->spentInPeriodForBudget($budget, $data['start'], $data['end']); - - return response()->json($result); - } -} diff --git a/app/Api/V2/Controllers/Model/Budget/SumController.php b/app/Api/V2/Controllers/Model/Budget/SumController.php deleted file mode 100644 index 0147fd061c..0000000000 --- a/app/Api/V2/Controllers/Model/Budget/SumController.php +++ /dev/null @@ -1,74 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Model\Budget; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Api\V2\Request\Generic\DateRequest; -use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; -use Illuminate\Http\JsonResponse; - -/** - * Class SumController - */ -class SumController extends Controller -{ - private BudgetRepositoryInterface $repository; - - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(BudgetRepositoryInterface::class); - - return $next($request); - } - ); - } - - /** - * This endpoint is documented at: - * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/budgets/getBudgetedForBudget - */ - public function budgeted(DateRequest $request): JsonResponse - { - $data = $request->getAll(); - $result = $this->repository->budgetedInPeriod($data['start'], $data['end']); - - return response()->json($result); - } - - /** - * This endpoint is documented at: - * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/budgets/getSpentForBudget - */ - public function spent(DateRequest $request): JsonResponse - { - $data = $request->getAll(); - $result = $this->repository->spentInPeriod($data['start'], $data['end']); - - return response()->json($result); - } -} diff --git a/app/Api/V2/Controllers/Model/BudgetLimit/IndexController.php b/app/Api/V2/Controllers/Model/BudgetLimit/IndexController.php deleted file mode 100644 index 1a54aa4ef9..0000000000 --- a/app/Api/V2/Controllers/Model/BudgetLimit/IndexController.php +++ /dev/null @@ -1,66 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Model\BudgetLimit; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Models\Budget; -use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; -use FireflyIII\Transformers\BudgetLimitTransformer; -use Illuminate\Http\JsonResponse; -use Illuminate\Pagination\LengthAwarePaginator; - -class IndexController extends Controller -{ - private BudgetLimitRepositoryInterface $repository; - - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(BudgetLimitRepositoryInterface::class); - - return $next($request); - } - ); - } - - /** - * This endpoint is documented at: - * TODO add URL - */ - public function index(Budget $budget): JsonResponse - { - $pageSize = $this->parameters->get('limit'); - $collection = $this->repository->getBudgetLimits($budget); - $total = $collection->count(); - $collection->slice($pageSize * $this->parameters->get('page'), $pageSize); - - $paginator = new LengthAwarePaginator($collection, $total, $pageSize, $this->parameters->get('page')); - $transformer = new BudgetLimitTransformer(); - - return response()->api($this->jsonApiList('budget-limits', $paginator, $transformer))->header('Content-Type', self::CONTENT_TYPE); - } -} diff --git a/app/Api/V2/Controllers/Model/BudgetLimit/ListController.php b/app/Api/V2/Controllers/Model/BudgetLimit/ListController.php deleted file mode 100644 index b87ba89314..0000000000 --- a/app/Api/V2/Controllers/Model/BudgetLimit/ListController.php +++ /dev/null @@ -1,71 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Model\BudgetLimit; - -use FireflyIII\Api\V2\Controllers\Controller; -use Illuminate\Http\JsonResponse; - -/** - * Class ListController - */ -class ListController extends Controller -{ - // private BudgetLimitRepositoryInterface $repository; - // - // public function __construct() - // { - // parent::__construct(); - // $this->middleware( - // function ($request, $next) { - // $this->repository = app(BudgetLimitRepositoryInterface::class); - // - // return $next($request); - // } - // ); - // } - - /** - * This endpoint is documented at: - * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/budgets/listBudgetLimitByBudget - * // DateRequest $request, Budget $budget - */ - public function index(): JsonResponse - { - return response()->json(); - // throw new FireflyException('Needs refactoring, move to IndexController.'); - // $pageSize = $this->parameters->get('limit'); - // $dates = $request->getAll(); - // $collection = $this->repository->getBudgetLimits($budget, $dates['start'], $dates['end']); - // $total = $collection->count(); - // $collection->slice($pageSize * $this->parameters->get('page'), $pageSize); - // - // $paginator = new LengthAwarePaginator($collection, $total, $pageSize, $this->parameters->get('page')); - // $transformer = new BudgetLimitTransformer(); - // - // return response() - // ->api($this->jsonApiList('budget-limits', $paginator, $transformer)) - // ->header('Content-Type', self::CONTENT_TYPE); - } -} diff --git a/app/Api/V2/Controllers/Model/Currency/IndexController.php b/app/Api/V2/Controllers/Model/Currency/IndexController.php deleted file mode 100644 index 80657188b4..0000000000 --- a/app/Api/V2/Controllers/Model/Currency/IndexController.php +++ /dev/null @@ -1,72 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Model\Currency; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; -use FireflyIII\Transformers\CurrencyTransformer; -use Illuminate\Http\JsonResponse; -use Illuminate\Pagination\LengthAwarePaginator; - -/** - * Class IndexController - */ -class IndexController extends Controller -{ - private CurrencyRepositoryInterface $repository; - - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(CurrencyRepositoryInterface::class); - - return $next($request); - } - ); - } - - /** - * TODO This endpoint is not yet documented. - * - * Display a listing of the resource. - */ - public function index(): JsonResponse - { - $bills = $this->repository->getAll(); - $pageSize = $this->parameters->get('limit'); - $count = $bills->count(); - $bills = $bills->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); - $paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page')); - $transformer = new CurrencyTransformer(); - $transformer->setParameters($this->parameters); // give params to transformer - - return response() - ->json($this->jsonApiList('currencies', $paginator, $transformer)) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } -} diff --git a/app/Api/V2/Controllers/Model/PiggyBank/IndexController.php b/app/Api/V2/Controllers/Model/PiggyBank/IndexController.php deleted file mode 100644 index 7577edf95a..0000000000 --- a/app/Api/V2/Controllers/Model/PiggyBank/IndexController.php +++ /dev/null @@ -1,74 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Model\PiggyBank; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; -use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; -use FireflyIII\Transformers\PiggyBankTransformer; -use Illuminate\Http\JsonResponse; -use Illuminate\Pagination\LengthAwarePaginator; - -/** - * Class ShowController - */ -class IndexController extends Controller -{ - use ValidatesUserGroupTrait; - - private PiggyBankRepositoryInterface $repository; - - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(PiggyBankRepositoryInterface::class); - $this->repository->setUserGroup($this->validateUserGroup($request)); - - return $next($request); - } - ); - } - - /** - * TODO see autocomplete/accountcontroller for list. - */ - public function index(): JsonResponse - { - $piggies = $this->repository->getPiggyBanks(); - $pageSize = $this->parameters->get('limit'); - $count = $piggies->count(); - $piggies = $piggies->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); - $paginator = new LengthAwarePaginator($piggies, $count, $pageSize, $this->parameters->get('page')); - $transformer = new PiggyBankTransformer(); - $transformer->setParameters($this->parameters); // give params to transformer - - return response() - ->json($this->jsonApiList('piggy-banks', $paginator, $transformer)) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } -} diff --git a/app/Api/V2/Controllers/Model/Transaction/ShowController.php b/app/Api/V2/Controllers/Model/Transaction/ShowController.php deleted file mode 100644 index 185bd41774..0000000000 --- a/app/Api/V2/Controllers/Model/Transaction/ShowController.php +++ /dev/null @@ -1,44 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Model\Transaction; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Models\TransactionGroup; -use FireflyIII\Transformers\TransactionGroupTransformer; -use Illuminate\Http\JsonResponse; - -class ShowController extends Controller -{ - /** - * TODO this endpoint is not yet reachable. - */ - public function show(TransactionGroup $transactionGroup): JsonResponse - { - $transformer = new TransactionGroupTransformer(); - $transformer->setParameters($this->parameters); - - return response()->api($this->jsonApiObject('transactions', $transactionGroup, $transformer))->header('Content-Type', self::CONTENT_TYPE); - } -} diff --git a/app/Api/V2/Controllers/Model/Transaction/StoreController.php b/app/Api/V2/Controllers/Model/Transaction/StoreController.php deleted file mode 100644 index 9c9d61592b..0000000000 --- a/app/Api/V2/Controllers/Model/Transaction/StoreController.php +++ /dev/null @@ -1,130 +0,0 @@ -. - */ - -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 FireflyIII\Helpers\Collector\GroupCollectorInterface; -use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface; -use FireflyIII\Rules\IsDuplicateTransaction; -use FireflyIII\Transformers\TransactionGroupTransformer; -use FireflyIII\User; -use Illuminate\Http\JsonResponse; -use Illuminate\Support\Facades\Validator; -use Illuminate\Validation\ValidationException; - -/** - * Class StoreController - */ -class StoreController extends Controller -{ - private TransactionGroupRepositoryInterface $groupRepository; - - /** - * TransactionController constructor. - */ - 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. - * - * @throws FireflyException - * @throws ValidationException - */ - public function post(StoreRequest $request): JsonResponse - { - 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); - } 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); - } - 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) - ; - } -} diff --git a/app/Api/V2/Controllers/Model/Transaction/UpdateController.php b/app/Api/V2/Controllers/Model/Transaction/UpdateController.php deleted file mode 100644 index b27ade514f..0000000000 --- a/app/Api/V2/Controllers/Model/Transaction/UpdateController.php +++ /dev/null @@ -1,94 +0,0 @@ -middleware( - function ($request, $next) { - $this->groupRepository = app(TransactionGroupRepositoryInterface::class); - - return $next($request); - } - ); - } - - /** - * This endpoint is documented at: - * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/transactions/updateTransaction - * - * Update a transaction. - * - * @throws FireflyException - */ - public function update(UpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse - { - app('log')->debug('Now in update routine for transaction group [v2]!'); - $data = $request->getAll(); - $transactionGroup = $this->groupRepository->update($transactionGroup, $data); - $applyRules = $data['apply_rules'] ?? true; - $fireWebhooks = $data['fire_webhooks'] ?? true; - - event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks, true)); - app('preferences')->mark(); - - /** @var User $admin */ - $admin = auth()->user(); - - // use new group collector: - /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); - $collector->setUser($admin)->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); - } -} diff --git a/app/Api/V2/Controllers/Model/TransactionCurrency/IndexController.php b/app/Api/V2/Controllers/Model/TransactionCurrency/IndexController.php deleted file mode 100644 index 7609a298a1..0000000000 --- a/app/Api/V2/Controllers/Model/TransactionCurrency/IndexController.php +++ /dev/null @@ -1,85 +0,0 @@ -middleware( - function ($request, $next) { - $this->repository = app(CurrencyRepositoryInterface::class); - // new way of user group validation - $userGroup = $this->validateUserGroup($request); - $this->repository->setUserGroup($userGroup); - - return $next($request); - } - ); - } - - public function index(IndexRequest $request): JsonResponse - { - $settings = $request->getAll(); - $currencies = new Collection(); - if (true === $settings['enabled']) { - $currencies = $this->repository->get(); - } - if (true !== $settings['enabled']) { - $currencies = $this->repository->getAll(); - } - - $pageSize = $this->parameters->get('limit'); - $count = $currencies->count(); - - // depending on the sort parameters, this list must not be split, because the - // order is calculated in the account transformer and by that time it's too late. - $accounts = $currencies->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); - $paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page')); - $transformer = new CurrencyTransformer(); - - $this->parameters->set('pageSize', $pageSize); - $transformer->setParameters($this->parameters); // give params to transformer - - return response() - ->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer)) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } -} diff --git a/app/Api/V2/Controllers/Model/TransactionCurrency/ShowController.php b/app/Api/V2/Controllers/Model/TransactionCurrency/ShowController.php deleted file mode 100644 index 7486f17cee..0000000000 --- a/app/Api/V2/Controllers/Model/TransactionCurrency/ShowController.php +++ /dev/null @@ -1,80 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Model\TransactionCurrency; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Models\TransactionCurrency; -use FireflyIII\Models\UserGroup; -use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; -use FireflyIII\Transformers\CurrencyTransformer; -use Illuminate\Http\JsonResponse; - -/** - * Class ShowController - */ -class ShowController extends Controller -{ - public const string RESOURCE_KEY = 'transaction-currencies'; - - private CurrencyRepositoryInterface $repository; - - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->repository = app(CurrencyRepositoryInterface::class); - // new way of user group validation - $userGroup = $this->validateUserGroup($request); - $this->repository->setUserGroup($userGroup); - - return $next($request); - } - ); - } - - public function show(TransactionCurrency $currency): JsonResponse - { - $groups = $currency->userGroups()->where('user_groups.id', $this->repository->getUserGroup()->id)->get(); - $enabled = $groups->count() > 0; - $default = false; - - /** @var UserGroup $group */ - foreach ($groups as $group) { - $default = 1 === $group->pivot->group_default; - } - $currency->userGroupEnabled = $enabled; - $currency->userGroupNative = $default; - - - $transformer = new CurrencyTransformer(); - $transformer->setParameters($this->parameters); - - return response() - ->api($this->jsonApiObject(self::RESOURCE_KEY, $currency, $transformer)) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } -} diff --git a/app/Api/V2/Controllers/Search/AccountController.php b/app/Api/V2/Controllers/Search/AccountController.php deleted file mode 100644 index af87a73b5a..0000000000 --- a/app/Api/V2/Controllers/Search/AccountController.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Search; - -use FireflyIII\Api\V2\Controllers\Controller; - -/** - * Class AccountController - */ -class AccountController extends Controller {} diff --git a/app/Api/V2/Controllers/Summary/BasicController.php b/app/Api/V2/Controllers/Summary/BasicController.php deleted file mode 100644 index 5a7ef94980..0000000000 --- a/app/Api/V2/Controllers/Summary/BasicController.php +++ /dev/null @@ -1,412 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Summary; - -use Exception; -use Carbon\Carbon; -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Api\V2\Request\Generic\DateRequest; -use FireflyIII\Enums\AccountTypeEnum; -use FireflyIII\Enums\TransactionTypeEnum; -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Helpers\Collector\GroupCollectorInterface; -use FireflyIII\Helpers\Report\NetWorthInterface; -use FireflyIII\Models\Account; -use FireflyIII\Models\UserGroup; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\Repositories\Bill\BillRepositoryInterface; -use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface; -use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; -use FireflyIII\Repositories\Budget\OperationsRepositoryInterface; -use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; -use FireflyIII\Support\Http\Api\ExchangeRateConverter; -use FireflyIII\Support\Http\Api\SummaryBalanceGrouped; -use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; -use FireflyIII\User; -use Illuminate\Http\JsonResponse; -use Illuminate\Support\Facades\Log; - -/** - * Class BasicController - */ -class BasicController extends Controller -{ - use ValidatesUserGroupTrait; - - private AvailableBudgetRepositoryInterface $abRepository; - private AccountRepositoryInterface $accountRepository; - private BillRepositoryInterface $billRepository; - private BudgetRepositoryInterface $budgetRepository; - private CurrencyRepositoryInterface $currencyRepos; - private OperationsRepositoryInterface $opsRepository; - - /** - * BasicController constructor. - */ - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->abRepository = app(AvailableBudgetRepositoryInterface::class); - $this->accountRepository = app(AccountRepositoryInterface::class); - $this->billRepository = app(BillRepositoryInterface::class); - $this->budgetRepository = app(BudgetRepositoryInterface::class); - $this->currencyRepos = app(CurrencyRepositoryInterface::class); - $this->opsRepository = app(OperationsRepositoryInterface::class); - - $userGroup = $this->validateUserGroup($request); - $this->abRepository->setUserGroup($userGroup); - $this->accountRepository->setUserGroup($userGroup); - $this->billRepository->setUserGroup($userGroup); - $this->budgetRepository->setUserGroup($userGroup); - $this->opsRepository->setUserGroup($userGroup); - - return $next($request); - } - ); - } - - /** - * This endpoint is documented at: - * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/summary/getBasicSummary - * - * @throws Exception - * - * @SuppressWarnings("PHPMD.UnusedFormalParameter") - */ - public function basic(DateRequest $request): JsonResponse - { - // parameters for boxes: - $start = $this->parameters->get('start'); - $end = $this->parameters->get('end'); - - // balance information: - $balanceData = $this->getBalanceInformation($start, $end); - $billData = $this->getBillInformation($start, $end); - $spentData = $this->getLeftToSpendInfo($start, $end); - $netWorthData = $this->getNetWorthInfo($start, $end); - $total = array_merge($balanceData, $billData, $spentData, $netWorthData); - - return response()->json($total); - } - - /** - * @throws FireflyException - */ - private function getBalanceInformation(Carbon $start, Carbon $end): array - { - $object = new SummaryBalanceGrouped(); - $default = app('amount')->getPrimaryCurrency(); - - $object->setDefault($default); - - /** @var User $user */ - $user = auth()->user(); - - // collect income of user using the new group collector. - /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); - $collector - ->setRange($start, $end) - ->setUserGroup($user->userGroup) - // set page to retrieve - ->setPage($this->parameters->get('page')) - // set types of transactions to return. - ->setTypes([TransactionTypeEnum::DEPOSIT->value]) - ->setRange($start, $end) - ; - - $set = $collector->getExtractedJournals(); - $object->groupTransactions('income', $set); - - // collect expenses of user using the new group collector. - /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); - $collector - ->setRange($start, $end) - ->setUserGroup($user->userGroup) - // set page to retrieve - ->setPage($this->parameters->get('page')) - // set types of transactions to return. - ->setTypes([TransactionTypeEnum::WITHDRAWAL->value]) - ->setRange($start, $end) - ; - $set = $collector->getExtractedJournals(); - $object->groupTransactions('expense', $set); - - return $object->groupData(); - } - - private function getBillInformation(Carbon $start, Carbon $end): array - { - /* - * Since both this method and the chart use the exact same data, we can suffice - * with calling the one method in the bill repository that will get this amount. - */ - $paidAmount = $this->billRepository->sumPaidInRange($start, $end); - $unpaidAmount = $this->billRepository->sumUnpaidInRange($start, $end); - - $return = []; - - /** - * @var array $info - */ - foreach ($paidAmount as $info) { - $amount = bcmul((string) $info['sum'], '-1'); - $nativeAmount = bcmul((string) $info['native_sum'], '-1'); - $return[] = [ - 'key' => sprintf('bills-paid-in-%s', $info['currency_code']), - 'value' => $amount, - 'currency_id' => (string) $info['currency_id'], - 'currency_code' => $info['currency_code'], - 'currency_symbol' => $info['currency_symbol'], - 'currency_decimal_places' => $info['currency_decimal_places'], - ]; - $return[] = [ - 'key' => 'bills-paid-in-native', - 'value' => $nativeAmount, - 'currency_id' => (string) $info['native_currency_id'], - 'currency_code' => $info['native_currency_code'], - 'currency_symbol' => $info['native_currency_symbol'], - 'currency_decimal_places' => $info['native_currency_decimal_places'], - ]; - } - - /** - * @var array $info - */ - foreach ($unpaidAmount as $info) { - $amount = bcmul((string) $info['sum'], '-1'); - $nativeAmount = bcmul((string) $info['native_sum'], '-1'); - $return[] = [ - 'key' => sprintf('bills-unpaid-in-%s', $info['currency_code']), - 'value' => $amount, - 'currency_id' => (string) $info['currency_id'], - 'currency_code' => $info['currency_code'], - 'currency_symbol' => $info['currency_symbol'], - 'currency_decimal_places' => $info['currency_decimal_places'], - ]; - $return[] = [ - 'key' => 'bills-unpaid-in-native', - 'value' => $nativeAmount, - 'currency_id' => (string) $info['native_currency_id'], - 'currency_code' => $info['native_currency_code'], - 'currency_symbol' => $info['native_currency_symbol'], - 'currency_decimal_places' => $info['native_currency_decimal_places'], - ]; - } - - return $return; - } - - /** - * @SuppressWarnings("PHPMD.ExcessiveMethodLength") - */ - private function getLeftToSpendInfo(Carbon $start, Carbon $end): array - { - Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__)); - app('log')->debug('Now in getLeftToSpendInfo'); - $return = []; - $today = today(config('app.timezone')); - $available = $this->abRepository->getAvailableBudgetWithCurrency($start, $end); - $budgets = $this->budgetRepository->getActiveBudgets(); - $spent = $this->opsRepository->listExpenses($start, $end, null, $budgets); - $default = app('amount')->getPrimaryCurrency(); - $currencies = []; - $converter = new ExchangeRateConverter(); - - // native info: - $nativeLeft = [ - 'key' => 'left-to-spend-in-native', - 'value' => '0', - 'currency_id' => (string) $default->id, - 'currency_code' => $default->code, - 'currency_symbol' => $default->symbol, - 'currency_decimal_places' => $default->decimal_places, - ]; - $nativePerDay = [ - 'key' => 'left-per-day-to-spend-in-native', - 'value' => '0', - 'currency_id' => (string) $default->id, - 'currency_code' => $default->code, - 'currency_symbol' => $default->symbol, - 'currency_decimal_places' => $default->decimal_places, - ]; - - /** - * @var int $currencyId - * @var array $row - */ - foreach ($spent as $currencyId => $row) { - app('log')->debug(sprintf('Processing spent array in currency #%d', $currencyId)); - $spent = '0'; - $spentNative = '0'; - - // get the sum from the array of transactions (double loop but who cares) - /** @var array $budget */ - foreach ($row['budgets'] as $budget) { - app('log')->debug(sprintf('Processing expenses in budget "%s".', $budget['name'])); - - /** @var array $journal */ - foreach ($budget['transaction_journals'] as $journal) { - $journalCurrencyId = $journal['currency_id']; - $currency = $currencies[$journalCurrencyId] ?? $this->currencyRepos->find($journalCurrencyId); - $currencies[$currencyId] = $currency; - $amount = app('steam')->negative($journal['amount']); - $amountNative = $converter->convert($default, $currency, $start, $amount); - if ((int) $journal['foreign_currency_id'] === $default->id) { - $amountNative = $journal['foreign_amount']; - } - $spent = bcadd($spent, (string) $amount); - $spentNative = bcadd($spentNative, (string) $amountNative); - } - app('log')->debug(sprintf('Total spent in budget "%s" is %s', $budget['name'], $spent)); - } - - // either an amount was budgeted or 0 is available. - $currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId); - $currencies[$currencyId] = $currency; - $amount = $available[$currencyId]['amount'] ?? '0'; - $amountNative = $available[$currencyId]['native_amount'] ?? '0'; - $left = bcadd($amount, $spent); - $leftNative = bcadd($amountNative, $spentNative); - app('log')->debug(sprintf('Available amount is %s', $amount)); - app('log')->debug(sprintf('Amount left is %s', $left)); - - // how much left per day? - $days = (int) $today->diffInDays($end, true) + 1; - $perDay = '0'; - $perDayNative = '0'; - if (0 !== $days && bccomp($left, '0') > -1) { - $perDay = bcdiv($left, (string) $days); - } - if (0 !== $days && bccomp($leftNative, '0') > -1) { - $perDayNative = bcdiv($leftNative, (string) $days); - } - - // left - $return[] = [ - 'key' => sprintf('left-to-spend-in-%s', $row['currency_code']), - 'value' => $left, - 'currency_id' => (string) $row['currency_id'], - 'currency_code' => $row['currency_code'], - 'currency_symbol' => $row['currency_symbol'], - 'currency_decimal_places' => (int) $row['currency_decimal_places'], - ]; - // left (native) - $nativeLeft['value'] = $leftNative; - - // left per day: - $return[] = [ - 'key' => sprintf('left-per-day-to-spend-in-%s', $row['currency_code']), - 'value' => $perDay, - 'currency_id' => (string) $row['currency_id'], - 'currency_code' => $row['currency_code'], - 'currency_symbol' => $row['currency_symbol'], - 'currency_decimal_places' => (int) $row['currency_decimal_places'], - ]; - - // left per day (native) - $nativePerDay['value'] = $perDayNative; - } - $return[] = $nativeLeft; - $return[] = $nativePerDay; - $converter->summarize(); - - return $return; - } - - private function getNetWorthInfo(Carbon $start, Carbon $end): array - { - /** @var UserGroup $userGroup */ - $userGroup = auth()->user()->userGroup; - $date = today(config('app.timezone'))->startOfDay(); - // start and end in the future? use $end - if ($this->notInDateRange($date, $start, $end)) { - /** @var Carbon $date */ - $date = session('end', today(config('app.timezone'))->endOfMonth()); - } - - /** @var NetWorthInterface $netWorthHelper */ - $netWorthHelper = app(NetWorthInterface::class); - $netWorthHelper->setUserGroup($userGroup); - $allAccounts = $this->accountRepository->getActiveAccountsByType( - [AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value] - ); - - // filter list on preference of being included. - $filtered = $allAccounts->filter( - function (Account $account) { - $includeNetWorth = $this->accountRepository->getMetaValue($account, 'include_net_worth'); - - return null === $includeNetWorth || '1' === $includeNetWorth; - } - ); - - $netWorthSet = $netWorthHelper->byAccounts($filtered, $date); - $return = []; - // in native amount - $return[] = [ - 'key' => 'net-worth-in-native', - 'value' => $netWorthSet['native']['balance'], - 'currency_id' => (string) $netWorthSet['native']['currency_id'], - 'currency_code' => $netWorthSet['native']['currency_code'], - 'currency_symbol' => $netWorthSet['native']['currency_symbol'], - 'currency_decimal_places' => $netWorthSet['native']['currency_decimal_places'], - ]; - foreach ($netWorthSet as $key => $data) { - if ('native' === $key) { - continue; - } - $return[] = [ - 'key' => sprintf('net-worth-in-%s', $data['currency_code']), - 'value' => $data['balance'], - 'currency_id' => (string) $data['currency_id'], - 'currency_code' => $data['currency_code'], - 'currency_symbol' => $data['currency_symbol'], - 'currency_decimal_places' => $data['currency_decimal_places'], - ]; - } - - return $return; - } - - /** - * Check if date is outside session range. - */ - protected function notInDateRange(Carbon $date, Carbon $start, Carbon $end): bool // Validate a preference - { - if ($start->greaterThanOrEqualTo($date) && $end->greaterThanOrEqualTo($date)) { - return true; - } - // start and end in the past? use $end - if ($start->lessThanOrEqualTo($date) && $end->lessThanOrEqualTo($date)) { - return true; - } - - return false; - } -} diff --git a/app/Api/V2/Controllers/Summary/NetWorthController.php b/app/Api/V2/Controllers/Summary/NetWorthController.php deleted file mode 100644 index f2c023620a..0000000000 --- a/app/Api/V2/Controllers/Summary/NetWorthController.php +++ /dev/null @@ -1,86 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Summary; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Api\V2\Request\Generic\SingleDateRequest; -use FireflyIII\Enums\AccountTypeEnum; -use FireflyIII\Helpers\Report\NetWorthInterface; -use FireflyIII\Models\Account; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; -use Illuminate\Http\JsonResponse; - -/** - * Class NetWorthController - */ -class NetWorthController extends Controller -{ - use ValidatesUserGroupTrait; - - private NetWorthInterface $netWorth; - private AccountRepositoryInterface $repository; - - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - $this->netWorth = app(NetWorthInterface::class); - $this->repository = app(AccountRepositoryInterface::class); - // new way of user group validation - $userGroup = $this->validateUserGroup($request); - $this->netWorth->setUserGroup($userGroup); - $this->repository->setUserGroup($userGroup); - - return $next($request); - } - ); - } - - /** - * This endpoint is documented at: - * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/net-worth/getNetWorth - */ - public function get(SingleDateRequest $request): JsonResponse - { - $date = $request->getDate(); - $accounts = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value]); - - // filter list on preference of being included. - $filtered = $accounts->filter( - function (Account $account) { - $includeNetWorth = $this->repository->getMetaValue($account, 'include_net_worth'); - - return null === $includeNetWorth || '1' === $includeNetWorth; - } - ); - - // skip accounts that should not be in the net worth - $result = $this->netWorth->byAccounts($filtered, $date); - - return response()->api($result); - } -} diff --git a/app/Api/V2/Controllers/System/ConfigurationController.php b/app/Api/V2/Controllers/System/ConfigurationController.php deleted file mode 100644 index e7c9b63ec6..0000000000 --- a/app/Api/V2/Controllers/System/ConfigurationController.php +++ /dev/null @@ -1,30 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\System; - -/** - * Class ConfigurationController - */ -class ConfigurationController {} diff --git a/app/Api/V2/Controllers/System/DebugController.php b/app/Api/V2/Controllers/System/DebugController.php deleted file mode 100644 index d87a51973c..0000000000 --- a/app/Api/V2/Controllers/System/DebugController.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\System; - -use FireflyIII\Api\V2\Controllers\Controller; - -/** - * Class DebugController - */ -class DebugController extends Controller {} diff --git a/app/Api/V2/Controllers/System/PreferencesController.php b/app/Api/V2/Controllers/System/PreferencesController.php deleted file mode 100644 index ad7ee52a27..0000000000 --- a/app/Api/V2/Controllers/System/PreferencesController.php +++ /dev/null @@ -1,48 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\System; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Models\Preference; -use FireflyIII\Transformers\PreferenceTransformer; -use Illuminate\Http\JsonResponse; - -/** - * Class PreferencesController - */ -class PreferencesController extends Controller -{ - /** - * This endpoint is documented at: - * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/preferences/getPreference - */ - public function get(Preference $preference): JsonResponse - { - return response() - ->json($this->jsonApiObject('preferences', $preference, new PreferenceTransformer())) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } -} diff --git a/app/Api/V2/Controllers/System/VersionUpdateController.php b/app/Api/V2/Controllers/System/VersionUpdateController.php deleted file mode 100644 index 979bdb1ece..0000000000 --- a/app/Api/V2/Controllers/System/VersionUpdateController.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\System; - -use FireflyIII\Api\V2\Controllers\Controller; - -/** - * Class VersionUpdateController - */ -class VersionUpdateController extends Controller {} diff --git a/app/Api/V2/Controllers/Transaction/List/AccountController.php b/app/Api/V2/Controllers/Transaction/List/AccountController.php deleted file mode 100644 index 7ba12c9940..0000000000 --- a/app/Api/V2/Controllers/Transaction/List/AccountController.php +++ /dev/null @@ -1,89 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Transaction\List; - -use Carbon\Carbon; -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Api\V2\Request\Model\Transaction\ListRequest; -use FireflyIII\Helpers\Collector\GroupCollectorInterface; -use FireflyIII\Models\Account; -use FireflyIII\Support\Http\Api\TransactionFilter; -use FireflyIII\Transformers\TransactionGroupTransformer; -use Illuminate\Http\JsonResponse; -use Illuminate\Support\Collection; - -/** - * Class AccountController - */ -class AccountController extends Controller -{ - use TransactionFilter; - - /** - * This endpoint is documented at: - * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/accounts/listTransactionByAccount - */ - public function list(ListRequest $request, Account $account): JsonResponse - { - // collect transactions: - $page = $request->getPage(); - $page = max($page, 1); - $pageSize = $this->parameters->get('limit'); - - /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); - $collector->setAccounts(new Collection([$account])) - ->withAPIInformation() - ->setLimit($pageSize) - ->setPage($page) - ->setTypes($request->getTransactionTypes()) - ; - - $start = $request->getStartDate(); - $end = $request->getEndDate(); - if ($start instanceof Carbon) { - app('log')->debug(sprintf('Set start date to %s', $start->toIso8601String())); - $collector->setStart($start); - } - if ($end instanceof Carbon) { - app('log')->debug(sprintf('Set end date to %s', $start->toIso8601String())); - $collector->setEnd($end); - } - - $paginator = $collector->getPaginatedGroups(); - $paginator->setPath( - sprintf( - '%s?%s', - route('api.v2.accounts.transactions', [$account->id]), - $request->buildParams($pageSize) - ) - ); - - return response() - ->json($this->jsonApiList('transactions', $paginator, new TransactionGroupTransformer())) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } -} diff --git a/app/Api/V2/Controllers/Transaction/List/TransactionController.php b/app/Api/V2/Controllers/Transaction/List/TransactionController.php deleted file mode 100644 index 0e630d7444..0000000000 --- a/app/Api/V2/Controllers/Transaction/List/TransactionController.php +++ /dev/null @@ -1,120 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Transaction\List; - -use FireflyIII\Api\V2\Controllers\Controller; -use FireflyIII\Api\V2\Request\Model\Transaction\InfiniteListRequest; -use FireflyIII\Api\V2\Request\Model\Transaction\ListRequest; -use FireflyIII\Helpers\Collector\GroupCollectorInterface; -use FireflyIII\Transformers\TransactionGroupTransformer; -use Illuminate\Http\JsonResponse; - -/** - * Class TransactionController - */ -class TransactionController extends Controller -{ - public function infiniteList(InfiniteListRequest $request): JsonResponse - { - // get sort instructions - $instructions = $request->getSortInstructions('transactions'); - - // collect transactions: - /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); - $collector->setUserGroup(auth()->user()->userGroup) - ->withAPIInformation() - ->setStartRow($request->getStartRow()) - ->setEndRow($request->getEndRow()) - ->setTypes($request->getTransactionTypes()) - ->setSorting($instructions) - ; - - $start = $this->parameters->get('start'); - $end = $this->parameters->get('end'); - if (null !== $start) { - $collector->setStart($start); - } - if (null !== $end) { - $collector->setEnd($end); - } - - $paginator = $collector->getPaginatedGroups(); - $params = $request->buildParams(); - $paginator->setPath( - sprintf( - '%s?%s', - route('api.v2.infinite.transactions.list'), - $params - ) - ); - - return response() - ->json($this->jsonApiList('transactions', $paginator, new TransactionGroupTransformer())) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } - - public function list(ListRequest $request): JsonResponse - { - // collect transactions: - $pageSize = $this->parameters->get('limit'); - $page = $request->getPage(); - $page = max($page, 1); - - /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); - $collector->setUserGroup(auth()->user()->userGroup) - ->withAPIInformation() - ->setLimit($pageSize) - ->setPage($page) - ->setTypes($request->getTransactionTypes()) - ; - - $start = $this->parameters->get('start'); - $end = $this->parameters->get('end'); - if (null !== $start) { - $collector->setStart($start); - } - if (null !== $end) { - $collector->setEnd($end); - } - - $paginator = $collector->getPaginatedGroups(); - $params = $request->buildParams($pageSize); - $paginator->setPath( - sprintf( - '%s?%s', - route('api.v2.transactions.list'), - $params - ) - ); - - return response() - ->json($this->jsonApiList('transactions', $paginator, new TransactionGroupTransformer())) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } -} diff --git a/app/Api/V2/Controllers/Transaction/Sum/BillController.php b/app/Api/V2/Controllers/Transaction/Sum/BillController.php deleted file mode 100644 index 19428e98e2..0000000000 --- a/app/Api/V2/Controllers/Transaction/Sum/BillController.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Controllers\Transaction\Sum; - -use FireflyIII\Api\V2\Controllers\Controller; - -/** - * Class BillController - */ -class BillController extends Controller {} diff --git a/app/Api/V2/Controllers/UserGroup/DestroyController.php b/app/Api/V2/Controllers/UserGroup/DestroyController.php deleted file mode 100644 index 216d00b9e9..0000000000 --- a/app/Api/V2/Controllers/UserGroup/DestroyController.php +++ /dev/null @@ -1,68 +0,0 @@ -. - */ - -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 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); - } - ); - } - - public function destroy(UserGroup $userGroup): JsonResponse - { - /** @var User $user */ - $user = auth()->user(); - // to access this function: must be group owner or sysadmin. - // need owner role or system owner role to delete user group. - $access = $user->hasSpecificRoleInGroup($userGroup, UserRoleEnum::OWNER) || $user->hasRole('owner'); - if (false === $access) { - throw new NotFoundHttpException(); - } - $this->repository->destroy($userGroup); - - return response()->json([], 204); - } -} diff --git a/app/Api/V2/Controllers/UserGroup/IndexController.php b/app/Api/V2/Controllers/UserGroup/IndexController.php deleted file mode 100644 index 5aabec109a..0000000000 --- a/app/Api/V2/Controllers/UserGroup/IndexController.php +++ /dev/null @@ -1,74 +0,0 @@ -middleware( - function ($request, $next) { - $this->repository = app(UserGroupRepositoryInterface::class); - - return $next($request); - } - ); - } - - /** - * TODO see autocomplete/accountcontroller for list. - */ - public function index(IndexRequest $request): JsonResponse - { - $administrations = $this->repository->get(); - $pageSize = $this->parameters->get('limit'); - $count = $administrations->count(); - $administrations = $administrations->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); - $paginator = new LengthAwarePaginator($administrations, $count, $pageSize, $this->parameters->get('page')); - $transformer = new UserGroupTransformer(); - - $transformer->setParameters($this->parameters); // give params to transformer - - return response() - ->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer)) - ->header('Content-Type', self::CONTENT_TYPE) - ; - } -} diff --git a/app/Api/V2/Controllers/UserGroup/ShowController.php b/app/Api/V2/Controllers/UserGroup/ShowController.php deleted file mode 100644 index 9b535aaf10..0000000000 --- a/app/Api/V2/Controllers/UserGroup/ShowController.php +++ /dev/null @@ -1,88 +0,0 @@ -. - */ - -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\UserGroupTransformer; -use Illuminate\Http\JsonResponse; -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); - } - ); - } - - public function index(): JsonResponse - { - $collection = new Collection(); - $pageSize = $this->parameters->get('limit'); - // 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) * $pageSize, $pageSize); - - $paginator = new LengthAwarePaginator($userGroups, $count, $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) - ; - } - - public function show(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) - ; - } -} diff --git a/app/Api/V2/Controllers/UserGroup/StoreController.php b/app/Api/V2/Controllers/UserGroup/StoreController.php deleted file mode 100644 index a84add787d..0000000000 --- a/app/Api/V2/Controllers/UserGroup/StoreController.php +++ /dev/null @@ -1,64 +0,0 @@ -. - */ - -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\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); - } - ); - } - - 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) - ; - } -} diff --git a/app/Api/V2/Controllers/UserGroup/UpdateController.php b/app/Api/V2/Controllers/UserGroup/UpdateController.php deleted file mode 100644 index c881eeb887..0000000000 --- a/app/Api/V2/Controllers/UserGroup/UpdateController.php +++ /dev/null @@ -1,90 +0,0 @@ -. - */ - -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\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); - } - ); - } - - 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) - ; - } - - 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) - ; - } - - public function useUserGroup(UserGroup $userGroup): JsonResponse - { - // group validation is already in place, so can just update the user. - $this->repository->useUserGroup($userGroup); - - return response()->json([], 204); - } -} diff --git a/app/Api/V2/Request/Autocomplete/AutocompleteRequest.php b/app/Api/V2/Request/Autocomplete/AutocompleteRequest.php deleted file mode 100644 index dbc934b394..0000000000 --- a/app/Api/V2/Request/Autocomplete/AutocompleteRequest.php +++ /dev/null @@ -1,97 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Request\Autocomplete; - -use FireflyIII\Enums\AccountTypeEnum; -use FireflyIII\Support\Http\Api\AccountFilter; -use FireflyIII\Support\Request\ChecksLogin; -use FireflyIII\Support\Request\ConvertsDataTypes; -use Illuminate\Foundation\Http\FormRequest; - -/** - * Class AutocompleteRequest - */ -class AutocompleteRequest extends FormRequest -{ - use AccountFilter; - use ChecksLogin; - use ConvertsDataTypes; - - /** - * Loops over all possible query parameters (these are shared over ALL auto complete requests) - * and returns a validated array of parameters. - * - * The advantage is a single class. But you may also submit "account types" to an endpoint that doesn't use these. - */ - public function getParameters(): array - { - $array = [ - 'date' => $this->convertDateTime('date'), - 'query' => $this->clearString((string) $this->get('query')), - 'size' => $this->integerFromValue('size'), - 'page' => $this->integerFromValue('page'), - 'account_types' => $this->arrayFromValue($this->get('account_types')), - 'transaction_types' => $this->arrayFromValue($this->get('transaction_types')), - ]; - $array['size'] = $array['size'] < 1 || $array['size'] > 100 ? 15 : $array['size']; - $array['page'] = max($array['page'], 1); - if (null === $array['account_types']) { - $array['account_types'] = []; - } - if (null === $array['transaction_types']) { - $array['transaction_types'] = []; - } - - // remove 'initial balance' from allowed types. its internal - $array['account_types'] = array_diff($array['account_types'], [AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::RECONCILIATION->value, AccountTypeEnum::CREDITCARD->value]); - $array['account_types'] = $this->getAccountTypeParameter($array['account_types']); - - return $array; - } - - private function getAccountTypeParameter(array $types): array - { - $return = []; - foreach ($types as $type) { - $return = array_merge($return, $this->mapAccountTypes($type)); - } - - return array_unique($return); - } - - public function rules(): array - { - $valid = array_keys($this->types); - - return [ - 'date' => 'nullable|date|after:1970-01-02|before:2038-01-17', - 'query' => 'nullable|string', - 'size' => 'nullable|integer|min:1|max:100', - 'page' => 'nullable|integer|min:1', - 'account_types' => sprintf('nullable|in:%s', implode(',', $valid)), - 'transaction_types' => 'nullable|in:todo', - ]; - } -} diff --git a/app/Api/V2/Request/Chart/BalanceChartRequest.php b/app/Api/V2/Request/Chart/BalanceChartRequest.php deleted file mode 100644 index 46c80d5f46..0000000000 --- a/app/Api/V2/Request/Chart/BalanceChartRequest.php +++ /dev/null @@ -1,90 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Request\Chart; - -use Illuminate\Contracts\Validation\Validator; -use FireflyIII\Enums\UserRoleEnum; -use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; -use FireflyIII\Support\Request\ChecksLogin; -use FireflyIII\Support\Request\ConvertsDataTypes; -use Illuminate\Foundation\Http\FormRequest; -use Illuminate\Support\Facades\Log; - -/** - * Class BalanceChartRequest - */ -class BalanceChartRequest extends FormRequest -{ - use ChecksLogin; - use ConvertsDataTypes; - use ValidatesUserGroupTrait; - - protected array $acceptedRoles = [UserRoleEnum::READ_ONLY]; - - /** - * Get all data from the request. - */ - public function getAll(): array - { - return [ - 'accounts' => $this->getAccountList(), - 'period' => $this->convertString('period'), - ]; - } - - /** - * The rules that the incoming request must be matched against. - */ - public function rules(): array - { - return [ - 'start' => 'required|date|after:1970-01-02|before:2038-01-17', - 'end' => 'required|date|after_or_equal:start|before:2038-01-17|after:1970-01-02', - 'accounts.*' => 'required|exists:accounts,id', - 'period' => sprintf('required|in:%s', implode(',', config('firefly.valid_view_ranges'))), - ]; - } - - public function withValidator(Validator $validator): void - { - $validator->after( - static function (Validator $validator): void { - // validate transaction query data. - $data = $validator->getData(); - if (!array_key_exists('accounts', $data)) { - $validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts'])); - - return; - } - if (!is_array($data['accounts'])) { - $validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts'])); - } - } - ); - if ($validator->fails()) { - Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray()); - } - } -} diff --git a/app/Api/V2/Request/Chart/ChartRequest.php b/app/Api/V2/Request/Chart/ChartRequest.php deleted file mode 100644 index d719129c6f..0000000000 --- a/app/Api/V2/Request/Chart/ChartRequest.php +++ /dev/null @@ -1,92 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Request\Chart; - -use Illuminate\Contracts\Validation\Validator; -use FireflyIII\Enums\UserRoleEnum; -use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; -use FireflyIII\Support\Request\ChecksLogin; -use FireflyIII\Support\Request\ConvertsDataTypes; -use Illuminate\Foundation\Http\FormRequest; -use Illuminate\Support\Facades\Log; - -/** - * Class ChartRequest - */ -class ChartRequest extends FormRequest -{ - use ChecksLogin; - use ConvertsDataTypes; - use ValidatesUserGroupTrait; - - protected array $acceptedRoles = [UserRoleEnum::READ_ONLY]; - - public function getParameters(): array - { - // $queryParameters = QueryParameters::cast($this->all()); - return [ - 'start' => $this->convertDateTime('start')?->startOfDay(), - 'end' => $this->convertDateTime('end')?->endOfDay(), - 'preselected' => $this->convertString('preselected', 'empty'), - 'period' => $this->convertString('period', '1M'), - 'accounts' => $this->arrayFromValue($this->get('accounts')), - ]; - } - - /** - * The rules that the incoming request must be matched against. - */ - public function rules(): array - { - return [ - 'start' => 'required|date|after:1970-01-02|before:2038-01-17|before_or_equal:end', - 'end' => 'required|date|after:1970-01-02|before:2038-01-17|after_or_equal:start', - 'preselected' => sprintf('nullable|in:%s', implode(',', config('firefly.preselected_accounts'))), - 'period' => sprintf('nullable|in:%s', implode(',', config('firefly.valid_view_ranges'))), - 'accounts.*' => 'exists:accounts,id', - ]; - - } - - public function withValidator(Validator $validator): void - { - $validator->after( - static function (Validator $validator): void { - // validate transaction query data. - $data = $validator->getData(); - if (!array_key_exists('accounts', $data)) { - // $validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts'])); - return; - } - if (!is_array($data['accounts'])) { - $validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts'])); - } - } - ); - if ($validator->fails()) { - Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray()); - } - } -} diff --git a/app/Api/V2/Request/Chart/DashboardChartRequest.php b/app/Api/V2/Request/Chart/DashboardChartRequest.php deleted file mode 100644 index 08f1845ff1..0000000000 --- a/app/Api/V2/Request/Chart/DashboardChartRequest.php +++ /dev/null @@ -1,89 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Request\Chart; - -use Illuminate\Contracts\Validation\Validator; -use FireflyIII\Enums\UserRoleEnum; -use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; -use FireflyIII\Support\Request\ChecksLogin; -use FireflyIII\Support\Request\ConvertsDataTypes; -use Illuminate\Foundation\Http\FormRequest; -use Illuminate\Support\Facades\Log; - -/** - * Class DashboardChartRequest - */ -class DashboardChartRequest extends FormRequest -{ - use ChecksLogin; - use ConvertsDataTypes; - use ValidatesUserGroupTrait; - - protected array $acceptedRoles = [UserRoleEnum::READ_ONLY]; - - /** - * Get all data from the request. - */ - public function getAll(): array - { - return [ - 'accounts' => $this->getAccountList(), - 'preselected' => $this->convertString('preselected'), - ]; - } - - /** - * The rules that the incoming request must be matched against. - */ - public function rules(): array - { - return [ - 'start' => 'required|date|after:1970-01-02|before:2038-01-17', - 'end' => 'required|date|after_or_equal:start|before:2038-01-17|after:1970-01-02', - 'preselected' => sprintf('in:%s', implode(',', config('firefly.preselected_accounts'))), - 'accounts.*' => 'exists:accounts,id', - ]; - } - - public function withValidator(Validator $validator): void - { - $validator->after( - static function (Validator $validator): void { - // validate transaction query data. - $data = $validator->getData(); - if (!array_key_exists('accounts', $data)) { - // $validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts'])); - return; - } - if (!is_array($data['accounts'])) { - $validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts'])); - } - } - ); - if ($validator->fails()) { - Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray()); - } - } -} diff --git a/app/Api/V2/Request/Generic/DateRequest.php b/app/Api/V2/Request/Generic/DateRequest.php deleted file mode 100644 index 54ee20d068..0000000000 --- a/app/Api/V2/Request/Generic/DateRequest.php +++ /dev/null @@ -1,62 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Request\Generic; - -use FireflyIII\Support\Request\ChecksLogin; -use FireflyIII\Support\Request\ConvertsDataTypes; -use Illuminate\Foundation\Http\FormRequest; - -/** - * Request class for end points that require date parameters. - * - * Class DateRequest - */ -class DateRequest extends FormRequest -{ - use ChecksLogin; - use ConvertsDataTypes; - - /** - * Get all data from the request. - */ - public function getAll(): array - { - return [ - 'start' => $this->getCarbonDate('start')->startOfDay(), - 'end' => $this->getCarbonDate('end')->endOfDay(), - ]; - } - - /** - * The rules that the incoming request must be matched against. - */ - public function rules(): array - { - return [ - 'start' => 'required|date|after:1970-01-02|before:2038-01-17', - 'end' => 'required|date|after_or_equal:start|before:2038-01-17|after:1970-01-02', - ]; - } -} diff --git a/app/Api/V2/Request/Generic/SingleDateRequest.php b/app/Api/V2/Request/Generic/SingleDateRequest.php deleted file mode 100644 index 12bd373c80..0000000000 --- a/app/Api/V2/Request/Generic/SingleDateRequest.php +++ /dev/null @@ -1,59 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Request\Generic; - -use Carbon\Carbon; -use FireflyIII\Support\Request\ChecksLogin; -use FireflyIII\Support\Request\ConvertsDataTypes; -use Illuminate\Foundation\Http\FormRequest; - -/** - * Request class for end points that require a date parameter. - * - * Class SingleDateRequest - */ -class SingleDateRequest extends FormRequest -{ - use ChecksLogin; - use ConvertsDataTypes; - - /** - * Get all data from the request. - */ - public function getDate(): Carbon - { - return $this->getCarbonDate('date'); - } - - /** - * The rules that the incoming request must be matched against. - */ - public function rules(): array - { - return [ - 'date' => 'required|date|after:1970-01-02|before:2038-01-17', - ]; - } -} diff --git a/app/Api/V2/Request/Model/Account/IndexRequest.php b/app/Api/V2/Request/Model/Account/IndexRequest.php deleted file mode 100644 index 64a748175c..0000000000 --- a/app/Api/V2/Request/Model/Account/IndexRequest.php +++ /dev/null @@ -1,71 +0,0 @@ -get('type', 'default'); - - return $this->mapAccountTypes($type); - } - - public function getDate(): Carbon - { - return $this->getCarbonDate('date'); - } - - /** - * The rules that the incoming request must be matched against. - */ - public function rules(): array - { - return [ - 'date' => 'date|after:1970-01-02|before:2038-01-17', - 'start' => 'date|after:1970-01-02|before:2038-01-17|before:end|required_with:end', - 'end' => 'date|after:1970-01-02|before:2038-01-17|after:start|required_with:start', - ]; - } -} diff --git a/app/Api/V2/Request/Model/Account/UpdateRequest.php b/app/Api/V2/Request/Model/Account/UpdateRequest.php deleted file mode 100644 index 19086211b3..0000000000 --- a/app/Api/V2/Request/Model/Account/UpdateRequest.php +++ /dev/null @@ -1,117 +0,0 @@ - ['name', 'convertString'], - 'active' => ['active', 'boolean'], - 'include_net_worth' => ['include_net_worth', 'boolean'], - 'account_type_name' => ['type', 'convertString'], - 'virtual_balance' => ['virtual_balance', 'convertString'], - 'iban' => ['iban', 'convertString'], - 'BIC' => ['bic', 'convertString'], - 'account_number' => ['account_number', 'convertString'], - 'account_role' => ['account_role', 'convertString'], - 'liability_type' => ['liability_type', 'convertString'], - 'opening_balance' => ['opening_balance', 'convertString'], - 'opening_balance_date' => ['opening_balance_date', 'convertDateTime'], - 'cc_type' => ['credit_card_type', 'convertString'], - 'cc_monthly_payment_date' => ['monthly_payment_date', 'convertDateTime'], - 'notes' => ['notes', 'stringWithNewlines'], - 'interest' => ['interest', 'convertString'], - 'interest_period' => ['interest_period', 'convertString'], - 'order' => ['order', 'convertInteger'], - 'currency_id' => ['currency_id', 'convertInteger'], - 'currency_code' => ['currency_code', 'convertString'], - 'liability_direction' => ['liability_direction', 'convertString'], - 'liability_amount' => ['liability_amount', 'convertString'], - 'liability_start_date' => ['liability_start_date', 'date'], - ]; - $data = $this->getAllData($fields); - - return $this->appendLocationData($data, null); - } - - /** - * TODO is a duplicate of the v1 UpdateRequest method. - * - * The rules that the incoming request must be matched against. - */ - public function rules(): array - { - /** @var Account $account */ - $account = $this->route()->parameter('account'); - $accountRoles = implode(',', config('firefly.accountRoles')); - $types = implode(',', array_keys(config('firefly.subTitlesByIdentifier'))); - $ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes'))); - - $rules = [ - 'name' => sprintf('min:1|max:1024|uniqueAccountForUser:%d', $account->id), - 'type' => sprintf('in:%s', $types), - 'iban' => ['iban', 'nullable', new UniqueIban($account, $this->convertString('type'))], - 'bic' => 'bic|nullable', - 'account_number' => ['min:1', 'max:255', 'nullable', new UniqueAccountNumber($account, $this->convertString('type'))], - 'opening_balance' => 'numeric|required_with:opening_balance_date|nullable', - 'opening_balance_date' => 'date|required_with:opening_balance|nullable', - 'virtual_balance' => 'numeric|nullable', - 'order' => 'numeric|nullable', - 'currency_id' => 'numeric|exists:transaction_currencies,id', - 'currency_code' => 'min:3|max:51|exists:transaction_currencies,code', - 'active' => [new IsBoolean()], - 'include_net_worth' => [new IsBoolean()], - 'account_role' => sprintf('in:%s|nullable|required_if:type,asset', $accountRoles), - 'credit_card_type' => sprintf('in:%s|nullable|required_if:account_role,ccAsset', $ccPaymentTypes), - 'monthly_payment_date' => 'date|nullable|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull', - 'liability_type' => 'required_if:type,liability|in:loan,debt,mortgage', - 'liability_direction' => 'required_if:type,liability|in:credit,debit', - 'interest' => 'required_if:type,liability|min:0|max:100|numeric', - 'interest_period' => 'required_if:type,liability|in:daily,monthly,yearly', - 'notes' => 'min:0|max:32768', - ]; - - return Location::requestRules($rules); - } -} diff --git a/app/Api/V2/Request/Model/Transaction/InfiniteListRequest.php b/app/Api/V2/Request/Model/Transaction/InfiniteListRequest.php deleted file mode 100644 index e54a4d836d..0000000000 --- a/app/Api/V2/Request/Model/Transaction/InfiniteListRequest.php +++ /dev/null @@ -1,118 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Request\Model\Transaction; - -use Carbon\Carbon; -use FireflyIII\Support\Http\Api\AccountFilter; -use FireflyIII\Support\Http\Api\TransactionFilter; -use FireflyIII\Support\Request\ChecksLogin; -use FireflyIII\Support\Request\ConvertsDataTypes; -use FireflyIII\Support\Request\GetSortInstructions; -use Illuminate\Foundation\Http\FormRequest; - -/** - * Class InfiniteListRequest - * Used specifically to list transactions. - */ -class InfiniteListRequest extends FormRequest -{ - use AccountFilter; - use ChecksLogin; - use ConvertsDataTypes; - use GetSortInstructions; - use TransactionFilter; - - public function buildParams(): string - { - $array = [ - 'start_row' => $this->getStartRow(), - 'end_row' => $this->getEndRow(), - ]; - - $start = $this->getStartDate(); - $end = $this->getEndDate(); - if ($start instanceof Carbon && $end instanceof Carbon) { - $array['start'] = $start->format('Y-m-d'); - $array['end'] = $end->format('Y-m-d'); - } - - return http_build_query($array); - } - - public function getStartRow(): int - { - $startRow = $this->convertInteger('start_row'); - - return $startRow < 0 || $startRow > 4294967296 ? 0 : $startRow; - } - - public function getEndRow(): int - { - $endRow = $this->convertInteger('end_row'); - - return $endRow <= 0 || $endRow > 4294967296 ? 100 : $endRow; - } - - public function getStartDate(): ?Carbon - { - return $this->getCarbonDate('start'); - } - - public function getEndDate(): ?Carbon - { - return $this->getCarbonDate('end'); - } - - public function getAccountTypes(): array - { - $type = (string) $this->get('type', 'default'); - - return $this->mapAccountTypes($type); - } - - public function getPage(): int - { - $page = $this->convertInteger('page'); - - return 0 === $page || $page > 65536 ? 1 : $page; - } - - public function getTransactionTypes(): array - { - $type = (string) $this->get('type', 'default'); - - return $this->mapTransactionTypes($type); - } - - public function rules(): array - { - return [ - 'start' => 'date|after:1970-01-02|before:2038-01-17', - 'end' => 'date|after:start|after:1970-01-02|before:2038-01-17', - 'start_row' => 'integer|min:0|max:4294967296', - 'end_row' => 'integer|min:0|max:4294967296|gt:start_row', - ]; - } -} diff --git a/app/Api/V2/Request/Model/Transaction/ListRequest.php b/app/Api/V2/Request/Model/Transaction/ListRequest.php deleted file mode 100644 index 70d4ae70c2..0000000000 --- a/app/Api/V2/Request/Model/Transaction/ListRequest.php +++ /dev/null @@ -1,91 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Request\Model\Transaction; - -use Carbon\Carbon; -use FireflyIII\Support\Http\Api\TransactionFilter; -use FireflyIII\Support\Request\ChecksLogin; -use FireflyIII\Support\Request\ConvertsDataTypes; -use Illuminate\Foundation\Http\FormRequest; - -/** - * Class ListRequest - * Used specifically to list transactions. - */ -class ListRequest extends FormRequest -{ - use ChecksLogin; - use ConvertsDataTypes; - use TransactionFilter; - - public function buildParams(int $pageSize): string - { - $array = [ - 'page' => $this->getPage(), - 'limit' => $pageSize, - ]; - - $start = $this->getStartDate(); - $end = $this->getEndDate(); - if ($start instanceof Carbon && $end instanceof Carbon) { - $array['start'] = $start->format('Y-m-d'); - $array['end'] = $end->format('Y-m-d'); - } - - return http_build_query($array); - } - - public function getPage(): int - { - $page = $this->convertInteger('page'); - - return 0 === $page || $page > 65536 ? 1 : $page; - } - - public function getStartDate(): ?Carbon - { - return $this->getCarbonDate('start'); - } - - public function getEndDate(): ?Carbon - { - return $this->getCarbonDate('end'); - } - - public function getTransactionTypes(): array - { - $type = (string) $this->get('type', 'default'); - - return $this->mapTransactionTypes($type); - } - - public function rules(): array - { - return [ - 'start' => 'date|after:1970-01-02|before:2038-01-17', - 'end' => 'date|after:start|after:1970-01-02|before:2038-01-17', - ]; - } -} diff --git a/app/Api/V2/Request/Model/Transaction/StoreRequest.php b/app/Api/V2/Request/Model/Transaction/StoreRequest.php deleted file mode 100644 index 18cc85d5a2..0000000000 --- a/app/Api/V2/Request/Model/Transaction/StoreRequest.php +++ /dev/null @@ -1,317 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Request\Model\Transaction; - -use Illuminate\Contracts\Validation\Validator; -use FireflyIII\Enums\UserRoleEnum; -use FireflyIII\Models\UserGroup; -use FireflyIII\Rules\BelongsUserGroup; -use FireflyIII\Rules\IsBoolean; -use FireflyIII\Rules\IsDateOrTime; -use FireflyIII\Rules\IsValidPositiveAmount; -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\Support\Facades\Log; - -/** - * 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 AppendsLocationData; - use ChecksLogin; - - use ConvertsDataTypes; - use CurrencyValidation; - use GroupValidation; - use TransactionValidation; - - protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS]; - - /** - * Get all data. - */ - 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(), - ]; - } - - /** - * Get transaction data. - */ - private function getTransactionData(): array - { - $return = []; - - /** - * @var array $transaction - */ - foreach ($this->get('transactions') as $transaction) { - $object = new NullArrayObject($transaction); - $result = [ - 'type' => $this->clearString($object['type']), - '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']), - - // foreign currency info: - 'foreign_currency_id' => $this->integerFromValue((string) $object['foreign_currency_id']), - 'foreign_currency_code' => $this->clearString((string) $object['foreign_currency_code']), - - // amount and foreign amount. Cannot be 0. - 'amount' => $this->clearString((string) $object['amount']), - 'foreign_amount' => $this->clearString((string) $object['foreign_amount']), - - // description. - 'description' => $this->clearString($object['description']), - - // 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']), - 'source_iban' => $this->clearString((string) $object['source_iban']), - 'source_number' => $this->clearString((string) $object['source_number']), - 'source_bic' => $this->clearString((string) $object['source_bic']), - - // 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']), - 'destination_iban' => $this->clearString((string) $object['destination_iban']), - 'destination_number' => $this->clearString((string) $object['destination_number']), - 'destination_bic' => $this->clearString((string) $object['destination_bic']), - - // budget info - 'budget_id' => $this->integerFromValue((string) $object['budget_id']), - 'budget_name' => $this->clearString((string) $object['budget_name']), - - // category info - 'category_id' => $this->integerFromValue((string) $object['category_id']), - 'category_name' => $this->clearString((string) $object['category_name']), - - // 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']), - - // 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']), - - // some other interesting properties - 'reconciled' => $this->convertBoolean((string) $object['reconciled']), - 'notes' => $this->clearStringKeepNewlines((string) $object['notes']), - 'tags' => $this->arrayFromValue($object['tags']), - - // all custom fields: - 'internal_reference' => $this->clearString((string) $object['internal_reference']), - 'external_id' => $this->clearString((string) $object['external_id']), - 'original_source' => sprintf('ff3-v%s', config('firefly.version')), - 'recurrence_id' => $this->integerFromValue($object['recurrence_id']), - 'bunq_payment_id' => $this->clearString((string) $object['bunq_payment_id']), - 'external_url' => $this->clearString((string) $object['external_url']), - - 'sepa_cc' => $this->clearString((string) $object['sepa_cc']), - 'sepa_ct_op' => $this->clearString((string) $object['sepa_ct_op']), - 'sepa_ct_id' => $this->clearString((string) $object['sepa_ct_id']), - 'sepa_db' => $this->clearString((string) $object['sepa_db']), - 'sepa_country' => $this->clearString((string) $object['sepa_country']), - 'sepa_ep' => $this->clearString((string) $object['sepa_ep']), - 'sepa_ci' => $this->clearString((string) $object['sepa_ci']), - 'sepa_batch_id' => $this->clearString((string) $object['sepa_batch_id']), - // 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']), - ]; - $result = $this->addFromromTransactionStore($transaction, $result); - $return[] = $result; - } - - return $return; - } - - /** - * The rules that the incoming request must be matched against. - */ - 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' => 'min:1|max: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', new IsValidPositiveAmount()], - 'transactions.*.foreign_amount' => ['nullable', new IsValidPositiveAmount()], - - // description - 'transactions.*.description' => 'nullable|min:1|max:1000', - - // source of transaction - 'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUserGroup($userGroup)], - 'transactions.*.source_name' => 'min:1|max:255|nullable', - 'transactions.*.source_iban' => 'min:1|max:255|nullable|iban', - 'transactions.*.source_number' => 'min:1|max:255|nullable', - 'transactions.*.source_bic' => 'min:1|max:255|nullable|bic', - - // destination of transaction - 'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUserGroup($userGroup)], - 'transactions.*.destination_name' => 'min:1|max:255|nullable', - 'transactions.*.destination_iban' => 'min:1|max:255|nullable|iban', - 'transactions.*.destination_number' => 'min:1|max:255|nullable', - 'transactions.*.destination_bic' => 'min:1|max:255|nullable|bic', - - // budget, category, bill and piggy - 'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUserGroup($userGroup)], - 'transactions.*.budget_name' => ['min:1', 'max:255', 'nullable', new BelongsUserGroup($userGroup)], - 'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUserGroup($userGroup), 'nullable'], - 'transactions.*.category_name' => 'min:1|max:255|nullable', - 'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUserGroup($userGroup)], - 'transactions.*.bill_name' => ['min:1', 'max:255', 'nullable', new BelongsUserGroup($userGroup)], - 'transactions.*.piggy_bank_id' => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUserGroup($userGroup)], - 'transactions.*.piggy_bank_name' => ['min:1', 'max:255', 'nullable', new BelongsUserGroup($userGroup)], - - // other interesting fields - 'transactions.*.reconciled' => [new IsBoolean()], - 'transactions.*.notes' => 'min:1|max:32768|nullable', - 'transactions.*.tags' => 'min:0|max:255', - 'transactions.*.tags.*' => 'min:0|max: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', - - // TODO include location and ability to process it. - ]; - } - - /** - * Configure the validator instance. - */ - 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): void { - // 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); - } - ); - if ($validator->fails()) { - Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray()); - } - } -} diff --git a/app/Api/V2/Request/Model/Transaction/UpdateRequest.php b/app/Api/V2/Request/Model/Transaction/UpdateRequest.php deleted file mode 100644 index ea4727a1bc..0000000000 --- a/app/Api/V2/Request/Model/Transaction/UpdateRequest.php +++ /dev/null @@ -1,371 +0,0 @@ -integerFields = ['order', 'currency_id', 'foreign_currency_id', 'transaction_journal_id', 'source_id', 'destination_id', 'budget_id', 'category_id', 'bill_id', 'recurrence_id']; - $this->dateFields = ['date', 'interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date']; - $this->textareaFields = ['notes']; - // not really floats, for validation. - $this->floatFields = ['amount', 'foreign_amount']; - $this->stringFields = ['type', 'currency_code', 'foreign_currency_code', 'description', 'source_name', 'source_iban', 'source_number', 'source_bic', 'destination_name', 'destination_iban', 'destination_number', 'destination_bic', 'budget_name', 'category_name', 'bill_name', 'internal_reference', 'external_id', 'bunq_payment_id', 'sepa_cc', 'sepa_ct_op', 'sepa_ct_id', 'sepa_db', 'sepa_country', 'sepa_ep', 'sepa_ci', 'sepa_batch_id', 'external_url']; - $this->booleanFields = ['reconciled']; - $this->arrayFields = ['tags']; - $data = []; - if ($this->has('transactions')) { - $data['transactions'] = $this->getTransactionData(); - } - if ($this->has('apply_rules')) { - $data['apply_rules'] = $this->boolean('apply_rules', true); - } - if ($this->has('fire_webhooks')) { - $data['fire_webhooks'] = $this->boolean('fire_webhooks', true); - } - if ($this->has('group_title')) { - $data['group_title'] = $this->convertString('group_title'); - } - - return $data; - } - - /** - * Get transaction data. - * - * @throws FireflyException - */ - private function getTransactionData(): array - { - Log::debug(sprintf('Now in %s', __METHOD__)); - $return = []; - - /** @var null|array $transactions */ - $transactions = $this->get('transactions'); - - if (!is_countable($transactions)) { - return $return; - } - - /** @var null|array $transaction */ - foreach ($transactions as $transaction) { - if (!is_array($transaction)) { - throw new FireflyException('Invalid data submitted: transaction is not array.'); - } - // default response is to update nothing in the transaction: - $current = []; - $current = $this->getIntegerData($current, $transaction); - $current = $this->getStringData($current, $transaction); - $current = $this->getNlStringData($current, $transaction); - $current = $this->getDateData($current, $transaction); - $current = $this->getBooleanData($current, $transaction); - $current = $this->getArrayData($current, $transaction); - $current = $this->getFloatData($current, $transaction); - $return[] = $current; - } - - return $return; - } - - /** - * For each field, add it to the array if a reference is present in the request: - * - * @param array $current - * @param array $transaction - */ - private function getIntegerData(array $current, array $transaction): array - { - foreach ($this->integerFields as $fieldName) { - if (array_key_exists($fieldName, $transaction)) { - $current[$fieldName] = $this->integerFromValue((string) $transaction[$fieldName]); - } - } - - return $current; - } - - /** - * @param array $current - * @param array $transaction - */ - private function getStringData(array $current, array $transaction): array - { - foreach ($this->stringFields as $fieldName) { - if (array_key_exists($fieldName, $transaction)) { - $current[$fieldName] = $this->clearString((string) $transaction[$fieldName]); - } - } - - return $current; - } - - /** - * @param array $current - * @param array $transaction - */ - private function getNlStringData(array $current, array $transaction): array - { - foreach ($this->textareaFields as $fieldName) { - if (array_key_exists($fieldName, $transaction)) { - $current[$fieldName] = $this->clearStringKeepNewlines((string) $transaction[$fieldName]); // keep newlines - } - } - - return $current; - } - - /** - * @param array $current - * @param array $transaction - */ - private function getDateData(array $current, array $transaction): array - { - foreach ($this->dateFields as $fieldName) { - Log::debug(sprintf('Now at date field %s', $fieldName)); - if (array_key_exists($fieldName, $transaction)) { - Log::debug(sprintf('New value: "%s"', $transaction[$fieldName])); - $current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]); - } - } - - return $current; - } - - /** - * @param array $current - * @param array $transaction - */ - private function getBooleanData(array $current, array $transaction): array - { - foreach ($this->booleanFields as $fieldName) { - if (array_key_exists($fieldName, $transaction)) { - $current[$fieldName] = $this->convertBoolean((string) $transaction[$fieldName]); - } - } - - return $current; - } - - /** - * @param array $current - * @param array $transaction - */ - private function getArrayData(array $current, array $transaction): array - { - foreach ($this->arrayFields as $fieldName) { - if (array_key_exists($fieldName, $transaction)) { - $current[$fieldName] = $this->arrayFromValue($transaction[$fieldName]); - } - } - - return $current; - } - - /** - * @param array $current - * @param array $transaction - */ - private function getFloatData(array $current, array $transaction): array - { - foreach ($this->floatFields as $fieldName) { - if (array_key_exists($fieldName, $transaction)) { - $value = $transaction[$fieldName]; - if (is_float($value)) { - $current[$fieldName] = sprintf('%.12f', $value); - } - if (!is_float($value)) { - $current[$fieldName] = (string) $value; - } - } - } - - return $current; - } - - /** - * The rules that the incoming request must be matched against. - */ - #[Override] - public function rules(): array - { - Log::debug(sprintf('Now in %s', __METHOD__)); - $validProtocols = config('firefly.valid_url_protocols'); - - return [ - // basic fields for group: - 'group_title' => 'min:1|max:1000|nullable', - 'apply_rules' => [new IsBoolean()], - - // transaction rules (in array for splits): - 'transactions.*.type' => 'in:withdrawal,deposit,transfer,opening-balance,reconciliation', - 'transactions.*.date' => [new IsDateOrTime()], - 'transactions.*.order' => 'numeric|min:0', - - // group id: - 'transactions.*.transaction_journal_id' => ['nullable', 'numeric', new BelongsUser()], - - // 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' => 'nullable|numeric|exists:transaction_currencies,id', - 'transactions.*.foreign_currency_code' => 'nullable|min:3|max:51|exists:transaction_currencies,code', - - // amount - 'transactions.*.amount' => ['nullable', new IsValidPositiveAmount()], - 'transactions.*.foreign_amount' => ['nullable', new IsValidZeroOrMoreAmount()], - - // description - 'transactions.*.description' => 'nullable|min:1|max:1000', - - // source of transaction - 'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()], - 'transactions.*.source_name' => 'min:1|max:255|nullable', - - // destination of transaction - 'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()], - 'transactions.*.destination_name' => 'min:1|max:255|nullable', - - // budget, category, bill and piggy - 'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser(), 'nullable'], - 'transactions.*.budget_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()], - 'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser(), 'nullable'], - 'transactions.*.category_name' => 'min:1|max:255|nullable', - 'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser()], - 'transactions.*.bill_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()], - - // other interesting fields - 'transactions.*.reconciled' => [new IsBoolean()], - 'transactions.*.notes' => 'min:1|max:32768|nullable', - 'transactions.*.tags' => 'min:0|max:255|nullable', - 'transactions.*.tags.*' => 'min:0|max: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' => sprintf('min:1|max:255|nullable|url:%s', $validProtocols), - - // 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. - */ - #[Override] - public function withValidator(Validator $validator): void - { - Log::debug('Now in withValidator'); - - /** @var TransactionGroup $transactionGroup */ - $transactionGroup = $this->route()->parameter('userGroupTransaction'); - $validator->after( - function (Validator $validator) use ($transactionGroup): void { - // if more than one, verify that there are journal ID's present. - $this->validateJournalIds($validator, $transactionGroup); - - // all transaction types must be equal: - $this->validateTransactionTypesForUpdate($validator); - - // user wants to update a reconciled transaction. - // source, destination, amount + foreign_amount cannot be changed - // and must be omitted from the request. - $this->preventUpdateReconciled($validator, $transactionGroup); - - // validate source/destination is equal, depending on the transaction journal type. - $this->validateEqualAccountsForUpdate($validator, $transactionGroup); - - // see method: - // $this->preventNoAccountInfo($validator, ); - - // validate that the currency fits the source and/or destination account. - // validate all account info - $this->validateAccountInformationUpdate($validator, $transactionGroup); - } - ); - if ($validator->fails()) { - Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray()); - } - } -} diff --git a/app/Api/V2/Request/Model/TransactionCurrency/IndexRequest.php b/app/Api/V2/Request/Model/TransactionCurrency/IndexRequest.php deleted file mode 100644 index 426ccdb415..0000000000 --- a/app/Api/V2/Request/Model/TransactionCurrency/IndexRequest.php +++ /dev/null @@ -1,64 +0,0 @@ - $this->convertBoolean($this->get('enabled')), - ]; - } - - /** - * The rules that the incoming request must be matched against. - */ - public function rules(): array - { - return [ - 'enabled' => 'nullable|boolean', - ]; - - } -} diff --git a/app/Api/V2/Request/UserGroup/StoreRequest.php b/app/Api/V2/Request/UserGroup/StoreRequest.php deleted file mode 100644 index d7196387a2..0000000000 --- a/app/Api/V2/Request/UserGroup/StoreRequest.php +++ /dev/null @@ -1,66 +0,0 @@ -. - */ - -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]; - - public function getAll(): array - { - return [ - 'title' => $this->convertString('title'), - ]; - } - - public function rules(): array - { - $roles = []; - foreach (UserRoleEnum::cases() as $role) { - $roles[] = $role->value; - } - $string = implode(',', $roles); - - return [ - 'title' => 'unique:user_groups,title|required|min:1|max:255', - 'members' => 'required|min:1', - 'members.*.user_email' => 'email|missing_with:members.*.user_id', - 'members.*.user_id' => 'integer|exists:users,id|missing_with:members.*.user_email', - 'members.*.roles' => 'required|array|min:1', - 'members.*.roles.*' => sprintf('required|in:%s', $string), - ]; - } -} diff --git a/app/Api/V2/Request/UserGroup/UpdateMembershipRequest.php b/app/Api/V2/Request/UserGroup/UpdateMembershipRequest.php deleted file mode 100644 index c4a2fa9b81..0000000000 --- a/app/Api/V2/Request/UserGroup/UpdateMembershipRequest.php +++ /dev/null @@ -1,64 +0,0 @@ -. - */ - -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]; - - public function getAll(): array - { - return [ - 'id' => $this->convertInteger('id'), - 'email' => $this->convertString('email'), - 'roles' => $this->get('roles') ?? [], - ]; - } - - 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:'.implode(',', $validRoles), - ]; - } -} diff --git a/app/Api/V2/Request/UserGroup/UpdateRequest.php b/app/Api/V2/Request/UserGroup/UpdateRequest.php deleted file mode 100644 index 3b02c60937..0000000000 --- a/app/Api/V2/Request/UserGroup/UpdateRequest.php +++ /dev/null @@ -1,60 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Request\UserGroup; - -use FireflyIII\Enums\UserRoleEnum; -use FireflyIII\Models\UserGroup; -use FireflyIII\Rules\IsDefaultUserGroupName; -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]; - - public function getAll(): array - { - return [ - 'title' => $this->convertString('title'), - ]; - } - - public function rules(): array - { - /** @var UserGroup $userGroup */ - $userGroup = $this->route()->parameter('userGroup'); - - return [ - 'title' => ['required', 'min:1', 'max:255', sprintf('unique:user_groups,title,%d', $userGroup->id), new IsDefaultUserGroupName($userGroup)], - ]; - } -} diff --git a/app/Api/V2/Response/Sum/AutoSum.php b/app/Api/V2/Response/Sum/AutoSum.php deleted file mode 100644 index 0f1d601f7c..0000000000 --- a/app/Api/V2/Response/Sum/AutoSum.php +++ /dev/null @@ -1,71 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V2\Response\Sum; - -use Closure; -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Models\TransactionCurrency; -use Illuminate\Database\Eloquent\Model; -use Illuminate\Support\Collection; - -/** - * Class AutoSum - * - * @deprecated - */ -class AutoSum -{ - /** - * @throws FireflyException - */ - public function autoSum(Collection $objects, Closure $getCurrency, Closure $getSum): array - { - $return = []; - - /** @var Model $object */ - foreach ($objects as $object) { - /** @var TransactionCurrency $currency */ - $currency = $getCurrency($object); - - /** @var string $amount */ - $amount = $getSum($object); - - $return[$currency->id] ??= [ - 'id' => (string) $currency->id, - 'name' => $currency->name, - 'symbol' => $currency->symbol, - 'code' => $currency->code, - 'decimal_places' => $currency->decimal_places, - 'sum' => '0', - ]; - - $return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], $amount); - } - - var_dump(array_values($return)); - - throw new FireflyException('Not implemented'); - } -}