diff --git a/CHANGELOG.md b/CHANGELOG.md index 370226ffff..90d89feb66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - No unreleased changes yet. +## [3.8.2] - 2016-04-03 +### Added +- Small user administration at /admin. +- Informational popups are working in reports. + +### Changed +- User activation emails are better + +### Fixed +- Some bugs related to accounts and rules. + + ## [3.8.1] - 2016-03-29 ### Added - More translations @@ -15,21 +27,11 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Changed - The pages related to rules have new URL's. -### Deprecated -- Initial release. - -### Removed -- Initial release. - ### Fixed - Spelling errors. - Problems related to the "account repository". - Some views showed empty (0.0) amounts. -### Security -- Initial release. - - ## [3.8.0] - 2016-03-20 ### Added - Two factor authentication, thanks to the excellent work of [zjean](https://github.com/zjean). diff --git a/LICENSE b/LICENSE index 88ab8e15bb..9dd7377ce7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (C) 2016 Sander Dorigo +Copyright (C) 2016 thegrumpydictator@gmail.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 7ce107879b..d077819913 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -3,7 +3,7 @@ declare(strict_types = 1); /** * Kernel.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Events/ResendConfirmation.php b/app/Events/ResendConfirmation.php index f221d76141..368e82a530 100644 --- a/app/Events/ResendConfirmation.php +++ b/app/Events/ResendConfirmation.php @@ -1,7 +1,8 @@ mapped[$this->index][$this->value])) { - /** @var Account $account */ - $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); + $account = $repository->find($this->mapped[$this->index][$this->value]); } else { - /** @var Account $account */ - $account = Auth::user()->accounts()->find($this->value); - - if (!is_null($account)) { - Log::debug('Found ' . $account->accountType->type . ' named "******" with ID: ' . $this->value . ' (not mapped) '); - } else { - // new account to prevent TypeErrors. - $account = new Account; - } + $account = $repository->find($this->value); } return $account; diff --git a/app/Helpers/Csv/Converter/AssetAccountIban.php b/app/Helpers/Csv/Converter/AssetAccountIban.php index d506b2d052..327d6e882e 100644 --- a/app/Helpers/Csv/Converter/AssetAccountIban.php +++ b/app/Helpers/Csv/Converter/AssetAccountIban.php @@ -5,6 +5,7 @@ namespace FireflyIII\Helpers\Csv\Converter; use Auth; use Carbon\Carbon; use FireflyIII\Models\Account; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; /** * Class AssetAccountIban @@ -19,60 +20,48 @@ class AssetAccountIban extends BasicConverter implements ConverterInterface */ public function convert(): Account { + /** @var AccountRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); // is mapped? Then it's easy! if (isset($this->mapped[$this->index][$this->value])) { - $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); + $account = $repository->find($this->mapped[$this->index][$this->value]); return $account; } + if (strlen($this->value) > 0) { // find or create new account: - $account = $this->findAccount(); + $set = $repository->getAccounts(['Default account', 'Asset account']); + /** @var Account $entry */ + foreach ($set as $entry) { + if ($entry->iban == $this->value) { - if (is_null($account->id)) { - // create it if doesn't exist. - - $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); - $accountData = [ - 'name' => $this->value, - 'accountType' => 'asset', - 'virtualBalance' => 0, - 'virtualBalanceCurrency' => 1, // hard coded. - 'active' => true, - 'user' => Auth::user()->id, - 'iban' => null, - 'accountNumber' => $this->value, - 'accountRole' => null, - 'openingBalance' => 0, - 'openingBalanceDate' => new Carbon, - 'openingBalanceCurrency' => 1, // hard coded. - - ]; - - $account = $repository->store($accountData); + return $entry; + } } + // create it if doesn't exist. + $accountData = [ + 'name' => $this->value, + 'accountType' => 'asset', + 'virtualBalance' => 0, + 'virtualBalanceCurrency' => 1, // hard coded. + 'active' => true, + 'user' => Auth::user()->id, + 'iban' => null, + 'accountNumber' => $this->value, + 'accountRole' => null, + 'openingBalance' => 0, + 'openingBalanceDate' => new Carbon, + 'openingBalanceCurrency' => 1, // hard coded. + + ]; + + $account = $repository->store($accountData); return $account; } return new Account; } - - /** - * @return Account - */ - protected function findAccount(): Account - { - $set = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']); - /** @var Account $entry */ - foreach ($set as $entry) { - if ($entry->iban == $this->value) { - - return $entry; - } - } - - return new Account; - } } diff --git a/app/Helpers/Csv/Converter/AssetAccountName.php b/app/Helpers/Csv/Converter/AssetAccountName.php index 407e54fc6d..681e168021 100644 --- a/app/Helpers/Csv/Converter/AssetAccountName.php +++ b/app/Helpers/Csv/Converter/AssetAccountName.php @@ -5,6 +5,7 @@ namespace FireflyIII\Helpers\Csv\Converter; use Auth; use Carbon\Carbon; use FireflyIII\Models\Account; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; /** * Class AssetAccountName @@ -19,14 +20,19 @@ class AssetAccountName extends BasicConverter implements ConverterInterface */ public function convert() { + /** @var AccountRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + // is mapped? Then it's easy! if (isset($this->mapped[$this->index][$this->value])) { - $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); + $account = $repository->find($this->mapped[$this->index][$this->value]); return $account; } + + // find or create new account: - $set = Auth::user()->accounts()->accountTypeIn(['Asset account', 'Default account'])->get(); + $set = $repository->getAccounts(['Default account', 'Asset account']); /** @var Account $entry */ foreach ($set as $entry) { if ($entry->name == $this->value) { @@ -35,8 +41,6 @@ class AssetAccountName extends BasicConverter implements ConverterInterface } // create it if doesnt exist. - - $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); $accountData = [ 'name' => $this->value, 'accountType' => 'asset', diff --git a/app/Helpers/Csv/Converter/AssetAccountNumber.php b/app/Helpers/Csv/Converter/AssetAccountNumber.php index 803fc9763f..9aadeaa4d0 100644 --- a/app/Helpers/Csv/Converter/AssetAccountNumber.php +++ b/app/Helpers/Csv/Converter/AssetAccountNumber.php @@ -1,7 +1,8 @@ mapped[$this->index][$this->value])) { - $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); + $account = $repository->find($this->mapped[$this->index][$this->value]); return $account; } @@ -37,53 +42,38 @@ class AssetAccountNumber extends BasicConverter implements ConverterInterface $value = $this->value ?? ''; if (strlen($value) > 0) { // find or create new account: - $account = $this->findAccount(); + $set = $repository->getAccounts(['Default account', 'Asset account']); + /** @var Account $entry */ + foreach ($set as $entry) { + $accountNumber = $entry->getMeta('accountNumber'); + if ($accountNumber == $this->value) { - if (is_null($account->id)) { - // create it if doesn't exist. - $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); - - - $accountData = [ - 'name' => $this->value, - 'accountType' => 'asset', - 'virtualBalance' => 0, - 'virtualBalanceCurrency' => 1, // hard coded. - 'active' => true, - 'user' => Auth::user()->id, - 'iban' => null, - 'accountNumber' => $this->value, - 'accountRole' => null, - 'openingBalance' => 0, - 'openingBalanceDate' => new Carbon, - 'openingBalanceCurrency' => 1, // hard coded. - - ]; - - $account = $repository->store($accountData); + return $entry; + } } + $accountData = [ + 'name' => $this->value, + 'accountType' => 'asset', + 'virtualBalance' => 0, + 'virtualBalanceCurrency' => 1, // hard coded. + 'active' => true, + 'user' => Auth::user()->id, + 'iban' => null, + 'accountNumber' => $this->value, + 'accountRole' => null, + 'openingBalance' => 0, + 'openingBalanceDate' => new Carbon, + 'openingBalanceCurrency' => 1, // hard coded. + + ]; + + $account = $repository->store($accountData); + return $account; } - return null; + return null; // is this accepted? } - /** - * @return Account - */ - protected function findAccount(): Account - { - $set = Auth::user()->accounts()->with(['accountmeta'])->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']); - /** @var Account $entry */ - foreach ($set as $entry) { - $accountNumber = $entry->getMeta('accountNumber'); - if ($accountNumber == $this->value) { - - return $entry; - } - } - - return new Account; - } } diff --git a/app/Helpers/Csv/Converter/BillId.php b/app/Helpers/Csv/Converter/BillId.php index 5dcde18d9a..77e9efa000 100644 --- a/app/Helpers/Csv/Converter/BillId.php +++ b/app/Helpers/Csv/Converter/BillId.php @@ -2,8 +2,8 @@ declare(strict_types = 1); namespace FireflyIII\Helpers\Csv\Converter; -use Auth; use FireflyIII\Models\Bill; +use FireflyIII\Repositories\Bill\BillRepositoryInterface; /** * Class BillId @@ -18,11 +18,14 @@ class BillId extends BasicConverter implements ConverterInterface */ public function convert() { + /** @var BillRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Bill\BillRepositoryInterface'); + // is mapped? Then it's easy! if (isset($this->mapped[$this->index][$this->value])) { - $bill = Auth::user()->bills()->find($this->mapped[$this->index][$this->value]); + $bill = $repository->find($this->mapped[$this->index][$this->value]); } else { - $bill = Auth::user()->bills()->find($this->value); + $bill = $repository->find($this->value); } return $bill; diff --git a/app/Helpers/Csv/Converter/BillName.php b/app/Helpers/Csv/Converter/BillName.php index e6229240d1..5f6c008f25 100644 --- a/app/Helpers/Csv/Converter/BillName.php +++ b/app/Helpers/Csv/Converter/BillName.php @@ -2,8 +2,8 @@ declare(strict_types = 1); namespace FireflyIII\Helpers\Csv\Converter; -use Auth; use FireflyIII\Models\Bill; +use FireflyIII\Repositories\Bill\BillRepositoryInterface; /** * Class BillName @@ -18,13 +18,15 @@ class BillName extends BasicConverter implements ConverterInterface */ public function convert() { + /** @var BillRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Bill\BillRepositoryInterface'); + $bill = null; // is mapped? Then it's easy! if (isset($this->mapped[$this->index][$this->value])) { - $bill = Auth::user()->bills()->find($this->mapped[$this->index][$this->value]); + $bill = $repository->find($this->mapped[$this->index][$this->value]); } else { - - $bills = Auth::user()->bills()->get(); + $bills = $repository->getBills(); /** @var Bill $bill */ foreach ($bills as $bill) { if ($bill->name == $this->value) { diff --git a/app/Helpers/Csv/Converter/BudgetId.php b/app/Helpers/Csv/Converter/BudgetId.php index e1368f9299..896178e822 100644 --- a/app/Helpers/Csv/Converter/BudgetId.php +++ b/app/Helpers/Csv/Converter/BudgetId.php @@ -2,8 +2,8 @@ declare(strict_types = 1); namespace FireflyIII\Helpers\Csv\Converter; -use Auth; use FireflyIII\Models\Budget; +use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; /** * Class BudgetId @@ -18,11 +18,15 @@ class BudgetId extends BasicConverter implements ConverterInterface */ public function convert() { + /** @var BudgetRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + + // is mapped? Then it's easy! if (isset($this->mapped[$this->index][$this->value])) { - $budget = Auth::user()->budgets()->find($this->mapped[$this->index][$this->value]); + $budget = $repository->find($this->mapped[$this->index][$this->value]); } else { - $budget = Auth::user()->budgets()->find($this->value); + $budget = $repository->find($this->value); } return $budget; diff --git a/app/Helpers/Csv/Converter/BudgetName.php b/app/Helpers/Csv/Converter/BudgetName.php index 17f80557b5..dcf8844d3d 100644 --- a/app/Helpers/Csv/Converter/BudgetName.php +++ b/app/Helpers/Csv/Converter/BudgetName.php @@ -4,6 +4,7 @@ namespace FireflyIII\Helpers\Csv\Converter; use Auth; use FireflyIII\Models\Budget; +use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; /** * Class BudgetName @@ -18,12 +19,14 @@ class BudgetName extends BasicConverter implements ConverterInterface */ public function convert() { + /** @var BudgetRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + // is mapped? Then it's easy! if (isset($this->mapped[$this->index][$this->value])) { - $budget = Auth::user()->budgets()->find($this->mapped[$this->index][$this->value]); // see issue #180 + $budget = $repository->find($this->mapped[$this->index][$this->value]); } else { - $repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); - $budget = $repository->store(['name' => $this->value, 'user' => Auth::user()->id]); + $budget = $repository->store(['name' => $this->value, 'user' => Auth::user()->id]); } return $budget; diff --git a/app/Helpers/Csv/Converter/CategoryId.php b/app/Helpers/Csv/Converter/CategoryId.php index f205f9edfe..67c91fdb2b 100644 --- a/app/Helpers/Csv/Converter/CategoryId.php +++ b/app/Helpers/Csv/Converter/CategoryId.php @@ -2,8 +2,8 @@ declare(strict_types = 1); namespace FireflyIII\Helpers\Csv\Converter; -use Auth; use FireflyIII\Models\Category; +use FireflyIII\Repositories\Category\SingleCategoryRepositoryInterface; /** * Class CategoryId @@ -18,11 +18,14 @@ class CategoryId extends BasicConverter implements ConverterInterface */ public function convert() { + /** @var SingleCategoryRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Category\SingleCategoryRepositoryInterface'); + // is mapped? Then it's easy! if (isset($this->mapped[$this->index][$this->value])) { - $category = Auth::user()->categories()->find($this->mapped[$this->index][$this->value]); + $category = $repository->find($this->mapped[$this->index][$this->value]); } else { - $category = Auth::user()->categories()->find($this->value); + $category = $repository->find($this->value); } return $category; diff --git a/app/Helpers/Csv/Converter/CategoryName.php b/app/Helpers/Csv/Converter/CategoryName.php index c7d7b27aca..8ce036eddc 100644 --- a/app/Helpers/Csv/Converter/CategoryName.php +++ b/app/Helpers/Csv/Converter/CategoryName.php @@ -4,6 +4,7 @@ namespace FireflyIII\Helpers\Csv\Converter; use Auth; use FireflyIII\Models\Category; +use FireflyIII\Repositories\Category\SingleCategoryRepositoryInterface; /** * Class CategoryName @@ -18,16 +19,20 @@ class CategoryName extends BasicConverter implements ConverterInterface */ public function convert() { + /** @var SingleCategoryRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Category\SingleCategoryRepositoryInterface'); + // is mapped? Then it's easy! if (isset($this->mapped[$this->index][$this->value])) { - $category = Auth::user()->categories()->find($this->mapped[$this->index][$this->value]); + $category = $repository->find($this->mapped[$this->index][$this->value]); } else { - $category = Category::firstOrCreateEncrypted( // See issue #180 - [ - 'name' => $this->value, - 'user_id' => Auth::user()->id, - ] - ); + + $data = [ + 'name' => $this->value, + 'user' => Auth::user()->id, + ]; + + $category = $repository->store($data); } return $category; diff --git a/app/Helpers/Csv/Converter/CurrencyCode.php b/app/Helpers/Csv/Converter/CurrencyCode.php index 98e01e5874..7054b1f5d5 100644 --- a/app/Helpers/Csv/Converter/CurrencyCode.php +++ b/app/Helpers/Csv/Converter/CurrencyCode.php @@ -3,6 +3,7 @@ declare(strict_types = 1); namespace FireflyIII\Helpers\Csv\Converter; use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; /** * Class CurrencyCode @@ -17,10 +18,14 @@ class CurrencyCode extends BasicConverter implements ConverterInterface */ public function convert() { + /** @var CurrencyRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface'); + + if (isset($this->mapped[$this->index][$this->value])) { - $currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]); + $currency = $repository->find($this->mapped[$this->index][$this->value]); } else { - $currency = TransactionCurrency::whereCode($this->value)->first(); + $currency = $repository->findByCode($this->value); } return $currency; diff --git a/app/Helpers/Csv/Converter/CurrencyId.php b/app/Helpers/Csv/Converter/CurrencyId.php index ae1fb9af47..ce21771f12 100644 --- a/app/Helpers/Csv/Converter/CurrencyId.php +++ b/app/Helpers/Csv/Converter/CurrencyId.php @@ -3,6 +3,7 @@ declare(strict_types = 1); namespace FireflyIII\Helpers\Csv\Converter; use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; /** * Class CurrencyId @@ -17,10 +18,13 @@ class CurrencyId extends BasicConverter implements ConverterInterface */ public function convert() { + /** @var CurrencyRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface'); + if (isset($this->mapped[$this->index][$this->value])) { - $currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]); + $currency = $repository->find($this->mapped[$this->index][$this->value]); } else { - $currency = TransactionCurrency::find($this->value); + $currency = $repository->find($this->value); } return $currency; diff --git a/app/Helpers/Csv/Converter/CurrencyName.php b/app/Helpers/Csv/Converter/CurrencyName.php index 4bdbe79c3a..336c533e6b 100644 --- a/app/Helpers/Csv/Converter/CurrencyName.php +++ b/app/Helpers/Csv/Converter/CurrencyName.php @@ -3,6 +3,7 @@ declare(strict_types = 1); namespace FireflyIII\Helpers\Csv\Converter; use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; /** * Class CurrencyName @@ -17,10 +18,14 @@ class CurrencyName extends BasicConverter implements ConverterInterface */ public function convert() { + /** @var CurrencyRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface'); + if (isset($this->mapped[$this->index][$this->value])) { - $currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]); + + $currency = $repository->find($this->mapped[$this->index][$this->value]); } else { - $currency = TransactionCurrency::whereName($this->value)->first(); + $currency = $repository->findByName($this->value); } return $currency; diff --git a/app/Helpers/Csv/Converter/CurrencySymbol.php b/app/Helpers/Csv/Converter/CurrencySymbol.php index 62cc92bcd6..b27c122db3 100644 --- a/app/Helpers/Csv/Converter/CurrencySymbol.php +++ b/app/Helpers/Csv/Converter/CurrencySymbol.php @@ -3,6 +3,7 @@ declare(strict_types = 1); namespace FireflyIII\Helpers\Csv\Converter; use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; /** * Class CurrencySymbol @@ -17,10 +18,13 @@ class CurrencySymbol extends BasicConverter implements ConverterInterface */ public function convert() { + /** @var CurrencyRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface'); + if (isset($this->mapped[$this->index][$this->value])) { - $currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]); + $currency = $repository->find($this->mapped[$this->index][$this->value]); } else { - $currency = TransactionCurrency::whereSymbol($this->value)->first(); + $currency = $repository->findBySymbol($this->value); } return $currency; diff --git a/app/Helpers/Csv/Converter/INGDebetCredit.php b/app/Helpers/Csv/Converter/INGDebetCredit.php index e41aee16ac..ac36539e22 100644 --- a/app/Helpers/Csv/Converter/INGDebetCredit.php +++ b/app/Helpers/Csv/Converter/INGDebetCredit.php @@ -1,7 +1,8 @@ mapped[$this->index][$this->value])) { - $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); + $account = $repository->find($this->mapped[$this->index][$this->value]); return $account; } else { if (strlen($this->value) > 0) { - $account = $this->findAccount(); - if (!is_null($account)) { - return $account; + + $set = $repository->getAccounts([]); + /** @var Account $account */ + foreach ($set as $account) { + if ($account->iban == $this->value) { + + return $account; + } } } @@ -37,21 +44,4 @@ class OpposingAccountIban extends BasicConverter implements ConverterInterface } } - /** - * @return Account|null - */ - protected function findAccount() - { - $set = Auth::user()->accounts()->get(); - /** @var Account $account */ - foreach ($set as $account) { - if ($account->iban == $this->value) { - Log::debug('OpposingAccountIban::convert found an Account (#' . $account->id . ': ******) with IBAN ******'); - - return $account; - } - } - - return null; - } } diff --git a/app/Helpers/Csv/Converter/OpposingAccountId.php b/app/Helpers/Csv/Converter/OpposingAccountId.php index cf85478056..3c11791fb8 100644 --- a/app/Helpers/Csv/Converter/OpposingAccountId.php +++ b/app/Helpers/Csv/Converter/OpposingAccountId.php @@ -2,8 +2,8 @@ declare(strict_types = 1); namespace FireflyIII\Helpers\Csv\Converter; -use Auth; use FireflyIII\Models\Account; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; /** * Class OpposingAccountId @@ -19,11 +19,14 @@ class OpposingAccountId extends BasicConverter implements ConverterInterface */ public function convert() { + /** @var AccountRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + if (isset($this->mapped[$this->index][$this->value])) { - $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); + $account = $repository->find($this->mapped[$this->index][$this->value]); } else { - $account = Auth::user()->accounts()->find($this->value); + $account = $repository->find($this->value); } return $account; diff --git a/app/Helpers/Csv/Converter/OpposingAccountName.php b/app/Helpers/Csv/Converter/OpposingAccountName.php index 0a2a1b8880..b55c7e1bf9 100644 --- a/app/Helpers/Csv/Converter/OpposingAccountName.php +++ b/app/Helpers/Csv/Converter/OpposingAccountName.php @@ -2,8 +2,8 @@ declare(strict_types = 1); namespace FireflyIII\Helpers\Csv\Converter; -use Auth; use FireflyIII\Models\Account; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; /** * Class OpposingAccountName @@ -20,8 +20,11 @@ class OpposingAccountName extends BasicConverter implements ConverterInterface */ public function convert() { + /** @var AccountRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + if (isset($this->mapped[$this->index][$this->value])) { - $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); + $account = $repository->find($this->mapped[$this->index][$this->value]); return $account; } else { diff --git a/app/Helpers/Csv/Converter/TagsComma.php b/app/Helpers/Csv/Converter/TagsComma.php index 02ac2bc14a..6c8715b01c 100644 --- a/app/Helpers/Csv/Converter/TagsComma.php +++ b/app/Helpers/Csv/Converter/TagsComma.php @@ -2,8 +2,7 @@ declare(strict_types = 1); namespace FireflyIII\Helpers\Csv\Converter; -use Auth; -use FireflyIII\Models\Tag; +use FireflyIII\Repositories\Tag\TagRepositoryInterface; use Illuminate\Support\Collection; /** @@ -19,17 +18,22 @@ class TagsComma extends BasicConverter implements ConverterInterface */ public function convert() { - $tags = new Collection; + /** @var TagRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Tag\TagRepositoryInterface'); + $tags = new Collection; $strings = explode(',', $this->value); foreach ($strings as $string) { - $tag = Tag::firstOrCreateEncrypted( // See issue #180 - [ - 'tag' => $string, - 'tagMode' => 'nothing', - 'user_id' => Auth::user()->id, - ] - ); + $data = [ + 'tag' => $string, + 'date' => null, + 'description' => null, + 'latitude' => null, + 'longitude' => null, + 'zoomLevel' => null, + 'tagMode' => 'nothing', + ]; + $tag = $repository->store($data); // should validate first? $tags->push($tag); } $tags = $tags->merge($this->data['tags']); diff --git a/app/Helpers/Csv/Converter/TagsSpace.php b/app/Helpers/Csv/Converter/TagsSpace.php index c0e7b5c4f8..72f41503dc 100644 --- a/app/Helpers/Csv/Converter/TagsSpace.php +++ b/app/Helpers/Csv/Converter/TagsSpace.php @@ -2,8 +2,7 @@ declare(strict_types = 1); namespace FireflyIII\Helpers\Csv\Converter; -use Auth; -use FireflyIII\Models\Tag; +use FireflyIII\Repositories\Tag\TagRepositoryInterface; use Illuminate\Support\Collection; /** @@ -19,17 +18,23 @@ class TagsSpace extends BasicConverter implements ConverterInterface */ public function convert() { + /** @var TagRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Tag\TagRepositoryInterface'); + $tags = new Collection; $strings = explode(' ', $this->value); foreach ($strings as $string) { - $tag = Tag::firstOrCreateEncrypted( // See issue #180 - [ - 'tag' => $string, - 'tagMode' => 'nothing', - 'user_id' => Auth::user()->id, - ] - ); + $data = [ + 'tag' => $string, + 'date' => null, + 'description' => null, + 'latitude' => null, + 'longitude' => null, + 'zoomLevel' => null, + 'tagMode' => 'nothing', + ]; + $tag = $repository->store($data); // should validate first? $tags->push($tag); } $tags = $tags->merge($this->data['tags']); diff --git a/app/Helpers/Csv/Importer.php b/app/Helpers/Csv/Importer.php index ac1bcdffb4..77553dab89 100644 --- a/app/Helpers/Csv/Importer.php +++ b/app/Helpers/Csv/Importer.php @@ -120,6 +120,8 @@ class Importer Log::error('Caught error at row #' . $index . ': ' . $result); $this->errors[$index] = $result; } else { + + $this->imported++; $this->journals->push($result); } diff --git a/app/Helpers/Csv/Specifix/Specifix.php b/app/Helpers/Csv/Specifix/Specifix.php index fa51625e8e..37c40ccc27 100644 --- a/app/Helpers/Csv/Specifix/Specifix.php +++ b/app/Helpers/Csv/Specifix/Specifix.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * Specifix.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Helpers/Report/AccountReportHelper.php b/app/Helpers/Report/AccountReportHelper.php index 6a75df21c6..1a1157d0ec 100644 --- a/app/Helpers/Report/AccountReportHelper.php +++ b/app/Helpers/Report/AccountReportHelper.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * AccountReportHelper.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Helpers/Report/AccountReportHelperInterface.php b/app/Helpers/Report/AccountReportHelperInterface.php index bf9f650633..02e56274f3 100644 --- a/app/Helpers/Report/AccountReportHelperInterface.php +++ b/app/Helpers/Report/AccountReportHelperInterface.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * AccountReportHelperInterface.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Helpers/Report/BalanceReportHelper.php b/app/Helpers/Report/BalanceReportHelper.php index 0e70cc3745..290f6896ba 100644 --- a/app/Helpers/Report/BalanceReportHelper.php +++ b/app/Helpers/Report/BalanceReportHelper.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * BalanceReportHelper.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Helpers/Report/BalanceReportHelperInterface.php b/app/Helpers/Report/BalanceReportHelperInterface.php index 4ef5d725b6..d225e94781 100644 --- a/app/Helpers/Report/BalanceReportHelperInterface.php +++ b/app/Helpers/Report/BalanceReportHelperInterface.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * BalanceReportHelperInterface.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Helpers/Report/BudgetReportHelper.php b/app/Helpers/Report/BudgetReportHelper.php index aee2bf4ee6..e7e8036fa2 100644 --- a/app/Helpers/Report/BudgetReportHelper.php +++ b/app/Helpers/Report/BudgetReportHelper.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * BudgetReportHelper.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Helpers/Report/BudgetReportHelperInterface.php b/app/Helpers/Report/BudgetReportHelperInterface.php index 69d479c3b0..1096a1b027 100644 --- a/app/Helpers/Report/BudgetReportHelperInterface.php +++ b/app/Helpers/Report/BudgetReportHelperInterface.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * BudgetReportHelperInterface.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Helpers/Report/ReportHelper.php b/app/Helpers/Report/ReportHelper.php index c63fdf7960..93b7a12e07 100644 --- a/app/Helpers/Report/ReportHelper.php +++ b/app/Helpers/Report/ReportHelper.php @@ -15,6 +15,8 @@ use FireflyIII\Models\Tag; use FireflyIII\Models\TransactionJournal; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Query\JoinClause; use Illuminate\Support\Collection; /** @@ -230,27 +232,36 @@ class ReportHelper implements ReportHelperInterface { $ids = $accounts->pluck('id')->toArray(); $set = Tag:: - distinct() - ->leftJoin('tag_transaction_journal', 'tags.id', '=', 'tag_transaction_journal.tag_id') + leftJoin('tag_transaction_journal', 'tags.id', '=', 'tag_transaction_journal.tag_id') ->leftJoin('transaction_journals', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') - ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') + ->leftJoin( + 'transactions AS source', function (JoinClause $join) { + $join->on('source.transaction_journal_id', '=', 'transaction_journals.id')->where('source.amount', '<', '0'); + } + ) + ->leftJoin( + 'transactions AS destination', function (JoinClause $join) { + $join->on('destination.transaction_journal_id', '=', 'transaction_journals.id')->where('destination.amount', '>', '0'); + } + ) ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) - ->whereIn('transactions.account_id', $ids)->get( - ['tags.id', 'tags.tag', 'transaction_journals.id as journal_id', 'transactions.amount'] - ); + ->where( + function (Builder $q) use ($ids) { + $q->whereIn('source.account_id', $ids) + ->whereIn('destination.account_id', $ids, 'xor'); + } + ) + ->get(['tags.id', 'tags.tag', 'transaction_journals.id as journal_id', 'destination.amount']); $collection = []; if ($set->count() === 0) { return $collection; } + /** @var Tag $entry */ foreach ($set as $entry) { // less than zero? multiply to be above zero. $amount = $entry->amount; - if (bccomp($amount, '0', 2) === -1) { - $amount = bcmul($amount, '-1'); - } - $id = intval($entry->id); - + $id = intval($entry->id); if (!isset($collection[$id])) { $collection[$id] = [ 'id' => $id, diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index d0992f9627..e16a91807b 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -42,6 +42,7 @@ class AccountController extends Controller $subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what); $subTitle = trans('firefly.make_new_' . $what . '_account'); + Session::flash('preFilled', []); // put previous url in session if not redirect from store (not "create another"). if (session('accounts.create.fromStore') !== true) { diff --git a/app/Http/Controllers/Admin/HomeController.php b/app/Http/Controllers/Admin/HomeController.php new file mode 100644 index 0000000000..81a75f086b --- /dev/null +++ b/app/Http/Controllers/Admin/HomeController.php @@ -0,0 +1,33 @@ +all(); + + // add meta stuff. + $users->each( + function (User $user) use ($confirmAccount) { + // is user activated? + $isConfirmed = Preferences::getForUser($user, 'user_confirmed', false)->data; + if ($isConfirmed === false && $confirmAccount === true) { + $user->activated = false; + } else { + $user->activated = true; + } + + // is user admin? + $user->isAdmin = $user->hasRole('owner'); + + // user has 2FA enabled? + $is2faEnabled = Preferences::getForUser($user, 'twoFactorAuthEnabled', false)->data; + $has2faSecret = !is_null(Preferences::getForUser($user, 'twoFactorAuthSecret')); + if ($is2faEnabled && $has2faSecret) { + $user->has2FA = true; + } else { + $user->has2FA = false; + } + + } + ); + + + return view('admin.users.index', compact('title', 'mainTitleIcon', 'subTitle', 'subTitleIcon', 'users')); + + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Auth/ConfirmationController.php b/app/Http/Controllers/Auth/ConfirmationController.php index d085966af0..6832edba8f 100644 --- a/app/Http/Controllers/Auth/ConfirmationController.php +++ b/app/Http/Controllers/Auth/ConfirmationController.php @@ -1,7 +1,8 @@ data; + $title = strval(trans('firefly.two_factor_title')); if (strlen($secret) === 0) { throw new FireflyException('Your two factor authentication secret is empty, which it cannot be at this point. Please check the log files.'); } Session::flash('two-factor-secret', $secret); - return view('auth.two-factor', compact('user')); + return view('auth.two-factor', compact('user', 'title')); } /** @@ -53,6 +55,7 @@ class TwoFactorController extends Controller { $user = Auth::user(); $siteOwner = env('SITE_OWNER', ''); + $title = strval(trans('firefly.two_factor_forgot_title')); Log::info( 'To reset the two factor authentication for user #' . $user->id . @@ -60,7 +63,7 @@ class TwoFactorController extends Controller ' "twoFactorAuthSecret" for user_id ' . $user->id . '. That will take care of it.' ); - return view('auth.lost-two-factor', compact('user', 'siteOwner')); + return view('auth.lost-two-factor', compact('user', 'siteOwner', 'title')); } /** diff --git a/app/Http/Controllers/ExportController.php b/app/Http/Controllers/ExportController.php index feb72426b6..9dcafa77a0 100644 --- a/app/Http/Controllers/ExportController.php +++ b/app/Http/Controllers/ExportController.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * ExportController.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Http/Controllers/Popup/ReportController.php b/app/Http/Controllers/Popup/ReportController.php new file mode 100644 index 0000000000..47c76aed89 --- /dev/null +++ b/app/Http/Controllers/Popup/ReportController.php @@ -0,0 +1,234 @@ +get('attributes'); + $attributes = $this->parseAttributes($attributes); + + View::share('start', $attributes['startDate']); + View::share('end', $attributes['endDate']); + + switch ($attributes['location']) { + default: + throw new FireflyException('Firefly cannot handle "' . e($attributes['location']) . '" '); + case 'budget-spent-amount': + $html = $this->budgetSpentAmount($attributes); + + break; + case 'expense-entry': + $html = $this->expenseEntry($attributes); + break; + case 'income-entry': + $html = $this->incomeEntry($attributes); + break; + case 'category-entry': + $html = $this->categoryEntry($attributes); + break; + case 'balance-amount': + $html = $this->balanceAmount($attributes); + break; + } + + return Response::json(['html' => $html]); + + + } + + /** + * @param $attributes + * + * @return string + * @throws FireflyException + */ + private function balanceAmount(array $attributes): string + { + $role = intval($attributes['role']); + + /** @var BudgetRepositoryInterface $budgetRepository */ + $budgetRepository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $budget = $budgetRepository->find(intval($attributes['budgetId'])); + + /** @var AccountRepositoryInterface $accountRepository */ + $accountRepository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $account = $accountRepository->find(intval($attributes['accountId'])); + + switch (true) { + case ($role === BalanceLine::ROLE_DEFAULTROLE && !is_null($budget->id)): + $journals = $budgetRepository->expensesSplit($budget, $account, $attributes['startDate'], $attributes['endDate']); + break; + case ($role === BalanceLine::ROLE_DEFAULTROLE && is_null($budget->id)): + $budget->name = strval(trans('firefly.no_budget')); + $journals = $budgetRepository->getAllWithoutBudget($account, $attributes['accounts'], $attributes['startDate'], $attributes['endDate']); + break; + case ($role === BalanceLine::ROLE_DIFFROLE): + // journals no budget, not corrected by a tag. + $journals = $budgetRepository->getAllWithoutBudget($account, $attributes['accounts'], $attributes['startDate'], $attributes['endDate']); + $budget->name = strval(trans('firefly.leftUnbalanced')); + $journals = $journals->filter( + function (TransactionJournal $journal) { + $tags = $journal->tags()->where('tagMode', 'balancingAct')->count(); + if ($tags === 0) { + return $journal; + } + } + ); + break; + case ($role === BalanceLine::ROLE_TAGROLE): + throw new FireflyException('Firefly cannot handle this type of info-button (BalanceLine::TagRole)'); + } + $view = view('popup.report.balance-amount', compact('journals', 'budget', 'account'))->render(); + + return $view; + } + + /** + * Returns all expenses inside the given budget for the given accounts. + * + * @param array $attributes + * + * @return string + * @throws FireflyException + */ + private function budgetSpentAmount(array $attributes): string + { + // need to find the budget + // then search for expenses in the given period + // list them in some table format. + /** @var BudgetRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $budget = $repository->find(intval($attributes['budgetId'])); + if (is_null($budget->id)) { + $journals = $repository->getWithoutBudgetForAccounts($attributes['accounts'], $attributes['startDate'], $attributes['endDate']); + } else { + // get all expenses in budget in period: + $journals = $repository->getExpenses($budget, $attributes['accounts'], $attributes['startDate'], $attributes['endDate']); + } + + $view = view('popup.report.budget-spent-amount', compact('journals', 'budget'))->render(); + + return $view; + } + + /** + * Returns all expenses in category in range. + * + * @param $attributes + * + * @return string + * @throws FireflyException + */ + private function categoryEntry(array $attributes): string + { + /** @var SingleCategoryRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Category\SingleCategoryRepositoryInterface'); + $category = $repository->find(intval($attributes['categoryId'])); + $journals = $repository->getJournalsForAccountsInRange($category, $attributes['accounts'], $attributes['startDate'], $attributes['endDate']); + $view = view('popup.report.category-entry', compact('journals', 'category'))->render(); + + return $view; + } + + /** + * Returns all the expenses that went to the given expense account. + * + * @param $attributes + * + * @return string + * @throws FireflyException + */ + private function expenseEntry(array $attributes): string + { + /** @var AccountRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $account = $repository->find(intval($attributes['accountId'])); + $journals = $repository->getExpensesByDestination($account, $attributes['accounts'], $attributes['startDate'], $attributes['endDate']); + $view = view('popup.report.expense-entry', compact('journals', 'account'))->render(); + + return $view; + } + + /** + * Returns all the incomes that went to the given asset account. + * + * @param $attributes + * + * @return string + * @throws FireflyException + */ + private function incomeEntry(array $attributes): string + { + /** @var AccountRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $account = $repository->find(intval($attributes['accountId'])); + $journals = $repository->getIncomeByDestination($account, $attributes['accounts'], $attributes['startDate'], $attributes['endDate']); + $view = view('popup.report.income-entry', compact('journals', 'account'))->render(); + + + return $view; + } + + /** + * @param array $attributes + * + * @return array + * @throws FireflyException + */ + private function parseAttributes(array $attributes): array + { + $attributes['location'] = $attributes['location'] ?? ''; + $attributes['accounts'] = AccountList::routeBinder($attributes['accounts'] ?? '', ''); + try { + $attributes['startDate'] = Carbon::createFromFormat('Ymd', $attributes['startDate']); + } catch (InvalidArgumentException $e) { + throw new FireflyException('Could not parse start date "' . e($attributes['startDate']) . '".'); + } + + try { + $attributes['endDate'] = Carbon::createFromFormat('Ymd', $attributes['endDate']); + } catch (InvalidArgumentException $e) { + throw new FireflyException('Could not parse start date "' . e($attributes['endDate']) . '".'); + } + + + return $attributes; + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/RuleController.php b/app/Http/Controllers/RuleController.php index 005c849bdc..bc3d228969 100644 --- a/app/Http/Controllers/RuleController.php +++ b/app/Http/Controllers/RuleController.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * RuleController.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index b59b2b02de..064d21119f 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -7,6 +7,7 @@ use FireflyIII\Http\Middleware\Authenticate; use FireflyIII\Http\Middleware\AuthenticateTwoFactor; use FireflyIII\Http\Middleware\Binder; use FireflyIII\Http\Middleware\EncryptCookies; +use FireflyIII\Http\Middleware\IsAdmin; use FireflyIII\Http\Middleware\IsConfirmed; use FireflyIII\Http\Middleware\IsNotConfirmed; use FireflyIII\Http\Middleware\Range; @@ -121,6 +122,25 @@ class Kernel extends HttpKernel Range::class, Binder::class, ], + // MUST be logged in + // MUST have 2fa + // MUST be confirmed. + // MUST have owner role + // (this group includes the other Firefly middleware) + 'admin' => [ + EncryptCookies::class, + AddQueuedCookiesToResponse::class, + StartSession::class, + ShareErrorsFromSession::class, + VerifyCsrfToken::class, + Authenticate::class, + AuthenticateTwoFactor::class, + IsConfirmed::class, + IsAdmin::class, + Range::class, + Binder::class, + + ], 'api' => [ 'throttle:60,1', diff --git a/app/Http/Middleware/AuthenticateTwoFactor.php b/app/Http/Middleware/AuthenticateTwoFactor.php index 13e62673f1..0c966add4c 100644 --- a/app/Http/Middleware/AuthenticateTwoFactor.php +++ b/app/Http/Middleware/AuthenticateTwoFactor.php @@ -1,7 +1,8 @@ guest()) { + if ($request->ajax()) { + return response('Unauthorized.', 401); + } else { + return redirect()->guest('login'); + } + } else { + /** @var User $user */ + $user = Auth::user(); + if (!$user->hasRole('owner')) { + return redirect(route('home')); + } + } + + return $next($request); + } +} diff --git a/app/Http/Middleware/IsConfirmed.php b/app/Http/Middleware/IsConfirmed.php index 50854de79a..92dd04bfb4 100644 --- a/app/Http/Middleware/IsConfirmed.php +++ b/app/Http/Middleware/IsConfirmed.php @@ -1,7 +1,8 @@ 'user-simple-auth'], function () { Route::get('/error', 'HomeController@displayError'); @@ -378,6 +377,28 @@ Route::group( Route::post('/transaction/destroy/{tj}', ['uses' => 'TransactionController@destroy', 'as' => 'transactions.destroy']); Route::post('/transaction/reorder', ['uses' => 'TransactionController@reorder', 'as' => 'transactions.reorder']); + /** + * POPUP Controllers + */ + /** + * Report popup + */ + Route::get('/popup/report', ['uses' => 'Popup\ReportController@info', 'as' => 'popup.report']); + } ); +/** + * For the admin routes, the user must be logged in and have the role of 'owner' + */ +Route::group( + ['middleware' => 'admin'], function () { + + // admin home + Route::get('/admin', ['uses' => 'Admin\HomeController@index', 'as' => 'admin.index']); + + // user manager + Route::get('/admin/users', ['uses' => 'Admin\UserController@index', 'as' => 'admin.users']); + +} +); diff --git a/app/Models/ExportJob.php b/app/Models/ExportJob.php index e37316f7cc..22a6d4020e 100644 --- a/app/Models/ExportJob.php +++ b/app/Models/ExportJob.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * ExportJob.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Models/Rule.php b/app/Models/Rule.php index 7805f32752..393617f6c7 100644 --- a/app/Models/Rule.php +++ b/app/Models/Rule.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * Rule.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Models/RuleAction.php b/app/Models/RuleAction.php index a789a3fc00..16676454e8 100644 --- a/app/Models/RuleAction.php +++ b/app/Models/RuleAction.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * RuleAction.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Models/RuleGroup.php b/app/Models/RuleGroup.php index c440d1b499..9453df6fe4 100644 --- a/app/Models/RuleGroup.php +++ b/app/Models/RuleGroup.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * RuleGroup.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Models/RuleTrigger.php b/app/Models/RuleTrigger.php index 3c5e92bc4a..1ec470c1f5 100644 --- a/app/Models/RuleTrigger.php +++ b/app/Models/RuleTrigger.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * RuleTrigger.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Models/Tag.php b/app/Models/Tag.php index b214986e21..c7bcd66d71 100644 --- a/app/Models/Tag.php +++ b/app/Models/Tag.php @@ -92,6 +92,22 @@ class Tag extends Model throw new NotFoundHttpException; } + /** + * @param Tag $tag + * + * @return string + */ + public static function tagSum(Tag $tag): string + { + $sum = '0'; + /** @var TransactionJournal $journal */ + foreach ($tag->transactionjournals as $journal) { + bcadd($sum, TransactionJournal::amount($journal)); + } + + return $sum; + } + /** * @codeCoverageIgnore * diff --git a/app/Models/TransactionJournal.php b/app/Models/TransactionJournal.php index 2c4cc12323..77e7601115 100644 --- a/app/Models/TransactionJournal.php +++ b/app/Models/TransactionJournal.php @@ -382,7 +382,8 @@ class TransactionJournal extends TransactionJournalSupport // join destination account $query->leftJoin('accounts as source_account', 'source_account.id', '=', 'source.account_id'); // join destination account type - $query->leftJoin('account_types as source_acct_type', 'source_account.account_type_id', '=', 'source_acct_type.id'); + $query->leftJoin('account_types as source_acct_type', 'source_account.account_type_id', '=', 'source_acct_type.id') + ->orderBy('transaction_journals.date', 'DESC')->orderBy('transaction_journals.order', 'ASC')->orderBy('transaction_journals.id', 'DESC'); $query->with(['categories', 'budgets', 'attachments', 'bill']); diff --git a/app/Models/TransactionJournalMeta.php b/app/Models/TransactionJournalMeta.php index 37bff90fae..2ebe924c1f 100644 --- a/app/Models/TransactionJournalMeta.php +++ b/app/Models/TransactionJournalMeta.php @@ -1,7 +1,8 @@ app->bind( + 'FireflyIII\Repositories\Category\SingleCategoryRepositoryInterface', + function (Application $app, array $arguments) { + if (!isset($arguments[0]) && Auth::check()) { + return app('FireflyIII\Repositories\Category\SingleCategoryRepository', [Auth::user()]); + } else { + if (!isset($arguments[0]) && !Auth::check()) { + throw new FireflyException('There is no user present.'); + } + } + + return app('FireflyIII\Repositories\Category\SingleCategoryRepository', $arguments); + } + ); + } } diff --git a/app/Providers/FireflyServiceProvider.php b/app/Providers/FireflyServiceProvider.php index 1318dafce1..40018fdb48 100644 --- a/app/Providers/FireflyServiceProvider.php +++ b/app/Providers/FireflyServiceProvider.php @@ -82,7 +82,7 @@ class FireflyServiceProvider extends ServiceProvider } ); - $this->app->bind('FireflyIII\Repositories\Category\SingleCategoryRepositoryInterface', 'FireflyIII\Repositories\Category\SingleCategoryRepository'); + $this->app->bind('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface', 'FireflyIII\Repositories\Currency\CurrencyRepository'); $this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search'); $this->app->bind('FireflyIII\Repositories\User\UserRepositoryInterface', 'FireflyIII\Repositories\User\UserRepository'); diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 6e98cf72f3..e37a21abbc 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -33,6 +33,8 @@ class AccountRepository implements AccountRepositoryInterface /** @var User */ private $user; + /** @var array */ + private $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType', 'accountNumber']; /** * AttachmentRepository constructor. @@ -75,15 +77,18 @@ class AccountRepository implements AccountRepositoryInterface } /** - * @deprecated - * * @param $accountId * * @return Account */ public function find(int $accountId): Account { - return $this->user->accounts()->findOrNew($accountId); + $account = $this->user->accounts()->find($accountId); + if (is_null($account)) { + $account = new Account; + } + + return $account; } /** @@ -106,11 +111,15 @@ class AccountRepository implements AccountRepositoryInterface public function getAccounts(array $types): Collection { /** @var Collection $result */ - $result = $this->user->accounts()->with( + $query = $this->user->accounts()->with( ['accountmeta' => function (HasMany $query) { $query->where('name', 'accountRole'); }] - )->accountTypeIn($types)->get(['accounts.*']); + ); + if (count($types) > 0) { + $query->accountTypeIn($types); + } + $result = $query->get(['accounts.*']); $result = $result->sortBy( function (Account $account) { @@ -154,6 +163,31 @@ class AccountRepository implements AccountRepositoryInterface return $set; } + /** + * Returns a list of transactions TO the $account, not including transfers + * and/or expenses in the $accounts list. + * + * @param Account $account + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getExpensesByDestination(Account $account, Collection $accounts, Carbon $start, Carbon $end) + { + $ids = $accounts->pluck('id')->toArray(); + $journals = $this->user->transactionjournals() + ->expanded() + ->before($end) + ->where('destination_account.id', $account->id) + ->whereIn('source_account.id', $ids) + ->after($start) + ->get(TransactionJournal::QUERYFIELDS); + + return $journals; + } + /** * @param TransactionJournal $journal * @param Account $account @@ -448,7 +482,7 @@ class AccountRepository implements AccountRepositoryInterface $this->updateMetadata($account, $data); $openingBalance = $this->openingBalanceTransaction($account); if ($data['openingBalance'] != 0) { - if ($openingBalance) { + if (!is_null($openingBalance->id)) { $this->updateInitialBalance($account, $openingBalance, $data); } else { $type = $data['openingBalance'] < 0 ? 'expense' : 'revenue'; @@ -570,8 +604,7 @@ class AccountRepository implements AccountRepositoryInterface */ protected function storeMetadata(Account $account, array $data) { - $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType']; - foreach ($validFields as $field) { + foreach ($this->validFields as $field) { if (isset($data[$field])) { $metaData = new AccountMeta( [ @@ -621,9 +654,7 @@ class AccountRepository implements AccountRepositoryInterface */ protected function updateMetadata(Account $account, array $data) { - $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType']; - - foreach ($validFields as $field) { + foreach ($this->validFields as $field) { $entry = $account->accountMeta()->where('name', $field)->first(); if (isset($data[$field])) { @@ -645,4 +676,29 @@ class AccountRepository implements AccountRepositoryInterface } } + + /** + * Returns a list of transactions TO the given (asset) $account, but none from the + * given list of accounts + * + * @param Account $account + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getIncomeByDestination(Account $account, Collection $accounts, Carbon $start, Carbon $end) + { + $ids = $accounts->pluck('id')->toArray(); + $journals = $this->user->transactionjournals() + ->expanded() + ->before($end) + ->where('source_account.id', $account->id) + ->whereIn('destination_account.id', $ids) + ->after($start) + ->get(TransactionJournal::QUERYFIELDS); + + return $journals; + } } diff --git a/app/Repositories/Account/AccountRepositoryInterface.php b/app/Repositories/Account/AccountRepositoryInterface.php index 40a40d2c6d..0e7fba5fd0 100644 --- a/app/Repositories/Account/AccountRepositoryInterface.php +++ b/app/Repositories/Account/AccountRepositoryInterface.php @@ -71,6 +71,19 @@ interface AccountRepositoryInterface */ public function getCreditCards(Carbon $date): Collection; + /** + * Returns a list of transactions TO the given (expense) $account, all from the + * given list of accounts + * + * @param Account $account + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getExpensesByDestination(Account $account, Collection $accounts, Carbon $start, Carbon $end); + /** * @param TransactionJournal $journal * @param Account $account @@ -95,6 +108,19 @@ interface AccountRepositoryInterface */ public function getFrontpageTransactions(Account $account, Carbon $start, Carbon $end): Collection; + /** + * Returns a list of transactions TO the given (asset) $account, but none from the + * given list of accounts + * + * @param Account $account + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getIncomeByDestination(Account $account, Collection $accounts, Carbon $start, Carbon $end); + /** * @param Account $account * @param $page diff --git a/app/Repositories/Bill/BillRepository.php b/app/Repositories/Bill/BillRepository.php index 7c5bc3da07..6eb28ea1d3 100644 --- a/app/Repositories/Bill/BillRepository.php +++ b/app/Repositories/Bill/BillRepository.php @@ -49,6 +49,23 @@ class BillRepository implements BillRepositoryInterface return true; } + /** + * Find a bill by ID. + * + * @param int $billId + * + * @return Bill + */ + public function find(int $billId) : Bill + { + $bill = $this->user->bills()->find($billId); + if (is_null($bill)) { + $bill = new Bill; + } + + return $bill; + } + /** * @return Collection */ @@ -252,7 +269,7 @@ class BillRepository implements BillRepositoryInterface foreach ($creditCards as $creditCard) { if ($creditCard->balance == 0) { // find a transfer TO the credit card which should account for anything paid. If not, the CC is not yet used. - $set = TransactionJournal::whereIn( + $set = TransactionJournal::whereIn( 'transaction_journals.id', function (Builder $q) use ($creditCard, $start, $end) { $q->select('transaction_journals.id') ->from('transactions') @@ -270,8 +287,8 @@ class BillRepository implements BillRepositoryInterface $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '>', 0); } )->first([DB::raw('SUM(`transactions`.`amount`) as `sum_amount`')]); - - $amount = bcadd($amount, $set->sum_amount); + $sumAmount = $set->sum_amount ?? '0'; + $amount = bcadd($amount, $sumAmount); } else { $amount = bcadd($amount, $creditCard->balance); } diff --git a/app/Repositories/Bill/BillRepositoryInterface.php b/app/Repositories/Bill/BillRepositoryInterface.php index 10b3156dd1..948e0c67fd 100644 --- a/app/Repositories/Bill/BillRepositoryInterface.php +++ b/app/Repositories/Bill/BillRepositoryInterface.php @@ -23,6 +23,15 @@ interface BillRepositoryInterface */ public function destroy(Bill $bill): bool; + /** + * Find a bill by ID. + * + * @param int $billId + * + * @return Bill + */ + public function find(int $billId) : Bill; + /** * @return Collection */ diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index 3def0840c6..dd7cffd278 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -5,6 +5,7 @@ namespace FireflyIII\Repositories\Budget; use Carbon\Carbon; use DB; +use FireflyIII\Models\Account; use FireflyIII\Models\Budget; use FireflyIII\Models\BudgetLimit; use FireflyIII\Models\LimitRepetition; @@ -74,6 +75,40 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn return true; } + /** + * @param Budget $budget + * @param Account $account + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function expensesSplit(Budget $budget, Account $account, Carbon $start, Carbon $end): Collection + { + return $budget->transactionjournals()->expanded() + ->before($end) + ->after($start) + ->where('source_account.id', $account->id) + ->get(TransactionJournal::QUERYFIELDS); + } + + /** + * Find a budget. + * + * @param int $budgetId + * + * @return Budget + */ + public function find(int $budgetId): Budget + { + $budget = $this->user->budgets()->find($budgetId); + if (is_null($budget)) { + $budget = new Budget; + } + + return $budget; + } + /** * @param Budget $budget * @@ -124,6 +159,30 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn ->get(['limit_repetitions.*', 'budget_limits.budget_id']); } + /** + * @param Account $account + * @param Carbon $start + * @param Carbon $end + * @param Collection $accounts + * + * @return Collection + */ + public function getAllWithoutBudget(Account $account, Collection $accounts, Carbon $start, Carbon $end) + { + $ids = $accounts->pluck('id')->toArray(); + + return $this->user + ->transactionjournals() + ->expanded() + ->where('source_account.id', $account->id) + ->whereNotIn('destination_account.id', $ids) + ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') + ->whereNull('budget_transaction_journal.id') + ->before($end) + ->after($start) + ->get(TransactionJournal::QUERYFIELDS); + } + /** * Get the budgeted amounts for each budgets in each year. * @@ -355,6 +414,30 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn return $data; } + /** + * Returns all expenses for the given budget and the given accounts, in the given period. + * + * @param Budget $budget + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getExpenses(Budget $budget, Collection $accounts, Carbon $start, Carbon $end):Collection + { + $ids = $accounts->pluck('id')->toArray(); + $set = $budget->transactionjournals() + ->before($end) + ->after($start) + ->expanded() + ->where('transaction_types.type', TransactionType::WITHDRAWAL) + ->whereIn('source_account.id', $ids) + ->get(TransactionJournal::QUERYFIELDS); + + return $set; + } + /** * Returns the expenses for this budget grouped per day, with the date * in "date" (a string, not a Carbon) and the amount in "dailyAmount". @@ -460,15 +543,36 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn { return $this->user ->transactionjournals() - ->transactionTypes([TransactionType::WITHDRAWAL]) + ->expanded() + ->where('transaction_types.type', TransactionType::WITHDRAWAL) ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') ->whereNull('budget_transaction_journal.id') ->before($end) ->after($start) - ->orderBy('transaction_journals.date', 'DESC') - ->orderBy('transaction_journals.order', 'ASC') - ->orderBy('transaction_journals.id', 'DESC') - ->get(['transaction_journals.*']); + ->get(TransactionJournal::QUERYFIELDS); + } + + /** + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getWithoutBudgetForAccounts(Collection $accounts, Carbon $start, Carbon $end) + { + $ids = $accounts->pluck('id')->toArray(); + + return $this->user + ->transactionjournals() + ->expanded() + ->whereIn('source_account.id', $ids) + ->where('transaction_types.type', TransactionType::WITHDRAWAL) + ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') + ->whereNull('budget_transaction_journal.id') + ->before($end) + ->after($start) + ->get(TransactionJournal::QUERYFIELDS); } /** diff --git a/app/Repositories/Budget/BudgetRepositoryInterface.php b/app/Repositories/Budget/BudgetRepositoryInterface.php index f14526831d..3c33aa0d0f 100644 --- a/app/Repositories/Budget/BudgetRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetRepositoryInterface.php @@ -4,6 +4,7 @@ declare(strict_types = 1); namespace FireflyIII\Repositories\Budget; use Carbon\Carbon; +use FireflyIII\Models\Account; use FireflyIII\Models\Budget; use FireflyIII\Models\LimitRepetition; use Illuminate\Pagination\LengthAwarePaginator; @@ -17,7 +18,6 @@ use Illuminate\Support\Collection; interface BudgetRepositoryInterface { - /** * * Same as ::spentInPeriod but corrects journals for a set of accounts @@ -43,6 +43,25 @@ interface BudgetRepositoryInterface */ public function destroy(Budget $budget); + /** + * @param Budget $budget + * @param Account $account + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function expensesSplit(Budget $budget, Account $account, Carbon $start, Carbon $end): Collection; + + /** + * Find a budget. + * + * @param int $budgetId + * + * @return Budget + */ + public function find(int $budgetId): Budget; + /** * @param Budget $budget * @@ -63,6 +82,16 @@ interface BudgetRepositoryInterface */ public function getAllBudgetLimitRepetitions(Carbon $start, Carbon $end); + /** + * @param Account $account + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getAllWithoutBudget(Account $account, Collection $accounts, Carbon $start, Carbon $end); + /** * Get the budgeted amounts for each budgets in each year. * @@ -124,6 +153,18 @@ interface BudgetRepositoryInterface */ public function getCurrentRepetition(Budget $budget, Carbon $start, Carbon $end); + /** + * Returns all expenses for the given budget and the given accounts, in the given period. + * + * @param Budget $budget + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getExpenses(Budget $budget, Collection $accounts, Carbon $start, Carbon $end):Collection; + /** * Returns the expenses for this budget grouped per day, with the date * in "date" (a string, not a Carbon) and the amount in "dailyAmount". @@ -167,6 +208,15 @@ interface BudgetRepositoryInterface */ public function getWithoutBudget(Carbon $start, Carbon $end); + /** + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getWithoutBudgetForAccounts(Collection $accounts, Carbon $start, Carbon $end); + /** * @param Collection $accounts * @param Carbon $start diff --git a/app/Repositories/Category/SingleCategoryRepository.php b/app/Repositories/Category/SingleCategoryRepository.php index ffc819ee1e..1562ed4846 100644 --- a/app/Repositories/Category/SingleCategoryRepository.php +++ b/app/Repositories/Category/SingleCategoryRepository.php @@ -9,6 +9,7 @@ use FireflyIII\Models\Category; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Shared\ComponentRepository; +use FireflyIII\User; use Illuminate\Support\Collection; /** @@ -18,6 +19,19 @@ use Illuminate\Support\Collection; */ class SingleCategoryRepository extends ComponentRepository implements SingleCategoryRepositoryInterface { + /** @var User */ + private $user; + + /** + * BillRepository constructor. + * + * @param User $user + */ + public function __construct(User $user) + { + $this->user = $user; + } + /** * @param Category $category * @@ -87,6 +101,23 @@ class SingleCategoryRepository extends ComponentRepository implements SingleCate return $return; } + /** + * Find a category + * + * @param int $categoryId + * + * @return Category + */ + public function find(int $categoryId) : Category + { + $category = $this->user->categories()->find($categoryId); + if (is_null($category)) { + $category = new Category; + } + + return $category; + } + /** * @param Category $category * @@ -122,6 +153,28 @@ class SingleCategoryRepository extends ComponentRepository implements SingleCate } + /** + * @param Category $category + * @param Collection $accounts + * + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getJournalsForAccountsInRange(Category $category, Collection $accounts, Carbon $start, Carbon $end) + { + $ids = $accounts->pluck('id')->toArray(); + + return $category->transactionjournals() + ->after($start) + ->before($end) + ->expanded() + ->whereIn('source_account.id', $ids) + ->whereNotIn('destination_account.id', $ids) + ->get(TransactionJournal::QUERYFIELDS); + } + /** * @param Category $category * @param int $page @@ -140,13 +193,9 @@ class SingleCategoryRepository extends ComponentRepository implements SingleCate ->expanded() ->take(50) ->offset($offset) - ->orderBy('transaction_journals.date', 'DESC') - ->orderBy('transaction_journals.order', 'ASC') - ->orderBy('transaction_journals.id', 'DESC') ->get(TransactionJournal::QUERYFIELDS); } - /** * @param Category $category * @@ -206,7 +255,7 @@ class SingleCategoryRepository extends ComponentRepository implements SingleCate */ public function store(array $data) { - $newCategory = new Category( + $newCategory = Category::firstOrCreateEncrypted( [ 'user_id' => $data['user'], 'name' => $data['name'], @@ -231,6 +280,4 @@ class SingleCategoryRepository extends ComponentRepository implements SingleCate return $category; } - - } diff --git a/app/Repositories/Category/SingleCategoryRepositoryInterface.php b/app/Repositories/Category/SingleCategoryRepositoryInterface.php index b954a0684a..88104b957b 100644 --- a/app/Repositories/Category/SingleCategoryRepositoryInterface.php +++ b/app/Repositories/Category/SingleCategoryRepositoryInterface.php @@ -14,6 +14,7 @@ use Illuminate\Support\Collection; */ interface SingleCategoryRepositoryInterface { + /** * @param Category $category * @@ -54,6 +55,14 @@ interface SingleCategoryRepositoryInterface */ public function earnedPerDay(Category $category, Carbon $start, Carbon $end); + /** + * Find a category + * + * @param int $categoryId + * + * @return Category + */ + public function find(int $categoryId) : Category; /** * @param Category $category @@ -70,6 +79,16 @@ interface SingleCategoryRepositoryInterface */ public function getJournals(Category $category, $page); + /** + * @param Category $category + * @param Collection $accounts + * + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getJournalsForAccountsInRange(Category $category, Collection $accounts, Carbon $start, Carbon $end); /** * @param Category $category diff --git a/app/Repositories/Currency/CurrencyRepository.php b/app/Repositories/Currency/CurrencyRepository.php index 28c4d35ca4..02328f291a 100644 --- a/app/Repositories/Currency/CurrencyRepository.php +++ b/app/Repositories/Currency/CurrencyRepository.php @@ -26,6 +26,75 @@ class CurrencyRepository implements CurrencyRepositoryInterface return $currency->transactionJournals()->count(); } + /** + * Find by ID + * + * @param int $currencyId + * + * @return TransactionCurrency + */ + public function find(int $currencyId) : TransactionCurrency + { + $currency = TransactionCurrency::find($currencyId); + if (is_null($currency)) { + $currency = new TransactionCurrency; + + } + + return $currency; + } + + /** + * Find by currency code + * + * @param string $currencyCode + * + * @return TransactionCurrency + */ + public function findByCode(string $currencyCode) : TransactionCurrency + { + $currency = TransactionCurrency::whereCode($currencyCode)->first(); + if (is_null($currency)) { + $currency = new TransactionCurrency; + } + + return $currency; + } + + /** + * Find by currency name + * + * @param string $currencyName + * + * @return TransactionCurrency + */ + public function findByName(string $currencyName) : TransactionCurrency + { + $preferred = TransactionCurrency::whereName($currencyName)->first(); + if (is_null($preferred)) { + $preferred = new TransactionCurrency; + } + + return $preferred; + } + + /** + * Find by currency symbol + * + * @param string $currencySymbol + * + * @return TransactionCurrency + */ + public function findBySymbol(string $currencySymbol) : TransactionCurrency + { + $currency = TransactionCurrency::whereSymbol($currencySymbol)->first(); + if (is_null($currency)) { + $currency = new TransactionCurrency; + } + + return $currency; + } + /** * @return Collection */ diff --git a/app/Repositories/Currency/CurrencyRepositoryInterface.php b/app/Repositories/Currency/CurrencyRepositoryInterface.php index 9284ad24c7..3b82882dd3 100644 --- a/app/Repositories/Currency/CurrencyRepositoryInterface.php +++ b/app/Repositories/Currency/CurrencyRepositoryInterface.php @@ -15,7 +15,6 @@ use Illuminate\Support\Collection; */ interface CurrencyRepositoryInterface { - /** * @param TransactionCurrency $currency * @@ -23,6 +22,42 @@ interface CurrencyRepositoryInterface */ public function countJournals(TransactionCurrency $currency); + /** + * Find by ID + * + * @param int $currencyId + * + * @return TransactionCurrency + */ + public function find(int $currencyId) : TransactionCurrency; + + /** + * Find by currency code + * + * @param string $currencyCode + * + * @return TransactionCurrency + */ + public function findByCode(string $currencyCode) : TransactionCurrency; + + /** + * Find by currency name + * + * @param string $currencyName + * + * @return TransactionCurrency + */ + public function findByName(string $currencyName) : TransactionCurrency; + + /** + * Find by currency symbol + * + * @param string $currencySymbol + * + * @return TransactionCurrency + */ + public function findBySymbol(string $currencySymbol) : TransactionCurrency; + /** * @return Collection */ diff --git a/app/Repositories/ExportJob/ExportJobRepository.php b/app/Repositories/ExportJob/ExportJobRepository.php index 179ddeb09b..6d477feb5d 100644 --- a/app/Repositories/ExportJob/ExportJobRepository.php +++ b/app/Repositories/ExportJob/ExportJobRepository.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * ExportJobRepository.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Repositories/ExportJob/ExportJobRepositoryInterface.php b/app/Repositories/ExportJob/ExportJobRepositoryInterface.php index 1eb1352f4f..9c1dd4c434 100644 --- a/app/Repositories/ExportJob/ExportJobRepositoryInterface.php +++ b/app/Repositories/ExportJob/ExportJobRepositoryInterface.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * ExportJobRepositoryInterface.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Repositories/Journal/JournalCollector.php b/app/Repositories/Journal/JournalCollector.php index f1e15fdd32..c971f9091a 100644 --- a/app/Repositories/Journal/JournalCollector.php +++ b/app/Repositories/Journal/JournalCollector.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * JournalCollector.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Repositories/Rule/RuleRepository.php b/app/Repositories/Rule/RuleRepository.php index afd48e1380..f5351ab955 100644 --- a/app/Repositories/Rule/RuleRepository.php +++ b/app/Repositories/Rule/RuleRepository.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * RuleRepository.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Repositories/Rule/RuleRepositoryInterface.php b/app/Repositories/Rule/RuleRepositoryInterface.php index 8e7963d841..c3556c7bbb 100644 --- a/app/Repositories/Rule/RuleRepositoryInterface.php +++ b/app/Repositories/Rule/RuleRepositoryInterface.php @@ -2,7 +2,7 @@ declare(strict_types = 1); /** * RuleRepositoryInterface.php - * Copyright (C) 2016 Sander Dorigo + * Copyright (C) 2016 thegrumpydictator@gmail.com * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. diff --git a/app/Repositories/User/UserRepository.php b/app/Repositories/User/UserRepository.php index a7155867ed..3f4f0764cd 100644 --- a/app/Repositories/User/UserRepository.php +++ b/app/Repositories/User/UserRepository.php @@ -1,7 +1,8 @@ get(['users.*']); + } + /** * @param User $user * @param string $role diff --git a/app/Repositories/User/UserRepositoryInterface.php b/app/Repositories/User/UserRepositoryInterface.php index 3af280c180..e26a36360d 100644 --- a/app/Repositories/User/UserRepositoryInterface.php +++ b/app/Repositories/User/UserRepositoryInterface.php @@ -1,7 +1,8 @@ getForUser(Auth::user(), $name, $default); + } + /** * @param string $name * @param string $default * * @return null|\FireflyIII\Models\Preference */ - public function get($name, $default = null) + public function getForUser(User $user, $name, $default = null) { - $fullName = 'preference' . Auth::user()->id . $name; + $fullName = 'preference' . $user->id . $name; if (Cache::has($fullName)) { return Cache::get($fullName); } - $preference = Preference::where('user_id', Auth::user()->id)->where('name', $name)->first(['id', 'name', 'data_encrypted']); + $preference = Preference::where('user_id', $user->id)->where('name', $name)->first(['id', 'name', 'data_encrypted']); if ($preference) { Cache::forever($fullName, $preference); @@ -60,7 +76,7 @@ class Preferences return null; } - return $this->set($name, $default); + return $this->setForUser($user, $name, $default); } diff --git a/app/Support/Twig/General.php b/app/Support/Twig/General.php index 8de911f5f1..2a4b16e1d3 100644 --- a/app/Support/Twig/General.php +++ b/app/Support/Twig/General.php @@ -52,7 +52,7 @@ class General extends Twig_Extension $this->getCurrencySymbol(), $this->phpdate(), $this->env(), - + $this->getAmountFromJournal(), $this->activeRouteStrict(), $this->activeRoutePartial(), $this->activeRoutePartialWhat(), @@ -306,4 +306,16 @@ class General extends Twig_Extension ); } + /** + * @return Twig_SimpleFunction + */ + private function getAmountFromJournal() + { + return new Twig_SimpleFunction( + 'getAmount', function (TransactionJournal $journal) : string { + return TransactionJournal::amount($journal); + } + ); + } + } diff --git a/app/User.php b/app/User.php index 6879e9c226..7fa2a18230 100644 --- a/app/User.php +++ b/app/User.php @@ -19,6 +19,9 @@ use Illuminate\Foundation\Auth\User as Authenticatable; * @property string $password * @property string $remember_token * @property string $reset + * @property bool $activated + * @property bool $isAdmin + * @property bool $has2FA * @property boolean $blocked * @property string $blocked_code * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Account[] $accounts diff --git a/composer.lock b/composer.lock index dad174cd40..ca0d8be608 100644 --- a/composer.lock +++ b/composer.lock @@ -855,16 +855,16 @@ }, { "name": "laravel/framework", - "version": "v5.2.23", + "version": "v5.2.29", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "87c090845f135ca94eba903f1c8462e60e3a6e36" + "reference": "e3d644eb131f18c5f3d28ff7bc678bc797091f20" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/87c090845f135ca94eba903f1c8462e60e3a6e36", - "reference": "87c090845f135ca94eba903f1c8462e60e3a6e36", + "url": "https://api.github.com/repos/laravel/framework/zipball/e3d644eb131f18c5f3d28ff7bc678bc797091f20", + "reference": "e3d644eb131f18c5f3d28ff7bc678bc797091f20", "shasum": "" }, "require": { @@ -877,7 +877,7 @@ "monolog/monolog": "~1.11", "mtdowling/cron-expression": "~1.0", "nesbot/carbon": "~1.20", - "paragonie/random_compat": "~1.1", + "paragonie/random_compat": "~1.4", "php": ">=5.5.9", "psy/psysh": "0.7.*", "swiftmailer/swiftmailer": "~5.1", @@ -979,7 +979,7 @@ "framework", "laravel" ], - "time": "2016-03-14 14:22:33" + "time": "2016-04-03 01:43:55" }, { "name": "laravelcollective/html", @@ -1037,16 +1037,16 @@ }, { "name": "league/commonmark", - "version": "0.13.1", + "version": "0.13.2", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "2c10de455649e3a544d45016d9df457248bcd37f" + "reference": "35ac362082ca983a8123df2ee2cdfcf456ab6295" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/2c10de455649e3a544d45016d9df457248bcd37f", - "reference": "2c10de455649e3a544d45016d9df457248bcd37f", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/35ac362082ca983a8123df2ee2cdfcf456ab6295", + "reference": "35ac362082ca983a8123df2ee2cdfcf456ab6295", "shasum": "" }, "require": { @@ -1058,7 +1058,7 @@ }, "require-dev": { "erusev/parsedown": "~1.0", - "jgm/commonmark": "0.24", + "jgm/commonmark": "0.25", "michelf/php-markdown": "~1.4", "mikehaertl/php-shellcommand": "~1.2.0", "phpunit/phpunit": "~4.3|~5.0", @@ -1090,7 +1090,7 @@ { "name": "Colin O'Dell", "email": "colinodell@gmail.com", - "homepage": "http://www.colinodell.com", + "homepage": "https://www.colinodell.com", "role": "Lead Developer" } ], @@ -1101,7 +1101,7 @@ "markdown", "parser" ], - "time": "2016-03-09 15:20:24" + "time": "2016-03-27 19:10:13" }, { "name": "league/csv", @@ -1245,16 +1245,16 @@ }, { "name": "monolog/monolog", - "version": "1.18.1", + "version": "1.18.2", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "a5f2734e8c16f3aa21b3da09715d10e15b4d2d45" + "reference": "064b38c16790249488e7a8b987acf1c9d7383c09" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/a5f2734e8c16f3aa21b3da09715d10e15b4d2d45", - "reference": "a5f2734e8c16f3aa21b3da09715d10e15b4d2d45", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/064b38c16790249488e7a8b987acf1c9d7383c09", + "reference": "064b38c16790249488e7a8b987acf1c9d7383c09", "shasum": "" }, "require": { @@ -1269,13 +1269,13 @@ "doctrine/couchdb": "~1.0@dev", "graylog2/gelf-php": "~1.0", "jakub-onderka/php-parallel-lint": "0.9", + "php-amqplib/php-amqplib": "~2.4", "php-console/php-console": "^3.1.3", "phpunit/phpunit": "~4.5", "phpunit/phpunit-mock-objects": "2.3.0", "raven/raven": "^0.13", "ruflin/elastica": ">=0.90 <3.0", - "swiftmailer/swiftmailer": "~5.3", - "videlalvaro/php-amqplib": "~2.4" + "swiftmailer/swiftmailer": "~5.3" }, "suggest": { "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", @@ -1284,11 +1284,11 @@ "ext-mongo": "Allow sending log messages to a MongoDB server", "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", "php-console/php-console": "Allow sending log messages to Google Chrome", "raven/raven": "Allow sending log messages to a Sentry server", "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server", - "videlalvaro/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib" + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" }, "type": "library", "extra": { @@ -1319,7 +1319,7 @@ "logging", "psr-3" ], - "time": "2016-03-13 16:08:35" + "time": "2016-04-02 13:12:58" }, { "name": "mtdowling/cron-expression", @@ -1894,16 +1894,16 @@ }, { "name": "symfony/console", - "version": "v3.0.3", + "version": "v3.0.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "2ed5e2706ce92313d120b8fe50d1063bcfd12e04" + "reference": "6b1175135bc2a74c08a28d89761272de8beed8cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/2ed5e2706ce92313d120b8fe50d1063bcfd12e04", - "reference": "2ed5e2706ce92313d120b8fe50d1063bcfd12e04", + "url": "https://api.github.com/repos/symfony/console/zipball/6b1175135bc2a74c08a28d89761272de8beed8cd", + "reference": "6b1175135bc2a74c08a28d89761272de8beed8cd", "shasum": "" }, "require": { @@ -1950,20 +1950,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-02-28 16:24:34" + "time": "2016-03-16 17:00:50" }, { "name": "symfony/debug", - "version": "v3.0.3", + "version": "v3.0.4", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "29606049ced1ec715475f88d1bbe587252a3476e" + "reference": "a06d10888a45afd97534506afb058ec38d9ba35b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/29606049ced1ec715475f88d1bbe587252a3476e", - "reference": "29606049ced1ec715475f88d1bbe587252a3476e", + "url": "https://api.github.com/repos/symfony/debug/zipball/a06d10888a45afd97534506afb058ec38d9ba35b", + "reference": "a06d10888a45afd97534506afb058ec38d9ba35b", "shasum": "" }, "require": { @@ -2007,20 +2007,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2016-01-27 05:14:46" + "time": "2016-03-30 10:41:14" }, { "name": "symfony/event-dispatcher", - "version": "v3.0.3", + "version": "v3.0.4", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "4dd5df31a28c0f82b41cb1e1599b74b5dcdbdafa" + "reference": "9002dcf018d884d294b1ef20a6f968efc1128f39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4dd5df31a28c0f82b41cb1e1599b74b5dcdbdafa", - "reference": "4dd5df31a28c0f82b41cb1e1599b74b5dcdbdafa", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9002dcf018d884d294b1ef20a6f968efc1128f39", + "reference": "9002dcf018d884d294b1ef20a6f968efc1128f39", "shasum": "" }, "require": { @@ -2067,20 +2067,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-01-27 05:14:46" + "time": "2016-03-10 10:34:12" }, { "name": "symfony/finder", - "version": "v3.0.3", + "version": "v3.0.4", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "623bda0abd9aa29e529c8e9c08b3b84171914723" + "reference": "c54e407b35bc098916704e9fd090da21da4c4f52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/623bda0abd9aa29e529c8e9c08b3b84171914723", - "reference": "623bda0abd9aa29e529c8e9c08b3b84171914723", + "url": "https://api.github.com/repos/symfony/finder/zipball/c54e407b35bc098916704e9fd090da21da4c4f52", + "reference": "c54e407b35bc098916704e9fd090da21da4c4f52", "shasum": "" }, "require": { @@ -2116,24 +2116,25 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2016-01-27 05:14:46" + "time": "2016-03-10 11:13:05" }, { "name": "symfony/http-foundation", - "version": "v3.0.3", + "version": "v3.0.4", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "52065702c71743c05d415a8facfcad6d4257e8d7" + "reference": "99f38445a874e7becb8afc4b4a79ee181cf6ec3f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/52065702c71743c05d415a8facfcad6d4257e8d7", - "reference": "52065702c71743c05d415a8facfcad6d4257e8d7", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/99f38445a874e7becb8afc4b4a79ee181cf6ec3f", + "reference": "99f38445a874e7becb8afc4b4a79ee181cf6ec3f", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.1" }, "require-dev": { "symfony/expression-language": "~2.8|~3.0" @@ -2168,20 +2169,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2016-02-28 16:24:34" + "time": "2016-03-27 14:50:32" }, { "name": "symfony/http-kernel", - "version": "v3.0.3", + "version": "v3.0.4", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "59c0a1972e9aad87b7a56bbe1ccee26b7535a0db" + "reference": "579f828489659d7b3430f4bd9b67b4618b387dea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/59c0a1972e9aad87b7a56bbe1ccee26b7535a0db", - "reference": "59c0a1972e9aad87b7a56bbe1ccee26b7535a0db", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/579f828489659d7b3430f4bd9b67b4618b387dea", + "reference": "579f828489659d7b3430f4bd9b67b4618b387dea", "shasum": "" }, "require": { @@ -2250,7 +2251,7 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2016-02-28 21:33:13" + "time": "2016-03-25 01:41:20" }, { "name": "symfony/polyfill-mbstring", @@ -2421,16 +2422,16 @@ }, { "name": "symfony/process", - "version": "v3.0.3", + "version": "v3.0.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "dfecef47506179db2501430e732adbf3793099c8" + "reference": "e6f1f98bbd355d209a992bfff45e7edfbd4a0776" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/dfecef47506179db2501430e732adbf3793099c8", - "reference": "dfecef47506179db2501430e732adbf3793099c8", + "url": "https://api.github.com/repos/symfony/process/zipball/e6f1f98bbd355d209a992bfff45e7edfbd4a0776", + "reference": "e6f1f98bbd355d209a992bfff45e7edfbd4a0776", "shasum": "" }, "require": { @@ -2466,20 +2467,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-02-02 13:44:19" + "time": "2016-03-30 10:41:14" }, { "name": "symfony/routing", - "version": "v3.0.3", + "version": "v3.0.4", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "fa1e9a8173cf0077dd995205da453eacd758fdf6" + "reference": "d061b609f2d0769494c381ec92f5c5cc5e4a20aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/fa1e9a8173cf0077dd995205da453eacd758fdf6", - "reference": "fa1e9a8173cf0077dd995205da453eacd758fdf6", + "url": "https://api.github.com/repos/symfony/routing/zipball/d061b609f2d0769494c381ec92f5c5cc5e4a20aa", + "reference": "d061b609f2d0769494c381ec92f5c5cc5e4a20aa", "shasum": "" }, "require": { @@ -2541,20 +2542,20 @@ "uri", "url" ], - "time": "2016-02-04 13:53:13" + "time": "2016-03-23 13:23:25" }, { "name": "symfony/translation", - "version": "v3.0.3", + "version": "v3.0.4", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "2de0b6f7ebe43cffd8a06996ebec6aab79ea9e91" + "reference": "f7a07af51ea067745a521dab1e3152044a2fb1f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/2de0b6f7ebe43cffd8a06996ebec6aab79ea9e91", - "reference": "2de0b6f7ebe43cffd8a06996ebec6aab79ea9e91", + "url": "https://api.github.com/repos/symfony/translation/zipball/f7a07af51ea067745a521dab1e3152044a2fb1f2", + "reference": "f7a07af51ea067745a521dab1e3152044a2fb1f2", "shasum": "" }, "require": { @@ -2605,20 +2606,20 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2016-02-02 13:44:19" + "time": "2016-03-25 01:41:20" }, { "name": "symfony/var-dumper", - "version": "v3.0.3", + "version": "v3.0.4", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "9a6a883c48acb215d4825ce9de61dccf93d62074" + "reference": "3841ed86527d18ee2c35fe4afb1b2fc60f8fae79" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9a6a883c48acb215d4825ce9de61dccf93d62074", - "reference": "9a6a883c48acb215d4825ce9de61dccf93d62074", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3841ed86527d18ee2c35fe4afb1b2fc60f8fae79", + "reference": "3841ed86527d18ee2c35fe4afb1b2fc60f8fae79", "shasum": "" }, "require": { @@ -2668,7 +2669,7 @@ "debug", "dump" ], - "time": "2016-02-13 09:23:44" + "time": "2016-03-10 10:34:12" }, { "name": "twig/twig", @@ -2784,16 +2785,16 @@ }, { "name": "watson/validating", - "version": "2.1.0", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/dwightwatson/validating.git", - "reference": "6acfec57bd480701b467570c4c08dcbfd6a9ea36" + "reference": "f86c284d599a66120c651b9cd41da60eb6124e96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dwightwatson/validating/zipball/6acfec57bd480701b467570c4c08dcbfd6a9ea36", - "reference": "6acfec57bd480701b467570c4c08dcbfd6a9ea36", + "url": "https://api.github.com/repos/dwightwatson/validating/zipball/f86c284d599a66120c651b9cd41da60eb6124e96", + "reference": "f86c284d599a66120c651b9cd41da60eb6124e96", "shasum": "" }, "require": { @@ -2835,7 +2836,7 @@ "laravel", "validation" ], - "time": "2016-03-02 00:37:06" + "time": "2016-03-29 13:54:50" } ], "packages-dev": null, diff --git a/config/firefly.php b/config/firefly.php index d43e12960b..45a42815f5 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -2,7 +2,7 @@ return [ 'chart' => 'chartjs', - 'version' => '3.8.1', + 'version' => '3.8.2', 'index_periods' => ['1D', '1W', '1M', '3M', '6M', '1Y', 'custom'], 'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'], 'csv_import_enabled' => true, diff --git a/config/upgrade.php b/config/upgrade.php index ba08607148..819b830b98 100644 --- a/config/upgrade.php +++ b/config/upgrade.php @@ -1,7 +1,7 @@ + + + + + + +{% endblock %} +{% block scripts %} +{% endblock %} +{% block styles %} +{% endblock %} diff --git a/resources/views/admin/users/index.twig b/resources/views/admin/users/index.twig new file mode 100644 index 0000000000..71fe8d4c90 --- /dev/null +++ b/resources/views/admin/users/index.twig @@ -0,0 +1,88 @@ +{% extends "./layout/default.twig" %} + +{% block breadcrumbs %} + {{ Breadcrumbs.renderIfExists }} +{% endblock %} +{% block content %} +
| + | {{ trans('list.email') }} | +{{ trans('list.registered_at') }} | +{{ trans('list.is_admin') }} | +{{ trans('list.has_two_factor') }} | +{{ trans('list.is_activated') }} | +{{ trans('list.is_blocked') }} | +{{ trans('list.blocked_code') }} | +|
|---|---|---|---|---|---|---|---|---|
| ~ | +#{{ user.id }} | +{{ user.email }} | ++ {{ user.created_at.formatLocalized(monthAndDayFormat) }} + {{ user.created_at.format('H:i') }} + | ++ {% if user.isAdmin %} + + {% else %} + + {% endif %} + | ++ {% if user.has2FA %} + + {% else %} + + {% endif %} + | ++ {% if user.activated %} + + {% else %} + + {% endif %} + | ++ {% if user.blocked == 1 %} + + {% else %} + + {% endif %} + | ++ + {% if user.blocked == 1 %} + {% if user.blocked_code == "" %} + ~ + {% else %} + {{ user.blocked_code }} + {% endif %} + {% endif %} + + | +
- Hey there, + Hey there!
-First of all: delete this email message if you did not expect it. + To start using your brand new Firefly III account, you need to activate it. Activating your account allows the website to verify that this email address is valid. Unfortunately, not even the most complex routines can work this out, without actually sending an email message. And here it is!
-Otherwise, in order to use your account, please - confirm this email address is yours. + To active your account, click on this link. +
++ If the link does not work, you can browse there manually by copy/pasting it: +
+- This link is valid for about 4 hours. + You should be redirected to the index page right away. The link expires in about four hours. +
+ ++ Thank you, and enjoy! +
+ ++ James Cole
- The registration has been created from IP {{ ip }} + You are getting this activation message because a new registration from IP {{ ip }} triggered it.
diff --git a/resources/views/emails/confirm-account.twig b/resources/views/emails/confirm-account.twig index 3d9d3b8087..3fa0b9be14 100644 --- a/resources/views/emails/confirm-account.twig +++ b/resources/views/emails/confirm-account.twig @@ -1,11 +1,16 @@ -Hey there, +Hey there! -First of all: delete this email message if you did not expect it. +To start using your brand new Firefly III account, you need to activate it. Activating your account allows the website to verify that this email address is valid. Unfortunately, not even the most complex routines can work this out, without actually sending an email message. And here it is! -Otherwise, in order to use your account, please confirm this email address is yours, by clicking on this link: +To active your account, you can click on the following link, or copy/paste it in your web browser: {{ route }} -This link is valid for about 4 hours. +You should be redirected to the index page right away. The link expires in about four hours. -The registration has been created from IP {{ ip }} +Thank you, and enjoy! + +James Cole + + +You are getting this activation message because a new registration from IP {{ ip }} triggered it. diff --git a/resources/views/layout/guest.twig b/resources/views/layout/guest.twig index 61c936f989..07c7cb903f 100644 --- a/resources/views/layout/guest.twig +++ b/resources/views/layout/guest.twig @@ -3,7 +3,16 @@ -| + | {{ trans('list.description') }} | +{{ trans('list.amount') }} | + + {% if not hideSource %} +{{ trans('list.from') }} | + {% endif %} + {% if not hideDestination %} +{{ trans('list.to') }} | + {% endif %} + + {% if not hideBudget %} ++ {% endif %} + + + {% if not hideCategory %} + | + {% endif %} + |
|---|---|---|---|---|---|---|
| + {{ journal|typeIcon }} + | ++ {{ journal.description }} + | ++ {{ journal|formatJournal }} + | + + {% if not hideSource %} ++ {% if journal.source_account_type == 'Cash account' %} + (cash) + {% else %} + {{ journal.source_account_name }} + {% endif %} + | + {% endif %} + {% if not hideDestination %} ++ {% if journal.destination_account_type == 'Cash account' %} + (cash) + {% else %} + {{ journal.destination_account_name }} + {% endif %} + | + {% endif %} + + + {% if not hideBudget %} ++ {% if journal.budgets[0] %} + {{ journal.budgets[0].name }} + {% endif %} + | + {% endif %} + + + {% if not hideCategory %} ++ {% if journal.categories[0] %} + {{ journal.categories[0].name }} + {% endif %} + | + {% endif %} +
| {{ 'sum'|_ }}: | +{{ sum|formatAmount }} | +|||||