Merge branch 'release/4.8.1'

This commit is contained in:
James Cole
2019-09-08 08:08:57 +02:00
520 changed files with 26607 additions and 16201 deletions

View File

@@ -12,6 +12,7 @@ mkdir -p $FIREFLY_PATH/storage/export
mkdir -p $FIREFLY_PATH/storage/framework/cache/data
mkdir -p $FIREFLY_PATH/storage/framework/sessions
mkdir -p $FIREFLY_PATH/storage/framework/testing
mkdir -p $FIREFLY_PATH/storage/framework/views/twig
mkdir -p $FIREFLY_PATH/storage/framework/views/v1
mkdir -p $FIREFLY_PATH/storage/framework/views/v2
mkdir -p $FIREFLY_PATH/storage/logs
@@ -56,7 +57,7 @@ php artisan cache:clear
php artisan migrate --seed
php artisan firefly-iii:decrypt-all
# there are 12 upgrade commands
# there are 13 upgrade commands
php artisan firefly-iii:transaction-identifiers
php artisan firefly-iii:migrate-to-groups
php artisan firefly-iii:account-currencies
@@ -69,6 +70,7 @@ php artisan firefly-iii:bl-currency
php artisan firefly-iii:cc-liabilities
php artisan firefly-iii:back-to-journals
php artisan firefly-iii:rename-account-meta
php artisan firefly-iii:migrate-recurrence-meta
# there are 14 verify commands
php artisan firefly-iii:fix-piggies

View File

@@ -1,14 +1,14 @@
en_US
cs_CZ
es_ES
de_DE
fr_FR
ro_RO
it_IT
nb_NO
nl_NL
pl_PL
pt_BR
ro_RO
ru_RU
nb_NO
cs_CZ
id_ID
hu_HU
el_GR

View File

@@ -39,13 +39,12 @@ APP_LOG_LEVEL=notice
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
# For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html
DB_CONNECTION=mysql
# If you use DOCKER COMPOSE, change this variable to "firefly_iii_db"
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
DB_CONNECTION=pgsql
DB_HOST=firefly_iii_db
DB_PORT=5432
DB_DATABASE=firefly
DB_USERNAME=firefly
DB_PASSWORD=secret_firefly_password
# PostgreSQL supports SSL. You can configure it here.
PGSQL_SSL_MODE=prefer

12
.github/security.md vendored Normal file
View File

@@ -0,0 +1,12 @@
# Security Policy
## Supported Versions
Only the latest version of Firefly III is supported. If you're not running the latest version of Firefly III, please upgrade at your earliest convenience.
## Reporting a Vulnerability
If you find something that compromises the security of Firefly III, you should [send me a message](mailto:thegrumpydictator@gmail.com) as soon as possible. These issues will be fixed immediately. You can also open an issue, but if you feel the issue is sensitive, please drop me a message instead.
You can use my [GPG key](https://keybase.io/jc5) for extra security. My [GitHub commits](https://github.com/firefly-iii/firefly-iii/commits/master) are almost always signed with this key.

View File

@@ -1,22 +1,78 @@
# 4.8.1 (API 0.10.2)
- Firefly III 4.8.1 requires PHP 7.3.
- Support for Greek
- [Issue 2383](https://github.com/firefly-iii/firefly-iii/issues/2383) Some tables in reports now also report percentages.
- [Issue 2389](https://github.com/firefly-iii/firefly-iii/issues/2389) Add category / budget information to transaction lists.
- [Issue 2464](https://github.com/firefly-iii/firefly-iii/issues/2464) Can now search for tag.
- [Issue 2466](https://github.com/firefly-iii/firefly-iii/issues/2466) Can order recurring transactions in a more useful manner.
- [Issue 2497](https://github.com/firefly-iii/firefly-iii/issues/2497) Transaction creation moment in hover of tag title.
- [Issue 2471](https://github.com/firefly-iii/firefly-iii/issues/2471) Added date tag to table cells.
- [Issue 2291](https://github.com/firefly-iii/firefly-iii/issues/2291) All reports are now properly multi-currency.
- [Issue 2481](https://github.com/firefly-iii/firefly-iii/issues/2481) As part of the removal of local encryption, uploads and imports are no longer encrypted.
- [Issue 2495](https://github.com/firefly-iii/firefly-iii/issues/2495) A better message of transaction submission.
- [Issue 2506](https://github.com/firefly-iii/firefly-iii/issues/2506) Some bugs in tag report fixed.
- [Issue 2510](https://github.com/firefly-iii/firefly-iii/issues/2510) All transaction descriptions cut off at 255 chars.
- Better sum in bill view.
- Clean up docker files for flawless operation.
- The bunq API has changed, and support for bunq has been disabled.
- [Issue 2470](https://github.com/firefly-iii/firefly-iii/issues/2470) Bad links for transactions.
- [Issue 2480](https://github.com/firefly-iii/firefly-iii/issues/2480) Large queries would break in SQLite.
- [Issue 2484](https://github.com/firefly-iii/firefly-iii/issues/2484) Transaction description auto-complete.
- [Issue 2487](https://github.com/firefly-iii/firefly-iii/issues/2487) Fix issues with FinTS
- [Issue 2488](https://github.com/firefly-iii/firefly-iii/issues/2488) 404 after deleting a tag.
- [Issue 2490](https://github.com/firefly-iii/firefly-iii/issues/2490) "Reset form after submission" doesn't work.
- [Issue 2492](https://github.com/firefly-iii/firefly-iii/issues/2492) After submitting and fixing an error, the error is persistent.
- [Issue 2493](https://github.com/firefly-iii/firefly-iii/issues/2493) Auto detect transaction type is a bit better now.
- [Issue 2498](https://github.com/firefly-iii/firefly-iii/issues/2498) Pressing enter in some fields breaks the form.
- [Issue 2499](https://github.com/firefly-iii/firefly-iii/issues/2499) Auto-complete issues in transaction link form.
- [Issue 2500](https://github.com/firefly-iii/firefly-iii/issues/2500) Issue when submitting edited transactions.
- [Issue 2501](https://github.com/firefly-iii/firefly-iii/issues/2501) Better error messages for empty submissions.
- [Issue 2508](https://github.com/firefly-iii/firefly-iii/issues/2508) Can remove category from transaction.
- [Issue 2516](https://github.com/firefly-iii/firefly-iii/issues/2516) Can no longer import transactions with no amount.
- [Issue 2518](https://github.com/firefly-iii/firefly-iii/issues/2518) Link in balance box goes to current period.
- [Issue 2521](https://github.com/firefly-iii/firefly-iii/issues/2521) Foreign transaction currency is hidden when the user hasn't enabled foreign currencies.
- [Issue 2522](https://github.com/firefly-iii/firefly-iii/issues/2522) Some reports were missing the "overspent" field.
- [Issue 2526](https://github.com/firefly-iii/firefly-iii/issues/2526) It was impossible to remove the budget of a transaction.
- [Issue 2527](https://github.com/firefly-iii/firefly-iii/issues/2527) Some bulk edits were buggy.
- [Issue 2539](https://github.com/firefly-iii/firefly-iii/issues/2539) Fixed a typo.
- [Issue 2545](https://github.com/firefly-iii/firefly-iii/issues/2545) Deleted tags would still show up.
- [Issue 2547](https://github.com/firefly-iii/firefly-iii/issues/2547) Changing the opening balance to 0 will now remove it.
- [Issue 2549](https://github.com/firefly-iii/firefly-iii/issues/2549) Can now clone transactions again.
- [Issue 2550](https://github.com/firefly-iii/firefly-iii/issues/2550) Added missing locales for moment.js
- [Issue 2553](https://github.com/firefly-iii/firefly-iii/issues/2553) Fixed an issue with split transactions.
- [Issue 2555](https://github.com/firefly-iii/firefly-iii/issues/2555) Better error for when you submit the same account twice.
- [Issue 2439](https://github.com/firefly-iii/firefly-iii/issues/2439) SQL error in API post new user
- ... and many other bugs.
- [Issue 2475](https://github.com/firefly-iii/firefly-iii/issues/2475) Tags are now the same for all views.
- [Issue 2476](https://github.com/firefly-iii/firefly-iii/issues/2476) Amount is now represented equally in all views.
- [Issue 2477](https://github.com/firefly-iii/firefly-iii/issues/2477) Rules are easier to update.
- [Issue 2483](https://github.com/firefly-iii/firefly-iii/issues/2483) Several consistencies fixed.
- [Issue 2484](https://github.com/firefly-iii/firefly-iii/issues/2484) Transaction link view fixed.
- [Issue 2557](https://github.com/firefly-iii/firefly-iii/issues/2557) Fix for issue in summary API
- No longer have to submit mandatory fields to account end point. Just submit the field you wish to update, the rest will be untouched.
- Rules will no longer list the "user-action" trigger Rules will have a "moment" field that says either "update-journal" or "store-journal".
# 4.8.0.3 (API 0.10.1)
- #2438 Some balance issues when working with multiple currencies (a known issue)
- #2425 Transaction edit/create form is weird with the enter button
- #2424 auto complete tab doesn't work.
- #2441 Inconsistent character limit for currencies.
- #2443 500 error when submitting budgets
- #2446 Can't update current amount for piggy bank
- #2440 Errors when interacting with recurring transactions
- #2439 SQL error in API post new user
- Autocomplete for transaction description.
- [Issue 2438](https://github.com/firefly-iii/firefly-iii/issues/2438) Some balance issues when working with multiple currencies (a known issue)
- [Issue 2425](https://github.com/firefly-iii/firefly-iii/issues/2425) Transaction edit/create form is weird with the enter button
- [Issue 2424](https://github.com/firefly-iii/firefly-iii/issues/2424) auto complete tab doesn't work.
- [Issue 2441](https://github.com/firefly-iii/firefly-iii/issues/2441) Inconsistent character limit for currencies.
- [Issue 2443](https://github.com/firefly-iii/firefly-iii/issues/2443) 500 error when submitting budgets
- [Issue 2446](https://github.com/firefly-iii/firefly-iii/issues/2446) Can't update current amount for piggy bank
- [Issue 2440](https://github.com/firefly-iii/firefly-iii/issues/2440) Errors when interacting with recurring transactions
- [Issue 2439](https://github.com/firefly-iii/firefly-iii/issues/2439) SQL error in API post new user
- Transaction report (after import, over email) is mostly empty
- Mass edit checkboxes doesn't work in a tag overview
- #2437 CPU issues when viewing accounts, probably run-away queries.
- #2432 Can't disable all currencies except one / can't disable EUR and switch to something else.
- [Issue 2437](https://github.com/firefly-iii/firefly-iii/issues/2437) CPU issues when viewing accounts, probably run-away queries.
- [Issue 2432](https://github.com/firefly-iii/firefly-iii/issues/2432) Can't disable all currencies except one / can't disable EUR and switch to something else.
- Option to edit the budget is gone from edit transaction form.
- #2453 Search view things
- #2449 Can't add invoice date.
- #2448 Bad link in transaction overview
- #2447 Bad link in bill overview
- [Issue 2453](https://github.com/firefly-iii/firefly-iii/issues/2453) Search view things
- [Issue 2449](https://github.com/firefly-iii/firefly-iii/issues/2449) Can't add invoice date.
- [Issue 2448](https://github.com/firefly-iii/firefly-iii/issues/2448) Bad link in transaction overview
- [Issue 2447](https://github.com/firefly-iii/firefly-iii/issues/2447) Bad link in bill overview
- Improvements to various API end-points. Docs are updated.
# 4.8.0.2 (API 0.10.0)
@@ -203,7 +259,7 @@
- [Issue 2009](https://github.com/firefly-iii/firefly-iii/issues/2009) Could not change recurrence back to "forever".
- [Issue 2033](https://github.com/firefly-iii/firefly-iii/issues/2033) Longitude can go from -180 to 180.
- [Issue 2034](https://github.com/firefly-iii/firefly-iii/issues/2034) Rules were not being triggered in mass-edit.
- #2043 In rare instances the repetition of a recurring transaction was displayed incorrectly.
- [Issue 2043](https://github.com/firefly-iii/firefly-iii/issues/2043) In rare instances the repetition of a recurring transaction was displayed incorrectly.
- Fixed broken translations in the recurring transactions overview.
- When you create a recurring transfer you make make it fill (or empty) a piggy bank. This was not working, despite a fix in 4.7.8.
- Fixed a bug where the importer would not be capable of creating new currencies.

View File

@@ -15,8 +15,8 @@ const pkgdef :Spk.PackageDefinition = (
manifest = (
appTitle = (defaultText = "Firefly III"),
appVersion = 35,
appMarketingVersion = (defaultText = "4.8.0.3"),
appVersion = 36,
appMarketingVersion = (defaultText = "4.8.1"),
actions = [
# Define your "new document" handlers here.

View File

@@ -29,6 +29,7 @@ sed -i 's/# ro_RO.UTF-8 UTF-8/ro_RO.UTF-8 UTF-8/g' /etc/locale.gen
sed -i 's/# cs_CZ.UTF-8 UTF-8/cs_CZ.UTF-8 UTF-8/g' /etc/locale.gen
sed -i 's/# id_ID.UTF-8 UTF-8/id_ID.UTF-8 UTF-8/g' /etc/locale.gen
sed -i 's/# hu_HU.UTF-8 UTF-8/hu_HU.UTF-8 UTF-8/g' /etc/locale.gen
sed -i 's/# el_GR.UTF-8 UTF-8/el_GR.UTF-8 UTF-8/g' /etc/locale.gen
dpkg-reconfigure --frontend=noninteractive locales

View File

@@ -1,7 +1,7 @@
sudo: required
language: bash
env:
- VERSION=4.8.0.3
- VERSION=4.8.1
dist: xenial

View File

@@ -1,4 +1,4 @@
FROM jc5x/firefly-iii-base-image:latest
FROM jc5x/firefly-iii-base-image:latest-arm
ENV FIREFLY_PATH=/var/www/firefly-iii COMPOSER_ALLOW_SUPERUSER=1
LABEL version="1.5" maintainer="thegrumpydictator@gmail.com"

View File

@@ -27,13 +27,11 @@ namespace FireflyIII\Api\V1\Controllers;
use DB;
use FireflyIII\Transformers\UserTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use League\Fractal\Manager;
use League\Fractal\Resource\Item;
use League\Fractal\Serializer\JsonApiSerializer;
/**
* Returns basic information about this installation.
*
* @codeCoverageIgnore
* Class AboutController.
*/
@@ -68,14 +66,11 @@ class AboutController extends Controller
/**
* Returns information about the user.
*
* @param Request $request
* @return JsonResponse
*/
public function user(Request $request): JsonResponse
public function user(): JsonResponse
{
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var UserTransformer $transformer */
$transformer = app(UserTransformer::class);

View File

@@ -38,16 +38,13 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
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;
/**
* Class AccountController.
*
*
*/
class AccountController extends Controller
{
@@ -101,12 +98,8 @@ class AccountController extends Controller
*/
public function index(Request $request): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
// read type from URI
$type = $request->get('type') ?? 'all';
$manager = $this->getManager();
$type = $request->get('type') ?? 'all';
$this->parameters->set('type', $type);
// types to get, page size:
@@ -122,8 +115,6 @@ class AccountController extends Controller
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.accounts.index') . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class);
@@ -139,18 +130,16 @@ class AccountController extends Controller
/**
* List all piggies.
*
* @param Request $request
* @param Account $account
*
* @return JsonResponse
* @codeCoverageIgnore
*
* @return JsonResponse
*/
public function piggyBanks(Request $request, Account $account): JsonResponse
public function piggyBanks(Account $account): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -164,9 +153,6 @@ class AccountController extends Controller
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.accounts.piggy_banks', [$account->id]) . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class);
$transformer->setParameters($this->parameters);
@@ -181,16 +167,13 @@ class AccountController extends Controller
/**
* Show single instance.
*
* @param Request $request
* @param Account $account
*
* @return JsonResponse
*/
public function show(Request $request, Account $account): JsonResponse
public function show(Account $account): JsonResponse
{
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class);
@@ -211,9 +194,7 @@ class AccountController extends Controller
{
$data = $request->getAllAccountData();
$account = $this->repository->store($data);
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class);
@@ -248,9 +229,7 @@ class AccountController extends Controller
}
$types = $this->mapTransactionTypes($this->parameters->get('type'));
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var User $admin */
$admin = auth()->user();
@@ -284,18 +263,16 @@ class AccountController extends Controller
* Update account.
*
* @param AccountUpdateRequest $request
* @param Account $account
* @param Account $account
*
* @return JsonResponse
*/
public function update(AccountUpdateRequest $request, Account $account): JsonResponse
{
$data = $request->getAllAccountData();
$data = $request->getUpdateData();
$data['type'] = config('firefly.shortNamesByFullName.' . $account->accountType->type);
$this->repository->update($account, $data);
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class);

View File

@@ -35,17 +35,14 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response as LaravelResponse;
use Illuminate\Pagination\LengthAwarePaginator;
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 function strlen;
/**
* Class AttachmentController.
*
*
*/
class AttachmentController extends Controller
{
@@ -54,6 +51,7 @@ class AttachmentController extends Controller
/**
* AccountController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
@@ -73,7 +71,9 @@ class AttachmentController extends Controller
/**
* Remove the specified resource from storage.
*
* @codeCoverageIgnore
*
* @param Attachment $attachment
*
* @return JsonResponse
@@ -89,6 +89,7 @@ class AttachmentController extends Controller
* Download an attachment.
*
* @param Attachment $attachment
*
* @codeCoverageIgnore
* @return LaravelResponse
* @throws FireflyException
@@ -123,15 +124,12 @@ class AttachmentController extends Controller
/**
* Display a listing of the resource.
*
* @param Request $request
* @codeCoverageIgnore
* @return JsonResponse
* @codeCoverageIgnore
*/
public function index(Request $request): JsonResponse
public function index(): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -145,9 +143,6 @@ class AttachmentController extends Controller
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.attachments.index') . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class);
$transformer->setParameters($this->parameters);
@@ -161,16 +156,13 @@ class AttachmentController extends Controller
/**
* Display the specified resource.
*
* @param Request $request
* @param Attachment $attachment
*
* @return JsonResponse
*/
public function show(Request $request, Attachment $attachment): JsonResponse
public function show(Attachment $attachment): JsonResponse
{
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class);
$transformer->setParameters($this->parameters);
@@ -192,9 +184,7 @@ class AttachmentController extends Controller
{
$data = $request->getAll();
$attachment = $this->repository->store($data);
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class);
@@ -209,7 +199,7 @@ class AttachmentController extends Controller
* Update the specified resource in storage.
*
* @param AttachmentUpdateRequest $request
* @param Attachment $attachment
* @param Attachment $attachment
*
* @return JsonResponse
*/
@@ -217,9 +207,7 @@ class AttachmentController extends Controller
{
$data = $request->getAll();
$this->repository->update($attachment, $data);
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class);
@@ -232,8 +220,10 @@ class AttachmentController extends Controller
/**
* Upload an attachment.
*
* @codeCoverageIgnore
* @param Request $request
*
* @param Request $request
* @param Attachment $attachment
*
* @return JsonResponse

View File

@@ -27,27 +27,23 @@ use FireflyIII\Api\V1\Requests\AvailableBudgetRequest;
use FireflyIII\Factory\TransactionCurrencyFactory;
use FireflyIII\Models\AvailableBudget;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Transformers\AvailableBudgetTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
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;
/**
* Class AvailableBudgetController.
*
*
*/
class AvailableBudgetController extends Controller
{
/** @var BudgetRepositoryInterface The budget repository */
private $repository;
/** @var AvailableBudgetRepositoryInterface */
private $abRepository;
/**
* AvailableBudgetController constructor.
@@ -60,9 +56,9 @@ class AvailableBudgetController extends Controller
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(BudgetRepositoryInterface::class);
$this->repository->setUser($user);
$user = auth()->user();
$this->abRepository = app(AvailableBudgetRepositoryInterface::class);
$this->abRepository->setUser($user);
return $next($request);
}
@@ -80,7 +76,7 @@ class AvailableBudgetController extends Controller
*/
public function delete(AvailableBudget $availableBudget): JsonResponse
{
$this->repository->destroyAvailableBudget($availableBudget);
$this->abRepository->destroyAvailableBudget($availableBudget);
return response()->json([], 204);
}
@@ -88,16 +84,12 @@ class AvailableBudgetController extends Controller
/**
* Display a listing of the resource.
*
* @param Request $request
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function index(Request $request): JsonResponse
public function index(): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -106,7 +98,7 @@ class AvailableBudgetController extends Controller
$end = $this->parameters->get('end');
// get list of available budgets. Count it and split it.
$collection = $this->repository->getAvailableBudgetsByDate($start, $end);
$collection = $this->abRepository->getAvailableBudgetsByDate($start, $end);
$count = $collection->count();
$availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
@@ -114,9 +106,6 @@ class AvailableBudgetController extends Controller
$paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.available_budgets.index') . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var AvailableBudgetTransformer $transformer */
$transformer = app(AvailableBudgetTransformer::class);
$transformer->setParameters($this->parameters);
@@ -130,17 +119,14 @@ class AvailableBudgetController extends Controller
/**
* Display the specified resource.
*
* @param Request $request
* @param AvailableBudget $availableBudget
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, AvailableBudget $availableBudget): JsonResponse
public function show(AvailableBudget $availableBudget): JsonResponse
{
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var AvailableBudgetTransformer $transformer */
$transformer = app(AvailableBudgetTransformer::class);
@@ -168,10 +154,9 @@ class AvailableBudgetController extends Controller
if (null === $currency) {
$currency = app('amount')->getDefaultCurrency();
}
$availableBudget = $this->repository->setAvailableBudget($currency, $data['start'], $data['end'], $data['amount']);
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$data['currency'] = $currency;
$availableBudget = $this->abRepository->store($data);
$manager = $this->getManager();
/** @var AvailableBudgetTransformer $transformer */
$transformer = app(AvailableBudgetTransformer::class);
@@ -187,7 +172,7 @@ class AvailableBudgetController extends Controller
* Update the specified resource in storage.
*
* @param AvailableBudgetRequest $request
* @param AvailableBudget $availableBudget
* @param AvailableBudget $availableBudget
*
* @return JsonResponse
*/
@@ -210,10 +195,8 @@ class AvailableBudgetController extends Controller
$data['currency_id'] = $currency->id;
$this->repository->updateAvailableBudget($availableBudget, $data);
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$this->abRepository->updateAvailableBudget($availableBudget, $data);
$manager = $this->getManager();
/** @var AvailableBudgetTransformer $transformer */
$transformer = app(AvailableBudgetTransformer::class);

View File

@@ -38,17 +38,13 @@ use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
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;
/**
* Class BillController.
*
*
*/
class BillController extends Controller
{
@@ -81,18 +77,14 @@ class BillController extends Controller
/**
* Display a listing of the resource.
*
* @param Request $request
* @param Bill $bill
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function attachments(Request $request, Bill $bill): JsonResponse
public function attachments(Bill $bill): JsonResponse
{
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $this->repository->getAttachments($bill);
@@ -103,9 +95,6 @@ class BillController extends Controller
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.bills.attachments', [$bill->id]) . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class);
$transformer->setParameters($this->parameters);
@@ -134,21 +123,17 @@ class BillController extends Controller
/**
* Display a listing of the resource.
*
* @param Request $request
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function index(Request $request): JsonResponse
public function index(): JsonResponse
{
$bills = $this->repository->getBills();
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$paginator = $this->repository->getPaginator($pageSize);
/** @var Collection $bills */
$bills = $paginator->getCollection();
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$count = $bills->count();
$bills = $bills->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
/** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class);
@@ -163,17 +148,14 @@ class BillController extends Controller
/**
* List all of them.
*
* @param Request $request
* @param Bill $bill
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function rules(Request $request, Bill $bill): JsonResponse
public function rules(Bill $bill): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -187,9 +169,6 @@ class BillController extends Controller
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.bills.rules', [$bill->id]) . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var RuleTransformer $transformer */
$transformer = app(RuleTransformer::class);
$transformer->setParameters($this->parameters);
@@ -205,18 +184,14 @@ class BillController extends Controller
/**
* Show the specified bill.
*
* @param Request $request
* @param Bill $bill
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, Bill $bill): JsonResponse
public function show(Bill $bill): JsonResponse
{
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class);
$transformer->setParameters($this->parameters);
@@ -238,9 +213,7 @@ class BillController extends Controller
{
$bill = $this->repository->store($request->getAll());
if (null !== $bill) {
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class);
@@ -259,7 +232,7 @@ class BillController extends Controller
*
* @param Request $request
*
* @param Bill $bill
* @param Bill $bill
*
* @return JsonResponse
* @codeCoverageIgnore
@@ -271,9 +244,7 @@ class BillController extends Controller
$this->parameters->set('type', $type);
$types = $this->mapTransactionTypes($this->parameters->get('type'));
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var User $admin */
$admin = auth()->user();
@@ -318,7 +289,7 @@ class BillController extends Controller
* Update a bill.
*
* @param BillRequest $request
* @param Bill $bill
* @param Bill $bill
*
* @return JsonResponse
*/
@@ -326,9 +297,7 @@ class BillController extends Controller
{
$data = $request->getAll();
$bill = $this->repository->update($bill, $data);
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class);

View File

@@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\BudgetRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\BudgetLimitTransformer;
@@ -38,20 +39,19 @@ use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
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;
/**
* Class BudgetController.
*
*
*/
class BudgetController extends Controller
{
use TransactionFilter;
/** @var BudgetLimitRepositoryInterface */
private $blRepository;
/** @var BudgetRepositoryInterface The budget repository */
private $repository;
@@ -68,9 +68,10 @@ class BudgetController extends Controller
/** @var User $admin */
$admin = auth()->user();
/** @var BudgetRepositoryInterface repository */
$this->repository = app(BudgetRepositoryInterface::class);
$this->repository = app(BudgetRepositoryInterface::class);
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
$this->repository->setUser($admin);
$this->blRepository->setUser($admin);
return $next($request);
}
@@ -79,26 +80,23 @@ class BudgetController extends Controller
/**
* Display a listing of the resource.
* @param Request $request
*
* @param Budget $budget
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function budgetLimits(Request $request, Budget $budget): JsonResponse
public function budgetLimits(Budget $budget): JsonResponse
{
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$this->parameters->set('budget_id', $budget->id);
$collection = $this->repository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end'));
$collection = $this->blRepository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end'));
$count = $collection->count();
$budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.budgets.budget_limits', [$budget->id]) . $this->buildParams());
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class);
$transformer->setParameters($this->parameters);
@@ -128,16 +126,12 @@ class BudgetController extends Controller
/**
* Display a listing of the resource.
*
* @param Request $request
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function index(Request $request): JsonResponse
public function index(): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -151,9 +145,6 @@ class BudgetController extends Controller
$paginator = new LengthAwarePaginator($budgets, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.budgets.index') . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var BudgetTransformer $transformer */
$transformer = app(BudgetTransformer::class);
$transformer->setParameters($this->parameters);
@@ -167,17 +158,14 @@ class BudgetController extends Controller
/**
* Show a budget.
*
* @param Request $request
* @param Budget $budget
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, Budget $budget): JsonResponse
public function show(Budget $budget): JsonResponse
{
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var BudgetTransformer $transformer */
$transformer = app(BudgetTransformer::class);
@@ -201,9 +189,7 @@ class BudgetController extends Controller
{
$budget = $this->repository->store($request->getAll());
if (null !== $budget) {
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var BudgetTransformer $transformer */
$transformer = app(BudgetTransformer::class);
@@ -220,7 +206,8 @@ class BudgetController extends Controller
* Store a newly created resource in storage.
*
* @param BudgetLimitRequest $request
* @param Budget $budget
* @param Budget $budget
*
* @return JsonResponse
* @throws Exception
*/
@@ -228,10 +215,8 @@ class BudgetController extends Controller
{
$data = $request->getAll();
$data['budget'] = $budget;
$budgetLimit = $this->repository->storeBudgetLimit($data);
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$budgetLimit = $this->blRepository->storeBudgetLimit($data);
$manager = $this->getManager();
/** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class);
@@ -247,7 +232,7 @@ class BudgetController extends Controller
*
* @param Request $request
*
* @param Budget $budget
* @param Budget $budget
*
* @return JsonResponse
* @codeCoverageIgnore
@@ -266,9 +251,7 @@ class BudgetController extends Controller
$this->parameters->set('type', $type);
$types = $this->mapTransactionTypes($this->parameters->get('type'));
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var User $admin */
$admin = auth()->user();
@@ -312,7 +295,7 @@ class BudgetController extends Controller
* Update a budget.
*
* @param BudgetRequest $request
* @param Budget $budget
* @param Budget $budget
*
* @return JsonResponse
*/
@@ -320,9 +303,7 @@ class BudgetController extends Controller
{
$data = $request->getAll();
$budget = $this->repository->update($budget, $data);
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var BudgetTransformer $transformer */
$transformer = app(BudgetTransformer::class);

View File

@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Requests\BudgetLimitRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\BudgetLimitTransformer;
@@ -37,20 +38,19 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
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;
/**
* Class BudgetLimitController.
*
*
*/
class BudgetLimitController extends Controller
{
use TransactionFilter;
/** @var BudgetLimitRepositoryInterface */
private $blRepository;
/** @var BudgetRepositoryInterface The budget repository */
private $repository;
@@ -65,9 +65,11 @@ class BudgetLimitController extends Controller
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(BudgetRepositoryInterface::class);
$user = auth()->user();
$this->repository = app(BudgetRepositoryInterface::class);
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
$this->repository->setUser($user);
$this->blRepository->setUser($user);
return $next($request);
}
@@ -84,7 +86,7 @@ class BudgetLimitController extends Controller
*/
public function delete(BudgetLimit $budgetLimit): JsonResponse
{
$this->repository->destroyBudgetLimit($budgetLimit);
$this->blRepository->destroyBudgetLimit($budgetLimit);
return response()->json([], 204);
}
@@ -99,8 +101,7 @@ class BudgetLimitController extends Controller
*/
public function index(Request $request): JsonResponse
{
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
$budgetId = (int)($request->get('budget_id') ?? 0);
$budget = $this->repository->findNull($budgetId);
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -108,10 +109,10 @@ class BudgetLimitController extends Controller
$collection = new Collection;
if (null === $budget) {
$collection = $this->repository->getAllBudgetLimits($this->parameters->get('start'), $this->parameters->get('end'));
$collection = $this->blRepository->getAllBudgetLimits($this->parameters->get('start'), $this->parameters->get('end'));
}
if (null !== $budget) {
$collection = $this->repository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end'));
$collection = $this->blRepository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end'));
}
$count = $collection->count();
@@ -119,8 +120,6 @@ class BudgetLimitController extends Controller
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.budget_limits.index') . $this->buildParams());
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class);
$transformer->setParameters($this->parameters);
@@ -134,17 +133,14 @@ class BudgetLimitController extends Controller
/**
* Display the specified resource.
*
* @param Request $request
* @param BudgetLimit $budgetLimit
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, BudgetLimit $budgetLimit): JsonResponse
public function show(BudgetLimit $budgetLimit): JsonResponse
{
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class);
@@ -172,10 +168,8 @@ class BudgetLimitController extends Controller
throw new FireflyException('Unknown budget.');
}
$data['budget'] = $budget;
$budgetLimit = $this->repository->storeBudgetLimit($data);
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$budgetLimit = $this->blRepository->storeBudgetLimit($data);
$manager = $this->getManager();
/** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class);
@@ -189,7 +183,7 @@ class BudgetLimitController extends Controller
/**
* Show all transactions.
*
* @param Request $request
* @param Request $request
* @param BudgetLimit $budgetLimit
*
* @return JsonResponse
@@ -202,9 +196,7 @@ class BudgetLimitController extends Controller
$this->parameters->set('type', $type);
$types = $this->mapTransactionTypes($this->parameters->get('type'));
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var User $admin */
$admin = auth()->user();
@@ -245,7 +237,7 @@ class BudgetLimitController extends Controller
* Update the specified resource in storage.
*
* @param BudgetLimitRequest $request
* @param BudgetLimit $budgetLimit
* @param BudgetLimit $budgetLimit
*
* @return JsonResponse
*/
@@ -253,10 +245,8 @@ class BudgetLimitController extends Controller
{
$data = $request->getAll();
$data['budget'] = $budgetLimit->budget;
$budgetLimit = $this->repository->updateBudgetLimit($budgetLimit, $data);
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$budgetLimit = $this->blRepository->updateBudgetLimit($budgetLimit, $data);
$manager = $this->getManager();
/** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class);

View File

@@ -35,16 +35,13 @@ use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
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;
/**
* Class CategoryController.
*
*
*/
class CategoryController extends Controller
{
@@ -92,16 +89,12 @@ class CategoryController extends Controller
/**
* Display a listing of the resource.
*
* @param Request $request
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function index(Request $request): JsonResponse
public function index(): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -115,9 +108,6 @@ class CategoryController extends Controller
$paginator = new LengthAwarePaginator($categories, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.categories.index') . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var CategoryTransformer $transformer */
$transformer = app(CategoryTransformer::class);
$transformer->setParameters($this->parameters);
@@ -133,17 +123,14 @@ class CategoryController extends Controller
/**
* Show the category.
*
* @param Request $request
* @param Category $category
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, Category $category): JsonResponse
public function show(Category $category): JsonResponse
{
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var CategoryTransformer $transformer */
$transformer = app(CategoryTransformer::class);
@@ -166,9 +153,7 @@ class CategoryController extends Controller
{
$category = $this->repository->store($request->getAll());
if (null !== $category) {
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var CategoryTransformer $transformer */
$transformer = app(CategoryTransformer::class);
@@ -184,7 +169,7 @@ class CategoryController extends Controller
/**
* Show all transactions.
*
* @param Request $request
* @param Request $request
*
* @param Category $category
*
@@ -198,9 +183,7 @@ class CategoryController extends Controller
$this->parameters->set('type', $type);
$types = $this->mapTransactionTypes($this->parameters->get('type'));
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var User $admin */
$admin = auth()->user();
@@ -243,7 +226,7 @@ class CategoryController extends Controller
* Update the category.
*
* @param CategoryRequest $request
* @param Category $category
* @param Category $category
*
* @return JsonResponse
*/
@@ -251,9 +234,7 @@ class CategoryController extends Controller
{
$data = $request->getAll();
$category = $this->repository->update($category, $data);
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var CategoryTransformer $transformer */
$transformer = app(CategoryTransformer::class);

View File

@@ -49,6 +49,7 @@ class AccountController extends Controller
/**
* AccountController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
@@ -126,7 +127,7 @@ class AccountController extends Controller
// loop all found currencies and build the data array for the chart.
/**
* @var int $currencyId
* @var int $currencyId
* @var TransactionCurrency $currency
*/
foreach ($currencies as $currencyId => $currency) {
@@ -275,7 +276,7 @@ class AccountController extends Controller
// loop all found currencies and build the data array for the chart.
/**
* @var int $currencyId
* @var int $currencyId
* @var TransactionCurrency $currency
*/
foreach ($currencies as $currencyId => $currency) {

View File

@@ -28,6 +28,7 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Models\AvailableBudget;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
@@ -37,11 +38,14 @@ use Illuminate\Support\Collection;
*/
class AvailableBudgetController extends Controller
{
/** @var OperationsRepositoryInterface */
private $opsRepository;
/** @var BudgetRepositoryInterface */
private $repository;
/**
* AvailableBudgetController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
@@ -50,9 +54,11 @@ class AvailableBudgetController extends Controller
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(BudgetRepositoryInterface::class);
$user = auth()->user();
$this->repository = app(BudgetRepositoryInterface::class);
$this->opsRepository = app(OperationsRepositoryInterface::class);
$this->repository->setUser($user);
$this->opsRepository->setUser($user);
return $next($request);
}
@@ -68,7 +74,7 @@ class AvailableBudgetController extends Controller
{
$currency = $availableBudget->transactionCurrency;
$budgets = $this->repository->getActiveBudgets();
$budgetInformation = $this->repository->spentInPeriodMc($budgets, new Collection, $availableBudget->start_date, $availableBudget->end_date);
$budgetInformation = $this->opsRepository->spentInPeriodMc($budgets, new Collection, $availableBudget->start_date, $availableBudget->end_date);
$spent = 0.0;
// get for current currency

View File

@@ -28,9 +28,10 @@ use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\DateRequest;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Category\NoCategoryRepositoryInterface;
use FireflyIII\Repositories\Category\OperationsRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
/**
* Class CategoryController
@@ -39,9 +40,14 @@ class CategoryController extends Controller
{
/** @var CategoryRepositoryInterface */
private $categoryRepository;
/** @var NoCategoryRepositoryInterface */
private $noCatRepository;
/** @var OperationsRepositoryInterface */
private $opsRepository;
/**
* AccountController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
@@ -52,7 +58,11 @@ class CategoryController extends Controller
/** @var User $user */
$user = auth()->user();
$this->categoryRepository = app(CategoryRepositoryInterface::class);
$this->opsRepository = app(OperationsRepositoryInterface::class);
$this->noCatRepository = app(NoCategoryRepositoryInterface::class);
$this->categoryRepository->setUser($user);
$this->opsRepository->setUser($user);
$this->noCatRepository->setUser($user);
return $next($request);
}
@@ -77,129 +87,111 @@ class CategoryController extends Controller
$end = $dates['end'];
$tempData = [];
$spent = $this->categoryRepository->spentInPeriodPerCurrency(new Collection, new Collection, $start, $end);
$earned = $this->categoryRepository->earnedInPeriodPerCurrency(new Collection, new Collection, $start, $end);
$categories = [];
$tempData = [];
$spentWith = $this->opsRepository->listExpenses($start, $end);
$earnedWith = $this->opsRepository->listIncome($start, $end);
$spentWithout = $this->noCatRepository->listExpenses($start, $end);
$earnedWithout = $this->noCatRepository->listIncome($start, $end);
$categories = [];
// earned:
foreach ($earned as $categoryId => $row) {
$categoryName = $row['name'];
foreach ($row['earned'] as $currencyId => $income) {
// find or make set for currency:
$key = sprintf('%s-e', $currencyId);
$decimalPlaces = $income['currency_decimal_places'];
if (!isset($tempData[$key])) {
$tempData[$key] = [
'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $income['currency_symbol']]),
'currency_id' => $income['currency_id'],
'currency_code' => $income['currency_code'],
'currency_symbol' => $income['currency_symbol'],
'currency_decimal_places' => $decimalPlaces,
foreach ([$spentWith, $earnedWith] as $set) {
foreach ($set as $currency) {
foreach ($currency['categories'] as $category) {
$categories[] = $category['name'];
$inKey = sprintf('%d-i', $currency['currency_id']);
$outKey = sprintf('%d-e', $currency['currency_id']);
// make data arrays if not yet present.
$tempData[$inKey] = $tempData[$inKey] ?? [
'currency_id' => $currency['currency_id'],
'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]),
'currency_code' => $currency['currency_code'],
'currency_symbol' => $currency['currency_symbol'],
'currency_decimal_places' => $currency['currency_decimal_places'],
'type' => 'bar', // line, area or bar
'yAxisID' => 0, // 0, 1, 2
'entries' => [
// per category:
// "category" => 5,
],
];
$tempData[$outKey] = $tempData[$outKey] ?? [
'currency_id' => $currency['currency_id'],
'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
'currency_code' => $currency['currency_code'],
'currency_symbol' => $currency['currency_symbol'],
'currency_decimal_places' => $currency['currency_decimal_places'],
'type' => 'bar', // line, area or bar
'yAxisID' => 0, // 0, 1, 2
'entries' => [
// per category:
// "category" => 5,
],
];
foreach ($category['transaction_journals'] as $journal) {
// is it expense or income?
$letter = -1 === bccomp($journal['amount'], '0') ? 'e' : 'i';
$currentKey = sprintf('%d-%s', $currency['currency_id'], $letter);
$name = $category['name'];
$tempData[$currentKey]['entries'][$name] = $tempData[$currentKey]['entries'][$name] ?? '0';
$tempData[$currentKey]['entries'][$name] = bcadd($tempData[$currentKey]['entries'][$name], $journal['amount']);
}
}
}
}
foreach ([$spentWithout, $earnedWithout] as $set) {
foreach ($set as $currency) {
$inKey = sprintf('%d-i', $currency['currency_id']);
$outKey = sprintf('%d-e', $currency['currency_id']);
$categories[] = (string)trans('firefly.no_category');
// make data arrays if not yet present.
$tempData[$inKey] = $tempData[$inKey] ?? [
'currency_id' => $currency['currency_id'],
'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]),
'currency_code' => $currency['currency_code'],
'currency_symbol' => $currency['currency_symbol'],
'currency_decimal_places' => $currency['currency_decimal_places'],
'type' => 'bar', // line, area or bar
'yAxisID' => 0, // 0, 1, 2
'entries' => [],
'entries' => [
// per category:
// "category" => 5,
],
];
}
$amount = round($income['earned'], $decimalPlaces);
$categories[$categoryName] = isset($categories[$categoryName]) ? $categories[$categoryName] + $amount : $amount;
$tempData[$key]['entries'][$categoryName]
= $amount;
}
}
// earned with no category:
$noCategory = $this->categoryRepository->earnedInPeriodPcWoCategory(new Collection, $start, $end);
foreach ($noCategory as $currencyId => $income) {
$categoryName = (string)trans('firefly.no_category');
// find or make set for currency:
$key = sprintf('%s-e', $currencyId);
$decimalPlaces = $income['currency_decimal_places'];
if (!isset($tempData[$key])) {
$tempData[$key] = [
'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $income['currency_symbol']]),
'currency_id' => $income['currency_id'],
'currency_code' => $income['currency_code'],
'currency_symbol' => $income['currency_symbol'],
'currency_decimal_places' => $decimalPlaces,
'type' => 'bar', // line, area or bar
'yAxisID' => 0, // 0, 1, 2
'entries' => [],
];
}
$amount = round($income['earned'], $decimalPlaces);
$categories[$categoryName] = isset($categories[$categoryName]) ? $categories[$categoryName] + $amount : $amount;
$tempData[$key]['entries'][$categoryName]
= $amount;
}
// spent
foreach ($spent as $categoryId => $row) {
$categoryName = $row['name'];
// create a new set if necessary, "spent (EUR)":
foreach ($row['spent'] as $currencyId => $expense) {
// find or make set for currency:
$key = sprintf('%s-s', $currencyId);
$decimalPlaces = $expense['currency_decimal_places'];
if (!isset($tempData[$key])) {
$tempData[$key] = [
'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $expense['currency_symbol']]),
'currency_id' => $expense['currency_id'],
'currency_code' => $expense['currency_code'],
'currency_symbol' => $expense['currency_symbol'],
'currency_decimal_places' => $decimalPlaces,
$tempData[$outKey] = $tempData[$outKey] ?? [
'currency_id' => $currency['currency_id'],
'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
'currency_code' => $currency['currency_code'],
'currency_symbol' => $currency['currency_symbol'],
'currency_decimal_places' => $currency['currency_decimal_places'],
'type' => 'bar', // line, area or bar
'yAxisID' => 0, // 0, 1, 2
'entries' => [],
'entries' => [
// per category:
// "category" => 5,
],
];
foreach ($currency['transaction_journals'] as $journal) {
// is it expense or income?
$letter = -1 === bccomp($journal['amount'], '0') ? 'e' : 'i';
$currentKey = sprintf('%d-%s', $currency['currency_id'], $letter);
$name = (string)trans('firefly.no_category');
$tempData[$currentKey]['entries'][$name] = $tempData[$currentKey]['entries'][$name] ?? '0';
$tempData[$currentKey]['entries'][$name] = bcadd($tempData[$currentKey]['entries'][$name], $journal['amount']);
}
$amount = round($expense['spent'], $decimalPlaces);
$categories[$categoryName] = isset($categories[$categoryName]) ? $categories[$categoryName] + $amount : $amount;
$tempData[$key]['entries'][$categoryName]
= $amount;
}
}
// spent with no category
$noCategory = $this->categoryRepository->spentInPeriodPcWoCategory(new Collection, $start, $end);
foreach ($noCategory as $currencyId => $expense) {
$categoryName = (string)trans('firefly.no_category');
// find or make set for currency:
$key = sprintf('%s-s', $currencyId);
$decimalPlaces = $expense['currency_decimal_places'];
if (!isset($tempData[$key])) {
$tempData[$key] = [
'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $expense['currency_symbol']]),
'currency_id' => $expense['currency_id'],
'currency_code' => $expense['currency_code'],
'currency_symbol' => $expense['currency_symbol'],
'currency_decimal_places' => $decimalPlaces,
'type' => 'bar', // line, area or bar
'yAxisID' => 0, // 0, 1, 2
'entries' => [],
];
}
$amount = round($expense['spent'], $decimalPlaces);
$categories[$categoryName] = isset($categories[$categoryName]) ? $categories[$categoryName] + $amount : $amount;
$tempData[$key]['entries'][$categoryName]
= $amount;
}
asort($categories);
$keys = array_keys($categories);
// re-sort every spent array and add 0 for missing entries.
foreach ($tempData as $index => $set) {
$oldSet = $set['entries'];
$newSet = [];
foreach ($keys as $key) {
$value = $oldSet[$key] ?? 0;
$value = $value < 0 ? $value * -1 : $value;
$newSet[$key] = $value;
foreach ($categories as $category) {
$value = $oldSet[$category] ?? '0';
$value = -1 === bccomp($value, '0') ? bcmul($value, '-1') : $value;
$newSet[$category] = $value;
}
$tempData[$index]['entries'] = $newSet;
}

View File

@@ -32,6 +32,7 @@ use Illuminate\Http\JsonResponse;
/**
* Class ConfigurationController.
*
* @codeCoverageIgnore
*/
class ConfigurationController extends Controller
@@ -80,7 +81,7 @@ class ConfigurationController extends Controller
* Update the configuration.
*
* @param ConfigurationRequest $request
* @param string $name
* @param string $name
*
* @return JsonResponse
*/

View File

@@ -30,6 +30,8 @@ use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use League\Fractal\Manager;
use League\Fractal\Serializer\JsonApiSerializer;
use Log;
use Symfony\Component\HttpFoundation\ParameterBag;
@@ -81,6 +83,19 @@ class Controller extends BaseController
return $return;
}
/**
* @return Manager
*/
protected function getManager(): Manager
{
// create some objects:
$manager = new Manager;
$baseUrl = request()->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
return $manager;
}
/**
* Method to grab all parameters from the URI.
*

View File

@@ -36,6 +36,8 @@ use FireflyIII\Models\RuleTrigger;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
@@ -56,17 +58,13 @@ use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
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;
/**
* Class CurrencyController.
*
*
*/
class CurrencyController extends Controller
{
@@ -78,6 +76,7 @@ class CurrencyController extends Controller
/**
* CurrencyRepository constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
@@ -101,7 +100,7 @@ class CurrencyController extends Controller
/**
* Display a list of accounts.
*
* @param Request $request
* @param Request $request
* @param TransactionCurrency $currency
*
* @return JsonResponse
@@ -109,9 +108,7 @@ class CurrencyController extends Controller
*/
public function accounts(Request $request, TransactionCurrency $currency): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// read type from URI
$type = $request->get('type') ?? 'all';
@@ -142,9 +139,6 @@ class CurrencyController extends Controller
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.accounts', [$currency->code]) . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters);
@@ -159,22 +153,17 @@ class CurrencyController extends Controller
/**
* Display a listing of the resource.
*
* @param Request $request
*
* @param TransactionCurrency $currency
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function availableBudgets(Request $request, TransactionCurrency $currency): JsonResponse
public function availableBudgets(TransactionCurrency $currency): JsonResponse
{
/** @var User $admin */
$admin = auth()->user();
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -182,8 +171,12 @@ class CurrencyController extends Controller
/** @var BudgetRepositoryInterface $repository */
$repository = app(BudgetRepositoryInterface::class);
/** @var AvailableBudgetRepositoryInterface $abRepository */
$abRepository = app(AvailableBudgetRepositoryInterface::class);
$repository->setUser($admin);
$collection = $repository->getAvailableBudgetsByCurrency($currency);
$collection = $abRepository->getAvailableBudgetsByCurrency($currency);
$count = $collection->count();
$availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
@@ -192,9 +185,6 @@ class CurrencyController extends Controller
$paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.available_budgets', [$currency->code]) . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var AvailableBudgetTransformer $transformer */
$transformer = app(AvailableBudgetTransformer::class);
$transformer->setParameters($this->parameters);
@@ -208,24 +198,19 @@ class CurrencyController extends Controller
/**
* List all bills
*
* @param Request $request
* @param TransactionCurrency $currency
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function bills(Request $request, TransactionCurrency $currency): JsonResponse
public function bills(TransactionCurrency $currency): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
/** @var BillRepositoryInterface $repository */
$repository = app(BillRepositoryInterface::class);
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$paginator = $repository->getPaginator($pageSize);
/** @var Collection $bills */
$unfiltered = $paginator->getCollection();
$unfiltered = $repository->getBills();
// filter and paginate list:
$collection = $unfiltered->filter(
@@ -240,9 +225,6 @@ class CurrencyController extends Controller
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.bills', [$currency->code]) . $this->buildParams());
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class);
$transformer->setParameters($this->parameters);
@@ -256,28 +238,24 @@ class CurrencyController extends Controller
/**
* List all budget limits
*
* @param Request $request
*
* @param TransactionCurrency $currency
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function budgetLimits(Request $request, TransactionCurrency $currency): JsonResponse
public function budgetLimits(TransactionCurrency $currency): JsonResponse
{
/** @var BudgetRepositoryInterface $repository */
$repository = app(BudgetRepositoryInterface::class);
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
/** @var BudgetLimitRepositoryInterface $blRepository */
$blRepository = app(BudgetLimitRepositoryInterface::class);
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $repository->getAllBudgetLimitsByCurrency($currency, $this->parameters->get('start'), $this->parameters->get('end'));
$collection = $blRepository->getAllBudgetLimitsByCurrency($currency, $this->parameters->get('start'), $this->parameters->get('end'));
$count = $collection->count();
$budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.budget_limits', [$currency->code]) . $this->buildParams());
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class);
$transformer->setParameters($this->parameters);
@@ -291,20 +269,17 @@ class CurrencyController extends Controller
/**
* Show a list of known exchange rates
*
* @param Request $request
* @param TransactionCurrency $currency
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function cer(Request $request, TransactionCurrency $currency): JsonResponse
public function cer(TransactionCurrency $currency): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $this->repository->getExchangeRates($currency);
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$count = $collection->count();
@@ -312,8 +287,6 @@ class CurrencyController extends Controller
$paginator = new LengthAwarePaginator($exchangeRates, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.cer', [$currency->code]) . $this->buildParams());
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var CurrencyExchangeRateTransformer $transformer */
$transformer = app(CurrencyExchangeRateTransformer::class);
$transformer->setParameters($this->parameters);
@@ -353,22 +326,19 @@ class CurrencyController extends Controller
/**
* Disable a currency.
*
* @param Request $request
* @param TransactionCurrency $currency
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function disable(Request $request, TransactionCurrency $currency): JsonResponse
public function disable(TransactionCurrency $currency): JsonResponse
{
// must be unused.
if ($this->repository->currencyInUse($currency)) {
return response()->json([], 409);
}
$this->repository->disable($currency);
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $defaultCurrency);
@@ -386,18 +356,15 @@ class CurrencyController extends Controller
/**
* Enable a currency.
*
* @param Request $request
* @param TransactionCurrency $currency
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function enable(Request $request, TransactionCurrency $currency): JsonResponse
public function enable(TransactionCurrency $currency): JsonResponse
{
$this->repository->enable($currency);
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $defaultCurrency);
@@ -415,12 +382,10 @@ class CurrencyController extends Controller
/**
* Display a listing of the resource.
*
* @param Request $request
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function index(Request $request): JsonResponse
public function index(): JsonResponse
{
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $this->repository->getAll();
@@ -431,9 +396,7 @@ class CurrencyController extends Controller
$paginator->setPath(route('api.v1.currencies.index') . $this->buildParams());
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $defaultCurrency);
@@ -450,22 +413,19 @@ class CurrencyController extends Controller
/**
* Make the currency a default currency.
*
* @param Request $request
* @param TransactionCurrency $currency
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function makeDefault(Request $request, TransactionCurrency $currency): JsonResponse
public function makeDefault(TransactionCurrency $currency): JsonResponse
{
$this->repository->enable($currency);
app('preferences')->set('currencyPreference', $currency->code);
app('preferences')->mark();
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
$this->parameters->set('defaultCurrency', $currency);
@@ -482,19 +442,14 @@ class CurrencyController extends Controller
/**
* List all recurring transactions.
*
* @param Request $request
*
* @param TransactionCurrency $currency
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function recurrences(Request $request, TransactionCurrency $currency): JsonResponse
public function recurrences(TransactionCurrency $currency): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -525,9 +480,6 @@ class CurrencyController extends Controller
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.recurrences', [$currency->code]) . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var RecurrenceTransformer $transformer */
$transformer = app(RecurrenceTransformer::class);
$transformer->setParameters($this->parameters);
@@ -542,16 +494,14 @@ class CurrencyController extends Controller
/**
* List all of them.
*
* @param Request $request
* @param TransactionCurrency $currency
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function rules(Request $request, TransactionCurrency $currency): JsonResponse
public function rules(TransactionCurrency $currency): JsonResponse
{
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it.
@@ -579,9 +529,6 @@ class CurrencyController extends Controller
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.rules.index') . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var RuleTransformer $transformer */
$transformer = app(RuleTransformer::class);
$transformer->setParameters($this->parameters);
@@ -596,17 +543,14 @@ class CurrencyController extends Controller
/**
* Show a currency.
*
* @param Request $request
* @param TransactionCurrency $currency
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, TransactionCurrency $currency): JsonResponse
public function show(TransactionCurrency $currency): JsonResponse
{
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $defaultCurrency);
@@ -636,9 +580,7 @@ class CurrencyController extends Controller
app('preferences')->set('currencyPreference', $currency->code);
app('preferences')->mark();
}
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $defaultCurrency);
@@ -657,7 +599,7 @@ class CurrencyController extends Controller
/**
* Show all transactions.
*
* @param Request $request
* @param Request $request
*
* @param TransactionCurrency $currency
*
@@ -671,9 +613,7 @@ class CurrencyController extends Controller
$this->parameters->set('type', $type);
$types = $this->mapTransactionTypes($this->parameters->get('type'));
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var User $admin */
$admin = auth()->user();
@@ -715,7 +655,7 @@ class CurrencyController extends Controller
/**
* Update a currency.
*
* @param CurrencyRequest $request
* @param CurrencyRequest $request
* @param TransactionCurrency $currency
*
* @return JsonResponse
@@ -730,9 +670,7 @@ class CurrencyController extends Controller
app('preferences')->mark();
}
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $defaultCurrency);

View File

@@ -31,12 +31,11 @@ use FireflyIII\Transformers\CurrencyExchangeRateTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use League\Fractal\Manager;
use League\Fractal\Resource\Item;
use League\Fractal\Serializer\JsonApiSerializer;
/**
* Class CurrencyExchangeRateController
*
* @codeCoverageIgnore
*/
class CurrencyExchangeRateController extends Controller
@@ -75,11 +74,7 @@ class CurrencyExchangeRateController extends Controller
*/
public function index(Request $request): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
$fromCurrency = $this->repository->findByCodeNull($request->get('from') ?? 'EUR');
$toCurrency = $this->repository->findByCodeNull($request->get('to') ?? 'USD');

View File

@@ -34,11 +34,9 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
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;
/**
* Class ImportController
@@ -51,6 +49,7 @@ class ImportController extends Controller
/**
* ImportController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
@@ -69,16 +68,13 @@ class ImportController extends Controller
}
/**
* @param Request $request
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function listAll(Request $request): JsonResponse
public function listAll(): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of accounts. Count it and split it.
@@ -90,9 +86,6 @@ class ImportController extends Controller
$paginator = new LengthAwarePaginator($importJobs, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.import.list') . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var ImportJobTransformer $transformer */
$transformer = app(ImportJobTransformer::class);
$transformer->setParameters($this->parameters);
@@ -104,18 +97,14 @@ class ImportController extends Controller
}
/**
* @param Request $request
* @param ImportJob $importJob
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, ImportJob $importJob): JsonResponse
public function show(ImportJob $importJob): JsonResponse
{
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var ImportJobTransformer $transformer */
$transformer = app(ImportJobTransformer::class);
$transformer->setParameters($this->parameters);
@@ -128,7 +117,7 @@ class ImportController extends Controller
/**
* Show all transactions
*
* @param Request $request
* @param Request $request
* @param ImportJob $importJob
*
* @return JsonResponse
@@ -141,9 +130,7 @@ class ImportController extends Controller
$this->parameters->set('type', $type);
$types = $this->mapTransactionTypes($this->parameters->get('type'));
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
$tag = $importJob->tag;
$transactions = new Collection();

View File

@@ -36,16 +36,13 @@ use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
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;
/**
* Class LinkTypeController.
*
*
*/
class LinkTypeController extends Controller
{
@@ -99,16 +96,13 @@ class LinkTypeController extends Controller
/**
* List all of them.
*
* @param Request $request
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function index(Request $request): JsonResponse
public function index(): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of accounts. Count it and split it.
@@ -120,9 +114,6 @@ class LinkTypeController extends Controller
$paginator = new LengthAwarePaginator($linkTypes, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.link_types.index') . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var LinkTypeTransformer $transformer */
$transformer = app(LinkTypeTransformer::class);
$transformer->setParameters($this->parameters);
@@ -137,17 +128,14 @@ class LinkTypeController extends Controller
/**
* List single resource.
*
* @param Request $request
* @param LinkType $linkType
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, LinkType $linkType): JsonResponse
public function show(LinkType $linkType): JsonResponse
{
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var LinkTypeTransformer $transformer */
$transformer = app(LinkTypeTransformer::class);
$transformer->setParameters($this->parameters);
@@ -177,9 +165,7 @@ class LinkTypeController extends Controller
$data = $request->getAll();
// if currency ID is 0, find the currency by the code:
$linkType = $this->repository->store($data);
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var LinkTypeTransformer $transformer */
$transformer = app(LinkTypeTransformer::class);
@@ -193,7 +179,7 @@ class LinkTypeController extends Controller
/**
* Delete the resource.
*
* @param Request $request
* @param Request $request
* @param LinkType $linkType
*
* @return JsonResponse
@@ -206,9 +192,7 @@ class LinkTypeController extends Controller
$this->parameters->set('type', $type);
$types = $this->mapTransactionTypes($this->parameters->get('type'));
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
// whatever is returned by the query, it must be part of these journals:
$journalIds = $this->repository->getJournalIds($linkType);
@@ -255,7 +239,7 @@ class LinkTypeController extends Controller
* Update object.
*
* @param LinkTypeRequest $request
* @param LinkType $linkType
* @param LinkType $linkType
*
* @return JsonResponse
* @throws FireflyException
@@ -275,10 +259,7 @@ class LinkTypeController extends Controller
$data = $request->getAll();
$this->repository->update($linkType, $data);
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var LinkTypeTransformer $transformer */
$transformer = app(LinkTypeTransformer::class);
$transformer->setParameters($this->parameters);

View File

@@ -31,18 +31,14 @@ use FireflyIII\Transformers\PiggyBankEventTransformer;
use FireflyIII\Transformers\PiggyBankTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
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;
/**
* Class PiggyBankController.
*
*
*/
class PiggyBankController extends Controller
{
@@ -90,17 +86,12 @@ class PiggyBankController extends Controller
/**
* List all of them.
*
* @param Request $request
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function index(Request $request): JsonResponse
public function index(): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -113,9 +104,6 @@ class PiggyBankController extends Controller
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.piggy_banks.index') . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class);
$transformer->setParameters($this->parameters);
@@ -130,19 +118,16 @@ class PiggyBankController extends Controller
/**
* List single resource.
*
* @param Request $request
* @param PiggyBank $piggyBank
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function piggyBankEvents(Request $request, PiggyBank $piggyBank): JsonResponse
public function piggyBankEvents(PiggyBank $piggyBank): JsonResponse
{
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
$collection = $this->repository->getEvents($piggyBank);
$count = $collection->count();
@@ -166,17 +151,14 @@ class PiggyBankController extends Controller
/**
* List single resource.
*
* @param Request $request
* @param PiggyBank $piggyBank
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, PiggyBank $piggyBank): JsonResponse
public function show(PiggyBank $piggyBank): JsonResponse
{
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class);
@@ -200,9 +182,7 @@ class PiggyBankController extends Controller
{
$piggyBank = $this->repository->store($request->getAll());
if (null !== $piggyBank) {
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class);
@@ -220,7 +200,7 @@ class PiggyBankController extends Controller
* Update piggy bank.
*
* @param PiggyBankRequest $request
* @param PiggyBank $piggyBank
* @param PiggyBank $piggyBank
*
* @return JsonResponse
*/
@@ -234,10 +214,7 @@ class PiggyBankController extends Controller
}
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class);
$transformer->setParameters($this->parameters);

View File

@@ -30,12 +30,9 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Transformers\PreferenceTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use League\Fractal\Manager;
use League\Fractal\Resource\Collection as FractalCollection;
use League\Fractal\Resource\Item;
use League\Fractal\Serializer\JsonApiSerializer;
/**
*
@@ -76,12 +73,10 @@ class PreferenceController extends Controller
/**
* List all of them.
*
* @param Request $request
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function index(Request $request): JsonResponse
public function index(): JsonResponse
{
/** @var User $user */
$user = auth()->user();
@@ -99,12 +94,7 @@ class PreferenceController extends Controller
}
}
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var PreferenceTransformer $transformer */
$transformer = app(PreferenceTransformer::class);
@@ -119,20 +109,14 @@ class PreferenceController extends Controller
/**
* Return a single preference by name.
*
* @param Request $request
* @param Preference $preference
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, Preference $preference): JsonResponse
public function show(Preference $preference): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var PreferenceTransformer $transformer */
$transformer = app(PreferenceTransformer::class);
$transformer->setParameters($this->parameters);
@@ -146,7 +130,7 @@ class PreferenceController extends Controller
* Update a preference.
*
* @param PreferenceRequest $request
* @param Preference $preference
* @param Preference $preference
*
* @return JsonResponse
*/
@@ -171,12 +155,7 @@ class PreferenceController extends Controller
}
$result = app('preferences')->set($preference->name, $newValue);
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var PreferenceTransformer $transformer */
$transformer = app(PreferenceTransformer::class);
$transformer->setParameters($this->parameters);

View File

@@ -37,11 +37,9 @@ use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
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 Log;
/**
@@ -93,16 +91,12 @@ class RecurrenceController extends Controller
/**
* List all of them.
*
* @param Request $request
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function index(Request $request): JsonResponse
public function index(): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -116,9 +110,6 @@ class RecurrenceController extends Controller
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.recurrences.index') . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var RecurrenceTransformer $transformer */
$transformer = app(RecurrenceTransformer::class);
$transformer->setParameters($this->parameters);
@@ -133,17 +124,14 @@ class RecurrenceController extends Controller
/**
* List single resource.
*
* @param Request $request
* @param Recurrence $recurrence
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, Recurrence $recurrence): JsonResponse
public function show(Recurrence $recurrence): JsonResponse
{
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var RecurrenceTransformer $transformer */
$transformer = app(RecurrenceTransformer::class);
@@ -162,13 +150,13 @@ class RecurrenceController extends Controller
* @param RecurrenceStoreRequest $request
*
* @return JsonResponse
* @throws FireflyException
*/
public function store(RecurrenceStoreRequest $request): JsonResponse
{
$recurrence = $this->repository->store($request->getAllRecurrenceData());
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$data = $request->getAll();
$recurrence = $this->repository->store($data);
$manager = $this->getManager();
/** @var RecurrenceTransformer $transformer */
$transformer = app(RecurrenceTransformer::class);
@@ -182,7 +170,7 @@ class RecurrenceController extends Controller
/**
* Show transactions for this recurrence.
*
* @param Request $request
* @param Request $request
* @param Recurrence $recurrence
*
* @return JsonResponse
@@ -195,10 +183,7 @@ class RecurrenceController extends Controller
$this->parameters->set('type', $type);
$types = $this->mapTransactionTypes($this->parameters->get('type'));
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
// whatever is returned by the query, it must be part of these journals:
$journalIds = $this->repository->getJournalIds($recurrence);
@@ -267,17 +252,16 @@ class RecurrenceController extends Controller
* Update single recurrence.
*
* @param RecurrenceUpdateRequest $request
* @param Recurrence $recurrence
* @param Recurrence $recurrence
*
* @return JsonResponse
*/
public function update(RecurrenceUpdateRequest $request, Recurrence $recurrence): JsonResponse
{
$data = $request->getAllRecurrenceData();
$data = $request->getAll();
$category = $this->repository->update($recurrence, $data);
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var RecurrenceTransformer $transformer */
$transformer = app(RecurrenceTransformer::class);
$transformer->setParameters($this->parameters);

View File

@@ -23,9 +23,10 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers;
use FireflyIII\Api\V1\Requests\RuleRequest;
use FireflyIII\Api\V1\Requests\RuleStoreRequest;
use FireflyIII\Api\V1\Requests\RuleTestRequest;
use FireflyIII\Api\V1\Requests\RuleTriggerRequest;
use FireflyIII\Api\V1\Requests\RuleUpdateRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Rule;
@@ -37,13 +38,10 @@ use FireflyIII\Transformers\RuleTransformer;
use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
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 Log;
/**
@@ -59,6 +57,7 @@ class RuleController extends Controller
/**
* RuleController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
@@ -98,16 +97,12 @@ class RuleController extends Controller
/**
* List all of them.
*
* @param Request $request
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function index(Request $request): JsonResponse
public function index(): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -121,9 +116,6 @@ class RuleController extends Controller
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.rules.index') . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var RuleTransformer $transformer */
$transformer = app(RuleTransformer::class);
$transformer->setParameters($this->parameters);
@@ -135,21 +127,59 @@ class RuleController extends Controller
}
/**
* @param Rule $rule
*
* @return JsonResponse
*/
public function moveDown(Rule $rule): JsonResponse
{
$this->ruleRepository->moveDown($rule);
$rule = $this->ruleRepository->find($rule->id);
$manager = $this->getManager();
/** @var RuleTransformer $transformer */
$transformer = app(RuleTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($rule, $transformer, 'rules');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* @param Rule $rule
*
* @return JsonResponse
*/
public function moveUp(Rule $rule): JsonResponse
{
$this->ruleRepository->moveUp($rule);
$rule = $this->ruleRepository->find($rule->id);
$manager = $this->getManager();
/** @var RuleTransformer $transformer */
$transformer = app(RuleTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($rule, $transformer, 'rules');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* List single resource.
*
* @param Request $request
* @param Rule $rule
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, Rule $rule): JsonResponse
public function show(Rule $rule): JsonResponse
{
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var RuleTransformer $transformer */
$transformer = app(RuleTransformer::class);
$transformer->setParameters($this->parameters);
@@ -163,17 +193,14 @@ class RuleController extends Controller
/**
* Store new object.
*
* @param RuleRequest $request
* @param RuleStoreRequest $request
*
* @return JsonResponse
*/
public function store(RuleRequest $request): JsonResponse
public function store(RuleStoreRequest $request): JsonResponse
{
$rule = $this->ruleRepository->store($request->getAll());
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var RuleTransformer $transformer */
$transformer = app(RuleTransformer::class);
$transformer->setParameters($this->parameters);
@@ -185,7 +212,7 @@ class RuleController extends Controller
/**
* @param RuleTestRequest $request
* @param Rule $rule
* @param Rule $rule
*
* @return JsonResponse
* @throws FireflyException
@@ -213,10 +240,7 @@ class RuleController extends Controller
$paginator->setPath(route('api.v1.rules.test', [$rule->id]) . $this->buildParams());
// resulting list is presented as JSON thing.
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var TransactionGroupTransformer $transformer */
$transformer = app(TransactionGroupTransformer::class);
$transformer->setParameters($this->parameters);
@@ -231,7 +255,7 @@ class RuleController extends Controller
* Execute the given rule group on a set of existing transactions.
*
* @param RuleTriggerRequest $request
* @param Rule $rule
* @param Rule $rule
*
* @return JsonResponse
*/
@@ -268,18 +292,16 @@ class RuleController extends Controller
/**
* Update a rule.
*
* @param RuleRequest $request
* @param Rule $rule
* @param RuleUpdateRequest $request
* @param Rule $rule
*
* @return JsonResponse
*/
public function update(RuleRequest $request, Rule $rule): JsonResponse
public function update(RuleUpdateRequest $request, Rule $rule): JsonResponse
{
$rule = $this->ruleRepository->update($rule, $request->getAll());
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$data = $request->getAll();
$rule = $this->ruleRepository->update($rule, $data);
$manager = $this->getManager();
/** @var RuleTransformer $transformer */
$transformer = app(RuleTransformer::class);
@@ -289,50 +311,4 @@ class RuleController extends Controller
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* @param Request $request
* @param Rule $rule
* @return JsonResponse
*/
public function moveDown(Request $request, Rule $rule): JsonResponse
{
$this->ruleRepository->moveDown($rule);
$rule = $this->ruleRepository->find($rule->id);
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var RuleTransformer $transformer */
$transformer = app(RuleTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($rule, $transformer, 'rules');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* @param Request $request
* @param Rule $rule
* @return JsonResponse
*/
public function moveUp(Request $request, Rule $rule): JsonResponse
{
$this->ruleRepository->moveUp($rule);
$rule = $this->ruleRepository->find($rule->id);
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var RuleTransformer $transformer */
$transformer = app(RuleTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($rule, $transformer, 'rules');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
}

View File

@@ -40,14 +40,11 @@ use FireflyIII\Transformers\RuleTransformer;
use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
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 Log;
/**
@@ -62,6 +59,7 @@ class RuleGroupController extends Controller
/**
* RuleGroupController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
@@ -101,17 +99,12 @@ class RuleGroupController extends Controller
/**
* List all of them.
*
* @param Request $request
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function index(Request $request): JsonResponse
public function index(): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -124,9 +117,6 @@ class RuleGroupController extends Controller
$paginator = new LengthAwarePaginator($ruleGroups, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.rule_groups.index') . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var RuleGroupTransformer $transformer */
$transformer = app(RuleGroupTransformer::class);
$transformer->setParameters($this->parameters);
@@ -138,18 +128,54 @@ class RuleGroupController extends Controller
}
/**
* @param Request $request
* @param RuleGroup $ruleGroup
*
* @return JsonResponse
*/
public function moveDown(RuleGroup $ruleGroup): JsonResponse
{
$this->ruleGroupRepository->moveDown($ruleGroup);
$ruleGroup = $this->ruleGroupRepository->find($ruleGroup->id);
$manager = $this->getManager();
/** @var RuleGroupTransformer $transformer */
$transformer = app(RuleGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($ruleGroup, $transformer, 'rule_groups');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* @param RuleGroup $ruleGroup
*
* @return JsonResponse
*/
public function moveUp(RuleGroup $ruleGroup): JsonResponse
{
$this->ruleGroupRepository->moveUp($ruleGroup);
$ruleGroup = $this->ruleGroupRepository->find($ruleGroup->id);
$manager = $this->getManager();
/** @var RuleGroupTransformer $transformer */
$transformer = app(RuleGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($ruleGroup, $transformer, 'rule_groups');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* @param RuleGroup $group
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function rules(Request $request, RuleGroup $group): JsonResponse
public function rules(RuleGroup $group): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -162,9 +188,6 @@ class RuleGroupController extends Controller
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.rule_groups.rules', [$group->id]) . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var RuleTransformer $transformer */
$transformer = app(RuleTransformer::class);
$transformer->setParameters($this->parameters);
@@ -179,18 +202,14 @@ class RuleGroupController extends Controller
/**
* List single resource.
*
* @param Request $request
* @param RuleGroup $ruleGroup
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, RuleGroup $ruleGroup): JsonResponse
public function show(RuleGroup $ruleGroup): JsonResponse
{
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var RuleGroupTransformer $transformer */
$transformer = app(RuleGroupTransformer::class);
$transformer->setParameters($this->parameters);
@@ -211,9 +230,7 @@ class RuleGroupController extends Controller
public function store(RuleGroupRequest $request): JsonResponse
{
$ruleGroup = $this->ruleGroupRepository->store($request->getAll());
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var RuleGroupTransformer $transformer */
$transformer = app(RuleGroupTransformer::class);
@@ -227,7 +244,7 @@ class RuleGroupController extends Controller
/**
* @param RuleGroupTestRequest $request
* @param RuleGroup $group
* @param RuleGroup $group
*
* @return JsonResponse
* @throws FireflyException
@@ -272,11 +289,7 @@ class RuleGroupController extends Controller
$paginator = new LengthAwarePaginator($transactions, $count, $pageSize, $parameters['page']);
$paginator->setPath(route('api.v1.rule_groups.test', [$group->id]) . $this->buildParams());
// resulting list is presented as JSON thing.
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
$transformer = app(TransactionGroupTransformer::class);
$transformer->setParameters($this->parameters);
@@ -290,7 +303,7 @@ class RuleGroupController extends Controller
* Execute the given rule group on a set of existing transactions.
*
* @param RuleGroupTriggerRequest $request
* @param RuleGroup $group
* @param RuleGroup $group
*
* @return JsonResponse
* @throws Exception
@@ -334,60 +347,14 @@ class RuleGroupController extends Controller
* Update a rule group.
*
* @param RuleGroupRequest $request
* @param RuleGroup $ruleGroup
* @param RuleGroup $ruleGroup
*
* @return JsonResponse
*/
public function update(RuleGroupRequest $request, RuleGroup $ruleGroup): JsonResponse
{
$ruleGroup = $this->ruleGroupRepository->update($ruleGroup, $request->getAll());
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var RuleGroupTransformer $transformer */
$transformer = app(RuleGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($ruleGroup, $transformer, 'rule_groups');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* @param Request $request
* @param RuleGroup $ruleGroup
* @return JsonResponse
*/
public function moveDown(Request $request, RuleGroup $ruleGroup): JsonResponse
{
$this->ruleGroupRepository->moveDown($ruleGroup);
$ruleGroup = $this->ruleGroupRepository->find($ruleGroup->id);
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var RuleGroupTransformer $transformer */
$transformer = app(RuleGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($ruleGroup, $transformer, 'rule_groups');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* @param Request $request
* @param RuleGroup $ruleGroup
* @return JsonResponse
*/
public function moveUp(Request $request, RuleGroup $ruleGroup): JsonResponse
{
$this->ruleGroupRepository->moveUp($ruleGroup);
$ruleGroup = $this->ruleGroupRepository->find($ruleGroup->id);
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var RuleGroupTransformer $transformer */
$transformer = app(RuleGroupTransformer::class);

View File

@@ -36,7 +36,9 @@ use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionType;
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\User;
use Illuminate\Http\JsonResponse;
@@ -47,6 +49,8 @@ use Illuminate\Support\Collection;
*/
class SummaryController extends Controller
{
/** @var AvailableBudgetRepositoryInterface */
private $abRepository;
/** @var AccountRepositoryInterface */
private $accountRepository;
/** @var BillRepositoryInterface */
@@ -56,8 +60,12 @@ class SummaryController extends Controller
/** @var CurrencyRepositoryInterface */
private $currencyRepos;
/** @var OperationsRepositoryInterface */
private $opsRepository;
/**
* SummaryController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
@@ -71,11 +79,15 @@ class SummaryController extends Controller
$this->billRepository = app(BillRepositoryInterface::class);
$this->budgetRepository = app(BudgetRepositoryInterface::class);
$this->accountRepository = app(AccountRepositoryInterface::class);
$this->abRepository = app(AvailableBudgetRepositoryInterface::class);
$this->opsRepository = app(OperationsRepositoryInterface::class);
$this->billRepository->setUser($user);
$this->currencyRepos->setUser($user);
$this->budgetRepository->setUser($user);
$this->accountRepository->setUser($user);
$this->abRepository->setUser($user);
$this->opsRepository->setUser($user);
return $next($request);
@@ -140,6 +152,25 @@ class SummaryController extends Controller
return $result;
}
/**
* This method will scroll through the results of the spentInPeriodMc() array and return the correct info.
*
* @param array $spentInfo
* @param TransactionCurrency $currency
*
* @return string
*/
private function findInSpentArray(array $spentInfo, TransactionCurrency $currency): string
{
foreach ($spentInfo as $array) {
if ($array['currency_id'] === $currency->id) {
return (string)$array['amount'];
}
}
return '0'; // @codeCoverageIgnore
}
/**
* @param Carbon $start
* @param Carbon $end
@@ -316,9 +347,9 @@ class SummaryController extends Controller
{
$return = [];
$today = new Carbon;
$available = $this->budgetRepository->getAvailableBudgetWithCurrency($start, $end);
$available = $this->abRepository->getAvailableBudgetWithCurrency($start, $end);
$budgets = $this->budgetRepository->getActiveBudgets();
$spentInfo = $this->budgetRepository->spentInPeriodMc($budgets, new Collection, $start, $end);
$spentInfo = $this->opsRepository->spentInPeriodMc($budgets, new Collection, $start, $end);
foreach ($available as $currencyId => $amount) {
$currency = $this->currencyRepos->findNull($currencyId);
if (null === $currency) {
@@ -350,25 +381,6 @@ class SummaryController extends Controller
return $return;
}
/**
* This method will scroll through the results of the spentInPeriodMc() array and return the correct info.
*
* @param array $spentInfo
* @param TransactionCurrency $currency
*
* @return float
*/
private function findInSpentArray(array $spentInfo, TransactionCurrency $currency): float
{
foreach ($spentInfo as $array) {
if ($array['currency_id'] === $currency->id) {
return $array['amount'];
}
}
return 0.0; // @codeCoverageIgnore
}
/**
* @param Carbon $start
* @param Carbon $end

View File

@@ -37,11 +37,9 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
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;
/**
* Class TagController
@@ -111,17 +109,12 @@ class TagController extends Controller
/**
* List all of them.
*
* @param Request $request
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function index(Request $request): JsonResponse
public function index(): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -134,9 +127,6 @@ class TagController extends Controller
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.tags.index') . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var TagTransformer $transformer */
$transformer = app(TagTransformer::class);
$transformer->setParameters($this->parameters);
@@ -150,18 +140,14 @@ class TagController extends Controller
/**
* List single resource.
*
* @param Request $request
* @param Tag $tag
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, Tag $tag): JsonResponse
public function show(Tag $tag): JsonResponse
{
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var TagTransformer $transformer */
$transformer = app(TagTransformer::class);
$transformer->setParameters($this->parameters);
@@ -182,10 +168,7 @@ class TagController extends Controller
public function store(TagRequest $request): JsonResponse
{
$rule = $this->repository->store($request->getAll());
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var TagTransformer $transformer */
$transformer = app(TagTransformer::class);
$transformer->setParameters($this->parameters);
@@ -199,7 +182,7 @@ class TagController extends Controller
* Show all transactions.
*
* @param Request $request
* @param Tag $tag
* @param Tag $tag
*
* @return JsonResponse
* @codeCoverageIgnore
@@ -211,10 +194,7 @@ class TagController extends Controller
$this->parameters->set('type', $type);
$types = $this->mapTransactionTypes($this->parameters->get('type'));
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var User $admin */
$admin = auth()->user();
@@ -255,16 +235,14 @@ class TagController extends Controller
* Update a rule.
*
* @param TagRequest $request
* @param Tag $tag
* @param Tag $tag
*
* @return JsonResponse
*/
public function update(TagRequest $request, Tag $tag): JsonResponse
{
$rule = $this->repository->update($tag, $request->getAll());
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var TagTransformer $transformer */
$transformer = app(TagTransformer::class);
$transformer->setParameters($this->parameters);
@@ -275,10 +253,29 @@ class TagController extends Controller
}
/**
* @param array $cloud
* @param float $min
* @param float $max
*
* @return array
*/
private function analyseTagCloud(array $cloud, float $min, float $max): array
{
foreach (array_keys($cloud['tags']) as $index) {
$cloud['tags'][$index]['relative'] = round($cloud['tags'][$index]['size'] / $max, 4);
}
$cloud['min'] = $min;
$cloud['max'] = $max;
return $cloud;
}
/**
* @param Collection $tags
* @param Carbon $start
* @param Carbon $end
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
private function getTagCloud(Collection $tags, Carbon $start, Carbon $end): array
@@ -307,21 +304,4 @@ class TagController extends Controller
return $cloud;
}
/**
* @param array $cloud
* @param float $min
* @param float $max
* @return array
*/
private function analyseTagCloud(array $cloud, float $min, float $max): array
{
foreach (array_keys($cloud['tags']) as $index) {
$cloud['tags'][$index]['relative'] = round($cloud['tags'][$index]['size'] / $max, 4);
}
$cloud['min'] = $min;
$cloud['max'] = $max;
return $cloud;
}
}

View File

@@ -28,7 +28,6 @@ use FireflyIII\Api\V1\Requests\TransactionStoreRequest;
use FireflyIII\Api\V1\Requests\TransactionUpdateRequest;
use FireflyIII\Events\StoredTransactionGroup;
use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
@@ -42,11 +41,9 @@ use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
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 Log;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -59,11 +56,10 @@ class TransactionController extends Controller
/** @var TransactionGroupRepositoryInterface Group repository. */
private $groupRepository;
/** @var JournalRepositoryInterface The journal repository */
private $repository;
/** @var JournalAPIRepositoryInterface Journal API repos */
private $journalAPIRepository;
/** @var JournalRepositoryInterface The journal repository */
private $repository;
/**
* TransactionController constructor.
@@ -91,18 +87,14 @@ class TransactionController extends Controller
}
/**
* @param Request $request
* @param TransactionJournal $transactionJournal
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function attachments(Request $request, TransactionJournal $transactionJournal): JsonResponse
public function attachments(TransactionJournal $transactionJournal): JsonResponse
{
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
$attachments = $this->journalAPIRepository->getAttachments($transactionJournal);
/** @var AttachmentTransformer $transformer */
@@ -160,10 +152,7 @@ class TransactionController extends Controller
$this->parameters->set('type', $type);
$types = $this->mapTransactionTypes($this->parameters->get('type'));
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var User $admin */
$admin = auth()->user();
@@ -200,19 +189,15 @@ class TransactionController extends Controller
}
/**
* @param Request $request
* @param TransactionJournal $transactionJournal
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function piggyBankEvents(Request $request, TransactionJournal $transactionJournal): JsonResponse
public function piggyBankEvents(TransactionJournal $transactionJournal): JsonResponse
{
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$events = $this->journalAPIRepository->getPiggyBankEvents($transactionJournal);
$manager = $this->getManager();
$events = $this->journalAPIRepository->getPiggyBankEvents($transactionJournal);
/** @var PiggyBankEventTransformer $transformer */
$transformer = app(PiggyBankEventTransformer::class);
@@ -227,18 +212,14 @@ class TransactionController extends Controller
/**
* Show a single transaction.
*
* @param Request $request
* @param TransactionGroup $transactionGroup
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, TransactionGroup $transactionGroup): JsonResponse
public function show(TransactionGroup $transactionGroup): JsonResponse
{
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var User $admin */
$admin = auth()->user();
// use new group collector:
@@ -269,7 +250,6 @@ class TransactionController extends Controller
* @param TransactionStoreRequest $request
*
* @return JsonResponse
* @throws FireflyException
*/
public function store(TransactionStoreRequest $request): JsonResponse
{
@@ -283,10 +263,7 @@ class TransactionController extends Controller
event(new StoredTransactionGroup($transactionGroup));
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var User $admin */
$admin = auth()->user();
// use new group collector:
@@ -316,7 +293,7 @@ class TransactionController extends Controller
* Update a transaction.
*
* @param TransactionUpdateRequest $request
* @param TransactionGroup $transactionGroup
* @param TransactionGroup $transactionGroup
*
* @return JsonResponse
*/
@@ -325,9 +302,7 @@ class TransactionController extends Controller
Log::debug('Now in update routine.');
$data = $request->getAll();
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
event(new UpdatedTransactionGroup($transactionGroup));

View File

@@ -34,11 +34,9 @@ use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
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;
/**
* Class TransactionLinkController
@@ -54,6 +52,7 @@ class TransactionLinkController extends Controller
/**
* TransactionLinkController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
@@ -101,9 +100,7 @@ class TransactionLinkController extends Controller
public function index(Request $request): JsonResponse
{
// create some objects:
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager = $this->getManager();
// read type from URI
$name = $request->get('name');
@@ -120,9 +117,6 @@ class TransactionLinkController extends Controller
$paginator = new LengthAwarePaginator($journalLinks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.transaction_links.index') . $this->buildParams());
// present to user.
$manager->setSerializer(new JsonApiSerializer($baseUrl));
/** @var TransactionLinkTransformer $transformer */
$transformer = app(TransactionLinkTransformer::class);
$transformer->setParameters($this->parameters);
@@ -137,17 +131,14 @@ class TransactionLinkController extends Controller
/**
* List single resource.
*
* @param Request $request
* @param TransactionJournalLink $journalLink
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, TransactionJournalLink $journalLink): JsonResponse
public function show(TransactionJournalLink $journalLink): JsonResponse
{
$manager = new Manager;
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
/** @var TransactionLinkTransformer $transformer */
$transformer = app(TransactionLinkTransformer::class);
@@ -169,7 +160,7 @@ class TransactionLinkController extends Controller
*/
public function store(TransactionLinkRequest $request): JsonResponse
{
$manager = new Manager;
$manager = $this->getManager();
$data = $request->getAll();
$inward = $this->journalRepository->findNull($data['inward_id'] ?? 0);
$outward = $this->journalRepository->findNull($data['outward_id'] ?? 0);
@@ -187,7 +178,6 @@ class TransactionLinkController extends Controller
$resource = new Item($journalLink, $transformer, 'transaction_links');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
@@ -201,7 +191,7 @@ class TransactionLinkController extends Controller
*/
public function update(TransactionLinkRequest $request, TransactionJournalLink $journalLink): JsonResponse
{
$manager = new Manager;
$manager = $this->getManager();
$data = $request->getAll();
$data['inward'] = $this->journalRepository->findNull($data['inward_id'] ?? 0);
$data['outward'] = $this->journalRepository->findNull($data['outward_id'] ?? 0);

View File

@@ -31,19 +31,15 @@ use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Transformers\UserTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
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;
/**
* Class UserController.
*
*
*/
class UserController extends Controller
{
@@ -53,6 +49,7 @@ class UserController extends Controller
/**
* UserController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
@@ -92,20 +89,14 @@ class UserController extends Controller
/**
* Display a listing of the resource.
*
* @param Request $request
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function index(Request $request): JsonResponse
public function index(): JsonResponse
{
// user preferences
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// make manager
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
// build collection
$collection = $this->repository->all();
@@ -130,19 +121,15 @@ class UserController extends Controller
/**
* Show a single user.
*
* @param Request $request
* @param User $user
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(Request $request, User $user): JsonResponse
public function show(User $user): JsonResponse
{
// make manager
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$manager = $this->getManager();
// make resource
/** @var UserTransformer $transformer */
$transformer = app(UserTransformer::class);
@@ -162,13 +149,9 @@ class UserController extends Controller
*/
public function store(UserStoreRequest $request): JsonResponse
{
$data = $request->getAll();
$user = $this->repository->store($data);
// make manager
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$data = $request->getAll();
$user = $this->repository->store($data);
$manager = $this->getManager();
// make resource
@@ -185,20 +168,15 @@ class UserController extends Controller
* Update a user.
*
* @param UserUpdateRequest $request
* @param User $user
* @param User $user
*
* @return JsonResponse
*/
public function update(UserUpdateRequest $request, User $user): JsonResponse
{
$data = $request->getAll();
$user = $this->repository->update($user, $data);
// make manager
$manager = new Manager();
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$data = $request->getAll();
$user = $this->repository->update($user, $data);
$manager = $this->getManager();
// make resource
/** @var UserTransformer $transformer */
$transformer = app(UserTransformer::class);

View File

@@ -28,6 +28,7 @@ use FireflyIII\Rules\IsBoolean;
/**
* Class AccountStoreRequest
*
* @codeCoverageIgnore
*/
class AccountStoreRequest extends Request

View File

@@ -28,6 +28,7 @@ use FireflyIII\Rules\IsBoolean;
/**
* Class AccountUpdateRequest
*
* @codeCoverageIgnore
*/
class AccountUpdateRequest extends Request
@@ -44,6 +45,52 @@ class AccountUpdateRequest extends Request
return auth()->check();
}
/**
* @return array
*/
public function getUpdateData(): array
{
$active = null;
$includeNetWorth = null;
if (null !== $this->get('active')) {
$active = $this->boolean('active');
}
if (null !== $this->get('include_net_worth')) {
$includeNetWorth = $this->boolean('include_net_worth');
}
$data = [
'name' => $this->nullableString('name'),
'active' => $active,
'include_net_worth' => $includeNetWorth,
'account_type' => $this->nullableString('type'),
'account_type_id' => null,
'currency_id' => $this->nullableInteger('currency_id'),
'currency_code' => $this->nullableString('currency_code'),
'virtual_balance' => $this->nullableString('virtual_balance'),
'iban' => $this->nullableString('iban'),
'BIC' => $this->nullableString('bic'),
'account_number' => $this->nullableString('account_number'),
'account_role' => $this->nullableString('account_role'),
'opening_balance' => $this->nullableString('opening_balance'),
'opening_balance_date' => $this->date('opening_balance_date'),
'cc_type' => $this->nullableString('credit_card_type'),
'cc_Monthly_payment_date' => $this->nullableString('monthly_payment_date'),
'notes' => $this->nullableString('notes'),
'interest' => $this->nullableString('interest'),
'interest_period' => $this->nullableString('interest_period'),
];
if ('liability' === $data['account_type']) {
$data['opening_balance'] = bcmul($this->nullableString('liability_amount'), '-1');
$data['opening_balance_date'] = $this->date('liability_start_date');
$data['account_type'] = $this->nullableString('liability_type');
$data['account_type_id'] = null;
}
return $data;
}
/**
* The rules that the incoming request must be matched against.
*
@@ -56,7 +103,7 @@ class AccountUpdateRequest extends Request
$types = implode(',', array_keys(config('firefly.subTitlesByIdentifier')));
$ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes')));
$rules = [
'name' => sprintf('required|min:1|uniqueAccountForUser:%d', $account->id),
'name' => sprintf('min:1|uniqueAccountForUser:%d', $account->id),
'type' => sprintf('in:%s', $types),
'iban' => 'iban|nullable',
'bic' => 'bic|nullable',

View File

@@ -30,6 +30,7 @@ use FireflyIII\Rules\IsValidAttachmentModel;
/**
* Class AttachmentStoreRequest
*
* @codeCoverageIgnore
*/
class AttachmentStoreRequest extends Request
@@ -77,6 +78,7 @@ class AttachmentStoreRequest extends Request
]
);
$model = $this->string('model');
return [
'filename' => 'required|between:1,255',
'title' => 'between:1,255',

View File

@@ -28,6 +28,7 @@ use FireflyIII\Rules\IsBoolean;
/**
* Class BudgetRequest
*
* @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/

View File

@@ -27,6 +27,7 @@ use FireflyIII\Models\Category;
/**
* Class CategoryRequest
*
* @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/

View File

@@ -28,6 +28,7 @@ use FireflyIII\Rules\IsBoolean;
/**
* Class ConfigurationRequest
*
* @codeCoverageIgnore
*/
class ConfigurationRequest extends Request

View File

@@ -28,6 +28,7 @@ use FireflyIII\Rules\IsBoolean;
/**
* Class CurrencyRequest
*
* @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/

View File

@@ -29,6 +29,7 @@ use Illuminate\Validation\Rule;
/**
*
* Class LinkTypeRequest
*
* @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/

View File

@@ -31,6 +31,7 @@ use FireflyIII\Rules\ZeroOrMore;
/**
*
* Class PiggyBankRequest
*
* @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests;
/**
*
* Class PreferenceRequest
*
* @codeCoverageIgnore
*/
class PreferenceRequest extends Request

View File

@@ -48,6 +48,39 @@ class RecurrenceStoreRequest extends Request
return auth()->check();
}
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
$active = true;
$applyRules = true;
if (null !== $this->get('active')) {
$active = $this->boolean('active');
}
if (null !== $this->get('apply_rules')) {
$applyRules = $this->boolean('apply_rules');
}
$return = [
'recurrence' => [
'type' => $this->string('type'),
'title' => $this->string('title'),
'description' => $this->string('description'),
'first_date' => $this->date('first_date'),
'repeat_until' => $this->date('repeat_until'),
'repetitions' => $this->integer('nr_of_repetitions'),
'apply_rules' => $applyRules,
'active' => $active,
],
'transactions' => $this->getTransactionData(),
'repetitions' => $this->getRepetitionData(),
];
return $return;
}
/**
* The rules that the incoming request must be matched against.
*
@@ -61,13 +94,11 @@ class RecurrenceStoreRequest extends Request
'type' => 'required|in:withdrawal,transfer,deposit',
'title' => 'required|between:1,255|uniqueObjectForUser:recurrences,title',
'description' => 'between:1,65000',
'first_date' => sprintf('required|date|after:%s', $today->format('Y-m-d')),
'first_date' => 'required|date',
'apply_rules' => [new IsBoolean],
'active' => [new IsBoolean],
'repeat_until' => sprintf('date|after:%s', $today->format('Y-m-d')),
'nr_of_repetitions' => 'numeric|between:1,31',
'tags' => 'between:1,64000',
'piggy_bank_id' => 'numeric',
'repetitions.*.type' => 'required|in:daily,weekly,ndom,monthly,yearly',
'repetitions.*.moment' => 'between:0,10',
'repetitions.*.skip' => 'required|numeric|between:0,31',
@@ -79,12 +110,21 @@ class RecurrenceStoreRequest extends Request
'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id',
'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser],
'transactions.*.category_name' => 'between:1,255|nullable',
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser],
'transactions.*.source_name' => 'between:1,255|nullable',
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser],
'transactions.*.destination_name' => 'between:1,255|nullable',
// new and updated fields:
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser],
'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser],
'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser],
'transactions.*.category_name' => 'between:1,255|nullable',
'transactions.*.piggy_bank_id' => ['numeric', 'mustExist:piggy_banks,id', new BelongsUser],
'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser],
'transactions.*.tags' => 'between:1,64000',
];
}
@@ -108,4 +148,76 @@ class RecurrenceStoreRequest extends Request
}
);
}
/**
* Returns the repetition data as it is found in the submitted data.
*
* @return array
*/
private function getRepetitionData(): array
{
$return = [];
// repetition data:
/** @var array $repetitions */
$repetitions = $this->get('repetitions');
if (null === $repetitions) {
return [];
}
/** @var array $repetition */
foreach ($repetitions as $repetition) {
$return[] = [
'type' => $repetition['type'],
'moment' => $repetition['moment'],
'skip' => (int)$repetition['skip'],
'weekend' => (int)$repetition['weekend'],
];
}
return $return;
}
/**
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
* standards but it just has a lot of ??-statements because of the fields that may or may not exist.
*
* @return array
*/
private function getTransactionData(): array
{
$return = [];
// transaction data:
/** @var array $transactions */
$transactions = $this->get('transactions');
if (null === $transactions) {
return [];
}
/** @var array $transaction */
foreach ($transactions as $transaction) {
$return[] = [
'amount' => $transaction['amount'],
'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null,
'currency_code' => $transaction['currency_code'] ?? null,
'foreign_amount' => $transaction['foreign_amount'] ?? null,
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null,
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null,
'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null,
'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null,
'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null,
'description' => $transaction['description'],
'type' => $this->string('type'),
// new and updated fields:
'piggy_bank_id' => isset($transaction['piggy_bank_id']) ? (int)$transaction['piggy_bank_id'] : null,
'piggy_bank_name' => $transaction['piggy_bank_name'] ?? null,
'tags' => $transaction['tags'] ?? [],
'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null,
'budget_name' => $transaction['budget_name'] ?? null,
'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null,
'category_name' => $transaction['category_name'] ?? null,
];
}
return $return;
}
}

View File

@@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use Carbon\Carbon;
use FireflyIII\Models\Recurrence;
use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean;
@@ -49,6 +48,40 @@ class RecurrenceUpdateRequest extends Request
return auth()->check();
}
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
$active = null;
$applyRules = null;
if (null !== $this->get('active')) {
$active = $this->boolean('active');
}
if (null !== $this->get('apply_rules')) {
$applyRules = $this->boolean('apply_rules');
}
$return = [
'recurrence' => [
'type' => $this->nullableString('type'),
'title' => $this->nullableString('title'),
'description' => $this->nullableString('description'),
'first_date' => $this->date('first_date'),
'notes' => $this->nullableString('notes'),
'repeat_until' => $this->date('repeat_until'),
'nr_of_repetitions' => $this->nullableInteger('nr_of_repetitions'),
'apply_rules' => $applyRules,
'active' => $active,
],
'transactions' => $this->getTransactionData(),
'repetitions' => $this->getRepetitionData(),
];
return $return;
}
/**
* The rules that the incoming request must be matched against.
*
@@ -58,24 +91,21 @@ class RecurrenceUpdateRequest extends Request
{
/** @var Recurrence $recurrence */
$recurrence = $this->route()->parameter('recurrence');
$first = clone $recurrence->first_date;
$first->subDay();
return [
'type' => 'required|in:withdrawal,transfer,deposit',
'title' => sprintf('required|between:1,255|uniqueObjectForUser:recurrences,title,%d', $recurrence->id),
'description' => 'between:1,65000',
'first_date' => sprintf('required|date|after:%s', $first->format('Y-m-d')),
'apply_rules' => [new IsBoolean],
'active' => [new IsBoolean],
'repeat_until' => sprintf('date|after:%s', $first->format('Y-m-d')),
'nr_of_repetitions' => 'numeric|between:1,31',
'tags' => 'between:1,64000',
'piggy_bank_id' => 'numeric',
'repetitions.*.type' => 'required|in:daily,weekly,ndom,monthly,yearly',
'repetitions.*.moment' => 'between:0,10',
'repetitions.*.skip' => 'required|numeric|between:0,31',
'repetitions.*.weekend' => 'required|numeric|min:1|max:4',
'type' => 'in:withdrawal,transfer,deposit',
'title' => sprintf('between:1,255|uniqueObjectForUser:recurrences,title,%d', $recurrence->id),
'description' => 'between:1,65000',
'first_date' => 'date',
'apply_rules' => [new IsBoolean],
'active' => [new IsBoolean],
'repeat_until' => 'date',
'nr_of_repetitions' => 'numeric|between:1,31',
'repetitions.*.type' => 'in:daily,weekly,ndom,monthly,yearly',
'repetitions.*.moment' => 'between:0,10',
'repetitions.*.skip' => 'required|numeric|between:0,31',
'repetitions.*.weekend' => 'required|numeric|min:1|max:4',
'transactions.*.description' => 'required|between:1,255',
'transactions.*.amount' => 'required|numeric|more:0',
'transactions.*.foreign_amount' => 'numeric|more:0',
@@ -83,12 +113,20 @@ class RecurrenceUpdateRequest extends Request
'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id',
'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser],
'transactions.*.category_name' => 'between:1,255|nullable',
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser],
'transactions.*.source_name' => 'between:1,255|nullable',
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser],
'transactions.*.destination_name' => 'between:1,255|nullable',
// new and updated fields:
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser],
'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser],
'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser],
'transactions.*.category_name' => 'between:1,255|nullable',
'transactions.*.piggy_bank_id' => ['numeric', 'mustExist:piggy_banks,id', new BelongsUser],
'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser],
'transactions.*.tags' => 'between:1,64000',
];
}
@@ -103,13 +141,85 @@ class RecurrenceUpdateRequest extends Request
{
$validator->after(
function (Validator $validator) {
$this->validateOneTransaction($validator);
$this->validateOneRepetition($validator);
$this->validateOneRecurrenceTransactionUpdate($validator);
$this->validateOneRepetitionUpdate($validator);
$this->validateRecurrenceRepetition($validator);
$this->validateRepetitionMoment($validator);
$this->validateForeignCurrencyInformation($validator);
$this->validateAccountInformation($validator);
$this->valUpdateAccountInfo($validator);
}
);
}
/**
* Returns the repetition data as it is found in the submitted data.
*
* @return array|null
*/
private function getRepetitionData(): ?array
{
$return = [];
// repetition data:
/** @var array $repetitions */
$repetitions = $this->get('repetitions');
if (null === $repetitions) {
return null;
}
/** @var array $repetition */
foreach ($repetitions as $repetition) {
$return[] = [
'type' => $repetition['type'],
'moment' => $repetition['moment'],
'skip' => (int)$repetition['skip'],
'weekend' => (int)$repetition['weekend'],
];
}
return $return;
}
/**
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
* standards but it just has a lot of ??-statements because of the fields that may or may not exist.
*
* @return array|null
*/
private function getTransactionData(): ?array
{
$return = [];
// transaction data:
/** @var array $transactions */
$transactions = $this->get('transactions');
if (null === $transactions) {
return null;
}
/** @var array $transaction */
foreach ($transactions as $transaction) {
$return[] = [
'amount' => $transaction['amount'],
'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null,
'currency_code' => $transaction['currency_code'] ?? null,
'foreign_amount' => $transaction['foreign_amount'] ?? null,
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null,
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null,
'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null,
'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null,
'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null,
'description' => $transaction['description'],
'type' => $this->string('type'),
// new and updated fields:
'piggy_bank_id' => isset($transaction['piggy_bank_id']) ? (int)$transaction['piggy_bank_id'] : null,
'piggy_bank_name' => $transaction['piggy_bank_name'] ?? null,
'tags' => $transaction['tags'] ?? [],
'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null,
'budget_name' => $transaction['budget_name'] ?? null,
'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null,
'category_name' => $transaction['category_name'] ?? null,
];
}
return $return;
}
}

View File

@@ -24,10 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use Carbon\Carbon;
use FireflyIII\Http\Requests\Request as FireflyIIIRequest;
use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean;
/**
* Class Request.
@@ -82,105 +79,4 @@ class Request extends FireflyIIIRequest
return $data;
}
/**
* Get all data from the request.
*
* @return array
*/
public function getAllRecurrenceData(): array
{
$active = true;
$applyRules = true;
if (null !== $this->get('active')) {
$active = $this->boolean('active');
}
if (null !== $this->get('apply_rules')) {
$applyRules = $this->boolean('apply_rules');
}
$return = [
'recurrence' => [
'type' => $this->string('type'),
'title' => $this->string('title'),
'description' => $this->string('description'),
'first_date' => $this->date('first_date'),
'repeat_until' => $this->date('repeat_until'),
'repetitions' => $this->integer('nr_of_repetitions'),
'apply_rules' => $applyRules,
'active' => $active,
],
'meta' => [
'piggy_bank_id' => $this->integer('piggy_bank_id'),
'piggy_bank_name' => $this->string('piggy_bank_name'),
'tags' => explode(',', $this->string('tags')),
],
'transactions' => $this->getRecurrenceTransactionData(),
'repetitions' => $this->getRecurrenceRepetitionData(),
];
return $return;
}
/**
* Returns the repetition data as it is found in the submitted data.
*
* @return array
*/
protected function getRecurrenceRepetitionData(): array
{
$return = [];
// repetition data:
/** @var array $repetitions */
$repetitions = $this->get('repetitions');
/** @var array $repetition */
foreach ($repetitions as $repetition) {
$return[] = [
'type' => $repetition['type'],
'moment' => $repetition['moment'],
'skip' => (int)$repetition['skip'],
'weekend' => (int)$repetition['weekend'],
];
}
return $return;
}
/**
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
* standards but it just has a lot of ??-statements because of the fields that may or may not exist.
*
* @return array
*/
protected function getRecurrenceTransactionData(): array
{
$return = [];
// transaction data:
/** @var array $transactions */
$transactions = $this->get('transactions');
/** @var array $transaction */
foreach ($transactions as $transaction) {
$return[] = [
'amount' => $transaction['amount'],
'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null,
'currency_code' => $transaction['currency_code'] ?? null,
'foreign_amount' => $transaction['foreign_amount'] ?? null,
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null,
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null,
'budget_name' => $transaction['budget_name'] ?? null,
'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null,
'category_name' => $transaction['category_name'] ?? null,
'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null,
'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null,
'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null,
'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null,
'description' => $transaction['description'],
'type' => $this->string('type'),
];
}
return $return;
}
}

View File

@@ -75,8 +75,33 @@ class RuleGroupTestRequest extends Request
return [];
}
/**
* @return Collection
*/
private function getAccounts(): Collection
{
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accounts = new Collection;
/** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app(AccountRepositoryInterface::class);
foreach ($accountList as $accountId) {
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
$account = $accountRepository->findNull((int)$accountId);
if ($this->validAccount($account)) {
/** @noinspection NullPointerExceptionInspection */
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
$accounts->push($account);
}
}
return $accounts;
}
/**
* @param string $field
*
* @return Carbon|null
*/
private function getDate(string $field): ?Carbon
@@ -112,32 +137,9 @@ class RuleGroupTestRequest extends Request
return 0 === (int)$this->query('triggered_limit') ? (int)config('firefly.test-triggers.range') : (int)$this->query('triggered_limit');
}
/**
* @return Collection
*/
private function getAccounts(): Collection
{
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accounts = new Collection;
/** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app(AccountRepositoryInterface::class);
foreach ($accountList as $accountId) {
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
$account = $accountRepository->findNull((int)$accountId);
if ($this->validAccount($account)) {
/** @noinspection NullPointerExceptionInspection */
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
$accounts->push($account);
}
}
return $accounts;
}
/**
* @param Account|null $account
*
* @return bool
*/
private function validAccount(?Account $account): bool

View File

@@ -75,18 +75,6 @@ class RuleGroupTriggerRequest extends Request
];
}
/**
* @param string $field
* @return Carbon|null
*/
private function getDate(string $field): ?Carbon
{
/** @var Carbon $result */
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
return $result;
}
/**
* @return Collection
*/
@@ -111,8 +99,22 @@ class RuleGroupTriggerRequest extends Request
return $accounts;
}
/**
* @param string $field
*
* @return Carbon|null
*/
private function getDate(string $field): ?Carbon
{
/** @var Carbon $result */
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
return $result;
}
/**
* @param Account|null $account
*
* @return bool
*/
private function validAccount(?Account $account): bool

View File

@@ -1,6 +1,6 @@
<?php
/**
* RuleRequest.php
* RuleStoreRequest.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
@@ -29,10 +29,10 @@ use function is_array;
/**
* Class RuleRequest
* Class RuleStoreRequest
*
*/
class RuleRequest extends Request
class RuleStoreRequest extends Request
{
/**
* Authorize logged in users.
@@ -133,21 +133,6 @@ class RuleRequest extends Request
);
}
/**
* Adds an error to the validator when there are no repetitions in the array of data.
*
* @param Validator $validator
*/
protected function atLeastOneTrigger(Validator $validator): void
{
$data = $validator->getData();
$triggers = $data['triggers'] ?? [];
// need at least one trigger
if (0 === count($triggers)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
}
}
/**
* Adds an error to the validator when there are no repetitions in the array of data.
*
@@ -164,24 +149,18 @@ class RuleRequest extends Request
}
/**
* @return array
* Adds an error to the validator when there are no repetitions in the array of data.
*
* @param Validator $validator
*/
private function getRuleTriggers(): array
protected function atLeastOneTrigger(Validator $validator): void
{
$triggers = $this->get('triggers');
$return = [];
if (is_array($triggers)) {
foreach ($triggers as $trigger) {
$return[] = [
'type' => $trigger['type'],
'value' => $trigger['value'],
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
];
}
$data = $validator->getData();
$triggers = $data['triggers'] ?? [];
// need at least one trigger
if (0 === count($triggers)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
}
return $return;
}
/**
@@ -204,4 +183,25 @@ class RuleRequest extends Request
return $return;
}
/**
* @return array
*/
private function getRuleTriggers(): array
{
$triggers = $this->get('triggers');
$return = [];
if (is_array($triggers)) {
foreach ($triggers as $trigger) {
$return[] = [
'type' => $trigger['type'],
'value' => $trigger['value'],
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
];
}
}
return $return;
}
}

View File

@@ -75,8 +75,33 @@ class RuleTestRequest extends Request
return [];
}
/**
* @return Collection
*/
private function getAccounts(): Collection
{
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accounts = new Collection;
/** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app(AccountRepositoryInterface::class);
foreach ($accountList as $accountId) {
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
$account = $accountRepository->findNull((int)$accountId);
if ($this->validAccount($account)) {
/** @noinspection NullPointerExceptionInspection */
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
$accounts->push($account);
}
}
return $accounts;
}
/**
* @param string $field
*
* @return Carbon|null
*/
private function getDate(string $field): ?Carbon
@@ -112,32 +137,9 @@ class RuleTestRequest extends Request
return 0 === (int)$this->query('triggered_limit') ? (int)config('firefly.test-triggers.range') : (int)$this->query('triggered_limit');
}
/**
* @return Collection
*/
private function getAccounts(): Collection
{
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accounts = new Collection;
/** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app(AccountRepositoryInterface::class);
foreach ($accountList as $accountId) {
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
$account = $accountRepository->findNull((int)$accountId);
if ($this->validAccount($account)) {
/** @noinspection NullPointerExceptionInspection */
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
$accounts->push($account);
}
}
return $accounts;
}
/**
* @param Account|null $account
*
* @return bool
*/
private function validAccount(?Account $account): bool

View File

@@ -74,18 +74,6 @@ class RuleTriggerRequest extends Request
];
}
/**
* @param string $field
* @return Carbon|null
*/
private function getDate(string $field): ?Carbon
{
/** @var Carbon $result */
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
return $result;
}
/**
* @return Collection
*/
@@ -110,8 +98,22 @@ class RuleTriggerRequest extends Request
return $accounts;
}
/**
* @param string $field
*
* @return Carbon|null
*/
private function getDate(string $field): ?Carbon
{
/** @var Carbon $result */
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
return $result;
}
/**
* @param Account|null $account
*
* @return bool
*/
private function validAccount(?Account $account): bool

View File

@@ -0,0 +1,214 @@
<?php
/**
* RuleUpdateRequest.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean;
use Illuminate\Validation\Validator;
use function is_array;
/**
* Class RuleUpdateRequest
*
*/
class RuleUpdateRequest extends Request
{
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
$strict = null;
$active = null;
$stopProcessing = null;
if (null !== $this->get('active')) {
$active = $this->boolean('active');
}
if (null !== $this->get('strict')) {
$strict = $this->boolean('strict');
}
if (null !== $this->get('stop_processing')) {
$stopProcessing = $this->boolean('stop_processing');
}
$data = [
'title' => $this->nullableString('title'),
'description' => $this->nullableString('description'),
'rule_group_id' => $this->nullableInteger('rule_group_id'),
'rule_group_title' => $this->nullableString('rule_group_title'),
'trigger' => $this->nullableString('trigger'),
'strict' => $strict,
'stop_processing' => $stopProcessing,
'active' => $active,
'triggers' => $this->getRuleTriggers(),
'actions' => $this->getRuleActions(),
];
return $data;
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
$validTriggers = array_keys(config('firefly.rule-triggers'));
$validActions = array_keys(config('firefly.rule-actions'));
$rule = $this->route()->parameter('rule');
// some triggers and actions require text:
$contextTriggers = implode(',', config('firefly.context-rule-triggers'));
$contextActions = implode(',', config('firefly.context-rule-actions'));
$rules = [
'title' => sprintf('between:1,100|uniqueObjectForUser:rules,title,%d', $rule->id),
'description' => 'between:1,5000|nullable',
'rule_group_id' => 'belongsToUser:rule_groups',
'rule_group_title' => 'nullable|between:1,255|belongsToUser:rule_groups,title',
'trigger' => 'in:store-journal,update-journal',
'triggers.*.type' => 'required|in:' . implode(',', $validTriggers),
'triggers.*.value' => 'required_if:actions.*.type,' . $contextTriggers . '|min:1|ruleTriggerValue',
'triggers.*.stop_processing' => [new IsBoolean],
'triggers.*.active' => [new IsBoolean],
'actions.*.type' => 'required|in:' . implode(',', $validActions),
'actions.*.value' => 'required_if:actions.*.type,' . $contextActions . '|ruleActionValue',
'actions.*.stop_processing' => [new IsBoolean],
'actions.*.active' => [new IsBoolean],
'strict' => [new IsBoolean],
'stop_processing' => [new IsBoolean],
'active' => [new IsBoolean],
];
return $rules;
}
/**
* Configure the validator instance.
*
* @param Validator $validator
*
* @return void
*/
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator) {
$this->atLeastOneTrigger($validator);
$this->atLeastOneAction($validator);
}
);
}
/**
* Adds an error to the validator when there are no repetitions in the array of data.
*
* @param Validator $validator
*/
protected function atLeastOneAction(Validator $validator): void
{
$data = $validator->getData();
$actions = $data['actions'] ?? null;
// need at least one action
if (is_array($actions) && 0 === count($actions)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
}
}
/**
* Adds an error to the validator when there are no repetitions in the array of data.
*
* @param Validator $validator
*/
protected function atLeastOneTrigger(Validator $validator): void
{
$data = $validator->getData();
$triggers = $data['triggers'] ?? null;
// need at least one trigger
if (is_array($triggers) && 0 === count($triggers)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
}
}
/**
* @return array|null
*/
private function getRuleActions(): ?array
{
if (!$this->has('actions')) {
return null;
}
$actions = $this->get('actions');
$return = [];
if (is_array($actions)) {
foreach ($actions as $action) {
$return[] = [
'type' => $action['type'],
'value' => $action['value'],
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
];
}
}
return $return;
}
/**
* @return array|null
*/
private function getRuleTriggers(): ?array
{
if (!$this->has('triggers')) {
return null;
}
$triggers = $this->get('triggers');
$return = [];
if (is_array($triggers)) {
foreach ($triggers as $trigger) {
$return[] = [
'type' => $trigger['type'],
'value' => $trigger['value'],
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
];
}
}
return $return;
}
}

View File

@@ -192,7 +192,7 @@ class TransactionStoreRequest extends Request
{
$return = [];
/**
* @var int $index
* @var int $index
* @var array $transaction
*/
foreach ($this->get('transactions') as $index => $transaction) {

View File

@@ -256,7 +256,6 @@ class TransactionUpdateRequest extends Request
// // validate foreign currency info
// $this->validateForeignCurrencyInformation($validator);
//
//
//
// // make sure all splits have valid source + dest info
@@ -277,7 +276,7 @@ class TransactionUpdateRequest extends Request
Log::debug('Now in getTransactionData()');
$return = [];
/**
* @var int $index
* @var int $index
* @var array $transaction
*/
foreach ($this->get('transactions') as $index => $transaction) {

View File

@@ -87,7 +87,7 @@ class UserStoreRequest extends Request
public function rules(): array
{
return [
'email' => 'required|email|unique:users,email,',
'email' => 'required|email|unique:users,email',
'blocked' => [new IsBoolean],
'blocked_code' => 'in:email_changed',
'role' => 'in:owner,demo',

View File

@@ -148,7 +148,7 @@ class DecryptDatabase extends Command
private function tryDecrypt($value)
{
try {
$value = Crypt::decrypt($value);
$value = Crypt::decrypt($value); // verified
} catch (DecryptException $e) {
if ('The MAC is invalid.' === $e->getMessage()) {
throw new FireflyException($e->getMessage()); // @codeCoverageIgnore

View File

@@ -30,6 +30,7 @@ use FireflyIII\Models\Attachment;
use Illuminate\Console\Command;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Log;
use Storage;
/**
@@ -51,7 +52,7 @@ class ScanAttachments extends Command
*
* @var string
*/
protected $signature = 'firefly:scan-attachments';
protected $signature = 'firefly-iii:scan-attachments';
/**
* Execute the console command.
@@ -62,21 +63,22 @@ class ScanAttachments extends Command
$disk = Storage::disk('upload');
/** @var Attachment $attachment */
foreach ($attachments as $attachment) {
$fileName = $attachment->fileName();
$fileName = $attachment->fileName();
$decryptedContent = '';
try {
$content = $disk->get($fileName);
$encryptedContent = $disk->get($fileName);
} catch (FileNotFoundException $e) {
$this->error(sprintf('Could not find data for attachment #%d: %s', $attachment->id, $e->getMessage()));
continue;
}
try {
$decrypted = Crypt::decrypt($content);
$decryptedContent = Crypt::decrypt($encryptedContent); // verified
} catch (DecryptException $e) {
$this->error(sprintf('Could not decrypt data of attachment #%d: %s', $attachment->id, $e->getMessage()));
continue;
Log::error(sprintf('Could not decrypt data of attachment #%d: %s', $attachment->id, $e->getMessage()));
$decryptedContent = $encryptedContent;
}
$tempFileName = tempnam(sys_get_temp_dir(), 'FireflyIII');
file_put_contents($tempFileName, $decrypted);
file_put_contents($tempFileName, $decryptedContent);
$md5 = md5_file($tempFileName);
$mime = mime_content_type($tempFileName);
$attachment->md5 = $md5;

View File

@@ -38,7 +38,7 @@ use Log;
*/
class AccountCurrencies extends Command
{
public const CONFIG_NAME = '4780_account_currencies';
public const CONFIG_NAME = '480_account_currencies';
/**
* The console command description.
*

View File

@@ -28,13 +28,15 @@ use FireflyIII\Models\Category;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
use Log;
/**
* Class BackToJournals
*/
class BackToJournals extends Command
{
public const CONFIG_NAME = '4780_back_to_journals';
public const CONFIG_NAME = '480_back_to_journals';
/**
* The console command description.
*
@@ -84,10 +86,18 @@ class BackToJournals extends Command
private function getIdsForBudgets(): array
{
$transactions = DB::table('budget_transaction')->distinct()->get(['transaction_id'])->pluck('transaction_id')->toArray();
$array = [];
$chunks = array_chunk($transactions, 500);
return DB::table('transactions')
->whereIn('transactions.id', $transactions)
->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray();
foreach ($chunks as $chunk) {
$set = DB::table('transactions')
->whereIn('transactions.id', $chunk)
->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray();
/** @noinspection SlowArrayOperationsInLoopInspection */
$array = array_merge($array, $set);
}
return $array;
}
/**
@@ -96,10 +106,18 @@ class BackToJournals extends Command
private function getIdsForCategories(): array
{
$transactions = DB::table('category_transaction')->distinct()->get(['transaction_id'])->pluck('transaction_id')->toArray();
$array = [];
$chunks = array_chunk($transactions, 500);
return DB::table('transactions')
->whereIn('transactions.id', $transactions)
->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray();
foreach ($chunks as $chunk) {
$set = DB::table('transactions')
->whereIn('transactions.id', $chunk)
->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray();
/** @noinspection SlowArrayOperationsInLoopInspection */
$array = array_merge($array, $set);
}
return $array;
}
/**
@@ -141,6 +159,7 @@ class BackToJournals extends Command
*/
private function migrateAll(): void
{
Log::debug('Now in migrateAll()');
$this->migrateBudgets();
$this->migrateCategories();
@@ -154,9 +173,13 @@ class BackToJournals extends Command
*/
private function migrateBudgets(): void
{
$journalIds = $this->getIdsForBudgets();
$journals = TransactionJournal::whereIn('id', $journalIds)->with(['transactions', 'budgets', 'transactions.budgets'])->get();
$journals = new Collection;
$allIds = $this->getIdsForBudgets();
$chunks = array_chunk($allIds, 500);
foreach ($chunks as $journalIds) {
$collected = TransactionJournal::whereIn('id', $journalIds)->with(['transactions', 'budgets', 'transactions.budgets'])->get();
$journals = $journals->merge($collected);
}
$this->line(sprintf('Check %d transaction journal(s) for budget info.', count($journals)));
/** @var TransactionJournal $journal */
foreach ($journals as $journal) {
@@ -205,8 +228,18 @@ class BackToJournals extends Command
*/
private function migrateCategories(): void
{
$journalIds = $this->getIdsForCategories();
$journals = TransactionJournal::whereIn('id', $journalIds)->with(['transactions', 'categories', 'transactions.categories'])->get();
Log::debug('Now in migrateCategories()');
$journals = new Collection;
$allIds = $this->getIdsForCategories();
Log::debug(sprintf('Total: %d', count($allIds)));
$chunks = array_chunk($allIds, 500);
foreach ($chunks as $chunk) {
Log::debug('Now doing a chunk.');
$collected = TransactionJournal::whereIn('id', $chunk)->with(['transactions', 'categories', 'transactions.categories'])->get();
$journals = $journals->merge($collected);
}
$this->line(sprintf('Check %d transaction journal(s) for category info.', count($journals)));
/** @var TransactionJournal $journal */
foreach ($journals as $journal) {

View File

@@ -33,7 +33,7 @@ use Illuminate\Console\Command;
*/
class BudgetLimitCurrency extends Command
{
public const CONFIG_NAME = '4780_bl_currency';
public const CONFIG_NAME = '480_bl_currency';
/**
* The console command description.
*

View File

@@ -36,7 +36,7 @@ class CCLiabilities extends Command
{
public const CONFIG_NAME = '4780_cc_liabilities';
public const CONFIG_NAME = '480_cc_liabilities';
/**
* The console command description.
*

View File

@@ -34,7 +34,7 @@ use Log;
*/
class MigrateAttachments extends Command
{
public const CONFIG_NAME = '4780_migrate_attachments';
public const CONFIG_NAME = '480_migrate_attachments';
/**
* The console command description.
*

View File

@@ -35,7 +35,7 @@ use Log;
*/
class MigrateJournalNotes extends Command
{
public const CONFIG_NAME = '4780_migrate_notes';
public const CONFIG_NAME = '480_migrate_notes';
/**
* The console command description.
*

View File

@@ -0,0 +1,148 @@
<?php
/**
* MigrateRecurrenceMeta.php
* Copyright (c) 2019 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Console\Commands\Upgrade;
use FireflyIII\Models\RecurrenceMeta;
use FireflyIII\Models\RecurrenceTransactionMeta;
use Illuminate\Console\Command;
/**
* Class MigrateRecurrenceMeta
*/
class MigrateRecurrenceMeta extends Command
{
public const CONFIG_NAME = '481_migrate_recurrence_meta';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Migrate recurrence meta data';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:migrate-recurrence-meta {--F|force : Force the execution of this command.}';
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
$start = microtime(true);
if ($this->isExecuted() && true !== $this->option('force')) {
$this->warn('This command has already been executed.');
return 0;
}
$count = $this->migrateMetaData();
if (0 === $count) {
$this->line('No recurrence meta data migrated.');
}
if ($count > 0) {
$this->line(sprintf('Migrated %d meta data entries', $count));
}
$this->markAsExecuted();
$end = round(microtime(true) - $start, 2);
$this->info(sprintf('Migrated recurrence meta data in %s seconds.', $end));
return 0;
}
/**
* @return bool
*/
private function isExecuted(): bool
{
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) {
return (bool)$configVar->data;
}
return false; // @codeCoverageIgnore
}
/**
*
*/
private function markAsExecuted(): void
{
app('fireflyconfig')->set(self::CONFIG_NAME, true);
}
/**
* @param RecurrenceMeta $meta
*
* @return int
*/
private function migrateEntry(RecurrenceMeta $meta): int
{
$recurrence = $meta->recurrence;
if (null === $recurrence) {
return 0;
}
$firstTransaction = $recurrence->recurrenceTransactions()->first();
if (null === $firstTransaction) {
return 0;
}
$value = $meta->value;
if ('tags' === $meta->name) {
$array = explode(',', $meta->value);
$value = json_encode($array);
}
RecurrenceTransactionMeta::create(
[
'rt_id' => $firstTransaction->id,
'name' => $meta->name,
'value' => $value,
]
);
$meta->forceDelete();
return 1;
}
/**
* @return int
*/
private function migrateMetaData(): int
{
$count = 0;
// get all recurrence meta data:
$collection = RecurrenceMeta::with('recurrence')->get();
/** @var RecurrenceMeta $meta */
foreach ($collection as $meta) {
$count += $this->migrateEntry($meta);
}
return $count;
}
}

View File

@@ -43,7 +43,7 @@ use Log;
*/
class MigrateToGroups extends Command
{
public const CONFIG_NAME = '4780_migrated_to_groups';
public const CONFIG_NAME = '480_migrated_to_groups';
/**
* The console command description.
*

View File

@@ -40,7 +40,7 @@ use Illuminate\Console\Command;
*/
class MigrateToRules extends Command
{
public const CONFIG_NAME = '4780_bills_to_rules';
public const CONFIG_NAME = '480_bills_to_rules';
/**
* The console command description.
*

View File

@@ -41,7 +41,7 @@ use Illuminate\Console\Command;
class OtherCurrenciesCorrections extends Command
{
public const CONFIG_NAME = '4780_other_currencies';
public const CONFIG_NAME = '480_other_currencies';
/**
* The console command description.
*

View File

@@ -30,7 +30,7 @@ use Illuminate\Console\Command;
*/
class RenameAccountMeta extends Command
{
public const CONFIG_NAME = '4780_rename_account_meta';
public const CONFIG_NAME = '480_rename_account_meta';
/**
* The console command description.
*

View File

@@ -36,7 +36,7 @@ use Schema;
*/
class TransactionIdentifier extends Command
{
public const CONFIG_NAME = '4780_transaction_identifier';
public const CONFIG_NAME = '480_transaction_identifier';
/**
* The console command description.
*

View File

@@ -41,7 +41,7 @@ use Log;
class TransferCurrenciesCorrections extends Command
{
public const CONFIG_NAME = '4780_transfer_currencies';
public const CONFIG_NAME = '480_transfer_currencies';
/**
* The console command description.
*

View File

@@ -58,7 +58,7 @@ class UpgradeDatabase extends Command
$commands = [
// there are 12 upgrade commands.
// there are 13 upgrade commands.
'firefly-iii:transaction-identifiers',
'firefly-iii:migrate-to-groups',
'firefly-iii:account-currencies',
@@ -71,6 +71,7 @@ class UpgradeDatabase extends Command
'firefly-iii:cc-liabilities',
'firefly-iii:back-to-journals',
'firefly-iii:rename-account-meta',
'firefly-iii:migrate-recurrence-meta',
// there are 14 verify commands.
'firefly-iii:fix-piggies',

View File

@@ -28,7 +28,7 @@ use Illuminate\Console\Command;
*/
class UpgradeSkeleton extends Command
{
public const CONFIG_NAME = '4780_some_name';
public const CONFIG_NAME = '480_some_name';
/**
* The console command description.
*

View File

@@ -45,23 +45,22 @@ class GracefulNotFoundHandler extends ExceptionHandler
* @param Request $request
* @param Exception $exception
*
*
* @return mixed
*/
public function render($request, Exception $exception)
{
$route = $request->route();
if(null === $route) {
if (null === $route) {
return parent::render($request, $exception);
}
$name = $route->getName();
$name = $route->getName();
if (!auth()->check()) {
return parent::render($request, $exception);
}
switch ($name) {
default:
Log::error(sprintf('GracefulNotFoundHandler cannot handle route with name "%s"', $name));
Log::debug(sprintf('GracefulNotFoundHandler cannot handle route with name "%s"', $name));
return parent::render($request, $exception);
case 'accounts.show':
@@ -99,6 +98,7 @@ class GracefulNotFoundHandler extends ExceptionHandler
return redirect(route('recurring.index'));
break;
case 'tags.show.all':
case 'tags.show':
$request->session()->reflash();

View File

@@ -49,7 +49,6 @@ class Handler extends ExceptionHandler
* @param Request $request
* @param Exception $exception
*
*
* @return mixed
*/
public function render($request, Exception $exception)

View File

@@ -49,6 +49,13 @@ class AccountFactory
/** @var array */
private $canHaveVirtual;
/** @var array */
protected $validAssetFields = ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'];
/** @var array */
protected $validCCFields = ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'];
/** @var array */
protected $validFields = ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth'];
/**
* AccountFactory constructor.
*

View File

@@ -96,7 +96,6 @@ class RecurrenceFactory
);
$recurrence->save();
$this->updateMetaData($recurrence, $data);
$this->createRepetitions($recurrence, $data['repetitions'] ?? []);
try {
$this->createTransactions($recurrence, $data['transactions'] ?? []);

View File

@@ -28,6 +28,7 @@ use FireflyIII\User;
/**
* Class TransactionGroupFactory
*
* @codeCoverageIgnore
*/
class TransactionGroupFactory
@@ -58,7 +59,12 @@ class TransactionGroupFactory
$collection = $this->journalFactory->create($data);
$title = $data['group_title'] ?? null;
$title = '' === $title ? null : $title;
$group = new TransactionGroup;
if (null !== $title) {
$title = substr($title, 0, 255);
}
$group = new TransactionGroup;
$group->user()->associate($this->user);
$group->title = $title;
$group->save();

View File

@@ -52,10 +52,10 @@ class TransactionJournalFactory
{
use JournalServiceTrait;
/** @var AccountValidator */
private $accountValidator;
/** @var AccountRepositoryInterface */
private $accountRepository;
/** @var AccountValidator */
private $accountValidator;
/** @var BillRepositoryInterface */
private $billRepository;
/** @var CurrencyRepositoryInterface */
@@ -143,7 +143,7 @@ class TransactionJournalFactory
if (null !== $journal) {
$collection->push($journal);
}
if(null === $journal) {
if (null === $journal) {
Log::error('The createJournal() method returned NULL. This may indicate an error.');
}
}
@@ -171,8 +171,8 @@ class TransactionJournalFactory
/**
* @param TransactionJournal $journal
* @param NullArrayObject $data
* @param string $field
* @param NullArrayObject $data
* @param string $field
*/
protected function storeMeta(TransactionJournal $journal, NullArrayObject $data, string $field): void
{
@@ -189,32 +189,6 @@ class TransactionJournalFactory
$factory->updateOrCreate($set);
}
/**
* Link a piggy bank to this journal.
*
* @param TransactionJournal $journal
* @param NullArrayObject $data
*/
private function storePiggyEvent(TransactionJournal $journal, NullArrayObject $data): void
{
Log::debug('Will now store piggy event.');
if (!$journal->isTransfer()) {
Log::debug('Journal is not a transfer, do nothing.');
return;
}
$piggyBank = $this->piggyRepository->findPiggyBank((int)$data['piggy_bank_id'], $data['piggy_bank_name']);
if (null !== $piggyBank) {
$this->piggyEventFactory->create($journal, $piggyBank);
Log::debug('Create piggy event.');
return;
}
Log::debug('Create no piggy event');
}
/**
* @param NullArrayObject $row
*
@@ -302,6 +276,10 @@ class TransactionJournalFactory
$destForeignCurrency = $foreignCurrency;
}
$description = '' === $description ? '(empty description)' : $description;
$description = substr($description, 0, 255);
/** Create a basic journal. */
$journal = TransactionJournal::create(
[
@@ -309,7 +287,7 @@ class TransactionJournalFactory
'transaction_type_id' => $type->id,
'bill_id' => $billId,
'transaction_currency_id' => $currency->id,
'description' => '' === $description ? '(empty description)' : $description,
'description' => $description,
'date' => $carbon->format('Y-m-d H:i:s'),
'order' => $order,
'tag_count' => 0,
@@ -342,19 +320,19 @@ class TransactionJournalFactory
// verify that journal has two transactions. Otherwise, delete and cancel.
// TODO this can't be faked so it can't be tested.
// $count = $journal->transactions()->count();
// if (2 !== $count) {
// // @codeCoverageIgnoreStart
// Log::error(sprintf('The journal unexpectedly has %d transaction(s). This is not OK. Cancel operation.', $count));
// try {
// $journal->delete();
// } catch (Exception $e) {
// Log::debug(sprintf('Dont care: %s.', $e->getMessage()));
// }
//
// return null;
// // @codeCoverageIgnoreEnd
// }
// $count = $journal->transactions()->count();
// if (2 !== $count) {
// // @codeCoverageIgnoreStart
// Log::error(sprintf('The journal unexpectedly has %d transaction(s). This is not OK. Cancel operation.', $count));
// try {
// $journal->delete();
// } catch (Exception $e) {
// Log::debug(sprintf('Dont care: %s.', $e->getMessage()));
// }
//
// return null;
// // @codeCoverageIgnoreEnd
// }
$journal->completed = true;
$journal->save();
@@ -381,6 +359,23 @@ class TransactionJournalFactory
return $journal;
}
/**
* @param TransactionCurrency|null $currency
* @param Account $account
*
* @return TransactionCurrency
*/
private function getCurrency(?TransactionCurrency $currency, Account $account): TransactionCurrency
{
$preference = $this->accountRepository->getAccountCurrency($account);
if (null === $preference && null === $currency) {
// return user's default:
return app('amount')->getDefaultCurrencyByUser($this->user);
}
return $preference ?? $currency;
}
/**
* @param NullArrayObject $row
*
@@ -391,7 +386,7 @@ class TransactionJournalFactory
$dataRow = $row->getArrayCopy();
unset($dataRow['import_hash_v2'], $dataRow['original_source']);
$json = json_encode($dataRow);
$json = json_encode($dataRow);
if (false === $json) {
// @codeCoverageIgnoreStart
$json = json_encode((string)microtime());
@@ -406,7 +401,7 @@ class TransactionJournalFactory
/**
* @param TransactionJournal $journal
* @param NullArrayObject $transaction
* @param NullArrayObject $transaction
*/
private function storeMetaFields(TransactionJournal $journal, NullArrayObject $transaction): void
{
@@ -415,9 +410,35 @@ class TransactionJournalFactory
}
}
/**
* Link a piggy bank to this journal.
*
* @param TransactionJournal $journal
* @param NullArrayObject $data
*/
private function storePiggyEvent(TransactionJournal $journal, NullArrayObject $data): void
{
Log::debug('Will now store piggy event.');
if (!$journal->isTransfer()) {
Log::debug('Journal is not a transfer, do nothing.');
return;
}
$piggyBank = $this->piggyRepository->findPiggyBank((int)$data['piggy_bank_id'], $data['piggy_bank_name']);
if (null !== $piggyBank) {
$this->piggyEventFactory->create($journal, $piggyBank);
Log::debug('Create piggy event.');
return;
}
Log::debug('Create no piggy event');
}
/**
* @param NullArrayObject $data
*
* @throws FireflyException
*/
private function validateAccounts(NullArrayObject $data): void
@@ -445,20 +466,4 @@ class TransactionJournalFactory
throw new FireflyException(sprintf('Destination: %s', $this->accountValidator->destError)); // @codeCoverageIgnore
}
}
/**
* @param TransactionCurrency|null $currency
* @param Account $account
* @return TransactionCurrency
*/
private function getCurrency(?TransactionCurrency $currency, Account $account): TransactionCurrency
{
$preference = $this->accountRepository->getAccountCurrency($account);
if (null === $preference && null === $currency) {
// return user's default:
return app('amount')->getDefaultCurrencyByUser($this->user);
}
return $preference ?? $currency;
}
}

View File

@@ -185,6 +185,7 @@ class ChartJsGenerator implements GeneratorInterface
// make larger than 0
$chartData['datasets'][0]['data'][] = (float)app('steam')->positive((string)$value);
$chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index);
$chartData['labels'][] = $key;
++$index;
}
@@ -196,7 +197,6 @@ class ChartJsGenerator implements GeneratorInterface
* Will generate a (ChartJS) compatible array from the given input. Expects this format:.
*
* 'label-of-entry' => value
* 'label-of-entry' => value
*
* @param string $setLabel
* @param array $data

View File

@@ -83,7 +83,6 @@ interface GeneratorInterface
* Will generate a (ChartJS) compatible array from the given input. Expects this format:.
*
* 'label-of-entry' => value
* 'label-of-entry' => value
*
* @param string $setLabel
* @param array $data

View File

@@ -52,17 +52,17 @@ class MonthReportGenerator implements ReportGeneratorInterface
public function generate(): string
{
$accountIds = implode(',', $this->accounts->pluck('id')->toArray());
$expenseIds = implode(',', $this->expense->pluck('id')->toArray());
$doubleIds = implode(',', $this->expense->pluck('id')->toArray());
$reportType = 'account';
$preferredPeriod = $this->preferredPeriod();
try {
$result = view(
'reports.account.report',
compact('accountIds', 'reportType', 'expenseIds', 'preferredPeriod')
)->with('start', $this->start)->with('end', $this->end)->render();
$result = view('reports.double.report', compact('accountIds', 'reportType', 'doubleIds', 'preferredPeriod'))
->with('start', $this->start)->with('end', $this->end)
->with('doubles', $this->expense)
->render();
} catch (Throwable $e) {
Log::error(sprintf('Cannot render reports.account.report: %s', $e->getMessage()));
$result = 'Could not render report view.';
Log::error(sprintf('Cannot render reports.double.report: %s', $e->getMessage()));
$result = sprintf('Could not render report view: %s', $e->getMessage());
}
return $result;

View File

@@ -94,6 +94,80 @@ class MonthReportGenerator implements ReportGeneratorInterface
return $result;
}
/**
* Get the audit report.
*
* @param Account $account
* @param Carbon $date
*
* @return array
*
* @throws FireflyException
*/
public function getAuditReport(Account $account, Carbon $date): array
{
/** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app(AccountRepositoryInterface::class);
$accountRepository->setUser($account->user);
/** @var JournalRepositoryInterface $journalRepository */
$journalRepository = app(JournalRepositoryInterface::class);
$journalRepository->setUser($account->user);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->setRange($this->start, $this->end)->withAccountInformation()
->withBudgetInformation()->withCategoryInformation()->withBillInformation();
$journals = $collector->getExtractedJournals();
$journals = array_reverse($journals, true);
$dayBeforeBalance = app('steam')->balance($account, $date);
$startBalance = $dayBeforeBalance;
$currency = $accountRepository->getAccountCurrency($account);
if (null === $currency) {
throw new FireflyException('Unexpected NULL value in account currency preference.'); // @codeCoverageIgnore
}
foreach ($journals as $index => $journal) {
$journals[$index]['balance_before'] = $startBalance;
$transactionAmount = $journal['amount'];
// make sure amount is in the right "direction".
if ($account->id === $journal['destination_account_id']) {
$transactionAmount = app('steam')->positive($journal['amount']);
}
if ($currency->id === $journal['foreign_currency_id']) {
$transactionAmount = $journal['foreign_amount'];
}
$newBalance = bcadd($startBalance, $transactionAmount);
$journals[$index]['balance_after'] = $newBalance;
$startBalance = $newBalance;
// add meta dates for each journal.
$journals[$index]['interest_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'interest_date');
$journals[$index]['book_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'book_date');
$journals[$index]['process_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'process_date');
$journals[$index]['due_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'due_date');
$journals[$index]['payment_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'payment_date');
$journals[$index]['invoice_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'invoice_date');
}
$return = [
'journals' => $journals,
'exists' => count($journals) > 0,
'end' => $this->end->formatLocalized((string)trans('config.month_and_day')),
'endBalance' => app('steam')->balance($account, $this->end),
'dayBefore' => $date->formatLocalized((string)trans('config.month_and_day')),
'dayBeforeBalance' => $dayBeforeBalance,
];
return $return;
}
/**
* Account collection setter.
*
@@ -191,71 +265,4 @@ class MonthReportGenerator implements ReportGeneratorInterface
{
return $this;
}
/**
* Get the audit report.
*
* @param Account $account
* @param Carbon $date
*
* @return array
*
* @throws FireflyException
*/
public function getAuditReport(Account $account, Carbon $date): array
{
/** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app(AccountRepositoryInterface::class);
$accountRepository->setUser($account->user);
/** @var JournalRepositoryInterface $journalRepository */
$journalRepository = app(JournalRepositoryInterface::class);
$journalRepository->setUser($account->user);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->setRange($this->start, $this->end)
->withAccountInformation();
$journals = $collector->getExtractedJournals();
$dayBeforeBalance = app('steam')->balance($account, $date);
$startBalance = $dayBeforeBalance;
$currency = $accountRepository->getAccountCurrency($account);
if (null === $currency) {
throw new FireflyException('Unexpected NULL value in account currency preference.'); // @codeCoverageIgnore
}
foreach ($journals as $index => $journal) {
$journals[$index]['balance_before'] = $startBalance;
$transactionAmount = $journal['amount'];
if ($currency->id === $journal['foreign_currency_id']) {
$transactionAmount = $journal['foreign_amount'];
}
$newBalance = bcadd($startBalance, $transactionAmount);
$journals[$index]['balance_after'] = $newBalance;
$startBalance = $newBalance;
// add meta dates for each journal.
$journals[$index]['interest_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'interest_date');
$journals[$index]['book_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'book_date');
$journals[$index]['process_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'process_date');
$journals[$index]['due_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'due_date');
$journals[$index]['payment_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'payment_date');
$journals[$index]['invoice_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'invoice_date');
}
$return = [
'journals' => $journals,
'exists' => count($journals) > 0,
'end' => $this->end->formatLocalized((string)trans('config.month_and_day')),
'endBalance' => app('steam')->balance($account, $this->end),
'dayBefore' => $date->formatLocalized((string)trans('config.month_and_day')),
'dayBeforeBalance' => $dayBeforeBalance,
];
return $return;
}
}

View File

@@ -35,10 +35,11 @@ use Throwable;
/**
* Class MonthReportGenerator.
* TODO include info about tags.
*
* @codeCoverageIgnore
*/
class MonthReportGenerator extends Support implements ReportGeneratorInterface
class MonthReportGenerator implements ReportGeneratorInterface
{
/** @var Collection The accounts in the report. */
private $accounts;
@@ -66,75 +67,20 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
*/
public function generate(): string
{
$accountIds = implode(',', $this->accounts->pluck('id')->toArray());
$budgetIds = implode(',', $this->budgets->pluck('id')->toArray());
$expenses = $this->getExpenses();
$accountSummary = $this->summarizeByAccount($expenses);
$budgetSummary = $this->summarizeByBudget($expenses);
$averageExpenses = $this->getAverages($expenses, SORT_ASC);
$topExpenses = $this->getTopExpenses();
// render!
$accountIds = implode(',', $this->accounts->pluck('id')->toArray());
$budgetIds = implode(',', $this->budgets->pluck('id')->toArray());
try {
$result = view('reports.budget.month', compact('accountIds', 'budgetIds', 'accountSummary', 'budgetSummary', 'averageExpenses', 'topExpenses'))
$result = view(
'reports.budget.month',
compact('accountIds', 'budgetIds')
)
->with('start', $this->start)->with('end', $this->end)
->with('budgets', $this->budgets)
->with('accounts', $this->accounts)
->render();
} catch (Throwable $e) {
Log::error(sprintf('Cannot render reports.account.report: %s', $e->getMessage()));
$result = 'Could not render report view.';
}
return $result;
}
/**
* Get the expenses.
*
* @return array
*/
protected function getExpenses(): array
{
if (count($this->expenses) > 0) {
Log::debug('Return previous set of expenses.');
return $this->expenses;
}
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
->setTypes([TransactionType::WITHDRAWAL])
->withAccountInformation()
->withBudgetInformation()
->setBudgets($this->budgets);
$journals = $collector->getExtractedJournals();
$this->expenses = $journals;
return $journals;
}
/**
* Summarize a collection by its budget.
*
* @param array $array
*
* @return array
*/
private function summarizeByBudget(array $array): array
{
$result = [
'sum' => '0',
];
/** @var array $journal */
foreach ($array as $journal) {
$budgetId = (int)$journal['budget_id'];
$result[$budgetId] = $result[$budgetId] ?? '0';
$result[$budgetId] = bcadd($journal['amount'], $result[$budgetId]);
$result['sum'] = bcadd($result['sum'], $journal['amount']);
$result = sprintf('Could not render report view: %s', $e->getMessage());
}
return $result;
@@ -231,4 +177,31 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
{
return $this;
}
/**
* Get the expenses.
*
* @return array
*/
protected function getExpenses(): array
{
if (count($this->expenses) > 0) {
Log::debug('Return previous set of expenses.');
return $this->expenses;
}
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
->setTypes([TransactionType::WITHDRAWAL])
->withAccountInformation()
->withBudgetInformation()
->setBudgets($this->budgets);
$journals = $collector->getExtractedJournals();
$this->expenses = $journals;
return $journals;
}
}

View File

@@ -35,10 +35,11 @@ use Throwable;
/**
* Class MonthReportGenerator.
* TODO include info about tags.
*
* @codeCoverageIgnore
*/
class MonthReportGenerator extends Support implements ReportGeneratorInterface
class MonthReportGenerator implements ReportGeneratorInterface
{
/** @var Collection The included accounts */
private $accounts;
@@ -69,102 +70,20 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
*/
public function generate(): string
{
$accountIds = implode(',', $this->accounts->pluck('id')->toArray());
$categoryIds = implode(',', $this->categories->pluck('id')->toArray());
$reportType = 'category';
$expenses = $this->getExpenses();
$income = $this->getIncome();
$accountSummary = $this->getObjectSummary($this->summarizeByAssetAccount($expenses), $this->summarizeByAssetAccount($income));
$categorySummary = $this->getObjectSummary($this->summarizeByCategory($expenses), $this->summarizeByCategory($income));
$averageExpenses = $this->getAverages($expenses, SORT_ASC);
$averageIncome = $this->getAverages($income, SORT_DESC);
$topExpenses = $this->getTopExpenses();
$topIncome = $this->getTopIncome();
$accountIds = implode(',', $this->accounts->pluck('id')->toArray());
$categoryIds = implode(',', $this->categories->pluck('id')->toArray());
$reportType = 'category';
// render!
try {
return view(
'reports.category.month', compact(
'accountIds', 'categoryIds', 'topIncome', 'reportType', 'accountSummary', 'categorySummary', 'averageExpenses',
'averageIncome', 'topExpenses'
)
)
return view('reports.category.month', compact('accountIds', 'categoryIds', 'reportType',))
->with('start', $this->start)->with('end', $this->end)
->with('categories', $this->categories)
->with('accounts', $this->accounts)
->render();
} catch (Throwable $e) {
Log::error(sprintf('Cannot render reports.category.month: %s', $e->getMessage()));
$result = 'Could not render report view.';
}
return $result;
}
/**
* Get the expenses for this report.
*
* @return array
*/
protected function getExpenses(): array
{
if (count($this->expenses) > 0) {
Log::debug('Return previous set of expenses.');
return $this->expenses;
}
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
->setCategories($this->categories)->withAccountInformation();
$transactions = $collector->getExtractedJournals();
$this->expenses = $transactions;
return $transactions;
}
/**
* Get the income for this report.
*
* @return array
*/
protected function getIncome(): array
{
if (count($this->income) > 0) {
return $this->income;
}
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
->setCategories($this->categories)->withAccountInformation();
$transactions = $collector->getExtractedJournals();
$this->income = $transactions;
return $transactions;
}
/**
* Summarize the category.
*
* @param array $array
*
* @return array
*/
private function summarizeByCategory(array $array): array
{
$result = [];
/** @var array $journal */
foreach ($array as $journal) {
$categoryId = (int)$journal['category_id'];
$result[$categoryId] = $result[$categoryId] ?? '0';
$result[$categoryId] = bcadd($journal['amount'], $result[$categoryId]);
$result = sprintf('Could not render report view: %s', $e->getMessage());
}
return $result;
@@ -261,4 +180,53 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
{
return $this;
}
/**
* Get the expenses for this report.
*
* @return array
*/
protected function getExpenses(): array
{
if (count($this->expenses) > 0) {
Log::debug('Return previous set of expenses.');
return $this->expenses;
}
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
->setCategories($this->categories)->withAccountInformation();
$transactions = $collector->getExtractedJournals();
$this->expenses = $transactions;
return $transactions;
}
/**
* Get the income for this report.
*
* @return array
*/
protected function getIncome(): array
{
if (count($this->income) > 0) {
return $this->income;
}
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
->setCategories($this->categories)->withAccountInformation();
$transactions = $collector->getExtractedJournals();
$this->income = $transactions;
return $transactions;
}
}

View File

@@ -60,7 +60,7 @@ class MultiYearReportGenerator implements ReportGeneratorInterface
)->with('start', $this->start)->with('end', $this->end)->render();
} catch (Throwable $e) {
Log::error(sprintf('Cannot render reports.default.multi-year: %s', $e->getMessage()));
$result = 'Could not render report view.';
$result = sprintf('Could not render report view: %s', $e->getMessage());
}
return $result;

View File

@@ -1,212 +0,0 @@
<?php
/**
* Support.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
/** @noinspection PhpUndefinedMethodInspection */
/** @noinspection PhpUndefinedMethodInspection */
declare(strict_types=1);
namespace FireflyIII\Generator\Report;
use FireflyIII\Models\TransactionType;
/**
* Class Support.
* @method array getExpenses()
* @method array getIncome()
*
* @codeCoverageIgnore
*/
class Support
{
/**
* Get the top expenses.
*
* @return array
*/
public function getTopExpenses(): array
{
$expenses = $this->getExpenses();
usort($expenses, function ($a, $b) {
return $a['amount'] <=> $b['amount'];
});
return $expenses;
}
/**
* Get the top income.
*
* @return array
*/
public function getTopIncome(): array
{
$income = $this->getIncome();
usort($income, function ($a, $b) {
return $b['amount'] <=> $a['amount'];
});
return $income;
}
/**
* Get averages from a collection.
*
* @param array $array
* @param int $sortFlag
*
* @return array
*/
protected function getAverages(array $array, int $sortFlag): array
{
$result = [];
/** @var array $journal */
foreach ($array as $journal) {
// opposing name and ID:
$opposingId = $journal['destination_account_id'];
// is not set?
if (!isset($result[$opposingId])) {
$name = $journal['destination_account_name'];
$result[$opposingId] = [
'name' => $name,
'count' => 1,
'id' => $opposingId,
'average' => $journal['amount'],
'sum' => $journal['amount'],
];
continue;
}
++$result[$opposingId]['count'];
$result[$opposingId]['sum'] = bcadd($result[$opposingId]['sum'], $journal['amount']);
$result[$opposingId]['average'] = bcdiv($result[$opposingId]['sum'], (string)$result[$opposingId]['count']);
}
// sort result by average:
$average = [];
foreach ($result as $key => $row) {
$average[$key] = (float)$row['average'];
}
array_multisort($average, $sortFlag, $result);
return $result;
}
/**
* Summarize collection by earned and spent data.
*
* // it's exactly five.
*
* @param array $spent
* @param array $earned
*
* @return array
*/
protected function getObjectSummary(array $spent, array $earned): array
{
$return = [
'sum' => [
'spent' => '0',
'earned' => '0',
],
];
/**
* @var int
* @var string $entry
*/
foreach ($spent as $objectId => $entry) {
if (!isset($return[$objectId])) {
$return[$objectId] = ['spent' => '0', 'earned' => '0'];
}
$return[$objectId]['spent'] = $entry;
$return['sum']['spent'] = bcadd($return['sum']['spent'], $entry);
}
/**
* @var int
* @var string $entry
*/
foreach ($earned as $objectId => $entry) {
$entry = bcmul($entry, '-1');
if (!isset($return[$objectId])) {
$return[$objectId] = ['spent' => '0', 'earned' => '0'];
}
$return[$objectId]['earned'] = $entry;
$return['sum']['earned'] = bcadd($return['sum']['earned'], $entry);
}
return $return;
}
/**
* Summarize the data by account.
*
* @param array $array
*
* @return array
*/
protected function summarizeByAccount(array $array): array
{
$result = [];
/** @var array $journal */
foreach ($array as $journal) {
$accountId = $journal['source_account_id'] ?? 0;
$result[$accountId] = $result[$accountId] ?? '0';
$result[$accountId] = bcadd($journal['amount'], $result[$accountId]);
}
return $result;
}
/**
* Summarize the data by the asset account or liability, depending on the type.
*
* In case of transfers, it will choose the source account.
*
* @param array $array
*
* @return array
*/
protected function summarizeByAssetAccount(array $array): array
{
$result = [];
/** @var array $journal */
foreach ($array as $journal) {
$accountId = 0;
switch ($journal['transaction_type_type']) {
case TransactionType::WITHDRAWAL:
case TransactionType::TRANSFER:
$accountId = $journal['source_account_id'] ?? 0;
break;
case TransactionType::DEPOSIT:
$accountId = $journal['destination_account_id'] ?? 0;
break;
}
$result[$accountId] = $result[$accountId] ?? '0';
$result[$accountId] = bcadd($journal['amount'], $result[$accountId]);
}
return $result;
}
}

View File

@@ -28,8 +28,6 @@ namespace FireflyIII\Generator\Report\Tag;
use Carbon\Carbon;
use FireflyIII\Generator\Report\ReportGeneratorInterface;
use FireflyIII\Generator\Report\Support;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\TransactionType;
use Illuminate\Support\Collection;
use Log;
use Throwable;
@@ -39,7 +37,7 @@ use Throwable;
*
* @codeCoverageIgnore
*/
class MonthReportGenerator extends Support implements ReportGeneratorInterface
class MonthReportGenerator implements ReportGeneratorInterface
{
/** @var Collection The accounts involved */
private $accounts;
@@ -71,30 +69,18 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
*/
public function generate(): string
{
$accountIds = implode(',', $this->accounts->pluck('id')->toArray());
$tagTags = implode(',', $this->tags->pluck('tag')->toArray());
$tagIds = implode(',', $this->tags->pluck('id')->toArray());
$reportType = 'tag';
$expenses = $this->getExpenses();
$income = $this->getIncome();
$accountSummary = $this->getObjectSummary($this->summarizeByAssetAccount($expenses), $this->summarizeByAssetAccount($income));
$tagSummary = $this->getObjectSummary($this->summarizeByTag($expenses), $this->summarizeByTag($income));
$averageExpenses = $this->getAverages($expenses, SORT_ASC);
$averageIncome = $this->getAverages($income, SORT_DESC);
$topExpenses = $this->getTopExpenses();
$topIncome = $this->getTopIncome();
$accountIds = implode(',', $this->accounts->pluck('id')->toArray());
$tagIds = implode(',', $this->tags->pluck('id')->toArray());
$reportType = 'tag';
// render!
try {
$result = view(
'reports.tag.month', compact(
'accountIds', 'tagTags', 'reportType', 'accountSummary', 'tagSummary', 'averageExpenses', 'averageIncome', 'topIncome',
'topExpenses', 'tagIds'
)
'reports.tag.month', compact('accountIds', 'reportType', 'tagIds')
)->with('start', $this->start)->with('end', $this->end)->with('tags', $this->tags)->with('accounts', $this->accounts)->render();
} catch (Throwable $e) {
Log::error(sprintf('Cannot render reports.tag.month: %s', $e->getMessage()));
$result = 'Could not render report view.';
$result = sprintf('Could not render report view: %s', $e->getMessage());
}
return $result;
@@ -192,79 +178,5 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
return $this;
}
/**
* Get expense collection for report.
*
* @return array
*/
protected function getExpenses(): array
{
if (count($this->expenses) > 0) {
Log::debug('Return previous set of expenses.');
return $this->expenses;
}
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
->setTags($this->tags)->withAccountInformation();
$journals = $collector->getExtractedJournals();
$this->expenses = $journals;
return $journals;
}
/**
* Get the income for this report.
*
* @return array
*/
protected function getIncome(): array
{
if (count($this->income) > 0) {
return $this->income;
}
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)
->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
->setTags($this->tags)->withAccountInformation();
$journals = $collector->getExtractedJournals();
$this->income = $journals;
return $journals;
}
/**
* Summarize by tag.
*
* @param array $array
*
* @return array
*/
protected function summarizeByTag(array $array): array
{
$tagIds = array_map('\intval', $this->tags->pluck('id')->toArray());
$result = [];
/** @var array $journal */
foreach ($array as $journal) {
/**
* @var int $id
* @var array $tag
*/
foreach ($journal['tags'] as $id => $tag) {
if (in_array($id, $tagIds, true)) {
$result[$id] = $result[$id] ?? '0';
$result[$id] = bcadd($journal['amount'], $result[$id]);
}
}
}
return $result;
}
}

View File

@@ -43,7 +43,6 @@ class VersionCheckEventHandler
/**
* Checks with GitHub to see if there is a new version.
*
*
* @param RequestedVersionCheckStatus $event
*/
public function checkForUpdates(RequestedVersionCheckStatus $event): void

View File

@@ -84,15 +84,20 @@ class AttachmentHelper implements AttachmentHelperInterface
*/
public function getAttachmentContent(Attachment $attachment): string
{
$encryptedData = '';
try {
$content = Crypt::decrypt($this->uploadDisk->get(sprintf('at-%d.data', $attachment->id)));
$encryptedData = $this->uploadDisk->get(sprintf('at-%d.data', $attachment->id));
} catch (FileNotFoundException $e) {
Log::error($e->getMessage());
}
try {
$unencryptedData = Crypt::decrypt($encryptedData); // verified
} catch (DecryptException|FileNotFoundException $e) {
Log::error(sprintf('Could not decrypt data of attachment #%d: %s', $attachment->id, $e->getMessage()));
$content = '';
$unencryptedData = $encryptedData;
}
return $content;
return $unencryptedData;
}
/**
@@ -167,9 +172,8 @@ class AttachmentHelper implements AttachmentHelperInterface
return false;
}
// is allowed? Save the file!
$encrypted = Crypt::encrypt($content);
$this->uploadDisk->put($attachment->fileName(), $encrypted);
// is allowed? Save the file, without encryption.
$this->uploadDisk->put($attachment->fileName(), $content);
// update attachment.
$attachment->md5 = md5_file($path);
@@ -275,12 +279,10 @@ class AttachmentHelper implements AttachmentHelperInterface
}
$content = $fileObject->fread($file->getSize());
$encrypted = Crypt::encrypt($content);
Log::debug(sprintf('Full file length is %d and upload size is %d.', strlen($content), $file->getSize()));
Log::debug(sprintf('Encrypted content is %d', strlen($encrypted)));
// store it:
$this->uploadDisk->put($attachment->fileName(), $encrypted);
$this->uploadDisk->put($attachment->fileName(), $content);
$attachment->uploaded = true; // update attachment
$attachment->save();
$this->attachments->push($attachment);

View File

@@ -1,392 +0,0 @@
<?php
/**
* MetaPieChart.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Chart;
use Carbon\Carbon;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\User;
use Illuminate\Support\Collection;
use Log;
/**
* Class MetaPieChart.
*/
class MetaPieChart implements MetaPieChartInterface
{
/** @var array The ways to group transactions, given the type of chart. */
static protected $grouping
= [
'account' => ['destination_account_id'],
'budget' => ['budget_id'],
'category' => ['category_id'],
'tag' => [],
];
/** @var Collection Involved accounts. */
protected $accounts;
/** @var Collection The budgets. */
protected $budgets;
/** @var Collection The categories. */
protected $categories;
/** @var bool Collect other objects. */
protected $collectOtherObjects = false;
/** @var Carbon The end date./ */
protected $end;
/** @var array The repositories. */
protected $repositories
= [
'account' => AccountRepositoryInterface::class,
'budget' => BudgetRepositoryInterface::class,
'category' => CategoryRepositoryInterface::class,
'tag' => TagRepositoryInterface::class,
];
/** @var Carbon The start date. */
protected $start;
/** @var Collection The involved tags/ */
protected $tags;
/** @var string The total amount. */
protected $total = '0';
/** @var User The user. */
protected $user;
/**
* MetaPieChart constructor.
*/
public function __construct()
{
$this->accounts = new Collection;
$this->budgets = new Collection;
$this->categories = new Collection;
$this->tags = new Collection;
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
}
/**
* Generate the chart.
*
* @param string $direction
* @param string $group
*
* @return array
*
*/
public function generate(string $direction, string $group): array
{
$transactions = $this->getTransactions($direction);
$grouped = $this->groupByFields($transactions, self::$grouping[$group]);
$chartData = $this->organizeByType($group, $grouped);
$key = (string)trans('firefly.everything_else');
// also collect all other transactions
if ($this->collectOtherObjects && 'expense' === $direction) {
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user);
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)->setTypes([TransactionType::WITHDRAWAL]);
$sum = $collector->getSum();
$sum = bcmul($sum, '-1');
$sum = bcsub($sum, $this->total);
$chartData[$key] = $sum;
}
if ($this->collectOtherObjects && 'income' === $direction) {
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user);
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)->setTypes([TransactionType::DEPOSIT]);
$sum = $collector->getSum();
$sum = bcsub($sum, $this->total);
$chartData[$key] = $sum;
}
return $chartData;
}
/**
* Get all transactions.
*
* @param string $direction
*
* @return array
*/
protected function getTransactions(string $direction): array
{
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$types = [TransactionType::DEPOSIT, TransactionType::TRANSFER];
if ('expense' === $direction) {
$types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER];
}
$collector->setUser($this->user);
$collector->setAccounts($this->accounts);
$collector->setRange($this->start, $this->end);
$collector->setTypes($types);
$collector->withAccountInformation();
$collector->setBudgets($this->budgets);
$collector->setCategories($this->categories);
// @codeCoverageIgnoreStart
if ($this->tags->count() > 0) {
$collector->setTags($this->tags);
}
// @codeCoverageIgnoreEnd
return $collector->getExtractedJournals();
}
/**
* Group by a specific field.
*
* @param array $array
* @param array $fields
*
* @return array
*
*/
protected function groupByFields(array $array, array $fields): array
{
$grouped = [];
if (0 === count($fields) && $this->tags->count() > 0) {
// do a special group on tags:
$grouped = $this->groupByTag($array); // @codeCoverageIgnore
}
if (0 !== count($fields) || $this->tags->count() <= 0) {
$grouped = [];
/** @var array $journal */
foreach ($array as $journal) {
$values = [];
foreach ($fields as $field) {
$values[] = (int)$journal[$field];
}
$value = max($values);
$grouped[$value] = $grouped[$value] ?? '0';
$grouped[$value] = bcadd($journal['amount'], $grouped[$value]);
}
}
return $grouped;
}
/**
* Group by tag (slightly different).
*
* @codeCoverageIgnore
*
* @param array $array
*
* @return array
*/
private function groupByTag(array $array): array
{
$grouped = [];
/** @var array $journal */
foreach ($array as $journal) {
$tags = $journal['tags'] ?? [];
/** @var Tag $tag */
foreach ($tags as $id => $tag) {
$grouped[$id] = $grouped[$id] ?? '0';
$grouped[$id] = bcadd($journal['amount'], $grouped[$id]);
}
}
return $grouped;
}
/**
* Organise by certain type.
*
* @param string $type
* @param array $array
*
* @return array
*/
protected function organizeByType(string $type, array $array): array
{
$chartData = [];
$names = [];
$repository = app($this->repositories[$type]);
$repository->setUser($this->user);
foreach ($array as $objectId => $amount) {
if (!isset($names[$objectId])) {
$object = $repository->findNull((int)$objectId);
$name = null === $object ? '(no name)' : $object->name;
$names[$objectId] = $name ?? $object->tag;
}
$amount = app('steam')->positive($amount);
$this->total = bcadd($this->total, $amount);
$chartData[$names[$objectId]] = $amount;
}
return $chartData;
}
/**
* Accounts setter.
*
* @codeCoverageIgnore
*
* @param Collection $accounts
*
* @return MetaPieChartInterface
*/
public function setAccounts(Collection $accounts): MetaPieChartInterface
{
$this->accounts = $accounts;
return $this;
}
/**
* Budgets setter.
*
* @codeCoverageIgnore
*
* @param Collection $budgets
*
* @return MetaPieChartInterface
*/
public function setBudgets(Collection $budgets): MetaPieChartInterface
{
$this->budgets = $budgets;
return $this;
}
/**
* Categories setter.
*
* @codeCoverageIgnore
*
* @param Collection $categories
*
* @return MetaPieChartInterface
*/
public function setCategories(Collection $categories): MetaPieChartInterface
{
$this->categories = $categories;
return $this;
}
/**
* Set if other objects should be collected.
*
* @codeCoverageIgnore
*
* @param bool $collectOtherObjects
*
* @return MetaPieChartInterface
*/
public function setCollectOtherObjects(bool $collectOtherObjects): MetaPieChartInterface
{
$this->collectOtherObjects = $collectOtherObjects;
return $this;
}
/**
* Set the end date.
*
* @codeCoverageIgnore
*
* @param Carbon $end
*
* @return MetaPieChartInterface
*/
public function setEnd(Carbon $end): MetaPieChartInterface
{
$this->end = $end;
return $this;
}
/**
* Set the start date.
*
* @codeCoverageIgnore
*
* @param Carbon $start
*
* @return MetaPieChartInterface
*/
public function setStart(Carbon $start): MetaPieChartInterface
{
$this->start = $start;
return $this;
}
/**
* Set the tags.
*
* @codeCoverageIgnore
*
* @param Collection $tags
*
* @return MetaPieChartInterface
*/
public function setTags(Collection $tags): MetaPieChartInterface
{
$this->tags = $tags;
return $this;
}
/**
* Set the user.
*
* @codeCoverageIgnore
*
* @param User $user
*
* @return MetaPieChartInterface
*/
public function setUser(User $user): MetaPieChartInterface
{
$this->user = $user;
return $this;
}
}

View File

@@ -1,115 +0,0 @@
<?php
/**
* MetaPieChartInterface.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Chart;
use Carbon\Carbon;
use FireflyIII\User;
use Illuminate\Support\Collection;
/**
* Interface MetaPieChartInterface.
*/
interface MetaPieChartInterface
{
/**
* Generate a chart.
*
* @param string $direction
* @param string $group
*
* @return array
*/
public function generate(string $direction, string $group): array;
/**
* Accounts setter.
*
* @param Collection $accounts
*
* @return MetaPieChartInterface
*/
public function setAccounts(Collection $accounts): MetaPieChartInterface;
/**
* Budgets setter.
*
* @param Collection $budgets
*
* @return MetaPieChartInterface
*/
public function setBudgets(Collection $budgets): MetaPieChartInterface;
/**
* Categories setter.
*
* @param Collection $categories
*
* @return MetaPieChartInterface
*/
public function setCategories(Collection $categories): MetaPieChartInterface;
/**
* Set if other objects should be collected.
*
* @param bool $collectOtherObjects
*
* @return MetaPieChartInterface
*/
public function setCollectOtherObjects(bool $collectOtherObjects): MetaPieChartInterface;
/**
* Set the end date.
*
* @param Carbon $end
*
* @return MetaPieChartInterface
*/
public function setEnd(Carbon $end): MetaPieChartInterface;
/**
* Set the start date.
*
* @param Carbon $start
*
* @return MetaPieChartInterface
*/
public function setStart(Carbon $start): MetaPieChartInterface;
/**
* Set the tags.
*
* @param Collection $tags
*
* @return MetaPieChartInterface
*/
public function setTags(Collection $tags): MetaPieChartInterface;
/**
* Set the user.
*
* @param User $user
*
* @return MetaPieChartInterface
*/
public function setUser(User $user): MetaPieChartInterface;
}

View File

@@ -403,6 +403,29 @@ class GroupCollector implements GroupCollectorInterface
return $this;
}
/**
* Both source AND destination must be in this list of accounts.
*
* @param Collection $accounts
*
* @return GroupCollectorInterface
*/
public function setBothAccounts(Collection $accounts): GroupCollectorInterface
{
if ($accounts->count() > 0) {
$accountIds = $accounts->pluck('id')->toArray();
$this->query->where(
static function (EloquentBuilder $query) use ($accountIds) {
$query->whereIn('source.account_id', $accountIds);
$query->whereIn('destination.account_id', $accountIds);
}
);
app('log')->debug(sprintf('GroupCollector: setBothAccounts: %s', implode(', ', $accountIds)));
}
return $this;
}
/**
* Limit the search to a specific budget.
*
@@ -499,7 +522,7 @@ class GroupCollector implements GroupCollectorInterface
$accountIds = $accounts->pluck('id')->toArray();
$this->query->whereIn('destination.account_id', $accountIds);
app('log')->debug(sprintf('GroupCollector: setSourceAccounts: %s', implode(', ', $accountIds)));
app('log')->debug(sprintf('GroupCollector: setDestinationAccounts: %s', implode(', ', $accountIds)));
}
return $this;
@@ -894,16 +917,16 @@ class GroupCollector implements GroupCollectorInterface
}
/**
* @param array $existingJournal
* @param TransactionGroup $newGroup
* @param array $existingJournal
* @param TransactionJournal $newJournal
*
* @return array
*/
private function mergeTags(array $existingJournal, TransactionGroup $newGroup): array
private function mergeTags(array $existingJournal, TransactionJournal $newJournal): array
{
$newArray = $newGroup->toArray();
$newArray = $newJournal->toArray();
if (isset($newArray['tag_id'])) { // assume the other fields are present as well.
$tagId = (int)$newGroup['tag_id'];
$tagId = (int)$newJournal['tag_id'];
$tagDate = null;
try {
@@ -1102,4 +1125,41 @@ class GroupCollector implements GroupCollectorInterface
->orderBy('transaction_journals.description', 'DESC')
->orderBy('source.amount', 'DESC');
}
/**
* Either account can be set, but NOT both. This effectively excludes internal transfers.
*
* @param Collection $accounts
*
* @return GroupCollectorInterface
*/
public function setXorAccounts(Collection $accounts): GroupCollectorInterface
{
if ($accounts->count() > 0) {
$accountIds = $accounts->pluck('id')->toArray();
$this->query->where(
static function (EloquentBuilder $q1) use ($accountIds) {
// sourceAccount is in the set, and destination is NOT.
$q1->where(
static function (EloquentBuilder $q2) use ($accountIds) {
$q2->whereIn('source.account_id', $accountIds);
$q2->whereNotIn('destination.account_id', $accountIds);
}
);
// destination is in the set, and source is NOT
$q1->orWhere(
static function (EloquentBuilder $q3) use ($accountIds) {
$q3->whereNotIn('source.account_id', $accountIds);
$q3->whereIn('destination.account_id', $accountIds);
}
);
}
);
app('log')->debug(sprintf('GroupCollector: setXorAccounts: %s', implode(', ', $accountIds)));
}
return $this;
}
}

View File

@@ -39,103 +39,6 @@ use Illuminate\Support\Collection;
*/
interface GroupCollectorInterface
{
/**
* Return the transaction journals without group information. Is useful in some instances.
*
* @return array
*/
public function getExtractedJournals(): array;
/**
* Set source accounts.
*
* @param Collection $accounts
*
* @return GroupCollectorInterface
*/
public function setSourceAccounts(Collection $accounts): GroupCollectorInterface;
/**
* These accounts must not be source accounts.
*
* @param Collection $accounts
*
* @return GroupCollectorInterface
*/
public function excludeSourceAccounts(Collection $accounts): GroupCollectorInterface;
/**
* Exclude destination accounts.
* @param Collection $accounts
*
* @return GroupCollectorInterface
*/
public function excludeDestinationAccounts(Collection $accounts): GroupCollectorInterface;
/**
* Set destination accounts.
*
* @param Collection $accounts
*
* @return GroupCollectorInterface
*/
public function setDestinationAccounts(Collection $accounts): GroupCollectorInterface;
/**
* Return the sum of all journals.
*
* @return string
*/
public function getSum(): string;
/**
* Add tag info.
*
* @return GroupCollectorInterface
*/
public function withTagInformation(): GroupCollectorInterface;
/**
* Return the groups.
*
* @return Collection
*/
public function getGroups(): Collection;
/**
* Same as getGroups but everything is in a paginator.
*
* @return LengthAwarePaginator
*/
public function getPaginatedGroups(): LengthAwarePaginator;
/**
* Define which accounts can be part of the source and destination transactions.
*
* @param Collection $accounts
*
* @return GroupCollectorInterface
*/
public function setAccounts(Collection $accounts): GroupCollectorInterface;
/**
* Limit the search to a specific bill.
*
* @param Bill $bill
*
* @return GroupCollectorInterface
*/
public function setBill(Bill $bill): GroupCollectorInterface;
/**
* Limit the search to a specific set of bills.
*
* @param Collection $bills
*
* @return GroupCollectorInterface
*/
public function setBills(Collection $bills): GroupCollectorInterface;
/**
* Get transactions with a specific amount.
*
@@ -163,6 +66,115 @@ interface GroupCollectorInterface
*/
public function amountMore(string $amount): GroupCollectorInterface;
/**
* Exclude destination accounts.
*
* @param Collection $accounts
*
* @return GroupCollectorInterface
*/
public function excludeDestinationAccounts(Collection $accounts): GroupCollectorInterface;
/**
* These accounts must not be source accounts.
*
* @param Collection $accounts
*
* @return GroupCollectorInterface
*/
public function excludeSourceAccounts(Collection $accounts): GroupCollectorInterface;
/**
* Return the transaction journals without group information. Is useful in some instances.
*
* @return array
*/
public function getExtractedJournals(): array;
/**
* Return the groups.
*
* @return Collection
*/
public function getGroups(): Collection;
/**
* Same as getGroups but everything is in a paginator.
*
* @return LengthAwarePaginator
*/
public function getPaginatedGroups(): LengthAwarePaginator;
/**
* Return the sum of all journals.
*
* @return string
*/
public function getSum(): string;
/**
* Define which accounts can be part of the source and destination transactions.
*
* @param Collection $accounts
*
* @return GroupCollectorInterface
*/
public function setAccounts(Collection $accounts): GroupCollectorInterface;
/**
* Either account can be set, but NOT both. This effectively excludes internal transfers.
*
* @param Collection $accounts
*
* @return GroupCollectorInterface
*/
public function setXorAccounts(Collection $accounts): GroupCollectorInterface;
/**
* Collect transactions after a specific date.
*
* @param Carbon $date
*
* @return GroupCollectorInterface
*/
public function setAfter(Carbon $date): GroupCollectorInterface;
/**
* Collect transactions before a specific date.
*
* @param Carbon $date
*
* @return GroupCollectorInterface
*/
public function setBefore(Carbon $date): GroupCollectorInterface;
/**
* Limit the search to a specific bill.
*
* @param Bill $bill
*
* @return GroupCollectorInterface
*/
public function setBill(Bill $bill): GroupCollectorInterface;
/**
* Limit the search to a specific set of bills.
*
* @param Collection $bills
*
* @return GroupCollectorInterface
*/
public function setBills(Collection $bills): GroupCollectorInterface;
/**
* Both source AND destination must be in this list of accounts.
*
* @param Collection $accounts
*
* @return GroupCollectorInterface
*/
public function setBothAccounts(Collection $accounts): GroupCollectorInterface;
/**
* Limit the search to a specific budget.
*
@@ -181,6 +193,15 @@ interface GroupCollectorInterface
*/
public function setBudgets(Collection $budgets): GroupCollectorInterface;
/**
* Limit the search to a specific bunch of categories.
*
* @param Collection $categories
*
* @return GroupCollectorInterface
*/
public function setCategories(Collection $categories): GroupCollectorInterface;
/**
* Limit the search to a specific category.
*
@@ -201,13 +222,13 @@ interface GroupCollectorInterface
public function setCurrency(TransactionCurrency $currency): GroupCollectorInterface;
/**
* Limit the result to a set of specific transaction journals.
* Set destination accounts.
*
* @param array $journalIds
* @param Collection $accounts
*
* @return GroupCollectorInterface
*/
public function setJournalIds(array $journalIds): GroupCollectorInterface;
public function setDestinationAccounts(Collection $accounts): GroupCollectorInterface;
/**
* Limit the result to a specific transaction group.
@@ -219,13 +240,13 @@ interface GroupCollectorInterface
public function setGroup(TransactionGroup $transactionGroup): GroupCollectorInterface;
/**
* Search for words in descriptions.
* Limit the result to a set of specific transaction journals.
*
* @param array $array
* @param array $journalIds
*
* @return GroupCollectorInterface
*/
public function setSearchWords(array $array): GroupCollectorInterface;
public function setJournalIds(array $journalIds): GroupCollectorInterface;
/**
* Limit the number of returned entries.
@@ -255,6 +276,24 @@ interface GroupCollectorInterface
*/
public function setRange(Carbon $start, Carbon $end): GroupCollectorInterface;
/**
* Search for words in descriptions.
*
* @param array $array
*
* @return GroupCollectorInterface
*/
public function setSearchWords(array $array): GroupCollectorInterface;
/**
* Set source accounts.
*
* @param Collection $accounts
*
* @return GroupCollectorInterface
*/
public function setSourceAccounts(Collection $accounts): GroupCollectorInterface;
/**
* Limit results to a specific tag.
*
@@ -273,20 +312,6 @@ interface GroupCollectorInterface
*/
public function setTags(Collection $tags): GroupCollectorInterface;
/**
* Limit results to a transactions without a budget.
*
* @return GroupCollectorInterface
*/
public function withoutBudget(): GroupCollectorInterface;
/**
* Limit results to a transactions without a category.
*
* @return GroupCollectorInterface
*/
public function withoutCategory(): GroupCollectorInterface;
/**
* Limit the search to one specific transaction group.
*
@@ -328,33 +353,6 @@ interface GroupCollectorInterface
*/
public function withAccountInformation(): GroupCollectorInterface;
/**
* Limit the search to a specific bunch of categories.
*
* @param Collection $categories
*
* @return GroupCollectorInterface
*/
public function setCategories(Collection $categories): GroupCollectorInterface;
/**
* Collect transactions before a specific date.
*
* @param Carbon $date
*
* @return GroupCollectorInterface
*/
public function setBefore(Carbon $date): GroupCollectorInterface;
/**
* Collect transactions after a specific date.
*
* @param Carbon $date
*
* @return GroupCollectorInterface
*/
public function setAfter(Carbon $date): GroupCollectorInterface;
/**
* Include bill name + ID.
*
@@ -376,4 +374,25 @@ interface GroupCollectorInterface
*/
public function withCategoryInformation(): GroupCollectorInterface;
/**
* Add tag info.
*
* @return GroupCollectorInterface
*/
public function withTagInformation(): GroupCollectorInterface;
/**
* Limit results to a transactions without a budget.
*
* @return GroupCollectorInterface
*/
public function withoutBudget(): GroupCollectorInterface;
/**
* Limit results to a transactions without a category.
*
* @return GroupCollectorInterface
*/
public function withoutCategory(): GroupCollectorInterface;
}

View File

@@ -1,139 +0,0 @@
<?php
/**
* BalanceReportHelper.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Report;
use Carbon\Carbon;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\Budget;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Illuminate\Support\Collection;
use Log;
/**
* Class BalanceReportHelper.
*
* @codeCoverageIgnore
*/
class BalanceReportHelper implements BalanceReportHelperInterface
{
/** @var BudgetRepositoryInterface Budget repository */
protected $budgetRepository;
/**
* ReportHelper constructor.
* @param BudgetRepositoryInterface $budgetRepository
*/
public function __construct(BudgetRepositoryInterface $budgetRepository)
{
$this->budgetRepository = $budgetRepository;
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
}
/**
* Generate a balance report.
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function getBalanceReport(Collection $accounts, Carbon $start, Carbon $end): array
{
Log::debug('Start of balance report');
$report = [
'budgets' => [],
'accounts' => [],
];
/** @var Account $account */
foreach ($accounts as $account) {
$report['accounts'][$account->id] = [
'id' => $account->id,
'name' => $account->name,
'iban' => $account->iban,
'sum' => '0',
];
}
$budgets = $this->budgetRepository->getBudgets();
/** @var Budget $budget */
foreach ($budgets as $budget) {
$budgetId = $budget->id;
$report['budgets'][$budgetId] = [
'budget_id' => $budgetId,
'budget_name' => $budget->name,
'spent' => [], // per account
'sums' => [], // per currency
];
$spent = [];
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$journals = $collector->setRange($start, $end)->setSourceAccounts($accounts)->setTypes([TransactionType::WITHDRAWAL])->setBudget($budget)
->getExtractedJournals();
/** @var array $journal */
foreach ($journals as $journal) {
$sourceAccount = $journal['source_account_id'];
$currencyId = $journal['currency_id'];
$spent[$sourceAccount] = $spent[$sourceAccount] ?? [
'source_account_id' => $sourceAccount,
'currency_id' => $journal['currency_id'],
'currency_code' => $journal['currency_code'],
'currency_name' => $journal['currency_name'],
'currency_symbol' => $journal['currency_symbol'],
'currency_decimal_places' => $journal['currency_decimal_places'],
'spent' => '0',
];
$spent[$sourceAccount]['spent'] = bcadd($spent[$sourceAccount]['spent'], $journal['amount']);
// also fix sum:
$report['sums'][$budgetId][$currencyId] = $report['sums'][$budgetId][$currencyId] ?? [
'sum' => '0',
'currency_id' => $journal['currency_id'],
'currency_code' => $journal['currency_code'],
'currency_name' => $journal['currency_name'],
'currency_symbol' => $journal['currency_symbol'],
'currency_decimal_places' => $journal['currency_decimal_places'],
];
$report['sums'][$budgetId][$currencyId]['sum'] = bcadd($report['sums'][$budgetId][$currencyId]['sum'], $journal['amount']);
$report['accounts'][$sourceAccount]['sum'] = bcadd($report['accounts'][$sourceAccount]['sum'], $journal['amount']);
// add currency info for account sum
$report['accounts'][$sourceAccount]['currency_id'] = $journal['currency_id'];
$report['accounts'][$sourceAccount]['currency_code'] = $journal['currency_code'];
$report['accounts'][$sourceAccount]['currency_name'] = $journal['currency_name'];
$report['accounts'][$sourceAccount]['currency_symbol'] = $journal['currency_symbol'];
$report['accounts'][$sourceAccount]['currency_decimal_places'] = $journal['currency_decimal_places'];
}
$report['budgets'][$budgetId]['spent'] = $spent;
// get transactions in budget
}
return $report;
}
}

View File

@@ -1,214 +0,0 @@
<?php
/**
* BudgetReportHelper.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Report;
use Carbon\Carbon;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Illuminate\Support\Collection;
use Log;
/**
* Class BudgetReportHelper.
*
* @codeCoverageIgnore
*/
class BudgetReportHelper implements BudgetReportHelperInterface
{
/** @var BudgetRepositoryInterface The budget repository interface. */
private $repository;
/**
* BudgetReportHelper constructor.
*
* @param BudgetRepositoryInterface $repository
*/
public function __construct(BudgetRepositoryInterface $repository)
{
$this->repository = $repository;
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
}
/**
* Get the full budget report.
*
* TODO one big method is very complex.
*
* @param Carbon $start
* @param Carbon $end
* @param Collection $accounts
*
* @return array
*/
public function getBudgetReport(Carbon $start, Carbon $end, Collection $accounts): array
{
$set = $this->repository->getBudgets();
$array = [
'budgets' => [],
'sums' => [],
];
/** @var Budget $budget */
foreach ($set as $budget) {
$entry = [
'budget_id' => $budget->id,
'budget_name' => $budget->name,
'no_budget' => false,
'rows' => [],
];
// get multi currency expenses first:
$budgetLimits = $this->repository->getBudgetLimits($budget, $start, $end);
$expenses = $this->repository->spentInPeriodMc(new Collection([$budget]), $accounts, $start, $end);
$defaultCurrency = app('amount')->getDefaultCurrencyByUser($budget->user);
Log::debug(sprintf('Default currency for getBudgetReport is %s', $defaultCurrency->code));
if (0 === count($expenses)) {
// list the budget limits, basic amounts.
/** @var BudgetLimit $limit */
foreach ($budgetLimits as $limit) {
$currency = $limit->transactionCurrency ?? $defaultCurrency;
Log::debug(sprintf('Default currency for limit #%d is %s', $limit->id, $currency->code));
$row = [
'limit_id' => $limit->id,
'start_date' => $limit->start_date,
'end_date' => $limit->end_date,
'budgeted' => $limit->amount,
'spent' => '0',
'left' => $limit->amount,
'overspent' => null,
'currency_id' => $currency->id,
'currency_code' => $currency->code,
'currency_name' => $currency->name,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
];
$entry['rows'][] = $row;
}
}
foreach ($expenses as $expense) {
$limit = $this->budgetLimitInCurrency($expense['currency_id'], $budgetLimits);
$row = [
'limit_id' => null,
'start_date' => null,
'end_date' => null,
'budgeted' => null,
'spent' => $expense['amount'],
'left' => null,
'overspent' => null,
'currency_id' => $expense['currency_id'],
'currency_code' => $expense['currency_name'],
'currency_name' => $expense['currency_name'],
'currency_symbol' => $expense['currency_symbol'],
'currency_decimal_places' => $expense['currency_decimal_places'],
];
if (null !== $limit) {
// yes
$row['start_date'] = $limit->start_date;
$row['end_date'] = $limit->end_date;
$row['budgeted'] = $limit->amount;
$row['limit_id'] = $limit->id;
// less than zero? Set to 0.0
$row['left'] = -1 === bccomp(bcadd($limit->amount, $row['spent']), '0') ? '0' : bcadd($limit->amount, $row['spent']);
// spent > budgeted? then sum, otherwise other sum
$row['overspent'] = 1 === bccomp($row['spent'], $row['budgeted']) ? bcadd($row['spent'], $row['budgeted']) : '0';
}
$entry['rows'][] = $row;
}
$array['budgets'][] = $entry;
}
$noBudget = $this->repository->spentInPeriodWoBudgetMc($accounts, $start, $end);
$noBudgetEntry = [
'budget_id' => null,
'budget_name' => null,
'no_budget' => true,
'rows' => [],
];
foreach ($noBudget as $row) {
$noBudgetEntry['rows'][] = [
'limit_id' => null,
'start_date' => null,
'end_date' => null,
'budgeted' => null,
'spent' => $row['amount'],
'left' => null,
'overspent' => null,
'currency_id' => $row['currency_id'],
'currency_code' => $row['currency_code'],
'currency_name' => $row['currency_name'],
'currency_symbol' => $row['currency_symbol'],
'currency_decimal_places' => $row['currency_decimal_places'],
];
}
$array['budgets'][] = $noBudgetEntry;
// fill sums:
/** @var array $budget */
foreach ($array['budgets'] as $budget) {
/** @var array $row */
foreach ($budget['rows'] as $row) {
$currencyId = $row['currency_id'];
$array['sums'][$currencyId] = $array['sums'][$currencyId] ?? [
'currency_id' => $row['currency_id'],
'currency_code' => $row['currency_code'],
'currency_name' => $row['currency_name'],
'currency_symbol' => $row['currency_symbol'],
'currency_decimal_places' => $row['currency_decimal_places'],
'budgeted' => '0',
'spent' => '0',
'left' => '0',
'overspent' => '0',
];
$array['sums'][$currencyId]['budgeted'] = bcadd($array['sums'][$currencyId]['budgeted'], $row['budgeted'] ?? '0');
$array['sums'][$currencyId]['spent'] = bcadd($array['sums'][$currencyId]['spent'], $row['spent'] ?? '0');
$array['sums'][$currencyId]['left'] = bcadd($array['sums'][$currencyId]['left'], $row['left'] ?? '0');
$array['sums'][$currencyId]['overspent'] = bcadd($array['sums'][$currencyId]['overspent'], $row['overspent'] ?? '0');
}
}
return $array;
}
/**
* Returns from the collection the budget limit with the indicated currency ID
*
* @param int $currencyId
* @param Collection $budgetLimits
*
* @return BudgetLimit|null
*/
private function budgetLimitInCurrency(int $currencyId, Collection $budgetLimits): ?BudgetLimit
{
return $budgetLimits->first(
static function (BudgetLimit $limit) use ($currencyId) {
return $limit->transaction_currency_id === $currencyId;
}
);
}
}

View File

@@ -30,7 +30,6 @@ use Illuminate\Support\Collection;
/**
* Interface NetWorthInterface
*
* @package FireflyIII\Helpers\Report
*/
interface NetWorthInterface
{

View File

@@ -52,9 +52,9 @@ class PopupReport implements PopupReportInterface
/**
* Collect the transactions for one account and one budget.
*
* @param Budget $budget
* @param Budget $budget
* @param Account $account
* @param array $attributes
* @param array $attributes
*
* @return array
*/
@@ -62,7 +62,11 @@ class PopupReport implements PopupReportInterface
{
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->setRange($attributes['startDate'], $attributes['endDate'])->setBudget($budget);
$collector->setAccounts(new Collection([$account]))
->withAccountInformation()
->withBudgetInformation()
->withCategoryInformation()
->setRange($attributes['startDate'], $attributes['endDate'])->setBudget($budget);
return $collector->getExtractedJournals();
}
@@ -71,20 +75,36 @@ class PopupReport implements PopupReportInterface
* Collect the transactions for one account and no budget.
*
* @param Account $account
* @param array $attributes
* @param array $attributes
*
* @return array
*/
public function balanceForNoBudget(Account $account, array $attributes): array
{
// filter by currency, if set.
$currencyId = $attributes['currencyId'] ?? null;
$currency = null;
if (null !== $currencyId) {
/** @var CurrencyRepositoryInterface $repos */
$repos = app(CurrencyRepositoryInterface::class);
$currency = $repos->find((int)$currencyId);
}
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector
->setAccounts(new Collection([$account]))
->setTypes([TransactionType::WITHDRAWAL])
->withAccountInformation()
->withCategoryInformation()
->setRange($attributes['startDate'], $attributes['endDate'])
->withoutBudget();
if (null !== $currency) {
$collector->setCurrency($currency);
}
return $collector->getExtractedJournals();
}
@@ -92,7 +112,7 @@ class PopupReport implements PopupReportInterface
* Collect the transactions for a budget.
*
* @param Budget $budget
* @param array $attributes
* @param array $attributes
*
* @return array
*/
@@ -110,7 +130,11 @@ class PopupReport implements PopupReportInterface
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts($attributes['accounts'])->setRange($attributes['startDate'], $attributes['endDate']);
$collector->setAccounts($attributes['accounts'])
->withAccountInformation()
->withBudgetInformation()
->withCategoryInformation()
->setRange($attributes['startDate'], $attributes['endDate']);
if (null !== $currency) {
$collector->setCurrency($currency);
@@ -129,12 +153,12 @@ class PopupReport implements PopupReportInterface
/**
* Collect journals by a category.
*
* @param Category $category
* @param array $attributes
* @param Category|null $category
* @param array $attributes
*
* @return array
*/
public function byCategory(Category $category, array $attributes): array
public function byCategory(?Category $category, array $attributes): array
{
// filter by currency, if set.
$currencyId = $attributes['currencyId'] ?? null;
@@ -150,8 +174,18 @@ class PopupReport implements PopupReportInterface
$collector->setAccounts($attributes['accounts'])
->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER, TransactionType::DEPOSIT])
->setRange($attributes['startDate'], $attributes['endDate'])->withAccountInformation()
->setCategory($category);
->withAccountInformation()
->withBudgetInformation()
->withCategoryInformation()
->setRange($attributes['startDate'], $attributes['endDate'])->withAccountInformation();
if(null!== $category) {
$collector->setCategory($category);
}
if(null === $category) {
$collector->withoutCategory();
}
if (null !== $currency) {
$collector->setCurrency($currency);
}
@@ -163,7 +197,7 @@ class PopupReport implements PopupReportInterface
* Group transactions by expense.
*
* @param Account $account
* @param array $attributes
* @param array $attributes
*
* @return array
*/
@@ -187,6 +221,9 @@ class PopupReport implements PopupReportInterface
$collector->setAccounts(new Collection([$account]))
->setRange($attributes['startDate'], $attributes['endDate'])
->withAccountInformation()
->withBudgetInformation()
->withCategoryInformation()
->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER]);
if (null !== $currency) {
@@ -200,7 +237,7 @@ class PopupReport implements PopupReportInterface
* Collect transactions by income.
*
* @param Account $account
* @param array $attributes
* @param array $attributes
*
* @return array
*/
@@ -216,7 +253,11 @@ class PopupReport implements PopupReportInterface
->setDestinationAccounts($attributes['accounts'])
->setRange($attributes['startDate'], $attributes['endDate'])
->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
->withAccountInformation()
->withBudgetInformation()
->withCategoryInformation()
->withAccountInformation();
return $collector->getExtractedJournals();
}
}

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