diff --git a/app/Http/Controllers/Account/EditController.php b/app/Http/Controllers/Account/EditController.php index 503aae8ad6..a62bfc4a15 100644 --- a/app/Http/Controllers/Account/EditController.php +++ b/app/Http/Controllers/Account/EditController.php @@ -119,7 +119,7 @@ class EditController extends Controller } $request->session()->forget('accounts.edit.fromUpdate'); - $openingBalanceAmount = (string) $repository->getOpeningBalanceAmount($account); + $openingBalanceAmount = (string) $repository->getOpeningBalanceAmount($account, false); if ('0' === $openingBalanceAmount) { $openingBalanceAmount = ''; } diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 6a97997004..40fd1efa16 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -293,7 +293,7 @@ class AccountRepository implements AccountRepositoryInterface /** * Returns the amount of the opening balance for this account. */ - public function getOpeningBalanceAmount(Account $account): ?string + public function getOpeningBalanceAmount(Account $account, bool $convertToNative): ?string { $journal = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') ->where('transactions.account_id', $account->id) @@ -307,6 +307,9 @@ class AccountRepository implements AccountRepositoryInterface if (null === $transaction) { return null; } + if($convertToNative) { + return $transaction->native_amount ?? '0'; + } return $transaction->amount; } diff --git a/app/Repositories/Account/AccountRepositoryInterface.php b/app/Repositories/Account/AccountRepositoryInterface.php index 8b301a7621..f79883c064 100644 --- a/app/Repositories/Account/AccountRepositoryInterface.php +++ b/app/Repositories/Account/AccountRepositoryInterface.php @@ -106,7 +106,7 @@ interface AccountRepositoryInterface /** * Returns the amount of the opening balance for this account. */ - public function getOpeningBalanceAmount(Account $account): ?string; + public function getOpeningBalanceAmount(Account $account, bool $convertToNative): ?string; /** * Return date of opening balance as string or null. diff --git a/app/Services/Internal/Support/CreditRecalculateService.php b/app/Services/Internal/Support/CreditRecalculateService.php index 514697e911..f9368bac65 100644 --- a/app/Services/Internal/Support/CreditRecalculateService.php +++ b/app/Services/Internal/Support/CreditRecalculateService.php @@ -170,7 +170,7 @@ class CreditRecalculateService $this->validateOpeningBalance($account, $openingBalance); } } - $startOfDebt = $this->repository->getOpeningBalanceAmount($account) ?? '0'; + $startOfDebt = $this->repository->getOpeningBalanceAmount($account, false) ?? '0'; $leftOfDebt = app('steam')->positive($startOfDebt); // Log::debug(sprintf('Start of debt is "%s", so initial left of debt is "%s"', app('steam')->bcround($startOfDebt, 2), app('steam')->bcround($leftOfDebt, 2))); diff --git a/app/Transformers/AccountTransformer.php b/app/Transformers/AccountTransformer.php index 70212444b4..893f8e7ae0 100644 --- a/app/Transformers/AccountTransformer.php +++ b/app/Transformers/AccountTransformer.php @@ -27,7 +27,9 @@ namespace FireflyIII\Transformers; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; +use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\Steam; use Symfony\Component\HttpFoundation\ParameterBag; @@ -57,28 +59,35 @@ class AccountTransformer extends AbstractTransformer $this->repository->setUser($account->user); // get account type: - $fullType = $account->accountType->type; - $accountType = (string) config(sprintf('firefly.shortNamesByFullName.%s', $fullType)); - $liabilityType = (string) config(sprintf('firefly.shortLiabilityNameByFullName.%s', $fullType)); - $liabilityType = '' === $liabilityType ? null : strtolower($liabilityType); - $liabilityDirection = $this->repository->getMetaValue($account, 'liability_direction'); + $fullType = $account->accountType->type; + $accountType = (string) config(sprintf('firefly.shortNamesByFullName.%s', $fullType)); + $liabilityType = (string) config(sprintf('firefly.shortLiabilityNameByFullName.%s', $fullType)); + $liabilityType = '' === $liabilityType ? null : strtolower($liabilityType); + $liabilityDirection = $this->repository->getMetaValue($account, 'liability_direction'); + $convertToNative = Amount::convertToNative(); - // get account role (will only work if the type is asset. - $accountRole = $this->getAccountRole($account, $accountType); - $date = $this->getDate(); + // get account role (will only work if the type is asset). + $default = Amount::getDefaultCurrency(); + $accountRole = $this->getAccountRole($account, $accountType); + $date = $this->getDate(); $date->endOfDay(); - [$currencyId, $currencyCode, $currencySymbol, $decimalPlaces] = $this->getCurrency($account); - [$creditCardType, $monthlyPaymentDate] = $this->getCCInfo($account, $accountRole, $accountType); - [$openingBalance, $openingBalanceDate] = $this->getOpeningBalance($account, $accountType); - [$interest, $interestPeriod] = $this->getInterest($account, $accountType); + [$currencyId, $currencyCode, $currencySymbol, $decimalPlaces] = $this->getCurrency($account, $default); + [$creditCardType, $monthlyPaymentDate] = $this->getCCInfo($account, $accountRole, $accountType); + [$openingBalance, $nativeOpeningBalance, $openingBalanceDate] = $this->getOpeningBalance($account, $accountType, $convertToNative); + [$interest, $interestPeriod] = $this->getInterest($account, $accountType); - $openingBalance = app('steam')->bcround($openingBalance, $decimalPlaces); - $includeNetWorth = '0' !== $this->repository->getMetaValue($account, 'include_net_worth'); - $longitude = null; - $latitude = null; - $zoomLevel = null; - $location = $this->repository->getLocation($account); + if (!$convertToNative) { + // reset default currency to NULL, not interesting. + $default = null; + } + + $openingBalance = app('steam')->bcround($openingBalance, $decimalPlaces); + $includeNetWorth = '0' !== $this->repository->getMetaValue($account, 'include_net_worth'); + $longitude = null; + $latitude = null; + $zoomLevel = null; + $location = $this->repository->getLocation($account); if (null !== $location) { $longitude = $location->longitude; $latitude = $location->latitude; @@ -86,48 +95,63 @@ class AccountTransformer extends AbstractTransformer } // no order for some accounts: - $order = $account->order; + $order = $account->order; if (!in_array(strtolower($accountType), ['liability', 'liabilities', 'asset'], true)) { $order = null; } + // balance, native balance, virtual balance, native virtual balance? + $finalBalance = Steam::finalAccountBalance($account, $date); + if($convertToNative) { + $finalBalance['balance'] = $finalBalance[$currencyCode] ?? '0'; + } + + $currentBalance = app('steam')->bcround($finalBalance['balance'] ?? '0', $decimalPlaces); + $nativeCurrentBalance = $convertToNative ? app('steam')->bcround($finalBalance['native_balance'] ?? '0', $default->decimal_places) : null; return [ - 'id' => (string) $account->id, - 'created_at' => $account->created_at->toAtomString(), - 'updated_at' => $account->updated_at->toAtomString(), - 'active' => $account->active, - 'order' => $order, - 'name' => $account->name, - 'type' => strtolower($accountType), - 'account_role' => $accountRole, - 'currency_id' => $currencyId, - 'currency_code' => $currencyCode, - 'currency_symbol' => $currencySymbol, - 'currency_decimal_places' => $decimalPlaces, - 'current_balance' => app('steam')->bcround(Steam::finalAccountBalance($account, $date)['balance'] ?? '0', $decimalPlaces), - 'current_balance_date' => $date->toAtomString(), - 'notes' => $this->repository->getNoteText($account), - 'monthly_payment_date' => $monthlyPaymentDate, - 'credit_card_type' => $creditCardType, - 'account_number' => $this->repository->getMetaValue($account, 'account_number'), - 'iban' => '' === $account->iban ? null : $account->iban, - 'bic' => $this->repository->getMetaValue($account, 'BIC'), - 'virtual_balance' => app('steam')->bcround($account->virtual_balance, $decimalPlaces), - 'opening_balance' => $openingBalance, - 'opening_balance_date' => $openingBalanceDate, - 'liability_type' => $liabilityType, - 'liability_direction' => $liabilityDirection, - 'interest' => $interest, - 'interest_period' => $interestPeriod, - 'current_debt' => $this->repository->getMetaValue($account, 'current_debt'), - 'include_net_worth' => $includeNetWorth, - 'longitude' => $longitude, - 'latitude' => $latitude, - 'zoom_level' => $zoomLevel, - 'links' => [ + 'id' => (string) $account->id, + 'created_at' => $account->created_at->toAtomString(), + 'updated_at' => $account->updated_at->toAtomString(), + 'active' => $account->active, + 'order' => $order, + 'name' => $account->name, + 'type' => strtolower($accountType), + 'account_role' => $accountRole, + 'currency_id' => $currencyId, + 'currency_code' => $currencyCode, + 'currency_symbol' => $currencySymbol, + 'currency_decimal_places' => $decimalPlaces, + 'native_currency_id' => null === $default ? null : (string) $default->id, + 'native_currency_code' => $default?->code, + 'native_currency_symbol' => $default?->symbol, + 'native_currency_decimal_places' => $default?->decimal_places, + 'current_balance' => $currentBalance, + 'native_current_balance' => $nativeCurrentBalance, + 'current_balance_date' => $date->toAtomString(), + 'notes' => $this->repository->getNoteText($account), + 'monthly_payment_date' => $monthlyPaymentDate, + 'credit_card_type' => $creditCardType, + 'account_number' => $this->repository->getMetaValue($account, 'account_number'), + 'iban' => '' === $account->iban ? null : $account->iban, + 'bic' => $this->repository->getMetaValue($account, 'BIC'), + 'virtual_balance' => app('steam')->bcround($account->virtual_balance, $decimalPlaces), + 'native_virtual_balance' => $convertToNative ? app('steam')->bcround($account->native_virtual_balance, $default->decimal_places) : null, + 'opening_balance' => $openingBalance, + 'native_opening_balance' => $nativeOpeningBalance, + 'opening_balance_date' => $openingBalanceDate, + 'liability_type' => $liabilityType, + 'liability_direction' => $liabilityDirection, + 'interest' => $interest, + 'interest_period' => $interestPeriod, + 'current_debt' => $this->repository->getMetaValue($account, 'current_debt'), + 'include_net_worth' => $includeNetWorth, + 'longitude' => $longitude, + 'latitude' => $latitude, + 'zoom_level' => $zoomLevel, + 'links' => [ [ 'rel' => 'self', - 'uri' => '/accounts/'.$account->id, + 'uri' => '/accounts/' . $account->id, ], ], ]; @@ -156,16 +180,13 @@ class AccountTransformer extends AbstractTransformer return $date; } - /** - * @throws FireflyException - */ - private function getCurrency(Account $account): array + private function getCurrency(Account $account, TransactionCurrency $default): array { - $currency = $this->repository->getAccountCurrency($account); + $currency = $this->repository->getAccountCurrency($account); // only grab default when result is null: if (null === $currency) { - $currency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup); + $currency = $default; } $currencyId = (string) $currency->id; $currencyCode = $currency->code; @@ -186,7 +207,7 @@ class AccountTransformer extends AbstractTransformer if (null !== $monthlyPaymentDate) { // try classic date: if (10 === strlen($monthlyPaymentDate)) { - $object = Carbon::createFromFormat('!Y-m-d', $monthlyPaymentDate, config('app.timezone')); + $object = Carbon::createFromFormat('!Y-m-d', $monthlyPaymentDate, config('app.timezone')); if (null === $object) { $object = today(config('app.timezone')); } @@ -203,24 +224,25 @@ class AccountTransformer extends AbstractTransformer /** * TODO refactor call to get~OpeningBalanceAmount / Date because it is a lot of queries */ - private function getOpeningBalance(Account $account, string $accountType): array + private function getOpeningBalance(Account $account, string $accountType, bool $convertToNative): array { - $openingBalance = null; - $openingBalanceDate = null; + $openingBalance = null; + $openingBalanceDate = null; + $nativeOpeningBalance = null; if (in_array($accountType, ['asset', 'liabilities'], true)) { - $amount = $this->repository->getOpeningBalanceAmount($account); - $openingBalance = $amount; - $openingBalanceDate = $this->repository->getOpeningBalanceDate($account); + $openingBalance = $this->repository->getOpeningBalanceAmount($account, false); + $nativeOpeningBalance = $this->repository->getOpeningBalanceAmount($account, true); + $openingBalanceDate = $this->repository->getOpeningBalanceDate($account); } if (null !== $openingBalanceDate) { - $object = Carbon::createFromFormat('Y-m-d H:i:s', $openingBalanceDate, config('app.timezone')); + $object = Carbon::createFromFormat('Y-m-d H:i:s', $openingBalanceDate, config('app.timezone')); if (null === $object) { $object = today(config('app.timezone')); } $openingBalanceDate = $object->toAtomString(); } - return [$openingBalance, $openingBalanceDate]; + return [$openingBalance, $nativeOpeningBalance, $openingBalanceDate]; } private function getInterest(Account $account, string $accountType): array