diff --git a/app/Helpers/Report/NetWorth.php b/app/Helpers/Report/NetWorth.php new file mode 100644 index 0000000000..8e27cfc519 --- /dev/null +++ b/app/Helpers/Report/NetWorth.php @@ -0,0 +1,148 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Helpers\Report; + +use Carbon\Carbon; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Support\CacheProperties; +use FireflyIII\User; +use Illuminate\Support\Collection; +use Log; + +/** + * + * Class NetWorth + */ +class NetWorth implements NetWorthInterface +{ + + /** @var AccountRepositoryInterface */ + private $accountRepository; + + /** @var CurrencyRepositoryInterface */ + private $currencyRepos; + /** @var User */ + private $user; + + /** + * Returns the user's net worth in an array with the following layout: + * + * - + * - currency: TransactionCurrency object + * - date: the current date + * - amount: the user's net worth in that currency. + * + * This repeats for each currency the user has transactions in. + * Result of this method is cached. + * + * @param Collection $accounts + * @param Carbon $date + * + * @return array + */ + public function getNetWorthByCurrency(Collection $accounts, Carbon $date): array + { + + // start in the past, end in the future? use $date + $cache = new CacheProperties; + $cache->addProperty($date); + $cache->addProperty('net-worth-by-currency'); + $cache->addProperty(implode(',', $accounts->pluck('id')->toArray())); + if ($cache->has()) { + return $cache->get(); // @codeCoverageIgnore + } + + $netWorth = []; + $result = []; + Log::debug(sprintf('Now in getNetWorthByCurrency(%s)', $date->format('Y-m-d'))); + + // get default currency + $default = app('amount')->getDefaultCurrencyByUser($this->user); + + // get all balances: + $balances = app('steam')->balancesByAccounts($accounts, $date); + + // get the preferred currency for this account + /** @var Account $account */ + foreach ($accounts as $account) { + Log::debug(sprintf('Now at account #%d: "%s"', $account->id, $account->name)); + $currencyId = (int)$this->accountRepository->getMetaValue($account, 'currency_id'); + $currencyId = 0 === $currencyId ? $default->id : $currencyId; + + Log::debug(sprintf('Currency ID is #%d', $currencyId)); + + // balance in array: + $balance = $balances[$account->id] ?? '0'; + + Log::debug(sprintf('Balance is %s', $balance)); + + // if the account is a credit card, subtract the virtual balance from the balance, + // to better reflect that this is not money that is actually "yours". + $role = (string)$this->accountRepository->getMetaValue($account, 'accountRole'); + $virtualBalance = (string)$account->virtual_balance; + if ('ccAsset' === $role && '' !== $virtualBalance && (float)$virtualBalance > 0) { + $balance = bcsub($balance, $virtualBalance); + } + + Log::debug(sprintf('Balance corrected to %s', $balance)); + + if (!isset($netWorth[$currencyId])) { + $netWorth[$currencyId] = '0'; + } + $netWorth[$currencyId] = bcadd($balance, $netWorth[$currencyId]); + + Log::debug(sprintf('Total net worth for currency #%d is %s', $currencyId, $netWorth[$currencyId])); + } + ksort($netWorth); + + // loop results and add currency information: + foreach ($netWorth as $currencyId => $balance) { + $result[] = [ + 'currency' => $this->currencyRepos->findNull($currencyId), + 'balance' => $balance, + ]; + } + $cache->store($result); + + return $result; + } + + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + + // make repository: + $this->accountRepository = app(AccountRepositoryInterface::class); + $this->accountRepository->setUser($this->user); + + $this->currencyRepos = app(CurrencyRepositoryInterface::class); + $this->currencyRepos->setUser($this->user); + } +} \ No newline at end of file diff --git a/app/Helpers/Report/NetWorthInterface.php b/app/Helpers/Report/NetWorthInterface.php new file mode 100644 index 0000000000..8e7e532211 --- /dev/null +++ b/app/Helpers/Report/NetWorthInterface.php @@ -0,0 +1,60 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Helpers\Report; + +use Carbon\Carbon; +use FireflyIII\User; +use Illuminate\Support\Collection; + +/** + * Interface NetWorthInterface + * + * @package FireflyIII\Helpers\Report + */ +interface NetWorthInterface +{ + /** + * Returns the user's net worth in an array with the following layout: + * + * - + * - currency: TransactionCurrency object + * - date: the current date + * - amount: the user's net worth in that currency. + * + * This repeats for each currency the user has transactions in. + * Result of this method is cached. + * + * @param Collection $accounts + * @param Carbon $date + * + * @return array + */ + public function getNetWorthByCurrency(Collection $accounts, Carbon $date): array; + + /** + * @param User $user + */ + public function setUser(User $user): void; + +} \ No newline at end of file diff --git a/app/Http/Controllers/Account/CreateController.php b/app/Http/Controllers/Account/CreateController.php index 38feabb864..11848ca120 100644 --- a/app/Http/Controllers/Account/CreateController.php +++ b/app/Http/Controllers/Account/CreateController.php @@ -99,7 +99,13 @@ class CreateController extends Controller ]; // pre fill some data - $request->session()->flash('preFilled', ['currency_id' => $defaultCurrency->id]); + $hasOldInput = null !== $request->old('_token'); + $request->session()->flash( + 'preFilled', [ + 'currency_id' => $defaultCurrency->id, + 'include_net_worth' => $hasOldInput ? (bool)$request->old('include_net_worth') : true, + ] + ); // put previous url in session if not redirect from store (not "create another"). if (true !== session('accounts.create.fromStore')) { diff --git a/app/Http/Controllers/Account/EditController.php b/app/Http/Controllers/Account/EditController.php index 0201d5659c..2ce4d98aa7 100644 --- a/app/Http/Controllers/Account/EditController.php +++ b/app/Http/Controllers/Account/EditController.php @@ -116,6 +116,11 @@ class EditController extends Controller $openingBalanceDate = $repository->getOpeningBalanceDate($account); $default = app('amount')->getDefaultCurrency(); $currency = $this->currencyRepos->findNull((int)$repository->getMetaValue($account, 'currency_id')); + + // include this account in net-worth charts? + $includeNetWorth = $repository->getMetaValue($account, 'include_net_worth'); + $includeNetWorth = null === $includeNetWorth ? true : '1' === $includeNetWorth; + if (null === $currency) { $currency = $default; } @@ -133,6 +138,7 @@ class EditController extends Controller 'openingBalance' => $openingBalanceAmount, 'virtualBalance' => $account->virtual_balance, 'currency_id' => $currency->id, + 'include_net_worth' => $includeNetWorth, 'interest' => $repository->getMetaValue($account, 'interest'), 'interest_period' => $repository->getMetaValue($account, 'interest_period'), 'notes' => $this->repository->getNoteText($account), diff --git a/app/Http/Controllers/Chart/ReportController.php b/app/Http/Controllers/Chart/ReportController.php index c68d8d6a23..8a85e95605 100644 --- a/app/Http/Controllers/Chart/ReportController.php +++ b/app/Http/Controllers/Chart/ReportController.php @@ -24,6 +24,7 @@ namespace FireflyIII\Http\Controllers\Chart; use Carbon\Carbon; use FireflyIII\Generator\Chart\Basic\GeneratorInterface; +use FireflyIII\Helpers\Report\NetWorthInterface; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Repositories\Account\AccountTaskerInterface; use FireflyIII\Support\CacheProperties; @@ -67,22 +68,41 @@ class ReportController extends Controller $cache = new CacheProperties; $cache->addProperty('chart.report.net-worth'); $cache->addProperty($start); - $cache->addProperty($accounts); + $cache->addProperty(implode(',', $accounts->pluck('id')->toArray())); $cache->addProperty($end); if ($cache->has()) { return response()->json($cache->get()); // @codeCoverageIgnore } $current = clone $start; $chartData = []; + /** @var NetWorthInterface $helper */ + $helper = app(NetWorthInterface::class); + $helper->setUser(auth()->user()); + while ($current < $end) { - $balances = app('steam')->balancesByAccounts($accounts, $current); - $sum = $this->arraySum($balances); - $label = $current->formatLocalized((string)trans('config.month_and_day')); - $chartData[$label] = $sum; + // get balances by date, grouped by currency. + $result = $helper->getNetWorthByCurrency($accounts, $current); + + // loop result, add to array. + /** @var array $netWorthItem */ + foreach ($result as $netWorthItem) { + $currencyId = $netWorthItem['currency']->id; + $label = $current->formatLocalized((string)trans('config.month_and_day')); + if (!isset($chartData[$currencyId])) { + $chartData[$currencyId] = [ + 'label' => 'Net worth in ' . $netWorthItem['currency']->name, + 'type' => 'line', + 'currency_symbol' => $netWorthItem['currency']->symbol, + 'entries' => [], + ]; + } + $chartData[$currencyId]['entries'][$label] = $netWorthItem['balance']; + + } $current->addDays(7); } - $data = $this->generator->singleSet((string)trans('firefly.net_worth'), $chartData); + $data = $this->generator->multiSet($chartData); $cache->store($data); return response()->json($data); diff --git a/app/Http/Controllers/Json/BoxController.php b/app/Http/Controllers/Json/BoxController.php index bbeba6146f..82a0a8c2eb 100644 --- a/app/Http/Controllers/Json/BoxController.php +++ b/app/Http/Controllers/Json/BoxController.php @@ -24,6 +24,7 @@ namespace FireflyIII\Http\Controllers\Json; use Carbon\Carbon; use FireflyIII\Helpers\Collector\TransactionCollectorInterface; +use FireflyIII\Helpers\Report\NetWorthInterface; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; @@ -37,6 +38,7 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Support\CacheProperties; use FireflyIII\Support\Http\Controllers\RequestInformation; use Illuminate\Http\JsonResponse; +use Log; /** * Class BoxController. @@ -235,16 +237,13 @@ class BoxController extends Controller /** * Total user net worth. * - * @param AccountRepositoryInterface $repository - * * @return JsonResponse - * * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function netWorth(AccountRepositoryInterface $repository): JsonResponse + public function netWorth(): JsonResponse { - $date = new Carbon(date('Y-m-d')); // needed so its per day. + $date = Carbon::create()->startOfDay(); // start and end in the future? use $end if ($this->notInSessionRange($date)) { @@ -252,48 +251,43 @@ class BoxController extends Controller $date = session('end', Carbon::now()->endOfMonth()); } - // start in the past, end in the future? use $date - $cache = new CacheProperties; - $cache->addProperty($date); - $cache->addProperty('box-net-worth'); - if ($cache->has()) { - return response()->json($cache->get()); // @codeCoverageIgnore - } - $netWorth = []; - $accounts = $repository->getActiveAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); + /** @var NetWorthInterface $netWorthHelper */ + $netWorthHelper = app(NetWorthInterface::class); + $netWorthHelper->setUser(auth()->user()); - $balances = app('steam')->balancesByAccounts($accounts, $date); + /** @var AccountRepositoryInterface $accountRepository */ + $accountRepository = app(AccountRepositoryInterface::class); + $allAccounts = $accountRepository->getActiveAccountsByType( + [AccountType::DEFAULT, AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD] + ); + Log::debug(sprintf('Found %d accounts.', $allAccounts->count())); - /** @var Account $account */ - foreach ($accounts as $account) { - $accountCurrency = $this->getCurrencyOrDefault($account); - $balance = $balances[$account->id] ?? '0'; + // filter list on preference of being included. + $filtered = $allAccounts->filter( + function (Account $account) use ($accountRepository) { + $includeNetWorth = $accountRepository->getMetaValue($account, 'include_net_worth'); + $result = null === $includeNetWorth ? true : '1' === $includeNetWorth; + if (false === $result) { + Log::debug(sprintf('Will not include "%s" in net worth charts.', $account->name)); + } - // if the account is a credit card, subtract the virtual balance from the balance, - // to better reflect that this is not money that is actually "yours". - $role = (string)$repository->getMetaValue($account, 'accountRole'); - $virtualBalance = (string)$account->virtual_balance; - if ('ccAsset' === $role && '' !== $virtualBalance && (float)$virtualBalance > 0) { - $balance = bcsub($balance, $virtualBalance); + return $result; } + ); + + $netWorthSet = $netWorthHelper->getNetWorthByCurrency($filtered, $date); - if (!isset($netWorth[$accountCurrency->id])) { - $netWorth[$accountCurrency->id]['currency'] = $accountCurrency; - $netWorth[$accountCurrency->id]['sum'] = '0'; - } - $netWorth[$accountCurrency->id]['sum'] = bcadd($netWorth[$accountCurrency->id]['sum'], $balance); - } $return = []; - foreach ($netWorth as $currencyId => $data) { - $return[$currencyId] = app('amount')->formatAnything($data['currency'], $data['sum'], false); + foreach ($netWorthSet as $index => $data) { + /** @var TransactionCurrency $currency */ + $currency = $data['currency']; + $return[$currency->id] = app('amount')->formatAnything($currency, $data['balance'], false); } $return = [ 'net_worths' => array_values($return), ]; - $cache->store($return); - return response()->json($return); } diff --git a/app/Http/Requests/AccountFormRequest.php b/app/Http/Requests/AccountFormRequest.php index 6a9986b9e7..3d01ff4a3c 100644 --- a/app/Http/Requests/AccountFormRequest.php +++ b/app/Http/Requests/AccountFormRequest.php @@ -66,7 +66,11 @@ class AccountFormRequest extends Request 'notes' => $this->string('notes'), 'interest' => $this->string('interest'), 'interest_period' => $this->string('interest_period'), + 'include_net_worth' => '1', ]; + if (false === $this->boolean('include_net_worth')) { + $data['include_net_worth'] = '0'; + } // if the account type is "liabilities" there are actually four types of liability // that could have been selected. diff --git a/app/Providers/FireflyServiceProvider.php b/app/Providers/FireflyServiceProvider.php index 4cef20c2bf..92de23b578 100644 --- a/app/Providers/FireflyServiceProvider.php +++ b/app/Providers/FireflyServiceProvider.php @@ -38,6 +38,8 @@ use FireflyIII\Helpers\Report\BalanceReportHelper; use FireflyIII\Helpers\Report\BalanceReportHelperInterface; use FireflyIII\Helpers\Report\BudgetReportHelper; use FireflyIII\Helpers\Report\BudgetReportHelperInterface; +use FireflyIII\Helpers\Report\NetWorth; +use FireflyIII\Helpers\Report\NetWorthInterface; use FireflyIII\Helpers\Report\PopupReport; use FireflyIII\Helpers\Report\PopupReportInterface; use FireflyIII\Helpers\Report\ReportHelper; @@ -188,5 +190,8 @@ class FireflyServiceProvider extends ServiceProvider // IP thing: $this->app->bind(IPRetrievalInterface::class, IpifyOrg::class); + + // net worth thing. + $this->app->bind(NetWorthInterface::class, NetWorth::class); } } diff --git a/app/Services/Internal/Support/AccountServiceTrait.php b/app/Services/Internal/Support/AccountServiceTrait.php index 8d4e2f3e33..8d0c087605 100644 --- a/app/Services/Internal/Support/AccountServiceTrait.php +++ b/app/Services/Internal/Support/AccountServiceTrait.php @@ -45,11 +45,11 @@ use Validator; trait AccountServiceTrait { /** @var array */ - public $validAssetFields = ['accountRole', 'accountNumber', 'currency_id', 'BIC']; + public $validAssetFields = ['accountRole', 'accountNumber', 'currency_id', 'BIC', 'include_net_worth']; /** @var array */ - public $validCCFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType', 'accountNumber', 'currency_id', 'BIC']; + public $validCCFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType', 'accountNumber', 'currency_id', 'BIC', 'include_net_worth']; /** @var array */ - public $validFields = ['accountNumber', 'currency_id', 'BIC', 'interest', 'interest_period']; + public $validFields = ['accountNumber', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth']; /** * @param Account $account @@ -332,6 +332,7 @@ trait AccountServiceTrait * @param string $note * * @return bool + * @throws \Exception */ public function updateNote(Account $account, string $note): bool { diff --git a/config/twigbridge.php b/config/twigbridge.php index e6b2803442..d1e807a6be 100644 --- a/config/twigbridge.php +++ b/config/twigbridge.php @@ -185,17 +185,11 @@ return [ 'Config', 'Request', 'ExpandedForm' => [ - 'is_safe' => [ - 'date', 'text', 'select', 'balance', 'optionsList', 'checkbox', 'amount', 'tags', 'integer', 'textarea', 'location', - 'file', 'staticText', 'password', 'nonSelectableAmount', - 'number', 'assetAccountList', 'amountNoCurrency', 'currencyList', 'ruleGroupList', 'assetAccountCheckList', 'ruleGroupListWithEmpty', - 'piggyBankList', 'currencyListEmpty', 'activeAssetAccountList', 'percentage', 'activeLongAccountList', 'longAccountList', - ], - ], - 'Form' => [ - 'is_safe' => [ - 'input', 'select', 'checkbox', 'model', 'open', 'radio', 'textarea', 'file', - ], + 'is_safe' => ['date', 'text', 'select', 'balance', 'optionsList', 'checkbox', 'amount', 'tags', 'integer', 'textarea', 'location', 'file', + 'staticText', 'password', 'nonSelectableAmount', 'number', 'assetAccountList', 'amountNoCurrency', 'currencyList', + 'ruleGroupList', 'assetAccountCheckList', 'ruleGroupListWithEmpty', 'piggyBankList', 'currencyListEmpty', + 'activeAssetAccountList', 'percentage', 'activeLongAccountList', 'longAccountList',],], + 'Form' => ['is_safe' => ['input', 'select', 'checkbox', 'model', 'open', 'radio', 'textarea', 'file',], ], ], diff --git a/resources/views/accounts/create.twig b/resources/views/accounts/create.twig index 7b8dc44121..87d90cbc2d 100644 --- a/resources/views/accounts/create.twig +++ b/resources/views/accounts/create.twig @@ -50,7 +50,8 @@ {{ ExpandedForm.select('accountRole', roles,null,{helpText : 'asset_account_role_help'|_}) }} {{ ExpandedForm.amountNoCurrency('virtualBalance') }} {% endif %} - + {# only correct way to do active checkbox #} + {{ ExpandedForm.checkbox('include_net_worth', 1) }} {{ ExpandedForm.textarea('notes',null,{helpText: trans('firefly.field_supports_markdown')}) }} diff --git a/resources/views/accounts/edit.twig b/resources/views/accounts/edit.twig index 8ea679f6f4..123cbef431 100644 --- a/resources/views/accounts/edit.twig +++ b/resources/views/accounts/edit.twig @@ -56,10 +56,14 @@ {{ ExpandedForm.amountNoCurrency('virtualBalance',null) }} {% endif %} + + {{ ExpandedForm.textarea('notes',preFilled.notes,{helpText: trans('firefly.field_supports_markdown')}) }} {# only correct way to do active checkbox #} {{ ExpandedForm.checkbox('active', 1) }} + {# only correct way to do active checkbox #} + {{ ExpandedForm.checkbox('include_net_worth', 1) }} diff --git a/resources/views/accounts/show.twig b/resources/views/accounts/show.twig index 7dc2787cd3..6508819793 100644 --- a/resources/views/accounts/show.twig +++ b/resources/views/accounts/show.twig @@ -27,11 +27,6 @@
-

- {% if isLiability %} - This chart pre-calculates rent starting from the last transaction you've entered. It's just an estimation. - {% endif %} -

diff --git a/tests/Api/V1/Controllers/AttachmentControllerTest.php b/tests/Api/V1/Controllers/AttachmentControllerTest.php index d6273d3952..1a06c7db01 100644 --- a/tests/Api/V1/Controllers/AttachmentControllerTest.php +++ b/tests/Api/V1/Controllers/AttachmentControllerTest.php @@ -199,7 +199,6 @@ class AttachmentControllerTest extends TestCase // test API $response = $this->get('/api/v1/attachments/' . $attachment->id); $response->assertStatus(200); - $response->assertStatus(200); $response->assertJson(['data' => ['type' => 'attachments', 'links' => true],]); $response->assertSee($attachment->filename); // attachment file name $response->assertHeader('Content-Type', 'application/vnd.api+json'); diff --git a/tests/Feature/Controllers/Account/EditControllerTest.php b/tests/Feature/Controllers/Account/EditControllerTest.php index ef9951d705..ed2ea90af1 100644 --- a/tests/Feature/Controllers/Account/EditControllerTest.php +++ b/tests/Feature/Controllers/Account/EditControllerTest.php @@ -70,6 +70,7 @@ class EditControllerTest extends TestCase $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'accountNumber'])->andReturn('123'); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'accountRole'])->andReturn('defaultAsset'); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'ccType'])->andReturn(''); + $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'include_net_worth'])->andReturn('1'); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'ccMonthlyPaymentDate'])->andReturn(''); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'BIC'])->andReturn('BIC'); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'interest'])->andReturn('1'); @@ -113,6 +114,7 @@ class EditControllerTest extends TestCase $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'accountRole'])->andReturn('defaultAsset'); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'ccType'])->andReturn(''); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'ccMonthlyPaymentDate'])->andReturn(''); + $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'include_net_worth'])->andReturn('1'); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'BIC'])->andReturn('BIC'); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'interest'])->andReturn('1'); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'interest_period'])->andReturn('monthly'); diff --git a/tests/Feature/Controllers/Chart/ReportControllerTest.php b/tests/Feature/Controllers/Chart/ReportControllerTest.php index 948a90c7d5..6efa3044d6 100644 --- a/tests/Feature/Controllers/Chart/ReportControllerTest.php +++ b/tests/Feature/Controllers/Chart/ReportControllerTest.php @@ -50,7 +50,7 @@ class ReportControllerTest extends TestCase $generator = $this->mock(GeneratorInterface::class); Steam::shouldReceive('balancesByAccounts')->andReturn(['5', '10']); - $generator->shouldReceive('singleSet')->andReturn([]); + $generator->shouldReceive('multiSet')->andReturn([]); $this->be($this->user()); $response = $this->get(route('chart.report.net-worth', [1, '20120101', '20120131'])); diff --git a/tests/Feature/Controllers/Json/BoxControllerTest.php b/tests/Feature/Controllers/Json/BoxControllerTest.php index 94e2528282..39396ef985 100644 --- a/tests/Feature/Controllers/Json/BoxControllerTest.php +++ b/tests/Feature/Controllers/Json/BoxControllerTest.php @@ -24,6 +24,7 @@ namespace Tests\Feature\Controllers\Json; use Carbon\Carbon; use FireflyIII\Helpers\Collector\TransactionCollectorInterface; +use FireflyIII\Helpers\Report\NetWorthInterface; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Account\AccountRepositoryInterface; @@ -155,12 +156,26 @@ class BoxControllerTest extends TestCase */ public function testNetWorth(): void { + $result = [ + [ + 'currency' => TransactionCurrency::find(1), + 'balance' => '3', + ], + ]; + + + $netWorthHelper = $this->mock(NetWorthInterface::class); + $netWorthHelper->shouldReceive('setUser')->once(); + $netWorthHelper->shouldReceive('getNetWorthByCurrency')->once()->andReturn($result); + $accountRepos = $this->mock(AccountRepositoryInterface::class); $currencyRepos = $this->mock(CurrencyRepositoryInterface::class); $accountRepos->shouldReceive('getActiveAccountsByType')->andReturn(new Collection([$this->user()->accounts()->first()])); $currencyRepos->shouldReceive('findNull')->andReturn(TransactionCurrency::find(1)); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'currency_id'])->andReturn('1'); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'accountRole'])->andReturn('ccAsset'); + $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'include_net_worth'])->andReturn('1'); + $this->be($this->user()); $response = $this->get(route('json.box.net-worth')); @@ -172,12 +187,25 @@ class BoxControllerTest extends TestCase */ public function testNetWorthFuture(): void { + $result = [ + [ + 'currency' => TransactionCurrency::find(1), + 'balance' => '3', + ], + ]; + $accountRepos = $this->mock(AccountRepositoryInterface::class); $currencyRepos = $this->mock(CurrencyRepositoryInterface::class); + + $netWorthHelper = $this->mock(NetWorthInterface::class); + $netWorthHelper->shouldReceive('setUser')->once(); + $netWorthHelper->shouldReceive('getNetWorthByCurrency')->once()->andReturn($result); + $accountRepos->shouldReceive('getActiveAccountsByType')->andReturn(new Collection([$this->user()->accounts()->first()])); $currencyRepos->shouldReceive('findNull')->andReturn(TransactionCurrency::find(1)); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'currency_id'])->andReturn('1'); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'accountRole'])->andReturn('ccAsset'); + $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'include_net_worth'])->andReturn('1'); $start = new Carbon; $start->addMonths(6)->startOfMonth(); @@ -194,12 +222,25 @@ class BoxControllerTest extends TestCase */ public function testNetWorthNoCurrency(): void { + $result = [ + [ + 'currency' => TransactionCurrency::find(1), + 'balance' => '3', + ], + ]; + $accountRepos = $this->mock(AccountRepositoryInterface::class); $currencyRepos = $this->mock(CurrencyRepositoryInterface::class); + + $netWorthHelper = $this->mock(NetWorthInterface::class); + $netWorthHelper->shouldReceive('setUser')->once(); + $netWorthHelper->shouldReceive('getNetWorthByCurrency')->once()->andReturn($result); + $accountRepos->shouldReceive('getActiveAccountsByType')->andReturn(new Collection([$this->user()->accounts()->first()])); $currencyRepos->shouldReceive('findNull')->andReturn(null); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'currency_id'])->andReturn('1'); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'accountRole'])->andReturn('ccAsset'); + $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'include_net_worth'])->andReturn('1'); $this->be($this->user()); $response = $this->get(route('json.box.net-worth')); @@ -211,14 +252,27 @@ class BoxControllerTest extends TestCase */ public function testNetWorthVirtual(): void { + $result = [ + [ + 'currency' => TransactionCurrency::find(1), + 'balance' => '3', + ], + ]; + $account = $this->user()->accounts()->first(); $account->virtual_balance = '1000'; $accountRepos = $this->mock(AccountRepositoryInterface::class); $currencyRepos = $this->mock(CurrencyRepositoryInterface::class); + + $netWorthHelper = $this->mock(NetWorthInterface::class); + $netWorthHelper->shouldReceive('setUser')->once(); + $netWorthHelper->shouldReceive('getNetWorthByCurrency')->once()->andReturn($result); + $accountRepos->shouldReceive('getActiveAccountsByType')->andReturn(new Collection([$account])); $currencyRepos->shouldReceive('findNull')->andReturn(TransactionCurrency::find(1)); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'currency_id'])->andReturn('1'); $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'accountRole'])->andReturn('ccAsset'); + $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'include_net_worth'])->andReturn('1'); $this->be($this->user()); $response = $this->get(route('json.box.net-worth')); diff --git a/tests/Feature/Controllers/Transaction/SingleControllerTest.php b/tests/Feature/Controllers/Transaction/SingleControllerTest.php index dd7a054abc..9ded6e76d6 100644 --- a/tests/Feature/Controllers/Transaction/SingleControllerTest.php +++ b/tests/Feature/Controllers/Transaction/SingleControllerTest.php @@ -249,7 +249,7 @@ class SingleControllerTest extends TestCase // mock new account list: $currency = TransactionCurrency::first(); $accountRepos->shouldReceive('getAccountsByType') - ->withArgs([[AccountType::ASSET, AccountType::DEFAULT]])->andReturn(new Collection([$account]))->once(); + ->withArgs([[AccountType::ASSET, AccountType::DEFAULT, AccountType::MORTGAGE, AccountType::DEBT, AccountType::CREDITCARD, AccountType::LOAN,]])->andReturn(new Collection([$account]))->once(); Amount::shouldReceive('getDefaultCurrency')->andReturn($currency)->times(6); $this->be($this->user()); diff --git a/tests/Unit/Factory/TransactionFactoryTest.php b/tests/Unit/Factory/TransactionFactoryTest.php index 4590025604..f4e8a88e32 100644 --- a/tests/Unit/Factory/TransactionFactoryTest.php +++ b/tests/Unit/Factory/TransactionFactoryTest.php @@ -1037,7 +1037,7 @@ class TransactionFactoryTest extends TestCase try { $factory->createPair($withdrawal, $data); } catch (FireflyException $e) { - $this->assertEquals('At least one of the accounts must be an asset account.', $e->getMessage()); + $this->assertEquals('At least one of the accounts must be an asset account (Expense account, Revenue account).', $e->getMessage()); } $newCount = $withdrawal->transactions()->count(); diff --git a/tests/Unit/Helpers/Attachments/AttachmentHelperTest.php b/tests/Unit/Helpers/Attachments/AttachmentHelperTest.php index 4ecafc8d1a..981ce3f85b 100644 --- a/tests/Unit/Helpers/Attachments/AttachmentHelperTest.php +++ b/tests/Unit/Helpers/Attachments/AttachmentHelperTest.php @@ -28,8 +28,8 @@ use FireflyIII\Models\Attachment; use FireflyIII\Models\TransactionJournal; use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\Storage; -use Tests\TestCase; use Log; +use Tests\TestCase; /** * Class AttachmentHelperTest @@ -114,15 +114,31 @@ class AttachmentHelperTest extends TestCase public function testSaveAttachmentFromApi(): void { // mock calls: - Crypt::shouldReceive('encrypt')->times(2)->andReturn('Some encrypted content'); + Crypt::shouldReceive('encrypt')->times(6)->andReturn('Some encrypted content'); Storage::fake('upload'); - $path = public_path('apple-touch-icon.png'); - $helper = new AttachmentHelper; - $attachment = Attachment::first(); + $path = public_path('apple-touch-icon.png'); + $helper = new AttachmentHelper; + + // make new attachment: + $journal = $this->user()->transactionJournals()->inRandomOrder()->first(); + $attachment = Attachment::create( + [ + 'attachable_id' => $journal->id, + 'user_id' => $this->user()->id, + 'attachable_type' => TransactionJournal::class, + 'md5' => md5('Hello' . random_int(1, 10000)), + 'filename' => 'file.txt', + 'title' => 'Some title', + 'description' => 'Some descr', + 'mime' => 'text/plain', + 'size' => 30, + 'uploaded' => true, + ] + ); // call helper - $result = $helper->saveAttachmentFromApi($attachment, file_get_contents($path)); + $result = $helper->saveAttachmentFromApi($attachment, file_get_contents($path)); $this->assertTrue($result); @@ -138,10 +154,26 @@ class AttachmentHelperTest extends TestCase $path = public_path('browserconfig.xml'); $helper = new AttachmentHelper; - $attachment = Attachment::first(); + + // make new attachment: + $journal = $this->user()->transactionJournals()->inRandomOrder()->first(); + $attachment = Attachment::create( + [ + 'attachable_id' => $journal->id, + 'user_id' => $this->user()->id, + 'attachable_type' => TransactionJournal::class, + 'md5' => md5('Hello' . random_int(1, 10000)), + 'filename' => 'file.txt', + 'title' => 'Some title', + 'description' => 'Some descr', + 'mime' => 'text/plain', + 'size' => 30, + 'uploaded' => true, + ] + ); // call helper - $result = $helper->saveAttachmentFromApi($attachment, file_get_contents($path)); + $result = $helper->saveAttachmentFromApi($attachment, file_get_contents($path)); $this->assertFalse($result);