mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-30 02:26:58 +00:00
Frontpage seems to be multi currency aware.
This commit is contained in:
@@ -322,6 +322,7 @@ class BasicController extends Controller
|
|||||||
|
|
||||||
private function getNetWorthInfo(Carbon $start, Carbon $end): array
|
private function getNetWorthInfo(Carbon $start, Carbon $end): array
|
||||||
{
|
{
|
||||||
|
Log::debug('getNetWorthInfo');
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$date = now(config('app.timezone'));
|
$date = now(config('app.timezone'));
|
||||||
@@ -369,6 +370,7 @@ class BasicController extends Controller
|
|||||||
'sub_title' => '',
|
'sub_title' => '',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
Log::debug('End of getNetWorthInfo');
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
@@ -108,6 +108,7 @@ class RecalculateNativeAmounts extends Command
|
|||||||
private function recalculatePiggyBanks(UserGroup $userGroup, TransactionCurrency $currency): void
|
private function recalculatePiggyBanks(UserGroup $userGroup, TransactionCurrency $currency): void
|
||||||
{
|
{
|
||||||
$converter = new ExchangeRateConverter();
|
$converter = new ExchangeRateConverter();
|
||||||
|
$converter->setUserGroup($userGroup);
|
||||||
$converter->setIgnoreSettings(true);
|
$converter->setIgnoreSettings(true);
|
||||||
$repository = app(PiggyBankRepositoryInterface::class);
|
$repository = app(PiggyBankRepositoryInterface::class);
|
||||||
$repository->setUserGroup($userGroup);
|
$repository->setUserGroup($userGroup);
|
||||||
|
@@ -48,6 +48,7 @@ class AvailableBudgetObserver
|
|||||||
$availableBudget->native_amount = null;
|
$availableBudget->native_amount = null;
|
||||||
if ($availableBudget->transactionCurrency->id !== $userCurrency->id) {
|
if ($availableBudget->transactionCurrency->id !== $userCurrency->id) {
|
||||||
$converter = new ExchangeRateConverter();
|
$converter = new ExchangeRateConverter();
|
||||||
|
$converter->setUserGroup($availableBudget->user->userGroup);
|
||||||
$converter->setIgnoreSettings(true);
|
$converter->setIgnoreSettings(true);
|
||||||
$availableBudget->native_amount = $converter->convert($availableBudget->transactionCurrency, $userCurrency, today(), $availableBudget->amount);
|
$availableBudget->native_amount = $converter->convert($availableBudget->transactionCurrency, $userCurrency, today(), $availableBudget->amount);
|
||||||
}
|
}
|
||||||
|
@@ -73,12 +73,14 @@ class TransactionObserver
|
|||||||
// first normal amount
|
// first normal amount
|
||||||
if ($transaction->transactionCurrency->id !== $userCurrency->id && (null === $transaction->foreign_currency_id || (null !== $transaction->foreign_currency_id && $transaction->foreign_currency_id !== $userCurrency->id))) {
|
if ($transaction->transactionCurrency->id !== $userCurrency->id && (null === $transaction->foreign_currency_id || (null !== $transaction->foreign_currency_id && $transaction->foreign_currency_id !== $userCurrency->id))) {
|
||||||
$converter = new ExchangeRateConverter();
|
$converter = new ExchangeRateConverter();
|
||||||
|
$converter->setUserGroup($transaction->transactionJournal->user->userGroup);
|
||||||
$converter->setIgnoreSettings(true);
|
$converter->setIgnoreSettings(true);
|
||||||
$transaction->native_amount = $converter->convert($transaction->transactionCurrency, $userCurrency, $transaction->transactionJournal->date, $transaction->amount);
|
$transaction->native_amount = $converter->convert($transaction->transactionCurrency, $userCurrency, $transaction->transactionJournal->date, $transaction->amount);
|
||||||
}
|
}
|
||||||
// then foreign amount
|
// then foreign amount
|
||||||
if ($transaction->foreignCurrency?->id !== $userCurrency->id && null !== $transaction->foreign_amount && null !== $transaction->foreignCurrency) {
|
if ($transaction->foreignCurrency?->id !== $userCurrency->id && null !== $transaction->foreign_amount && null !== $transaction->foreignCurrency) {
|
||||||
$converter = new ExchangeRateConverter();
|
$converter = new ExchangeRateConverter();
|
||||||
|
$converter->setUserGroup($transaction->transactionJournal->user->userGroup);
|
||||||
$converter->setIgnoreSettings(true);
|
$converter->setIgnoreSettings(true);
|
||||||
$transaction->native_foreign_amount = $converter->convert($transaction->foreignCurrency, $userCurrency, $transaction->transactionJournal->date, $transaction->foreign_amount);
|
$transaction->native_foreign_amount = $converter->convert($transaction->foreignCurrency, $userCurrency, $transaction->transactionJournal->date, $transaction->foreign_amount);
|
||||||
}
|
}
|
||||||
|
@@ -874,6 +874,16 @@ class GroupCollector implements GroupCollectorInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limit results to a specific currency, only normal one.
|
||||||
|
*/
|
||||||
|
public function setNormalCurrency(TransactionCurrency $currency): GroupCollectorInterface
|
||||||
|
{
|
||||||
|
$this->query->where('source.transaction_currency_id', $currency->id);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function setEndRow(int $endRow): self
|
public function setEndRow(int $endRow): self
|
||||||
{
|
{
|
||||||
$this->endRow = $endRow;
|
$this->endRow = $endRow;
|
||||||
|
@@ -457,6 +457,11 @@ interface GroupCollectorInterface
|
|||||||
*/
|
*/
|
||||||
public function setCurrency(TransactionCurrency $currency): self;
|
public function setCurrency(TransactionCurrency $currency): self;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limit results to a specific currency, either foreign or normal one.
|
||||||
|
*/
|
||||||
|
public function setNormalCurrency(TransactionCurrency $currency): self;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set destination accounts.
|
* Set destination accounts.
|
||||||
*/
|
*/
|
||||||
|
@@ -83,6 +83,7 @@ class AccountController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function expenseAccounts(): JsonResponse
|
public function expenseAccounts(): JsonResponse
|
||||||
{
|
{
|
||||||
|
Log::debug('RevenueAccounts');
|
||||||
/** @var Carbon $start */
|
/** @var Carbon $start */
|
||||||
$start = clone session('start', today(config('app.timezone'))->startOfMonth());
|
$start = clone session('start', today(config('app.timezone'))->startOfMonth());
|
||||||
|
|
||||||
@@ -95,7 +96,7 @@ class AccountController extends Controller
|
|||||||
$cache->addProperty($convertToNative);
|
$cache->addProperty($convertToNative);
|
||||||
$cache->addProperty('chart.account.expense-accounts');
|
$cache->addProperty('chart.account.expense-accounts');
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
// return response()->json($cache->get());
|
// return response()->json($cache->get());
|
||||||
}
|
}
|
||||||
$start->subDay();
|
$start->subDay();
|
||||||
|
|
||||||
@@ -113,7 +114,6 @@ class AccountController extends Controller
|
|||||||
$startBalances = app('steam')->finalAccountsBalance($accounts, $start);
|
$startBalances = app('steam')->finalAccountsBalance($accounts, $start);
|
||||||
$endBalances = app('steam')->finalAccountsBalance($accounts, $end);
|
$endBalances = app('steam')->finalAccountsBalance($accounts, $end);
|
||||||
|
|
||||||
// loop the end balances. This is an array for each account ($expenses)
|
|
||||||
// loop the accounts, then check for balance and currency info.
|
// loop the accounts, then check for balance and currency info.
|
||||||
foreach($accounts as $account) {
|
foreach($accounts as $account) {
|
||||||
Log::debug(sprintf('Now in account #%d ("%s")', $account->id, $account->name));
|
Log::debug(sprintf('Now in account #%d ("%s")', $account->id, $account->name));
|
||||||
@@ -518,11 +518,13 @@ class AccountController extends Controller
|
|||||||
/** @var Carbon $end */
|
/** @var Carbon $end */
|
||||||
$end = clone session('end', today(config('app.timezone'))->endOfMonth());
|
$end = clone session('end', today(config('app.timezone'))->endOfMonth());
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
|
$convertToNative = app('preferences')->get('convert_to_native', false)->data;
|
||||||
$cache->addProperty($start);
|
$cache->addProperty($start);
|
||||||
$cache->addProperty($end);
|
$cache->addProperty($end);
|
||||||
|
$cache->addProperty($convertToNative);
|
||||||
$cache->addProperty('chart.account.revenue-accounts');
|
$cache->addProperty('chart.account.revenue-accounts');
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
return response()->json($cache->get());
|
// return response()->json($cache->get());
|
||||||
}
|
}
|
||||||
$start->subDay();
|
$start->subDay();
|
||||||
|
|
||||||
@@ -530,9 +532,10 @@ class AccountController extends Controller
|
|||||||
$currencies = [];
|
$currencies = [];
|
||||||
$chartData = [];
|
$chartData = [];
|
||||||
$tempData = [];
|
$tempData = [];
|
||||||
|
$default = Amount::getDefaultCurrency();
|
||||||
|
|
||||||
// grab all accounts and names
|
// grab all accounts and names
|
||||||
$accounts = $this->accountRepository->getAccountsByType([AccountType::REVENUE]);
|
$accounts = $this->accountRepository->getAccountsByType([AccountTypeEnum::REVENUE->value]);
|
||||||
$accountNames = $this->extractNames($accounts);
|
$accountNames = $this->extractNames($accounts);
|
||||||
|
|
||||||
// grab all balances
|
// grab all balances
|
||||||
@@ -540,33 +543,49 @@ class AccountController extends Controller
|
|||||||
$endBalances = app('steam')->finalAccountsBalance($accounts, $end);
|
$endBalances = app('steam')->finalAccountsBalance($accounts, $end);
|
||||||
|
|
||||||
|
|
||||||
|
// loop the accounts, then check for balance and currency info.
|
||||||
// loop the end balances. This is an array for each account ($expenses)
|
foreach($accounts as $account) {
|
||||||
foreach ($endBalances as $accountId => $expenses) {
|
Log::debug(sprintf('Now in account #%d ("%s")', $account->id, $account->name));
|
||||||
$accountId = (int) $accountId;
|
$expenses = $endBalances[$account->id] ?? false;
|
||||||
// loop each expense entry (each entry can be a different currency).
|
if(false === $expenses) {
|
||||||
foreach ($expenses as $currencyCode => $endAmount) {
|
Log::error(sprintf('Found no end balance for account #%d',$account->id));
|
||||||
if (3 !== strlen($currencyCode)) {
|
continue;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @var string $key
|
||||||
|
* @var string $endBalance
|
||||||
|
*/
|
||||||
|
foreach ($expenses as $key => $endBalance) {
|
||||||
|
if(!$convertToNative && 'native_balance' === $key) {
|
||||||
|
Log::debug(sprintf('[a] Will skip expense array "%s"', $key));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if($convertToNative && 'native_balance' !== $key) {
|
||||||
|
Log::debug(sprintf('[b] Will skip expense array "%s"', $key));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance));
|
||||||
|
$searchCode = $convertToNative ? $default->code: $key;
|
||||||
|
Log::debug(sprintf('Search code is %s', $searchCode));
|
||||||
// see if there is an accompanying start amount.
|
// see if there is an accompanying start amount.
|
||||||
// grab the difference and find the currency.
|
// grab the difference and find the currency.
|
||||||
$startAmount = (string) ($startBalances[$accountId][$currencyCode] ?? '0');
|
$startBalance = ($startBalances[$account->id][$key] ?? '0');
|
||||||
$diff = bcsub((string) $endAmount, $startAmount);
|
Log::debug(sprintf('Start balance is %s', $startBalance));
|
||||||
$currencies[$currencyCode] ??= $this->currencyRepository->findByCode($currencyCode);
|
$diff = bcsub($endBalance, $startBalance);
|
||||||
|
$currencies[$searchCode] ??= $this->currencyRepository->findByCode($searchCode);
|
||||||
if (0 !== bccomp($diff, '0')) {
|
if (0 !== bccomp($diff, '0')) {
|
||||||
// store the values in a temporary array.
|
// store the values in a temporary array.
|
||||||
$tempData[] = [
|
$tempData[] = [
|
||||||
'name' => $accountNames[$accountId],
|
'name' => $accountNames[$account->id],
|
||||||
'difference' => $diff,
|
'difference' => $diff,
|
||||||
'diff_float' => (float) $diff, // intentional float
|
'diff_float' => (float) $diff, // intentional float
|
||||||
'currency_id' => $currencies[$currencyCode]->id,
|
'currency_id' => $currencies[$searchCode]->id,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// recreate currencies, but on ID instead of code.
|
// recreate currencies, but on ID instead of code.
|
||||||
$newCurrencies = [];
|
$newCurrencies = [];
|
||||||
foreach ($currencies as $currency) {
|
foreach ($currencies as $currency) {
|
||||||
|
@@ -563,11 +563,12 @@ 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));
|
//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;
|
||||||
$average = bcdiv(bcadd($bill->$maxField, $bill->$minField), '2');
|
$average = bcdiv(bcadd($bill->$maxField, $bill->$minField), '2');
|
||||||
|
Log::debug(sprintf('Amount to pay is %s %s (%d times)', $currency->code, $average, $total));
|
||||||
$return[$currency->id] ??= [
|
$return[$currency->id] ??= [
|
||||||
'id' => (string) $currency->id,
|
'id' => (string) $currency->id,
|
||||||
'name' => $currency->name,
|
'name' => $currency->name,
|
||||||
|
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Repositories\Budget;
|
namespace FireflyIII\Repositories\Budget;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Enums\TransactionTypeEnum;
|
||||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
@@ -239,7 +240,7 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
$collector->setUser($this->user)
|
$collector->setUser($this->user)
|
||||||
->setRange($start, $end)
|
->setRange($start, $end)
|
||||||
// ->excludeDestinationAccounts($selection)
|
// ->excludeDestinationAccounts($selection)
|
||||||
->setTypes([TransactionType::WITHDRAWAL]);
|
->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
|
||||||
|
|
||||||
if (null !== $accounts) {
|
if (null !== $accounts) {
|
||||||
$collector->setAccounts($accounts);
|
$collector->setAccounts($accounts);
|
||||||
@@ -249,26 +250,29 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
}
|
}
|
||||||
if (null !== $currency) {
|
if (null !== $currency) {
|
||||||
Log::debug(sprintf('Limit to currency %s', $currency->code));
|
Log::debug(sprintf('Limit to currency %s', $currency->code));
|
||||||
$collector->setCurrency($currency);
|
$collector->setNormalCurrency($currency);
|
||||||
}
|
}
|
||||||
$collector->setBudgets($budgets);
|
$collector->setBudgets($budgets);
|
||||||
$journals = $collector->getExtractedJournals();
|
$journals = $collector->getExtractedJournals();
|
||||||
|
|
||||||
// same but for transactions in the foreign currency:
|
// same but for transactions in the foreign currency:
|
||||||
if (null !== $currency) {
|
if (null !== $currency) {
|
||||||
// app('log')->debug(sprintf('Currency is "%s".', $currency->name));
|
Log::debug('STOP looking for transactions in the foreign currency.');
|
||||||
/** @var GroupCollectorInterface $collector */
|
|
||||||
$collector = app(GroupCollectorInterface::class);
|
|
||||||
$collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setForeignCurrency($currency)->setBudgets($budgets);
|
|
||||||
|
|
||||||
if (null !== $accounts) {
|
// Log::debug(sprintf('Look for transactions with foreign currency %s', $currency->code));
|
||||||
$collector->setAccounts($accounts);
|
// // app('log')->debug(sprintf('Currency is "%s".', $currency->name));
|
||||||
}
|
// /** @var GroupCollectorInterface $collector */
|
||||||
$result = $collector->getExtractedJournals();
|
// $collector = app(GroupCollectorInterface::class);
|
||||||
// app('log')->debug(sprintf('Found %d journals with currency %s.', count($result), $currency->code));
|
// $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->setForeignCurrency($currency)->setBudgets($budgets);
|
||||||
// do not use array_merge because you want keys to overwrite (otherwise you get double results):
|
//
|
||||||
Log::debug(sprintf('Found %d extra journals in foreign currency.', count($result)));
|
// if (null !== $accounts) {
|
||||||
$journals = $result + $journals;
|
// $collector->setAccounts($accounts);
|
||||||
|
// }
|
||||||
|
// $result = $collector->getExtractedJournals();
|
||||||
|
// // app('log')->debug(sprintf('Found %d journals with currency %s.', count($result), $currency->code));
|
||||||
|
// // do not use array_merge because you want keys to overwrite (otherwise you get double results):
|
||||||
|
// Log::debug(sprintf('Found %d extra journals in foreign currency.', count($result)));
|
||||||
|
// $journals = $result + $journals;
|
||||||
}
|
}
|
||||||
$array = [];
|
$array = [];
|
||||||
|
|
||||||
@@ -289,6 +293,7 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
$useNative = $default->id !== (int) $journal['currency_id'];
|
$useNative = $default->id !== (int) $journal['currency_id'];
|
||||||
$amount = Amount::getAmountFromJournal($journal);
|
$amount = Amount::getAmountFromJournal($journal);
|
||||||
if($useNative) {
|
if($useNative) {
|
||||||
|
Log::debug(sprintf('Journal #%d switches to native amount (original is %s)', $journal['transaction_journal_id'], $journal['currency_code']));
|
||||||
$currencyId = $default->id;
|
$currencyId = $default->id;
|
||||||
$currencyName = $default->name;
|
$currencyName = $default->name;
|
||||||
$currencySymbol = $default->symbol;
|
$currencySymbol = $default->symbol;
|
||||||
@@ -301,6 +306,7 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
// if the amount is not in $currency (but should be), use the foreign_amount if that one is correct.
|
// if the amount is not in $currency (but should be), use the foreign_amount if that one is correct.
|
||||||
// otherwise, ignore the transaction all together.
|
// otherwise, ignore the transaction all together.
|
||||||
if (null !== $currency && $currencyId !== $currency->id && $currency->id === (int) $journal['foreign_currency_id']) {
|
if (null !== $currency && $currencyId !== $currency->id && $currency->id === (int) $journal['foreign_currency_id']) {
|
||||||
|
Log::debug(sprintf('Journal #%d switches to foreign amount because it matches native.', $journal['transaction_journal_id']));
|
||||||
$amount = $journal['foreign_amount'];
|
$amount = $journal['foreign_amount'];
|
||||||
$currencyId = (int) $journal['foreign_currency_id'];
|
$currencyId = (int) $journal['foreign_currency_id'];
|
||||||
$currencyName = $journal['foreign_currency_name'];
|
$currencyName = $journal['foreign_currency_name'];
|
||||||
|
@@ -150,8 +150,7 @@ class FrontpageChartGenerator
|
|||||||
$useNative = $this->convertToNative && $this->default->id !== $limit->transaction_currency_id;
|
$useNative = $this->convertToNative && $this->default->id !== $limit->transaction_currency_id;
|
||||||
$currency = $limit->transactionCurrency;
|
$currency = $limit->transactionCurrency;
|
||||||
if ($useNative) {
|
if ($useNative) {
|
||||||
Log::debug(sprintf('Processing limit #%d with %s %s', $limit->id, $this->default->code, $limit->native_amount));
|
Log::debug(sprintf('Processing limit #%d with (native) %s %s', $limit->id, $this->default->code, $limit->native_amount));
|
||||||
$currency = null;
|
|
||||||
}
|
}
|
||||||
if (!$useNative) {
|
if (!$useNative) {
|
||||||
Log::debug(sprintf('Processing limit #%d with %s %s', $limit->id, $limit->transactionCurrency->code, $limit->amount));
|
Log::debug(sprintf('Processing limit #%d with %s %s', $limit->id, $limit->transactionCurrency->code, $limit->amount));
|
||||||
@@ -167,6 +166,9 @@ class FrontpageChartGenerator
|
|||||||
Log::debug(sprintf('Process spent row (%s)', $entry['currency_code']));
|
Log::debug(sprintf('Process spent row (%s)', $entry['currency_code']));
|
||||||
$data = $this->processRow($data, $budget, $limit, $entry);
|
$data = $this->processRow($data, $budget, $limit, $entry);
|
||||||
}
|
}
|
||||||
|
if (!($entry['currency_id'] === $limit->transaction_currency_id || $useNative)) {
|
||||||
|
Log::debug(sprintf('Skipping spent row (%s).', $entry['currency_code']));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
@@ -181,6 +183,7 @@ class FrontpageChartGenerator
|
|||||||
private function processRow(array $data, Budget $budget, BudgetLimit $limit, array $entry): array
|
private function processRow(array $data, Budget $budget, BudgetLimit $limit, array $entry): array
|
||||||
{
|
{
|
||||||
$title = sprintf('%s (%s)', $budget->name, $entry['currency_name']);
|
$title = sprintf('%s (%s)', $budget->name, $entry['currency_name']);
|
||||||
|
Log::debug(sprintf('Title is "%s"', $title));
|
||||||
if ($limit->start_date->startOfDay()->ne($this->start->startOfDay()) || $limit->end_date->startOfDay()->ne($this->end->startOfDay())) {
|
if ($limit->start_date->startOfDay()->ne($this->start->startOfDay()) || $limit->end_date->startOfDay()->ne($this->end->startOfDay())) {
|
||||||
$title = sprintf(
|
$title = sprintf(
|
||||||
'%s (%s) (%s - %s)',
|
'%s (%s) (%s - %s)',
|
||||||
@@ -190,15 +193,26 @@ class FrontpageChartGenerator
|
|||||||
$limit->end_date->isoFormat($this->monthAndDayFormat)
|
$limit->end_date->isoFormat($this->monthAndDayFormat)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
$useNative = $this->convertToNative && $this->default->id !== $limit->transaction_currency_id;
|
||||||
|
$amount = $limit->amount;
|
||||||
|
if($useNative) {
|
||||||
|
$amount = $limit->native_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$sumSpent = bcmul($entry['sum'], '-1'); // spent
|
$sumSpent = bcmul($entry['sum'], '-1'); // spent
|
||||||
$data[0]['entries'][$title] ??= '0';
|
$data[0]['entries'][$title] ??= '0';
|
||||||
$data[1]['entries'][$title] ??= '0';
|
$data[1]['entries'][$title] ??= '0';
|
||||||
$data[2]['entries'][$title] ??= '0';
|
$data[2]['entries'][$title] ??= '0';
|
||||||
|
|
||||||
|
|
||||||
$data[0]['entries'][$title] = bcadd($data[0]['entries'][$title], 1 === bccomp($sumSpent, $limit->amount) ? $limit->amount : $sumSpent); // spent
|
$data[0]['entries'][$title] = bcadd($data[0]['entries'][$title], 1 === bccomp($sumSpent, $amount) ? $amount : $sumSpent); // spent
|
||||||
$data[1]['entries'][$title] = bcadd($data[1]['entries'][$title],1 === bccomp($limit->amount, $sumSpent) ? bcadd($entry['sum'], $limit->amount) : '0'); // left to spent
|
$data[1]['entries'][$title] = bcadd($data[1]['entries'][$title],1 === bccomp($amount, $sumSpent) ? bcadd($entry['sum'], $amount) : '0'); // left to spent
|
||||||
$data[2]['entries'][$title] = bcadd($data[2]['entries'][$title],1 === bccomp($limit->amount, $sumSpent) ? '0' : bcmul(bcadd($entry['sum'], $limit->amount), '-1')); // overspent
|
$data[2]['entries'][$title] = bcadd($data[2]['entries'][$title],1 === bccomp($amount, $sumSpent) ? '0' : bcmul(bcadd($entry['sum'], $amount), '-1')); // overspent
|
||||||
|
|
||||||
|
Log::debug(sprintf('Amount [spent] is now %s.', $data[0]['entries'][$title]));
|
||||||
|
Log::debug(sprintf('Amount [left] is now %s.', $data[1]['entries'][$title]));
|
||||||
|
Log::debug(sprintf('Amount [overspent] is now %s.', $data[2]['entries'][$title]));
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,9 @@ use Carbon\Carbon;
|
|||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\CurrencyExchangeRate;
|
use FireflyIII\Models\CurrencyExchangeRate;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
|
use FireflyIII\Models\UserGroup;
|
||||||
use FireflyIII\Support\CacheProperties;
|
use FireflyIII\Support\CacheProperties;
|
||||||
|
use FireflyIII\User;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
@@ -45,6 +47,20 @@ class ExchangeRateConverter
|
|||||||
private array $prepared = [];
|
private array $prepared = [];
|
||||||
private int $queryCount = 0;
|
private int $queryCount = 0;
|
||||||
|
|
||||||
|
private UserGroup $userGroup;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
if (auth()->check()) {
|
||||||
|
$this->userGroup = auth()->user()->userGroup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUserGroup(UserGroup $userGroup): void
|
||||||
|
{
|
||||||
|
$this->userGroup = $userGroup;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
@@ -85,8 +101,8 @@ class ExchangeRateConverter
|
|||||||
*/
|
*/
|
||||||
private function getRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
|
private function getRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
|
||||||
{
|
{
|
||||||
$key = $this->getCacheKey($from, $to, $date);
|
$key = $this->getCacheKey($from, $to, $date);
|
||||||
$res = Cache::get($key, null);
|
$res = Cache::get($key, null);
|
||||||
|
|
||||||
// find in cache
|
// find in cache
|
||||||
if (null !== $res) {
|
if (null !== $res) {
|
||||||
@@ -96,7 +112,7 @@ class ExchangeRateConverter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// find in database
|
// find in database
|
||||||
$rate = $this->getFromDB($from->id, $to->id, $date->format('Y-m-d'));
|
$rate = $this->getFromDB($from->id, $to->id, $date->format('Y-m-d'));
|
||||||
if (null !== $rate) {
|
if (null !== $rate) {
|
||||||
Cache::forever($key, $rate);
|
Cache::forever($key, $rate);
|
||||||
Log::debug(sprintf('ExchangeRateConverter: Return DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
|
Log::debug(sprintf('ExchangeRateConverter: Return DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
|
||||||
@@ -105,11 +121,11 @@ class ExchangeRateConverter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// find reverse in database
|
// find reverse in database
|
||||||
$rate = $this->getFromDB($to->id, $from->id, $date->format('Y-m-d'));
|
$rate = $this->getFromDB($to->id, $from->id, $date->format('Y-m-d'));
|
||||||
if (null !== $rate) {
|
if (null !== $rate) {
|
||||||
$rate = bcdiv('1', $rate);
|
$rate = bcdiv('1', $rate);
|
||||||
Cache::forever($key, $rate);
|
Cache::forever($key, $rate);
|
||||||
Log::debug(sprintf('ExchangeRateConverter: Return DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
|
Log::debug(sprintf('ExchangeRateConverter: Return inverse DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
|
||||||
|
|
||||||
return $rate;
|
return $rate;
|
||||||
}
|
}
|
||||||
@@ -143,7 +159,7 @@ class ExchangeRateConverter
|
|||||||
if ($from === $to) {
|
if ($from === $to) {
|
||||||
return '1';
|
return '1';
|
||||||
}
|
}
|
||||||
$key = sprintf('cer-%d-%d-%s', $from, $to, $date);
|
$key = sprintf('cer-%d-%d-%s', $from, $to, $date);
|
||||||
|
|
||||||
// perhaps the rate has been cached during this particular run
|
// perhaps the rate has been cached during this particular run
|
||||||
$preparedRate = $this->prepared[$date][$from][$to] ?? null;
|
$preparedRate = $this->prepared[$date][$from][$to] ?? null;
|
||||||
@@ -153,7 +169,7 @@ class ExchangeRateConverter
|
|||||||
return $preparedRate;
|
return $preparedRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($key);
|
$cache->addProperty($key);
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
$rate = $cache->get();
|
$rate = $cache->get();
|
||||||
@@ -166,16 +182,14 @@ class ExchangeRateConverter
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @var null|CurrencyExchangeRate $result */
|
/** @var null|CurrencyExchangeRate $result */
|
||||||
$result = auth()->user()
|
$result = $this->userGroup->currencyExchangeRates()
|
||||||
?->currencyExchangeRates()
|
->where('from_currency_id', $from)
|
||||||
->where('from_currency_id', $from)
|
->where('to_currency_id', $to)
|
||||||
->where('to_currency_id', $to)
|
->where('date', '<=', $date)
|
||||||
->where('date', '<=', $date)
|
->orderBy('date', 'DESC')
|
||||||
->orderBy('date', 'DESC')
|
->first();
|
||||||
->first()
|
|
||||||
;
|
|
||||||
++$this->queryCount;
|
++$this->queryCount;
|
||||||
$rate = (string) $result?->rate;
|
$rate = (string) $result?->rate;
|
||||||
|
|
||||||
if ('' === $rate) {
|
if ('' === $rate) {
|
||||||
app('log')->debug(sprintf('ExchangeRateConverter: Found no rate for #%d->#%d (%s) in the DB.', $from, $to, $date));
|
app('log')->debug(sprintf('ExchangeRateConverter: Found no rate for #%d->#%d (%s) in the DB.', $from, $to, $date));
|
||||||
@@ -215,13 +229,13 @@ class ExchangeRateConverter
|
|||||||
if ($euroId === $currency->id) {
|
if ($euroId === $currency->id) {
|
||||||
return '1';
|
return '1';
|
||||||
}
|
}
|
||||||
$rate = $this->getFromDB($currency->id, $euroId, $date->format('Y-m-d'));
|
$rate = $this->getFromDB($currency->id, $euroId, $date->format('Y-m-d'));
|
||||||
|
|
||||||
if (null !== $rate) {
|
if (null !== $rate) {
|
||||||
// app('log')->debug(sprintf('Rate for %s to EUR is %s.', $currency->code, $rate));
|
// app('log')->debug(sprintf('Rate for %s to EUR is %s.', $currency->code, $rate));
|
||||||
return $rate;
|
return $rate;
|
||||||
}
|
}
|
||||||
$rate = $this->getFromDB($euroId, $currency->id, $date->format('Y-m-d'));
|
$rate = $this->getFromDB($euroId, $currency->id, $date->format('Y-m-d'));
|
||||||
if (null !== $rate) {
|
if (null !== $rate) {
|
||||||
return bcdiv('1', $rate);
|
return bcdiv('1', $rate);
|
||||||
// app('log')->debug(sprintf('Inverted rate for %s to EUR is %s.', $currency->code, $rate));
|
// app('log')->debug(sprintf('Inverted rate for %s to EUR is %s.', $currency->code, $rate));
|
||||||
@@ -250,7 +264,7 @@ class ExchangeRateConverter
|
|||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
return (int) $cache->get();
|
return (int) $cache->get();
|
||||||
}
|
}
|
||||||
$euro = TransactionCurrency::whereCode('EUR')->first();
|
$euro = TransactionCurrency::whereCode('EUR')->first();
|
||||||
++$this->queryCount;
|
++$this->queryCount;
|
||||||
if (null === $euro) {
|
if (null === $euro) {
|
||||||
throw new FireflyException('Cannot find EUR in system, cannot do currency conversion.');
|
throw new FireflyException('Cannot find EUR in system, cannot do currency conversion.');
|
||||||
@@ -272,14 +286,13 @@ class ExchangeRateConverter
|
|||||||
$start->startOfDay();
|
$start->startOfDay();
|
||||||
$end->endOfDay();
|
$end->endOfDay();
|
||||||
Log::debug(sprintf('Preparing for %s to %s between %s and %s', $from->code, $to->code, $start->format('Y-m-d'), $end->format('Y-m-d')));
|
Log::debug(sprintf('Preparing for %s to %s between %s and %s', $from->code, $to->code, $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||||
$set = auth()->user()
|
$set = $this->userGroup
|
||||||
->currencyExchangeRates()
|
->currencyExchangeRates()
|
||||||
->where('from_currency_id', $from->id)
|
->where('from_currency_id', $from->id)
|
||||||
->where('to_currency_id', $to->id)
|
->where('to_currency_id', $to->id)
|
||||||
->where('date', '<=', $end->format('Y-m-d'))
|
->where('date', '<=', $end->format('Y-m-d'))
|
||||||
->where('date', '>=', $start->format('Y-m-d'))
|
->where('date', '>=', $start->format('Y-m-d'))
|
||||||
->orderBy('date', 'DESC')->get()
|
->orderBy('date', 'DESC')->get();
|
||||||
;
|
|
||||||
++$this->queryCount;
|
++$this->queryCount;
|
||||||
if (0 === $set->count()) {
|
if (0 === $set->count()) {
|
||||||
Log::debug('No prepared rates found in this period, use the fallback');
|
Log::debug('No prepared rates found in this period, use the fallback');
|
||||||
@@ -293,10 +306,10 @@ class ExchangeRateConverter
|
|||||||
$this->isPrepared = true;
|
$this->isPrepared = true;
|
||||||
|
|
||||||
// so there is a fallback just in case. Now loop the set of rates we DO have.
|
// so there is a fallback just in case. Now loop the set of rates we DO have.
|
||||||
$temp = [];
|
$temp = [];
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($set as $rate) {
|
foreach ($set as $rate) {
|
||||||
$date = $rate->date->format('Y-m-d');
|
$date = $rate->date->format('Y-m-d');
|
||||||
$temp[$date] ??= [
|
$temp[$date] ??= [
|
||||||
$from->id => [
|
$from->id => [
|
||||||
$to->id => $rate->rate,
|
$to->id => $rate->rate,
|
||||||
@@ -305,11 +318,11 @@ class ExchangeRateConverter
|
|||||||
++$count;
|
++$count;
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('Found %d rates in this period.', $count));
|
Log::debug(sprintf('Found %d rates in this period.', $count));
|
||||||
$currentStart = clone $start;
|
$currentStart = clone $start;
|
||||||
while ($currentStart->lte($end)) {
|
while ($currentStart->lte($end)) {
|
||||||
$currentDate = $currentStart->format('Y-m-d');
|
$currentDate = $currentStart->format('Y-m-d');
|
||||||
$this->prepared[$currentDate] ??= [];
|
$this->prepared[$currentDate] ??= [];
|
||||||
$fallback = $temp[$currentDate][$from->id][$to->id] ?? $this->fallback[$from->id][$to->id] ?? '0';
|
$fallback = $temp[$currentDate][$from->id][$to->id] ?? $this->fallback[$from->id][$to->id] ?? '0';
|
||||||
if (0 === count($this->prepared[$currentDate]) && 0 !== bccomp('0', $fallback)) {
|
if (0 === count($this->prepared[$currentDate]) && 0 !== bccomp('0', $fallback)) {
|
||||||
// fill from temp or fallback or from temp (see before)
|
// fill from temp or fallback or from temp (see before)
|
||||||
$this->prepared[$currentDate][$from->id][$to->id] = $fallback;
|
$this->prepared[$currentDate][$from->id][$to->id] = $fallback;
|
||||||
|
@@ -54,7 +54,7 @@ trait ChartGeneration
|
|||||||
$cache->addProperty($accounts);
|
$cache->addProperty($accounts);
|
||||||
$cache->addProperty($convertToNative);
|
$cache->addProperty($convertToNative);
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
return $cache->get();
|
//return $cache->get();
|
||||||
}
|
}
|
||||||
app('log')->debug('Regenerate chart.account.account-balance-chart from scratch.');
|
app('log')->debug('Regenerate chart.account.account-balance-chart from scratch.');
|
||||||
$locale = app('steam')->getLocale();
|
$locale = app('steam')->getLocale();
|
||||||
|
@@ -62,7 +62,9 @@ class Steam
|
|||||||
$value = (string) ($transaction[$key] ?? '0');
|
$value = (string) ($transaction[$key] ?? '0');
|
||||||
$value = '' === $value ? '0' : $value;
|
$value = '' === $value ? '0' : $value;
|
||||||
$sum = bcadd($sum, $value);
|
$sum = bcadd($sum, $value);
|
||||||
|
//Log::debug(sprintf('Add value from "%s": %s', $key, $value));
|
||||||
}
|
}
|
||||||
|
Log::debug(sprintf('Sum of "%s"-fields is %s', $key, $sum));
|
||||||
|
|
||||||
return $sum;
|
return $sum;
|
||||||
}
|
}
|
||||||
@@ -257,64 +259,95 @@ class Steam
|
|||||||
* THAT currency.
|
* THAT currency.
|
||||||
* "native_balance" the balance according to the "native_amount" + "native_foreign_amount" fields.
|
* "native_balance" the balance according to the "native_amount" + "native_foreign_amount" fields.
|
||||||
* "ABC" the balance in this particular currency code (may repeat for each found currency).
|
* "ABC" the balance in this particular currency code (may repeat for each found currency).
|
||||||
|
*
|
||||||
|
* Het maakt niet uit of de native currency wel of niet gelijk is aan de account currency.
|
||||||
|
* Optelsom zou hetzelfde moeten zijn. Als het EUR is en de rekening ook is native_amount 0.
|
||||||
|
* Zo niet is amount 0 en native_amount het bedrag.
|
||||||
|
*
|
||||||
|
* Eerst een som van alle transacties in de native currency. Alle EUR bij elkaar opgeteld.
|
||||||
|
* Om te weten wat er nog meer op de rekening gebeurt, pak alles waar currency niet EUR is, en de foreign ook niet,
|
||||||
|
* en tel native_amount erbij op.
|
||||||
|
* Daarna pak je alle transacties waar currency niet EUR is, en de foreign wel, en tel foreign_amount erbij op.
|
||||||
|
*
|
||||||
|
* Wil je niks weten van native currencies, pak je:
|
||||||
|
*
|
||||||
|
* Eerst een som van alle transacties gegroepeerd op currency. Einde.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public function finalAccountBalance(Account $account, Carbon $date): array
|
public function finalAccountBalance(Account $account, Carbon $date): array
|
||||||
{
|
{
|
||||||
|
Log::debug(sprintf('Now in finalAccountBalance(#%d, "%s", "%s")', $account->id, $account->name, $date->format('Y-m-d H:i:s')));
|
||||||
$native = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
|
$native = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
|
||||||
|
$convertToNative = app('preferences')->getForUser($account->user, 'convert_to_native', false)->data;
|
||||||
$accountCurrency = $this->getAccountCurrency($account);
|
$accountCurrency = $this->getAccountCurrency($account);
|
||||||
$hasCurrency = null !== $accountCurrency;
|
$hasCurrency = null !== $accountCurrency;
|
||||||
$currency = $accountCurrency ?? $native;
|
$currency = $hasCurrency ? $accountCurrency : $native;
|
||||||
if (!$hasCurrency) {
|
if (!$hasCurrency) {
|
||||||
Log::debug('Gave account fake currency.');
|
//Log::debug('Pretend native currency is fake, because account has no currency.');
|
||||||
// fake currency
|
// fake currency
|
||||||
$native = new TransactionCurrency();
|
//$native = new TransactionCurrency();
|
||||||
}
|
}
|
||||||
$return = [
|
//unset($accountCurrency);
|
||||||
'native_balance' => '0',
|
$return = [];
|
||||||
];
|
|
||||||
Log::debug(sprintf('Now in finalAccountBalance("%s", "%s")', $account->name, $date->format('Y-m-d H:i:s')));
|
|
||||||
// first, the "balance", as described earlier.
|
// first, the "balance", as described earlier.
|
||||||
$array = $account->transactions()
|
if ($convertToNative) {
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
// normal balance
|
||||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
$return['balance'] = (string) $account->transactions()
|
||||||
->where('transactions.transaction_currency_id', $currency->id)
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
->get(['transactions.amount'])->toArray();
|
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
||||||
$return['balance'] = $this->sumTransactions($array, 'amount');
|
->where('transactions.transaction_currency_id', $native->id)
|
||||||
//Log::debug(sprintf('balance is %s', $return['balance']));
|
->sum('transactions.amount');
|
||||||
// add virtual balance:
|
// plus virtual balance, if the account has a virtual_balance in the native currency
|
||||||
$return['balance'] = bcadd('' === (string) $account->virtual_balance ? '0' : $account->virtual_balance, $return['balance']);
|
if($native->id === $accountCurrency?->id) {
|
||||||
Log::debug(sprintf('balance is %s (with virtual balance)', $return['balance']));
|
$return['balance'] = bcadd('' === (string) $account->virtual_balance ? '0' : $account->virtual_balance, $return['balance']);
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('balance is (%s only) %s (with virtual balance)', $native->code, $return['balance']));
|
||||||
|
|
||||||
// then, native balance (if necessary(
|
// native balance
|
||||||
if ($native->id !== $currency->id) {
|
$return['native_balance'] = (string) $account->transactions()
|
||||||
Log::debug('Will grab native balance for transactions on this account.');
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
$array = $account->transactions()
|
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
->whereNot('transactions.transaction_currency_id', $native->id)
|
||||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
->sum('transactions.native_amount');
|
||||||
->get(['transactions.native_amount'])->toArray();
|
// plus native virtual balance.
|
||||||
$return['native_balance'] = $this->sumTransactions($array, 'native_amount');
|
|
||||||
// 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['native_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 (all transactions to %s) %s (with virtual balance)', $native->code, $return['native_balance']));
|
||||||
|
|
||||||
|
// plus foreign transactions in THIS currency.
|
||||||
|
$sum = (string) $account->transactions()
|
||||||
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
|
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
||||||
|
->whereNot('transactions.transaction_currency_id', $native->id)
|
||||||
|
->where('transactions.foreign_currency_id', $native->id)
|
||||||
|
->sum('transactions.foreign_amount');
|
||||||
|
$return['native_balance'] = bcadd($return['native_balance'], $sum);
|
||||||
|
|
||||||
|
Log::debug(sprintf('Foreign amount transactions add (%s only) %s, total native_balance is now %s', $native->code, $sum, $return['native_balance']));
|
||||||
}
|
}
|
||||||
|
|
||||||
// balance(s) in other currencies.
|
// balance(s) in other (all) currencies.
|
||||||
$array = $account->transactions()
|
$array = $account->transactions()
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id')
|
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id')
|
||||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
||||||
->get(['transaction_currencies.code', 'transactions.amount'])->toArray();
|
->get(['transaction_currencies.code', 'transactions.amount'])->toArray();
|
||||||
$others = $this->groupAndSumTransactions($array, 'code', 'amount');
|
$others = $this->groupAndSumTransactions($array, 'code', 'amount');
|
||||||
|
Log::debug('All balances are (joined)', $others);
|
||||||
// if the account has no own currency preference, drop balance in favor of native balance
|
// if the account has no own currency preference, drop balance in favor of native balance
|
||||||
|
if ($hasCurrency && !$convertToNative) {
|
||||||
|
$return['balance'] = $others[$currency->code] ?? null;
|
||||||
|
$return['native_balance'] = $others[$currency->code] ?? null;
|
||||||
|
Log::debug(sprintf('Set balance + native_balance to %s', $return['balance']));
|
||||||
|
}
|
||||||
if (!$hasCurrency) {
|
if (!$hasCurrency) {
|
||||||
Log::debug('Account has no currency preference, dropping balance in favor of native balance.');
|
Log::debug('Account has no currency preference, dropping balance in favor of native balance.');
|
||||||
$return['native_balance'] = bcadd($return['balance'], $return['native_balance']);
|
$sum = bcadd($return['balance'], $return['native_balance']);
|
||||||
|
Log::debug(sprintf('%s + %s = %s', $return['balance'], $return['native_balance'], $sum));
|
||||||
|
$return['native_balance'] = $sum;
|
||||||
unset($return['balance']);
|
unset($return['balance']);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::debug('All others are (joined)', $others);
|
|
||||||
|
|
||||||
return array_merge($return, $others);
|
return array_merge($return, $others);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -79,10 +79,6 @@ class General extends AbstractExtension
|
|||||||
if (!$useNative) {
|
if (!$useNative) {
|
||||||
$strings[] = app('amount')->formatAnything($currency, $balance, false);
|
$strings[] = app('amount')->formatAnything($currency, $balance, false);
|
||||||
}
|
}
|
||||||
if($useNative) {
|
|
||||||
$strings[] =sprintf('(%s)', app('amount')->formatAnything($currency, $balance, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ('native_balance' === $key) {
|
if ('native_balance' === $key) {
|
||||||
@@ -94,7 +90,7 @@ class General extends AbstractExtension
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// for multi currency accounts.
|
// for multi currency accounts.
|
||||||
if ($key !== $currency->code) {
|
if ($useNative && $key !== $default->code) {
|
||||||
$strings[] = app('amount')->formatAnything(TransactionCurrency::where('code', $key)->first(), $balance, false);
|
$strings[] = app('amount')->formatAnything(TransactionCurrency::where('code', $key)->first(), $balance, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user