Improved implementation of liability accounts and the option to add or remove accounts from the net-worth calculations.

This commit is contained in:
James Cole 2018-08-26 18:40:38 +02:00
parent 7dc72a2894
commit 8c1d1d1db0
20 changed files with 399 additions and 74 deletions

View File

@ -0,0 +1,148 @@
<?php
/**
* NetWorth.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\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);
}
}

View File

@ -0,0 +1,60 @@
<?php
/**
* NetWorthInterface.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\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;
}

View File

@ -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')) {

View File

@ -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),

View File

@ -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);

View File

@ -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);
}

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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
{

View File

@ -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',],
],
],

View File

@ -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')}) }}
</div>

View File

@ -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) }}
</div>
</div>

View File

@ -27,11 +27,6 @@
<div>
<canvas id="overview-chart" style="width:100%;height:400px;" height="400" width="100%"></canvas>
</div>
<p>
{% if isLiability %}
<em>This chart pre-calculates rent starting from the last transaction you've entered. It's just an estimation.</em>
{% endif %}
</p>
</div>
</div>
</div>

View File

@ -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');

View File

@ -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');

View File

@ -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']));

View File

@ -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'));

View File

@ -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());

View File

@ -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();

View File

@ -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);