mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-03 19:16:51 +00:00
Expand native amount things.
This commit is contained in:
@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Summary;
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Data\DateRequest;
|
use FireflyIII\Api\V1\Requests\Data\DateRequest;
|
||||||
|
use FireflyIII\Enums\AccountTypeEnum;
|
||||||
use FireflyIII\Enums\TransactionTypeEnum;
|
use FireflyIII\Enums\TransactionTypeEnum;
|
||||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
use FireflyIII\Helpers\Report\NetWorthInterface;
|
use FireflyIII\Helpers\Report\NetWorthInterface;
|
||||||
@@ -38,6 +39,7 @@ use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
|
|||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
|
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
|
||||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
||||||
|
use FireflyIII\Support\Facades\Amount;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
@@ -102,10 +104,10 @@ class BasicController extends Controller
|
|||||||
$billData = $this->getBillInformation($start, $end);
|
$billData = $this->getBillInformation($start, $end);
|
||||||
$spentData = $this->getLeftToSpendInfo($start, $end);
|
$spentData = $this->getLeftToSpendInfo($start, $end);
|
||||||
$netWorthData = $this->getNetWorthInfo($start, $end);
|
$netWorthData = $this->getNetWorthInfo($start, $end);
|
||||||
$balanceData = [];
|
// $balanceData = [];
|
||||||
$billData = [];
|
// $billData = [];
|
||||||
// $spentData = [];
|
// $spentData = [];
|
||||||
$netWorthData = [];
|
// $netWorthData = [];
|
||||||
$total = array_merge($balanceData, $billData, $spentData, $netWorthData);
|
$total = array_merge($balanceData, $billData, $spentData, $netWorthData);
|
||||||
|
|
||||||
// give new keys
|
// give new keys
|
||||||
@@ -121,6 +123,9 @@ class BasicController extends Controller
|
|||||||
|
|
||||||
private function getBalanceInformation(Carbon $start, Carbon $end): array
|
private function getBalanceInformation(Carbon $start, Carbon $end): array
|
||||||
{
|
{
|
||||||
|
// some config settings
|
||||||
|
$convertToNative = app('preferences')->get('convert_to_native', false)->data;
|
||||||
|
$default = app('amount')->getDefaultCurrency();
|
||||||
// prep some arrays:
|
// prep some arrays:
|
||||||
$incomes = [];
|
$incomes = [];
|
||||||
$expenses = [];
|
$expenses = [];
|
||||||
@@ -134,16 +139,17 @@ class BasicController extends Controller
|
|||||||
|
|
||||||
$set = $collector->getExtractedJournals();
|
$set = $collector->getExtractedJournals();
|
||||||
|
|
||||||
/** @var array $transactionJournal */
|
/** @var array $journal */
|
||||||
foreach ($set as $transactionJournal) {
|
foreach ($set as $journal) {
|
||||||
$currencyId = (int) $transactionJournal['currency_id'];
|
$currencyId = $convertToNative ? $default->id : (int) $journal['currency_id'];
|
||||||
|
$amount = Amount::getAmountFromJournal($journal);
|
||||||
$incomes[$currencyId] ??= '0';
|
$incomes[$currencyId] ??= '0';
|
||||||
$incomes[$currencyId] = bcadd(
|
$incomes[$currencyId] = bcadd(
|
||||||
$incomes[$currencyId],
|
$incomes[$currencyId],
|
||||||
bcmul($transactionJournal['amount'], '-1')
|
bcmul($amount, '-1')
|
||||||
);
|
);
|
||||||
$sums[$currencyId] ??= '0';
|
$sums[$currencyId] ??= '0';
|
||||||
$sums[$currencyId] = bcadd($sums[$currencyId], bcmul($transactionJournal['amount'], '-1'));
|
$sums[$currencyId] = bcadd($sums[$currencyId], bcmul($amount, '-1'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect expenses of user using the new group collector.
|
// collect expenses of user using the new group collector.
|
||||||
@@ -152,13 +158,14 @@ class BasicController extends Controller
|
|||||||
$collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
|
$collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
|
||||||
$set = $collector->getExtractedJournals();
|
$set = $collector->getExtractedJournals();
|
||||||
|
|
||||||
/** @var array $transactionJournal */
|
/** @var array $journal */
|
||||||
foreach ($set as $transactionJournal) {
|
foreach ($set as $journal) {
|
||||||
$currencyId = (int) $transactionJournal['currency_id'];
|
$currencyId = $convertToNative ? $default->id : (int) $journal['currency_id'];
|
||||||
|
$amount = Amount::getAmountFromJournal($journal);
|
||||||
$expenses[$currencyId] ??= '0';
|
$expenses[$currencyId] ??= '0';
|
||||||
$expenses[$currencyId] = bcadd($expenses[$currencyId], $transactionJournal['amount']);
|
$expenses[$currencyId] = bcadd($expenses[$currencyId], $amount);
|
||||||
$sums[$currencyId] ??= '0';
|
$sums[$currencyId] ??= '0';
|
||||||
$sums[$currencyId] = bcadd($sums[$currencyId], $transactionJournal['amount']);
|
$sums[$currencyId] = bcadd($sums[$currencyId], $amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// format amounts:
|
// format amounts:
|
||||||
@@ -317,7 +324,7 @@ class BasicController extends Controller
|
|||||||
{
|
{
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$date = today(config('app.timezone'))->startOfDay();
|
$date = now(config('app.timezone'));
|
||||||
// start and end in the future? use $end
|
// start and end in the future? use $end
|
||||||
if ($this->notInDateRange($date, $start, $end)) {
|
if ($this->notInDateRange($date, $start, $end)) {
|
||||||
/** @var Carbon $date */
|
/** @var Carbon $date */
|
||||||
@@ -327,9 +334,7 @@ class BasicController extends Controller
|
|||||||
/** @var NetWorthInterface $netWorthHelper */
|
/** @var NetWorthInterface $netWorthHelper */
|
||||||
$netWorthHelper = app(NetWorthInterface::class);
|
$netWorthHelper = app(NetWorthInterface::class);
|
||||||
$netWorthHelper->setUser($user);
|
$netWorthHelper->setUser($user);
|
||||||
$allAccounts = $this->accountRepository->getActiveAccountsByType(
|
$allAccounts = $this->accountRepository->getActiveAccountsByType([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value]);
|
||||||
[AccountType::ASSET, AccountType::DEFAULT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::DEBT]
|
|
||||||
);
|
|
||||||
|
|
||||||
// filter list on preference of being included.
|
// filter list on preference of being included.
|
||||||
$filtered = $allAccounts->filter(
|
$filtered = $allAccounts->filter(
|
||||||
|
@@ -33,7 +33,8 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
|||||||
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface;
|
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
||||||
use FireflyIII\Support\CacheProperties;
|
use FireflyIII\Support\CacheProperties;
|
||||||
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
use FireflyIII\Support\Facades\Amount;
|
||||||
|
use FireflyIII\Support\Facades\Steam;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Contracts\Auth\Authenticatable;
|
use Illuminate\Contracts\Auth\Authenticatable;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@@ -65,87 +66,58 @@ class NetWorth implements NetWorthInterface
|
|||||||
public function byAccounts(Collection $accounts, Carbon $date): array
|
public function byAccounts(Collection $accounts, Carbon $date): array
|
||||||
{
|
{
|
||||||
// start in the past, end in the future? use $date
|
// start in the past, end in the future? use $date
|
||||||
$ids = implode(',', $accounts->pluck('id')->toArray());
|
$convertToNative = app('preferences')->get('convert_to_native', false)->data;
|
||||||
$cache = new CacheProperties();
|
$ids = implode(',', $accounts->pluck('id')->toArray());
|
||||||
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($date);
|
$cache->addProperty($date);
|
||||||
|
$cache->addProperty($convertToNative);
|
||||||
$cache->addProperty('net-worth-by-accounts');
|
$cache->addProperty('net-worth-by-accounts');
|
||||||
$cache->addProperty($ids);
|
$cache->addProperty($ids);
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
return $cache->get();
|
// return $cache->get();
|
||||||
}
|
}
|
||||||
app('log')->debug(sprintf('Now in byAccounts("%s", "%s")', $ids, $date->format('Y-m-d')));
|
Log::debug(sprintf('Now in byAccounts("%s", "%s")', $ids, $date->format('Y-m-d H:i:s')));
|
||||||
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
|
$default = Amount::getDefaultCurrency();
|
||||||
$default = app('amount')->getDefaultCurrency();
|
$netWorth = [];
|
||||||
$converter = new ExchangeRateConverter();
|
$balances = Steam::finalAccountsBalance($accounts, $date);
|
||||||
|
|
||||||
// default "native" currency has everything twice, for consistency.
|
|
||||||
$netWorth = [
|
|
||||||
'native' => [
|
|
||||||
'balance' => '0',
|
|
||||||
'native_balance' => '0',
|
|
||||||
'currency_id' => $default->id,
|
|
||||||
'currency_code' => $default->code,
|
|
||||||
'currency_name' => $default->name,
|
|
||||||
'currency_symbol' => $default->symbol,
|
|
||||||
'currency_decimal_places' => $default->decimal_places,
|
|
||||||
'native_currency_id' => $default->id,
|
|
||||||
'native_currency_code' => $default->code,
|
|
||||||
'native_currency_name' => $default->name,
|
|
||||||
'native_currency_symbol' => $default->symbol,
|
|
||||||
'native_currency_decimal_places' => $default->decimal_places,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
$balances = app('steam')->finalAccountsBalance($accounts, $date);
|
|
||||||
|
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
app('log')->debug(sprintf('Now at account #%d ("%s")', $account->id, $account->name));
|
Log::debug(sprintf('Now at account #%d ("%s")', $account->id, $account->name));
|
||||||
$currency = $this->getRepository()->getAccountCurrency($account);
|
$currency = $this->getRepository()->getAccountCurrency($account) ?? $default;
|
||||||
if (null === $currency) {
|
$useNative = $convertToNative && $default->id !== $currency->id;
|
||||||
$currency = app('amount')->getDefaultCurrency();
|
$currency = $useNative ? $default : $currency;
|
||||||
}
|
$currencyCode = $currency->code;
|
||||||
$currencyCode = $currency->code;
|
$balance = '0';
|
||||||
$balance = '0';
|
$nativeBalance = '0';
|
||||||
$nativeBalance = '0';
|
|
||||||
if (array_key_exists($account->id, $balances)) {
|
if (array_key_exists($account->id, $balances)) {
|
||||||
$balance = $balances[$account->id]['balance'] ?? '0';
|
$balance = $balances[$account->id]['balance'] ?? '0';
|
||||||
$nativeBalance = $balances[$account->id]['native_balance'] ?? '0';
|
$nativeBalance = $balances[$account->id]['native_balance'] ?? '0';
|
||||||
}
|
}
|
||||||
app('log')->debug(sprintf('Balance is %s, native balance is %s', $balance, $nativeBalance));
|
Log::debug(sprintf('Balance is %s, native balance is %s', $balance, $nativeBalance));
|
||||||
// always subtract virtual balance
|
// always subtract virtual balance again.
|
||||||
$virtualBalance = $account->virtual_balance;
|
$balance = '' !== (string) $account->virtual_balance ? bcsub($balance, $account->virtual_balance) : $balance;
|
||||||
if ('' !== $virtualBalance) {
|
$nativeBalance = '' !== (string) $account->native_virtual_balance ? bcsub($nativeBalance, $account->native_virtual_balance) : $nativeBalance;
|
||||||
$balance = bcsub($balance, $virtualBalance);
|
$amountToUse = $useNative ? $nativeBalance : $balance;
|
||||||
$nativeVirtualBalance = $converter->convert($default, $currency, $account->created_at, $virtualBalance);
|
Log::debug(sprintf('Will use %s %s', $currencyCode, $amountToUse));
|
||||||
$nativeBalance = bcsub($nativeBalance, $nativeVirtualBalance);
|
|
||||||
}
|
|
||||||
$netWorth[$currencyCode] ??= [
|
$netWorth[$currencyCode] ??= [
|
||||||
'balance' => '0',
|
'balance' => '0',
|
||||||
'native_balance' => '0',
|
'currency_id' => (string) $currency->id,
|
||||||
'currency_id' => (string) $currency->id,
|
'currency_code' => $currency->code,
|
||||||
'currency_code' => $currency->code,
|
'currency_name' => $currency->name,
|
||||||
'currency_name' => $currency->name,
|
'currency_symbol' => $currency->symbol,
|
||||||
'currency_symbol' => $currency->symbol,
|
'currency_decimal_places' => $currency->decimal_places,
|
||||||
'currency_decimal_places' => $currency->decimal_places,
|
|
||||||
'native_currency_id' => (string) $default->id,
|
|
||||||
'native_currency_code' => $default->code,
|
|
||||||
'native_currency_name' => $default->name,
|
|
||||||
'native_currency_symbol' => $default->symbol,
|
|
||||||
'native_currency_decimal_places' => $default->decimal_places,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$netWorth[$currencyCode]['balance'] = bcadd($balance, $netWorth[$currencyCode]['balance']);
|
$netWorth[$currencyCode]['balance'] = bcadd($amountToUse, $netWorth[$currencyCode]['balance']);
|
||||||
$netWorth[$currencyCode]['native_balance'] = bcadd($nativeBalance, $netWorth[$currencyCode]['native_balance']);
|
|
||||||
$netWorth['native']['balance'] = bcadd($nativeBalance, $netWorth['native']['balance']);
|
|
||||||
$netWorth['native']['native_balance'] = bcadd($nativeBalance, $netWorth['native']['native_balance']);
|
|
||||||
}
|
}
|
||||||
$cache->store($netWorth);
|
$cache->store($netWorth);
|
||||||
$converter->summarize();
|
|
||||||
|
|
||||||
return $netWorth;
|
return $netWorth;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getRepository(): AccountRepositoryInterface|AdminAccountRepositoryInterface
|
private function getRepository(): AccountRepositoryInterface | AdminAccountRepositoryInterface
|
||||||
{
|
{
|
||||||
if (null === $this->userGroup) {
|
if (null === $this->userGroup) {
|
||||||
return $this->accountRepository;
|
return $this->accountRepository;
|
||||||
@@ -154,19 +126,19 @@ class NetWorth implements NetWorthInterface
|
|||||||
return $this->adminAccountRepository;
|
return $this->adminAccountRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUser(null|Authenticatable|User $user): void
|
public function setUser(null | Authenticatable | User $user): void
|
||||||
{
|
{
|
||||||
if (!$user instanceof User) {
|
if (!$user instanceof User) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->user = $user;
|
$this->user = $user;
|
||||||
$this->userGroup = null;
|
$this->userGroup = null;
|
||||||
|
|
||||||
// make repository:
|
// make repository:
|
||||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||||
$this->accountRepository->setUser($this->user);
|
$this->accountRepository->setUser($this->user);
|
||||||
|
|
||||||
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
|
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||||
$this->currencyRepos->setUser($this->user);
|
$this->currencyRepos->setUser($this->user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,18 +159,18 @@ class NetWorth implements NetWorthInterface
|
|||||||
*/
|
*/
|
||||||
$accounts = $this->getAccounts();
|
$accounts = $this->getAccounts();
|
||||||
$return = [];
|
$return = [];
|
||||||
$balances = app('steam')->finalAccountsBalance($accounts, $date);
|
$balances = Steam::finalAccountsBalance($accounts, $date);
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
$currency = $this->getRepository()->getAccountCurrency($account);
|
$currency = $this->getRepository()->getAccountCurrency($account);
|
||||||
$balance = $balances[$account->id]['balance'] ?? '0';
|
$balance = $balances[$account->id]['balance'] ?? '0';
|
||||||
|
|
||||||
// always subtract virtual balance.
|
// always subtract virtual balance.
|
||||||
$virtualBalance = $account->virtual_balance;
|
$virtualBalance = $account->virtual_balance;
|
||||||
if ('' !== $virtualBalance) {
|
if ('' !== $virtualBalance) {
|
||||||
$balance = bcsub($balance, $virtualBalance);
|
$balance = bcsub($balance, $virtualBalance);
|
||||||
}
|
}
|
||||||
|
|
||||||
$return[$currency->id] ??= [
|
$return[$currency->id] ??= [
|
||||||
'id' => (string) $currency->id,
|
'id' => (string) $currency->id,
|
||||||
'name' => $currency->name,
|
'name' => $currency->name,
|
||||||
'symbol' => $currency->symbol,
|
'symbol' => $currency->symbol,
|
||||||
|
@@ -29,13 +29,11 @@ use FireflyIII\Helpers\Report\NetWorthInterface;
|
|||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\AvailableBudget;
|
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
|
|
||||||
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
|
|
||||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
||||||
use FireflyIII\Support\CacheProperties;
|
use FireflyIII\Support\CacheProperties;
|
||||||
|
use FireflyIII\Support\Facades\Amount;
|
||||||
use FireflyIII\Support\Http\Controllers\DateCalculation;
|
use FireflyIII\Support\Http\Controllers\DateCalculation;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
@@ -48,6 +46,7 @@ class BoxController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deprecated method, no longer in use.
|
* Deprecated method, no longer in use.
|
||||||
|
*
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function available(): JsonResponse
|
public function available(): JsonResponse
|
||||||
@@ -73,7 +72,7 @@ class BoxController extends Controller
|
|||||||
$cache->addProperty($convertToNative);
|
$cache->addProperty($convertToNative);
|
||||||
$cache->addProperty('box-balance');
|
$cache->addProperty('box-balance');
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
return response()->json($cache->get());
|
// return response()->json($cache->get());
|
||||||
}
|
}
|
||||||
// prep some arrays:
|
// prep some arrays:
|
||||||
$incomes = [];
|
$incomes = [];
|
||||||
@@ -91,9 +90,8 @@ class BoxController extends Controller
|
|||||||
|
|
||||||
/** @var array $journal */
|
/** @var array $journal */
|
||||||
foreach ($set as $journal) {
|
foreach ($set as $journal) {
|
||||||
$field = $convertToNative && $currency->id !== $journal['currency_id'] ? 'native_amount' : 'amount';
|
|
||||||
$currencyId = $convertToNative ? $currency->id : (int) $journal['currency_id'];
|
$currencyId = $convertToNative ? $currency->id : (int) $journal['currency_id'];
|
||||||
$amount = $journal[$field] ?? '0';
|
$amount = Amount::getAmountFromJournal($journal);
|
||||||
$incomes[$currencyId] ??= '0';
|
$incomes[$currencyId] ??= '0';
|
||||||
$incomes[$currencyId] = bcadd($incomes[$currencyId], app('steam')->positive($amount));
|
$incomes[$currencyId] = bcadd($incomes[$currencyId], app('steam')->positive($amount));
|
||||||
$sums[$currencyId] ??= '0';
|
$sums[$currencyId] ??= '0';
|
||||||
@@ -109,9 +107,8 @@ class BoxController extends Controller
|
|||||||
|
|
||||||
/** @var array $journal */
|
/** @var array $journal */
|
||||||
foreach ($set as $journal) {
|
foreach ($set as $journal) {
|
||||||
$field = $convertToNative && $currency->id !== $journal['currency_id'] ? 'native_amount' : 'amount';
|
|
||||||
$currencyId = $convertToNative ? $currency->id : (int) $journal['currency_id'];
|
$currencyId = $convertToNative ? $currency->id : (int) $journal['currency_id'];
|
||||||
$amount = $journal[$field] ?? '0';
|
$amount = Amount::getAmountFromJournal($journal);
|
||||||
$expenses[$currencyId] ??= '0';
|
$expenses[$currencyId] ??= '0';
|
||||||
$expenses[$currencyId] = bcadd($expenses[$currencyId], $amount);
|
$expenses[$currencyId] = bcadd($expenses[$currencyId], $amount);
|
||||||
$sums[$currencyId] ??= '0';
|
$sums[$currencyId] ??= '0';
|
||||||
|
@@ -61,7 +61,7 @@ class Account extends Model
|
|||||||
'virtual_balance' => 'string',
|
'virtual_balance' => 'string',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $fillable = ['user_id', 'user_group_id', 'account_type_id', 'name', 'active', 'virtual_balance', 'iban'];
|
protected $fillable = ['user_id', 'user_group_id', 'account_type_id', 'name', 'active', 'virtual_balance', 'iban','native_virtual_balance'];
|
||||||
|
|
||||||
protected $hidden = ['encrypted'];
|
protected $hidden = ['encrypted'];
|
||||||
private bool $joinedAccountTypes = false;
|
private bool $joinedAccountTypes = false;
|
||||||
|
@@ -37,6 +37,7 @@ use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
|
|||||||
use FireflyIII\Services\Internal\Destroy\BillDestroyService;
|
use FireflyIII\Services\Internal\Destroy\BillDestroyService;
|
||||||
use FireflyIII\Services\Internal\Update\BillUpdateService;
|
use FireflyIII\Services\Internal\Update\BillUpdateService;
|
||||||
use FireflyIII\Support\CacheProperties;
|
use FireflyIII\Support\CacheProperties;
|
||||||
|
use FireflyIII\Support\Facades\Amount;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Contracts\Auth\Authenticatable;
|
use Illuminate\Contracts\Auth\Authenticatable;
|
||||||
use Illuminate\Database\Query\JoinClause;
|
use Illuminate\Database\Query\JoinClause;
|
||||||
@@ -501,6 +502,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
|
|
||||||
public function sumPaidInRange(Carbon $start, Carbon $end): array
|
public function sumPaidInRange(Carbon $start, Carbon $end): array
|
||||||
{
|
{
|
||||||
|
Log::debug(sprintf('sumPaidInRange from %s to %s', $start->toW3cString(), $end->toW3cString()));
|
||||||
$bills = $this->getActiveBills();
|
$bills = $this->getActiveBills();
|
||||||
$return = [];
|
$return = [];
|
||||||
$convertToNative = app('preferences')->getForUser($this->user, 'convert_to_native', false)->data;
|
$convertToNative = app('preferences')->getForUser($this->user, 'convert_to_native', false)->data;
|
||||||
@@ -508,12 +510,11 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
|
|
||||||
/** @var Bill $bill */
|
/** @var Bill $bill */
|
||||||
foreach ($bills as $bill) {
|
foreach ($bills as $bill) {
|
||||||
|
|
||||||
/** @var Collection $set */
|
/** @var Collection $set */
|
||||||
$set = $bill->transactionJournals()->after($start)->before($end)->get(['transaction_journals.*']);
|
$set = $bill->transactionJournals()->after($start)->before($end)->get(['transaction_journals.*']);
|
||||||
$currency = $convertToNative && $bill->transactionCurrency->id !== $default->id ? $default : $bill->transactionCurrency;
|
$currency = $convertToNative && $bill->transactionCurrency->id !== $default->id ? $default : $bill->transactionCurrency;
|
||||||
$field = $convertToNative && $bill->transactionCurrency->id !== $default->id ? 'native_amount' : 'amount';
|
$return[(int) $currency->id] ??= [
|
||||||
$foreignField = $convertToNative && $bill->transactionCurrency->id !== $default->id ? 'native_foreign_amount' : 'foreign_amount';
|
|
||||||
$return[$currency->id] ??= [
|
|
||||||
'id' => (string) $currency->id,
|
'id' => (string) $currency->id,
|
||||||
'name' => $currency->name,
|
'name' => $currency->name,
|
||||||
'symbol' => $currency->symbol,
|
'symbol' => $currency->symbol,
|
||||||
@@ -521,20 +522,14 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
'decimal_places' => $currency->decimal_places,
|
'decimal_places' => $currency->decimal_places,
|
||||||
'sum' => '0',
|
'sum' => '0',
|
||||||
];
|
];
|
||||||
|
$setAmount = '0';
|
||||||
/** @var TransactionJournal $transactionJournal */
|
/** @var TransactionJournal $transactionJournal */
|
||||||
foreach ($set as $transactionJournal) {
|
foreach ($set as $transactionJournal) {
|
||||||
/** @var null|Transaction $sourceTransaction */
|
$setAmount = bcadd($setAmount, Amount::getAmountFromJournalObject($transactionJournal));
|
||||||
$sourceTransaction = $transactionJournal->transactions()->where('amount', '<', 0)->first();
|
|
||||||
if (null !== $sourceTransaction) {
|
|
||||||
$amount = $sourceTransaction->$field;
|
|
||||||
if ((int) $sourceTransaction->foreign_currency_id === $currency->id) {
|
|
||||||
// use foreign amount instead!
|
|
||||||
$amount = (string) $sourceTransaction->$foreignField;
|
|
||||||
}
|
|
||||||
$return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], $amount);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Log::debug(sprintf('Bill #%d ("%s") with %d transaction(s) and sum %s %s', $bill->id, $bill->name, $set->count(), $currency->code, $setAmount));
|
||||||
|
$return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], $setAmount);
|
||||||
|
Log::debug(sprintf('Total sum is now %s', $return[$currency->id]['sum']));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
@@ -568,6 +563,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
|
|
||||||
$minField = $convertToNative && $bill->transactionCurrency->id !== $default->id ? 'native_amount_min' : 'amount_min';
|
$minField = $convertToNative && $bill->transactionCurrency->id !== $default->id ? 'native_amount_min' : 'amount_min';
|
||||||
$maxField = $convertToNative && $bill->transactionCurrency->id !== $default->id ? 'native_amount_max' : 'amount_max';
|
$maxField = $convertToNative && $bill->transactionCurrency->id !== $default->id ? 'native_amount_max' : 'amount_max';
|
||||||
|
Log::debug(sprintf('min field is %s, max field is %s', $minField, $maxField));
|
||||||
|
|
||||||
if ($total > 0) {
|
if ($total > 0) {
|
||||||
$currency = $convertToNative && $bill->transactionCurrency->id !== $default->id ? $default : $bill->transactionCurrency;
|
$currency = $convertToNative && $bill->transactionCurrency->id !== $default->id ? $default : $bill->transactionCurrency;
|
||||||
|
@@ -31,9 +31,11 @@ use FireflyIII\Models\Budget;
|
|||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use FireflyIII\Support\Facades\Amount;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Contracts\Auth\Authenticatable;
|
use Illuminate\Contracts\Auth\Authenticatable;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class OperationsRepository
|
* Class OperationsRepository
|
||||||
@@ -209,11 +211,12 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
?TransactionCurrency $currency = null
|
?TransactionCurrency $currency = null
|
||||||
): array
|
): array
|
||||||
{
|
{
|
||||||
// this collector excludes all transfers TO
|
// this collector excludes all transfers TO liabilities (which are also withdrawals)
|
||||||
// liabilities (which are also withdrawals)
|
// because those expenses only become expenses once they move from the liability to the friend.
|
||||||
// because those expenses only become expenses
|
|
||||||
// once they move from the liability to the friend.
|
|
||||||
// TODO this filter must be somewhere in AccountRepositoryInterface because I suspect its needed more often (A113)
|
// TODO this filter must be somewhere in AccountRepositoryInterface because I suspect its needed more often (A113)
|
||||||
|
|
||||||
|
// 2024-12-24 disable the exclusion for now.
|
||||||
|
|
||||||
$repository = app(AccountRepositoryInterface::class);
|
$repository = app(AccountRepositoryInterface::class);
|
||||||
$repository->setUser($this->user);
|
$repository->setUser($this->user);
|
||||||
$subset = $repository->getAccountsByType(config('firefly.valid_liabilities'));
|
$subset = $repository->getAccountsByType(config('firefly.valid_liabilities'));
|
||||||
@@ -234,7 +237,7 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setUser($this->user)
|
$collector->setUser($this->user)
|
||||||
->setRange($start, $end)
|
->setRange($start, $end)
|
||||||
->excludeDestinationAccounts($selection)
|
// ->excludeDestinationAccounts($selection)
|
||||||
->setTypes([TransactionType::WITHDRAWAL]);
|
->setTypes([TransactionType::WITHDRAWAL]);
|
||||||
|
|
||||||
if (null !== $accounts) {
|
if (null !== $accounts) {
|
||||||
@@ -249,13 +252,12 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
$collector->setBudgets($budgets);
|
$collector->setBudgets($budgets);
|
||||||
$journals = $collector->getExtractedJournals();
|
$journals = $collector->getExtractedJournals();
|
||||||
|
|
||||||
// same but for foreign currencies:
|
// same but for transactions in the foreign currency:
|
||||||
if (null !== $currency) {
|
if (null !== $currency) {
|
||||||
// app('log')->debug(sprintf('Currency is "%s".', $currency->name));
|
// app('log')->debug(sprintf('Currency is "%s".', $currency->name));
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])
|
$collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setForeignCurrency($currency)->setBudgets($budgets);
|
||||||
->setForeignCurrency($currency)->setBudgets($budgets);
|
|
||||||
|
|
||||||
if (null !== $accounts) {
|
if (null !== $accounts) {
|
||||||
$collector->setAccounts($accounts);
|
$collector->setAccounts($accounts);
|
||||||
@@ -273,9 +275,9 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
$currencySymbol = $journal['currency_symbol'];
|
$currencySymbol = $journal['currency_symbol'];
|
||||||
$currencyCode = $journal['currency_code'];
|
$currencyCode = $journal['currency_code'];
|
||||||
$currencyDecimalPlaces = $journal['currency_decimal_places'];
|
$currencyDecimalPlaces = $journal['currency_decimal_places'];
|
||||||
$field = 'amount';
|
|
||||||
$foreignField = 'foreign_amount';
|
|
||||||
// if the user wants everything in native currency, use it.
|
// if the user wants everything in native currency, use it.
|
||||||
|
// if the foreign amount is in this currency it's OK because Amount::getAmountFromJournal catches that.
|
||||||
if ($convertToNative && $default->id !== (int) $journal['currency_id']) {
|
if ($convertToNative && $default->id !== (int) $journal['currency_id']) {
|
||||||
// use default currency info
|
// use default currency info
|
||||||
$currencyId = $default->id;
|
$currencyId = $default->id;
|
||||||
@@ -283,8 +285,6 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
$currencySymbol = $default->symbol;
|
$currencySymbol = $default->symbol;
|
||||||
$currencyCode = $default->code;
|
$currencyCode = $default->code;
|
||||||
$currencyDecimalPlaces = $default->decimal_places;
|
$currencyDecimalPlaces = $default->decimal_places;
|
||||||
$field = 'native_amount';
|
|
||||||
$foreignField = 'native_foreign_amount';
|
|
||||||
}
|
}
|
||||||
$array[$currencyId] ??= [
|
$array[$currencyId] ??= [
|
||||||
'sum' => '0',
|
'sum' => '0',
|
||||||
@@ -294,21 +294,9 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
'currency_code' => $currencyCode,
|
'currency_code' => $currencyCode,
|
||||||
'currency_decimal_places' => $currencyDecimalPlaces,
|
'currency_decimal_places' => $currencyDecimalPlaces,
|
||||||
];
|
];
|
||||||
$array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->negative($journal[$field]));
|
$amount = Amount::getAmountFromJournal($journal);
|
||||||
|
$array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->negative($amount));
|
||||||
// also do foreign amount:
|
Log::debug(sprintf('Journal #%d adds amount %s %s', $journal['transaction_journal_id'], $currencyCode, $amount));
|
||||||
$foreignId = (int) $journal['foreign_currency_id'];
|
|
||||||
if (0 !== $foreignId && $foreignId !== $currencyId) {
|
|
||||||
$array[$foreignId] ??= [
|
|
||||||
'sum' => '0',
|
|
||||||
'currency_id' => $foreignId,
|
|
||||||
'currency_name' => $journal['foreign_currency_name'],
|
|
||||||
'currency_symbol' => $journal['foreign_currency_symbol'],
|
|
||||||
'currency_code' => $journal['foreign_currency_code'],
|
|
||||||
'currency_decimal_places' => $journal['foreign_currency_decimal_places'],
|
|
||||||
];
|
|
||||||
$array[$foreignId]['sum'] = bcadd($array[$foreignId]['sum'], app('steam')->negative($journal['foreign_amount']));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $array;
|
return $array;
|
||||||
|
@@ -24,7 +24,9 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Support;
|
namespace FireflyIII\Support;
|
||||||
|
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Models\UserGroup;
|
use FireflyIII\Models\UserGroup;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@@ -45,6 +47,46 @@ class Amount
|
|||||||
return $this->formatFlat($format->symbol, $format->decimal_places, $amount, $coloured);
|
return $this->formatFlat($format->symbol, $format->decimal_places, $amount, $coloured);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Experimental function to see if we can quickly and quietly get the amount from a journal.
|
||||||
|
* This depends on the user's default currency and the wish to have it converted.
|
||||||
|
*/
|
||||||
|
public function getAmountFromJournal(array $journal): string
|
||||||
|
{
|
||||||
|
$convertToNative = app('preferences')->get('convert_to_native', false)->data;
|
||||||
|
$currency = app('amount')->getDefaultCurrency();
|
||||||
|
$field = $convertToNative && $currency->id !== $journal['currency_id'] ? 'native_amount' : 'amount';
|
||||||
|
$amount = $journal[$field] ?? '0';
|
||||||
|
// fallback, the transaction has a foreign amount in $currency.
|
||||||
|
if ($convertToNative && null !== $journal['foreign_amount'] && $currency->id === $journal['foreign_currency_id']) {
|
||||||
|
$amount = $journal['foreign_amount'];
|
||||||
|
}
|
||||||
|
return $amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Experimental function to see if we can quickly and quietly get the amount from a journal.
|
||||||
|
* This depends on the user's default currency and the wish to have it converted.
|
||||||
|
*/
|
||||||
|
public function getAmountFromJournalObject(TransactionJournal $journal): string
|
||||||
|
{
|
||||||
|
$convertToNative = app('preferences')->get('convert_to_native', false)->data;
|
||||||
|
$currency = app('amount')->getDefaultCurrency();
|
||||||
|
$field = $convertToNative && $currency->id !== $journal->transaction_currency_id ? 'native_amount' : 'amount';
|
||||||
|
/** @var null|Transaction $sourceTransaction */
|
||||||
|
$sourceTransaction = $journal->transactions()->where('amount', '<', 0)->first();
|
||||||
|
if (null === $sourceTransaction) {
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
$amount = $sourceTransaction->$field;
|
||||||
|
if ((int) $sourceTransaction->foreign_currency_id === $currency->id) {
|
||||||
|
// use foreign amount instead!
|
||||||
|
$amount = (string) $sourceTransaction->foreign_amount; // hard coded to be foreign amount.
|
||||||
|
}
|
||||||
|
return $amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will properly format the given number, in color or "black and white",
|
* This method will properly format the given number, in color or "black and white",
|
||||||
* as a currency, given two things: the currency required and the current locale.
|
* as a currency, given two things: the currency required and the current locale.
|
||||||
@@ -55,15 +97,15 @@ class Amount
|
|||||||
*/
|
*/
|
||||||
public function formatFlat(string $symbol, int $decimalPlaces, string $amount, ?bool $coloured = null): string
|
public function formatFlat(string $symbol, int $decimalPlaces, string $amount, ?bool $coloured = null): string
|
||||||
{
|
{
|
||||||
$locale = app('steam')->getLocale();
|
$locale = app('steam')->getLocale();
|
||||||
$rounded = app('steam')->bcround($amount, $decimalPlaces);
|
$rounded = app('steam')->bcround($amount, $decimalPlaces);
|
||||||
$coloured ??= true;
|
$coloured ??= true;
|
||||||
|
|
||||||
$fmt = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);
|
$fmt = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);
|
||||||
$fmt->setSymbol(\NumberFormatter::CURRENCY_SYMBOL, $symbol);
|
$fmt->setSymbol(\NumberFormatter::CURRENCY_SYMBOL, $symbol);
|
||||||
$fmt->setAttribute(\NumberFormatter::MIN_FRACTION_DIGITS, $decimalPlaces);
|
$fmt->setAttribute(\NumberFormatter::MIN_FRACTION_DIGITS, $decimalPlaces);
|
||||||
$fmt->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, $decimalPlaces);
|
$fmt->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, $decimalPlaces);
|
||||||
$result = (string) $fmt->format((float) $rounded); // intentional float
|
$result = (string) $fmt->format((float) $rounded); // intentional float
|
||||||
|
|
||||||
if (true === $coloured) {
|
if (true === $coloured) {
|
||||||
if (1 === bccomp($rounded, '0')) {
|
if (1 === bccomp($rounded, '0')) {
|
||||||
@@ -109,7 +151,7 @@ class Amount
|
|||||||
|
|
||||||
public function getDefaultCurrencyByUserGroup(UserGroup $userGroup): TransactionCurrency
|
public function getDefaultCurrencyByUserGroup(UserGroup $userGroup): TransactionCurrency
|
||||||
{
|
{
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty('getDefaultCurrencyByGroup');
|
$cache->addProperty('getDefaultCurrencyByGroup');
|
||||||
$cache->addProperty($userGroup->id);
|
$cache->addProperty($userGroup->id);
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
@@ -172,20 +214,20 @@ class Amount
|
|||||||
private function getLocaleInfo(): array
|
private function getLocaleInfo(): array
|
||||||
{
|
{
|
||||||
// get config from preference, not from translation:
|
// get config from preference, not from translation:
|
||||||
$locale = app('steam')->getLocale();
|
$locale = app('steam')->getLocale();
|
||||||
$array = app('steam')->getLocaleArray($locale);
|
$array = app('steam')->getLocaleArray($locale);
|
||||||
|
|
||||||
setlocale(LC_MONETARY, $array);
|
setlocale(LC_MONETARY, $array);
|
||||||
$info = localeconv();
|
$info = localeconv();
|
||||||
|
|
||||||
// correct variables
|
// correct variables
|
||||||
$info['n_cs_precedes'] = $this->getLocaleField($info, 'n_cs_precedes');
|
$info['n_cs_precedes'] = $this->getLocaleField($info, 'n_cs_precedes');
|
||||||
$info['p_cs_precedes'] = $this->getLocaleField($info, 'p_cs_precedes');
|
$info['p_cs_precedes'] = $this->getLocaleField($info, 'p_cs_precedes');
|
||||||
|
|
||||||
$info['n_sep_by_space'] = $this->getLocaleField($info, 'n_sep_by_space');
|
$info['n_sep_by_space'] = $this->getLocaleField($info, 'n_sep_by_space');
|
||||||
$info['p_sep_by_space'] = $this->getLocaleField($info, 'p_sep_by_space');
|
$info['p_sep_by_space'] = $this->getLocaleField($info, 'p_sep_by_space');
|
||||||
|
|
||||||
$fmt = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);
|
$fmt = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);
|
||||||
|
|
||||||
$info['mon_decimal_point'] = $fmt->getSymbol(\NumberFormatter::MONETARY_SEPARATOR_SYMBOL);
|
$info['mon_decimal_point'] = $fmt->getSymbol(\NumberFormatter::MONETARY_SEPARATOR_SYMBOL);
|
||||||
$info['mon_thousands_sep'] = $fmt->getSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL);
|
$info['mon_thousands_sep'] = $fmt->getSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL);
|
||||||
@@ -208,7 +250,7 @@ class Amount
|
|||||||
public static function getAmountJsConfig(bool $sepBySpace, int $signPosn, string $sign, bool $csPrecedes): string
|
public static function getAmountJsConfig(bool $sepBySpace, int $signPosn, string $sign, bool $csPrecedes): string
|
||||||
{
|
{
|
||||||
// negative first:
|
// negative first:
|
||||||
$space = ' ';
|
$space = ' ';
|
||||||
|
|
||||||
// require space between symbol and amount?
|
// require space between symbol and amount?
|
||||||
if (false === $sepBySpace) {
|
if (false === $sepBySpace) {
|
||||||
@@ -217,11 +259,11 @@ class Amount
|
|||||||
|
|
||||||
// there are five possible positions for the "+" or "-" sign (if it is even used)
|
// there are five possible positions for the "+" or "-" sign (if it is even used)
|
||||||
// pos_a and pos_e could be the ( and ) symbol.
|
// pos_a and pos_e could be the ( and ) symbol.
|
||||||
$posA = ''; // before everything
|
$posA = ''; // before everything
|
||||||
$posB = ''; // before currency symbol
|
$posB = ''; // before currency symbol
|
||||||
$posC = ''; // after currency symbol
|
$posC = ''; // after currency symbol
|
||||||
$posD = ''; // before amount
|
$posD = ''; // before amount
|
||||||
$posE = ''; // after everything
|
$posE = ''; // after everything
|
||||||
|
|
||||||
// format would be (currency before amount)
|
// format would be (currency before amount)
|
||||||
// AB%sC_D%vE
|
// AB%sC_D%vE
|
||||||
@@ -263,11 +305,11 @@ class Amount
|
|||||||
}
|
}
|
||||||
|
|
||||||
// default is amount before currency
|
// default is amount before currency
|
||||||
$format = $posA.$posD.'%v'.$space.$posB.'%s'.$posC.$posE;
|
$format = $posA . $posD . '%v' . $space . $posB . '%s' . $posC . $posE;
|
||||||
|
|
||||||
if ($csPrecedes) {
|
if ($csPrecedes) {
|
||||||
// alternative is currency before amount
|
// alternative is currency before amount
|
||||||
$format = $posA.$posB.'%s'.$posC.$space.$posD.'%v'.$posE;
|
$format = $posA . $posB . '%s' . $posC . $space . $posD . '%v' . $posE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $format;
|
return $format;
|
||||||
|
@@ -289,7 +289,7 @@ class Steam
|
|||||||
;
|
;
|
||||||
$return['native_balance'] = $this->sumTransactions($array, 'native_amount');
|
$return['native_balance'] = $this->sumTransactions($array, 'native_amount');
|
||||||
// Log::debug(sprintf('native_balance is %s', $return['native_balance']));
|
// Log::debug(sprintf('native_balance is %s', $return['native_balance']));
|
||||||
$return['native_balance'] = bcadd('' === (string) $account->native_virtual_balance ? '0' : $account->native_virtual_balance, $return['balance']);
|
$return['native_balance'] = bcadd('' === (string) $account->native_virtual_balance ? '0' : $account->native_virtual_balance, $return['native_balance']);
|
||||||
// Log::debug(sprintf('native_balance is %s (with virtual balance)', $return['native_balance']));
|
// Log::debug(sprintf('native_balance is %s (with virtual balance)', $return['native_balance']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,6 +26,7 @@ $(function () {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function drawChart() {
|
function drawChart() {
|
||||||
"use strict";
|
"use strict";
|
||||||
lineChart(accountFrontpageUrl, 'accounts-chart');
|
lineChart(accountFrontpageUrl, 'accounts-chart');
|
||||||
@@ -37,13 +38,77 @@ function drawChart() {
|
|||||||
columnChart('chart/category/frontpage', 'categories-chart');
|
columnChart('chart/category/frontpage', 'categories-chart');
|
||||||
columnChart(accountExpenseUrl, 'expense-accounts-chart');
|
columnChart(accountExpenseUrl, 'expense-accounts-chart');
|
||||||
columnChart(accountRevenueUrl, 'revenue-accounts-chart');
|
columnChart(accountRevenueUrl, 'revenue-accounts-chart');
|
||||||
|
|
||||||
// get balance box:
|
|
||||||
getBalanceBox();
|
|
||||||
getBillsBox();
|
|
||||||
getAvailableBox();
|
|
||||||
getNetWorthBox();
|
|
||||||
getPiggyBanks();
|
getPiggyBanks();
|
||||||
|
getAllBoxes();
|
||||||
|
|
||||||
|
function getAllBoxes() {
|
||||||
|
// get summary.
|
||||||
|
$.getJSON('api/v1/summary/basic?start=' + sessionStart + '&end=' + sessionEnd).done(function (data) {
|
||||||
|
var key;
|
||||||
|
|
||||||
|
// balance.
|
||||||
|
var balance_top = [];
|
||||||
|
var balance_bottom = [];
|
||||||
|
|
||||||
|
// bills
|
||||||
|
var unpaid = [];
|
||||||
|
var paid = [];
|
||||||
|
|
||||||
|
// left to spend.
|
||||||
|
var left_to_spend_top = [];
|
||||||
|
var left_to_spend_bottom = [];
|
||||||
|
|
||||||
|
// net worth
|
||||||
|
var net_worth = [];
|
||||||
|
|
||||||
|
|
||||||
|
for (key in data) {
|
||||||
|
// balance
|
||||||
|
if (key.substring(0, 11) === 'balance-in-') {
|
||||||
|
balance_top.push(data[key].value_parsed);
|
||||||
|
balance_bottom.push(data[key].sub_title);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bills
|
||||||
|
if (key.substring(0, 16) === 'bills-unpaid-in-') {
|
||||||
|
unpaid.push(data[key].value_parsed);
|
||||||
|
}
|
||||||
|
if (key.substring(0, 14) === 'bills-paid-in-') {
|
||||||
|
paid.push(data[key].value_parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// left to spend
|
||||||
|
if (key.substring(0, 17) === 'left-to-spend-in-') {
|
||||||
|
left_to_spend_top.push(data[key].value_parsed);
|
||||||
|
left_to_spend_bottom.push(data[key].sub_title);
|
||||||
|
if(parseFloat(data[key].monetary_value) < 0) {
|
||||||
|
$('#box-left-to-spend-box').removeClass('bg-green-gradient').addClass('bg-red-gradient');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// net worth
|
||||||
|
if (key.substring(0, 13) === 'net-worth-in-') {
|
||||||
|
net_worth.push(data[key].value_parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// balance
|
||||||
|
$('#box-balance-sums').html(balance_top.join(', '));
|
||||||
|
$('#box-balance-list').html(balance_bottom.join(', '));
|
||||||
|
|
||||||
|
// bills
|
||||||
|
$('#box-bills-unpaid').html(unpaid.join(', '));
|
||||||
|
$('#box-bills-paid').html(paid.join(', '));
|
||||||
|
|
||||||
|
// left to spend
|
||||||
|
$('#box-left-to-spend').html(left_to_spend_top.join(', '));
|
||||||
|
$('#box-left-per-day').html(left_to_spend_bottom.join(', '));
|
||||||
|
|
||||||
|
// net worth
|
||||||
|
$('#box-net-worth').html(net_worth.join(', '));
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//getBoxAmounts();
|
//getBoxAmounts();
|
||||||
}
|
}
|
||||||
@@ -58,121 +123,3 @@ function getPiggyBanks() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNetWorthBox() {
|
|
||||||
// box-net-worth
|
|
||||||
$.getJSON('json/box/net-worth').done(function (data) {
|
|
||||||
$('#box-net-worth').html(data.net_worths.join(', '));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function getAvailableBox() {
|
|
||||||
// box-left-to-spend
|
|
||||||
// box-left-per-day
|
|
||||||
// * 0) If the user has available amount this period and has overspent: overspent box.
|
|
||||||
// * 1) If the user has available amount this period and has NOT overspent: left to spend box.
|
|
||||||
// * 2) if the user has no available amount set this period: spent per day
|
|
||||||
$.getJSON('json/box/available').done(function (data) {
|
|
||||||
$('#box-left-to-spend-text').text(data.title);
|
|
||||||
if (0 === data.display) {
|
|
||||||
$('#box-left-to-spend-box').removeClass('bg-green-gradient').addClass('bg-red-gradient');
|
|
||||||
$('#box-left-to-spend').html(data.left_to_spend);
|
|
||||||
$('#box-left-per-day').html(data.left_per_day);
|
|
||||||
}
|
|
||||||
if (1 === data.display) {
|
|
||||||
$('#box-left-to-spend').html(data.left_to_spend);
|
|
||||||
$('#box-left-per-day').html(data.left_per_day);
|
|
||||||
}
|
|
||||||
if (2 === data.display) {
|
|
||||||
$('#box-left-to-spend').html(data.spent_total);
|
|
||||||
$('#box-left-per-day').html(data.spent_per_day);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function getBillsBox() {
|
|
||||||
// box-bills-unpaid
|
|
||||||
// box-bills-paid
|
|
||||||
|
|
||||||
// get summary.
|
|
||||||
|
|
||||||
$.getJSON('api/v1/summary/basic?start=' + sessionStart + '&end=' + sessionEnd).done(function (data) {
|
|
||||||
var key;
|
|
||||||
var unpaid = [];
|
|
||||||
var paid = [];
|
|
||||||
for (key in data) {
|
|
||||||
//console.log(key);
|
|
||||||
if (key.substr(0, 16) === 'bills-unpaid-in-') {
|
|
||||||
// only when less than 3.
|
|
||||||
if (unpaid.length < 3) {
|
|
||||||
unpaid.push(data[key].value_parsed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (key.substr(0, 14) === 'bills-paid-in-') {
|
|
||||||
// only when less than 5.
|
|
||||||
if (paid.length < 3) {
|
|
||||||
paid.push(data[key].value_parsed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$('#box-bills-unpaid').html(unpaid.join(', '));
|
|
||||||
$('#box-bills-paid').html(paid.join(', '));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function getBalanceBox() {
|
|
||||||
// box-balance-sums
|
|
||||||
// box-balance-list
|
|
||||||
$.getJSON('json/box/balance').done(function (data) {
|
|
||||||
if (data.size === 1) {
|
|
||||||
// show balance in "sums", show single entry in list.
|
|
||||||
for (var x in data.sums) {
|
|
||||||
$('#box-balance-sums').html(data.sums[x]);
|
|
||||||
$('#box-balance-list').html(data.incomes[x] + ' + ' + data.expenses[x]);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// do not use "sums", only use list.
|
|
||||||
$('#box-balance-progress').remove();
|
|
||||||
var expense, string, sum, income, current;
|
|
||||||
|
|
||||||
// first loop, echo only "preferred".
|
|
||||||
for (x in data.sums) {
|
|
||||||
current = $('#box-balance-list').html();
|
|
||||||
sum = data.sums[x];
|
|
||||||
expense = data.expenses[x];
|
|
||||||
income = data.incomes[x];
|
|
||||||
string = income + ' + ' + expense + ': ' + sum;
|
|
||||||
if (data.preferred == x) {
|
|
||||||
$('#box-balance-list').html(current + '<span title="' + string + '">' + string + '</span>' + '<br>');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// then list the others (only 1 space)
|
|
||||||
|
|
||||||
var count = 0;
|
|
||||||
for (x in data.sums) {
|
|
||||||
if (count > 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
current = $('#box-balance-list').html();
|
|
||||||
sum = data.sums[x];
|
|
||||||
expense = data.expenses[x];
|
|
||||||
income = data.incomes[x];
|
|
||||||
string = income + ' + ' + expense + ': ' + sum;
|
|
||||||
if (data.preferred != x) {
|
|
||||||
$('#box-balance-list').html(current + '<span title="' + string + '">' + string + '</span>' + '<br>');
|
|
||||||
}
|
|
||||||
count++;
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
Reference in New Issue
Block a user