Move account balance logic to enrichment.

This commit is contained in:
James Cole
2025-08-03 10:22:12 +02:00
parent 0c7f04fb17
commit d4e14dd262
11 changed files with 248 additions and 196 deletions

View File

@@ -96,6 +96,7 @@ class ShowController extends Controller
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate($this->parameters->get('date'));
$enrichment->setUser($admin); $enrichment->setUser($admin);
$accounts = $enrichment->enrich($accounts); $accounts = $enrichment->enrich($accounts);
@@ -130,6 +131,7 @@ class ShowController extends Controller
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate($this->parameters->get('date'));
$enrichment->setUser($admin); $enrichment->setUser($admin);
$account = $enrichment->enrichSingle($account); $account = $enrichment->enrichSingle($account);

View File

@@ -75,6 +75,7 @@ class StoreController extends Controller
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate(null);
$enrichment->setUser($admin); $enrichment->setUser($admin);
$account = $enrichment->enrichSingle($account); $account = $enrichment->enrichSingle($account);

View File

@@ -80,6 +80,7 @@ class UpdateController extends Controller
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate(null);
$enrichment->setUser($admin); $enrichment->setUser($admin);
$account = $enrichment->enrichSingle($account); $account = $enrichment->enrichSingle($account);

View File

@@ -83,6 +83,7 @@ class ListController extends Controller
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate($this->parameters->get('date'));
$enrichment->setUser($admin); $enrichment->setUser($admin);
$accounts = $enrichment->enrich($accounts); $accounts = $enrichment->enrich($accounts);

View File

@@ -107,6 +107,7 @@ class ListController extends Controller
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate($this->parameters->get('date'));
$enrichment->setUser($admin); $enrichment->setUser($admin);
$accounts = $enrichment->enrich($accounts); $accounts = $enrichment->enrich($accounts);

View File

@@ -88,6 +88,7 @@ class AccountController extends Controller
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate($this->parameters->get('date'));
$enrichment->setUser($admin); $enrichment->setUser($admin);
$accounts = $enrichment->enrich($accounts); $accounts = $enrichment->enrich($accounts);

View File

@@ -176,6 +176,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
/** @var TransactionGroup $model */ /** @var TransactionGroup $model */
$accounts = $this->collectAccounts($model); $accounts = $this->collectAccounts($model);
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate(null);
$enrichment->setUser($model->user); $enrichment->setUser($model->user);
$accounts = $enrichment->enrich($accounts); $accounts = $enrichment->enrich($accounts);
foreach ($accounts as $account) { foreach ($accounts as $account) {

View File

@@ -148,6 +148,7 @@ class IndexController extends Controller
// enrich each account. // enrich each account.
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setUser(auth()->user()); $enrichment->setUser(auth()->user());
$enrichment->setDate($end);
$return = []; $return = [];
/** @var PiggyBank $piggy */ /** @var PiggyBank $piggy */

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Support\JsonApi\Enrichments; namespace FireflyIII\Support\JsonApi\Enrichments;
use Carbon\Carbon;
use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
@@ -36,6 +37,7 @@ use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\UserGroup; use FireflyIII\Models\UserGroup;
use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Steam; use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@@ -62,6 +64,8 @@ class AccountEnrichment implements EnrichmentInterface
private User $user; private User $user;
private UserGroup $userGroup; private UserGroup $userGroup;
private array $lastActivities; private array $lastActivities;
private ?Carbon $date = null;
private bool $convertToPrimary = false;
/** /**
* TODO The account enricher must do conversion from and to the primary currency. * TODO The account enricher must do conversion from and to the primary currency.
@@ -78,6 +82,7 @@ class AccountEnrichment implements EnrichmentInterface
$this->lastActivities = []; $this->lastActivities = [];
$this->locations = []; $this->locations = [];
$this->primaryCurrency = Amount::getPrimaryCurrency(); $this->primaryCurrency = Amount::getPrimaryCurrency();
$this->convertToPrimary = Amount::convertToPrimary();
} }
#[Override] #[Override]
@@ -107,6 +112,7 @@ class AccountEnrichment implements EnrichmentInterface
$this->collectLastActivities(); $this->collectLastActivities();
$this->collectLocations(); $this->collectLocations();
$this->collectOpeningBalances(); $this->collectOpeningBalances();
$this->collectBalances();
$this->appendCollectedData(); $this->appendCollectedData();
return $this->collection; return $this->collection;
@@ -137,8 +143,7 @@ class AccountEnrichment implements EnrichmentInterface
{ {
$set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth', 'currency_id', 'account_role', 'account_number', 'BIC', 'liability_direction', 'interest', 'interest_period', 'current_debt']) $set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth', 'currency_id', 'account_role', 'account_number', 'BIC', 'liability_direction', 'interest', 'interest_period', 'current_debt'])
->whereIn('account_id', $this->accountIds) ->whereIn('account_id', $this->accountIds)
->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data'])->toArray() ->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data'])->toArray();
;
/** @var array $entry */ /** @var array $entry */
foreach ($set as $entry) { foreach ($set as $entry) {
@@ -164,8 +169,7 @@ class AccountEnrichment implements EnrichmentInterface
$notes = Note::query()->whereIn('noteable_id', $this->accountIds) $notes = Note::query()->whereIn('noteable_id', $this->accountIds)
->whereNotNull('notes.text') ->whereNotNull('notes.text')
->where('notes.text', '!=', '') ->where('notes.text', '!=', '')
->where('noteable_type', Account::class)->get(['notes.noteable_id', 'notes.text'])->toArray() ->where('noteable_type', Account::class)->get(['notes.noteable_id', 'notes.text'])->toArray();
;
foreach ($notes as $note) { foreach ($notes as $note) {
$this->notes[(int) $note['noteable_id']] = (string) $note['text']; $this->notes[(int) $note['noteable_id']] = (string) $note['text'];
} }
@@ -175,8 +179,7 @@ class AccountEnrichment implements EnrichmentInterface
private function collectLocations(): void private function collectLocations(): void
{ {
$locations = Location::query()->whereIn('locatable_id', $this->accountIds) $locations = Location::query()->whereIn('locatable_id', $this->accountIds)
->where('locatable_type', Account::class)->get(['locations.locatable_id', 'locations.latitude', 'locations.longitude', 'locations.zoom_level'])->toArray() ->where('locatable_type', Account::class)->get(['locations.locatable_id', 'locations.latitude', 'locations.longitude', 'locations.zoom_level'])->toArray();
;
foreach ($locations as $location) { foreach ($locations as $location) {
$this->locations[(int) $location['locatable_id']] $this->locations[(int) $location['locatable_id']]
= [ = [
@@ -198,8 +201,7 @@ class AccountEnrichment implements EnrichmentInterface
->setUserGroup($this->userGroup) ->setUserGroup($this->userGroup)
->setAccounts($this->collection) ->setAccounts($this->collection)
->withAccountInformation() ->withAccountInformation()
->setTypes([TransactionTypeEnum::OPENING_BALANCE->value]) ->setTypes([TransactionTypeEnum::OPENING_BALANCE->value]);
;
$journals = $collector->getExtractedJournals(); $journals = $collector->getExtractedJournals();
foreach ($journals as $journal) { foreach ($journals as $journal) {
$this->openingBalances[(int) $journal['source_account_id']] $this->openingBalances[(int) $journal['source_account_id']]
@@ -228,15 +230,12 @@ class AccountEnrichment implements EnrichmentInterface
private function appendCollectedData(): void private function appendCollectedData(): void
{ {
$accountTypes = $this->accountTypes;
$meta = $this->meta;
$currencies = $this->currencies;
$notes = $this->notes; $notes = $this->notes;
$openingBalances = $this->openingBalances; $openingBalances = $this->openingBalances;
$locations = $this->locations; $locations = $this->locations;
$lastActivities = $this->lastActivities; $lastActivities = $this->lastActivities;
$this->collection = $this->collection->map(function (Account $item) use ($accountTypes, $meta, $currencies, $notes, $openingBalances, $locations, $lastActivities) { $this->collection = $this->collection->map(function (Account $item) use ($notes, $openingBalances, $locations, $lastActivities) {
$item->full_account_type = $accountTypes[(int) $item->account_type_id] ?? null; $item->full_account_type = $this->accountTypes[(int) $item->account_type_id] ?? null;
$accountMeta = [ $accountMeta = [
'currency' => null, 'currency' => null,
'location' => [ 'location' => [
@@ -244,16 +243,17 @@ class AccountEnrichment implements EnrichmentInterface
'longitude' => null, 'longitude' => null,
'zoom_level' => null, 'zoom_level' => null,
], ],
'opening_balance_date' => null,
]; ];
if (array_key_exists((int) $item->id, $meta)) { if (array_key_exists((int) $item->id, $this->meta)) {
foreach ($meta[(int) $item->id] as $name => $value) { foreach ($this->meta[(int) $item->id] as $name => $value) {
$accountMeta[$name] = $value; $accountMeta[$name] = $value;
} }
} }
// also add currency, if present. // also add currency, if present.
if (array_key_exists('currency_id', $accountMeta)) { if (array_key_exists('currency_id', $accountMeta)) {
$currencyId = (int) $accountMeta['currency_id']; $currencyId = (int) $accountMeta['currency_id'];
$accountMeta['currency'] = $currencies[$currencyId]; $accountMeta['currency'] = $this->currencies[$currencyId];
} }
// if notes, add notes. // if notes, add notes.
@@ -266,6 +266,64 @@ class AccountEnrichment implements EnrichmentInterface
$accountMeta['opening_balance_amount'] = $openingBalances[$item->id]['amount']; $accountMeta['opening_balance_amount'] = $openingBalances[$item->id]['amount'];
} }
// add balances
// get currencies:
$currency = $this->primaryCurrency; // assume primary currency
if (null !== $accountMeta['currency']) {
$currency = $accountMeta['currency'];
}
// get the current balance:
$date = $this->getDate();
$finalBalance = Steam::finalAccountBalance($item, $date, $this->primaryCurrency, $this->convertToPrimary);
Log::debug(sprintf('Call finalAccountBalance(%s) with date/time "%s"', var_export($this->convertToPrimary, true), $date->toIso8601String()), $finalBalance);
// collect current balances:
$currentBalance = Steam::bcround($finalBalance[$currency->code] ?? '0', $currency->decimal_places);
$openingBalance = Steam::bcround($accountMeta['opening_balance_amount'] ?? '0', $currency->decimal_places);
$virtualBalance = Steam::bcround($account->virtual_balance ?? '0', $currency->decimal_places);
$debtAmount = $accountMeta['current_debt'] ?? null;
// set some pc_ default values to NULL:
$pcCurrentBalance = null;
$pcOpeningBalance = null;
$pcVirtualBalance = null;
$pcDebtAmount = null;
// convert to primary currency if needed:
if ($this->convertToPrimary && $currency->id !== $this->primaryCurrency->id) {
Log::debug(sprintf('Convert to primary, from %s to %s', $currency->code, $this->primaryCurrency->code));
$converter = new ExchangeRateConverter();
$pcCurrentBalance = $converter->convert($currency, $this->primaryCurrency, $date, $currentBalance);
$pcOpeningBalance = $converter->convert($currency, $this->primaryCurrency, $date, $openingBalance);
$pcVirtualBalance = $converter->convert($currency, $this->primaryCurrency, $date, $virtualBalance);
$pcDebtAmount = null === $debtAmount ? null : $converter->convert($currency, $this->primaryCurrency, $date, $debtAmount);
}
if ($this->convertToPrimary && $currency->id === $this->primaryCurrency->id) {
$pcCurrentBalance = $currentBalance;
$pcOpeningBalance = $openingBalance;
$pcVirtualBalance = $virtualBalance;
$pcDebtAmount = $debtAmount;
}
// set opening balance(s) to NULL if the date is null
if (null === $accountMeta['opening_balance_date']) {
$openingBalance = null;
$pcOpeningBalance = null;
}
$accountMeta['balances'] = [
'current_balance' => $currentBalance,
'pc_current_balance' => $pcCurrentBalance,
'opening_balance' => $openingBalance,
'pc_opening_balance' => $pcOpeningBalance,
'virtual_balance' => $virtualBalance,
'pc_virtual_balance' => $pcVirtualBalance,
'debt_amount' => $debtAmount,
'pc_debt_amount' => $pcDebtAmount,
];
// end add balances
// if location, add location: // if location, add location:
if (array_key_exists($item->id, $locations)) { if (array_key_exists($item->id, $locations)) {
$accountMeta['location'] = $locations[$item->id]; $accountMeta['location'] = $locations[$item->id];
@@ -283,4 +341,21 @@ class AccountEnrichment implements EnrichmentInterface
{ {
$this->lastActivities = Steam::getLastActivities($this->accountIds); $this->lastActivities = Steam::getLastActivities($this->accountIds);
} }
private function collectBalances(): void {}
public function setDate(?Carbon $date): void
{
$this->date = $date;
}
public function getDate(): Carbon
{
if (null === $this->date) {
return today();
}
return $this->date;
}
} }

View File

@@ -131,8 +131,7 @@ class SubscriptionEnrichment implements EnrichmentInterface
$notes = Note::query()->whereIn('noteable_id', $this->subscriptionIds) $notes = Note::query()->whereIn('noteable_id', $this->subscriptionIds)
->whereNotNull('notes.text') ->whereNotNull('notes.text')
->where('notes.text', '!=', '') ->where('notes.text', '!=', '')
->where('noteable_type', Bill::class)->get(['notes.noteable_id', 'notes.text'])->toArray() ->where('noteable_type', Bill::class)->get(['notes.noteable_id', 'notes.text'])->toArray();
;
foreach ($notes as $note) { foreach ($notes as $note) {
$this->notes[(int) $note['noteable_id']] = (string) $note['text']; $this->notes[(int) $note['noteable_id']] = (string) $note['text'];
} }
@@ -164,8 +163,7 @@ class SubscriptionEnrichment implements EnrichmentInterface
$set = DB::table('object_groupables') $set = DB::table('object_groupables')
->whereIn('object_groupable_id', $this->subscriptionIds) ->whereIn('object_groupable_id', $this->subscriptionIds)
->where('object_groupable_type', Bill::class) ->where('object_groupable_type', Bill::class)
->get(['object_groupable_id', 'object_group_id']) ->get(['object_groupable_id', 'object_group_id']);
;
$ids = array_unique($set->pluck('object_group_id')->toArray()); $ids = array_unique($set->pluck('object_group_id')->toArray());
@@ -224,15 +222,16 @@ class SubscriptionEnrichment implements EnrichmentInterface
'transaction_journals.transaction_group_id', 'transaction_journals.transaction_group_id',
'transactions.transaction_currency_id', 'transactions.transaction_currency_id',
'currency.code AS transaction_currency_code', 'currency.code AS transaction_currency_code',
'currency.symbol AS transaction_currency_symbol',
'currency.decimal_places AS transaction_currency_decimal_places', 'currency.decimal_places AS transaction_currency_decimal_places',
'transactions.foreign_currency_id', 'transactions.foreign_currency_id',
'foreign_currency.code AS foreign_currency_code', 'foreign_currency.code AS foreign_currency_code',
'foreign_currency.symbol AS foreign_currency_symbol',
'foreign_currency.decimal_places AS foreign_currency_decimal_places', 'foreign_currency.decimal_places AS foreign_currency_decimal_places',
'transactions.amount', 'transactions.amount',
'transactions.foreign_amount', 'transactions.foreign_amount',
] ]
) );
;
Log::debug(sprintf('Count %d entries in set', $set->count())); Log::debug(sprintf('Count %d entries in set', $set->count()));
// for each bill, do a loop. // for each bill, do a loop.
@@ -256,26 +255,46 @@ class SubscriptionEnrichment implements EnrichmentInterface
'transaction_journal_id' => (string) $entry->id, 'transaction_journal_id' => (string) $entry->id,
'date' => $entry->date->toAtomString(), 'date' => $entry->date->toAtomString(),
'date_object' => $entry->date, 'date_object' => $entry->date,
'bill_id' => $entry->bill_id, 'subscription_id' => (string) $entry->bill_id,
'currency_id' => $entry->transaction_currency_id, 'currency_id' => (string) $entry->transaction_currency_id,
'currency_code' => $entry->transaction_currency_code, 'currency_code' => $entry->transaction_currency_code,
'currency_symbol' => $entry->transaction_currency_symbol,
'currency_decimal_places' => $entry->transaction_currency_decimal_places, 'currency_decimal_places' => $entry->transaction_currency_decimal_places,
'primary_currency_id' => (string) $this->primaryCurrency->id,
'primary_currency_code' => $this->primaryCurrency->code,
'primary_currency_symbol' => $this->primaryCurrency->symbol,
'primary_currency_decimal_places' => $this->primaryCurrency->decimal_places,
'amount' => Steam::bcround($entry->amount, $entry->transaction_currency_decimal_places), 'amount' => Steam::bcround($entry->amount, $entry->transaction_currency_decimal_places),
'pc_amount' => null,
'foreign_amount' => null,
'pc_foreign_amount' => null,
]; ];
if (null !== $entry->foreign_amount && null !== $entry->foreign_currency_code) { if (null !== $entry->foreign_amount && null !== $entry->foreign_currency_code) {
$array['foreign_currency_id'] = $entry->foreign_currency_id; $array['foreign_currency_id'] = (string) $entry->foreign_currency_id;
$array['foreign_currency_code'] = $entry->foreign_currency_code; $array['foreign_currency_code'] = $entry->foreign_currency_code;
$array['foreign_currency_symbol'] = $entry->foreign_currency_symbol;
$array['foreign_currency_decimal_places'] = $entry->foreign_currency_decimal_places; $array['foreign_currency_decimal_places'] = $entry->foreign_currency_decimal_places;
$array['foreign_amount'] = Steam::bcround($entry->foreign_amount, $entry->foreign_currency_decimal_places); $array['foreign_amount'] = Steam::bcround($entry->foreign_amount, $entry->foreign_currency_decimal_places);
} }
if ($this->convertToPrimary) { // convert to primary, but is already primary.
$array['amount'] = $converter->convert($entry->transactionCurrency, $this->primaryCurrency, $entry->date, $entry->amount); if ($this->convertToPrimary && (int) $entry->transaction_currency_id === $this->primaryCurrency->id) {
$array['currency_id'] = $this->primaryCurrency->id; $array['pc_amount'] = $array['amount'];
$array['currency_code'] = $this->primaryCurrency->code; }
$array['currency_decimal_places'] = $this->primaryCurrency->decimal_places; // convert to primary, but is NOT already primary.
if ($this->convertToPrimary && (int) $entry->transaction_currency_id !== $this->primaryCurrency->id) {
$array['pc_amount'] = $converter->convert($entry->transactionCurrency, $this->primaryCurrency, $entry->date, $entry->amount);
}
// convert to primary, but foreign is already primary.
if ($this->convertToPrimary && (int) $entry->foreign_currency_id === $this->primaryCurrency->id) {
$array['pc_foreign_amount'] = $array['foreign_amount'];
}
// convert to primary, but foreign is NOT already primary.
if ($this->convertToPrimary && null !== $entry->foreign_currency_id && (int) $entry->foreign_currency_id !== $this->primaryCurrency->id) {
// TODO this is very database intensive.
$foreignCurrency = TransactionCurrency::find($entry->foreign_currency_id);
$array['pc_foreign_amount'] = $converter->convert($foreignCurrency, $this->primaryCurrency, $entry->date, $entry->amount);
} }
$result[] = $array; $result[] = $array;
} }
$this->paidDates[(int) $subscription->id] = $result; $this->paidDates[(int) $subscription->id] = $result;

View File

@@ -30,9 +30,6 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\ParameterBag;
/** /**
@@ -63,7 +60,9 @@ class AccountTransformer extends AbstractTransformer
public function transform(Account $account): array public function transform(Account $account): array
{ {
if (null === $account->meta) { if (null === $account->meta) {
$account->meta = []; $account->meta = [
'currency' => null,
];
} }
// get account type: // get account type:
@@ -72,7 +71,7 @@ class AccountTransformer extends AbstractTransformer
$liabilityType = '' === $liabilityType ? null : strtolower($liabilityType); $liabilityType = '' === $liabilityType ? null : strtolower($liabilityType);
$liabilityDirection = $account->meta['liability_direction'] ?? null; $liabilityDirection = $account->meta['liability_direction'] ?? null;
$accountRole = $this->getAccountRole($account, $accountType); $accountRole = $this->getAccountRole($account, $accountType);
$hasCurrencySettings = array_key_exists('currency_id', $account->meta) && (int)$account->meta['currency_id'] > 0; $hasCurrencySettings = null !== $account->meta['currency'];
$includeNetWorth = 1 === (int) ($account->meta['include_net_worth'] ?? 0); $includeNetWorth = 1 === (int) ($account->meta['include_net_worth'] ?? 0);
$longitude = $account->meta['location']['longitude'] ?? null; $longitude = $account->meta['location']['longitude'] ?? null;
$latitude = $account->meta['location']['latitude'] ?? null; $latitude = $account->meta['location']['latitude'] ?? null;
@@ -83,6 +82,12 @@ class AccountTransformer extends AbstractTransformer
$date = $this->getDate(); $date = $this->getDate();
$date->endOfDay(); $date->endOfDay();
// get primary currency as fallback:
$currency = $this->primary; // assume primary currency
if ($hasCurrencySettings) {
$currency = $account->meta['currency'];
}
// no order for some accounts: // no order for some accounts:
if (!in_array(strtolower($accountType), ['liability', 'liabilities', 'asset'], true)) { if (!in_array(strtolower($accountType), ['liability', 'liabilities', 'asset'], true)) {
$order = null; $order = null;
@@ -90,54 +95,9 @@ class AccountTransformer extends AbstractTransformer
// get some listed information from the account meta-data: // get some listed information from the account meta-data:
[$creditCardType, $monthlyPaymentDate] = $this->getCCInfo($account, $accountRole, $accountType); [$creditCardType, $monthlyPaymentDate] = $this->getCCInfo($account, $accountRole, $accountType);
[$openingBalance, $openingBalanceDate] = $this->getOpeningBalance($account, $accountType); $openingBalanceDate = $this->getOpeningBalance($account, $accountType);
[$interest, $interestPeriod] = $this->getInterest($account, $accountType); [$interest, $interestPeriod] = $this->getInterest($account, $accountType);
// get currencies:
$currency = $this->primary; // assume primary currency
if ($hasCurrencySettings) {
$currency = $account->meta['currency'];
}
// get the current balance:
$finalBalance = Steam::finalAccountBalance($account, $date, $this->primary, $this->convertToPrimary);
Log::debug(sprintf('Call finalAccountBalance(%s) with date/time "%s"', var_export($this->convertToPrimary, true), $date->toIso8601String()), $finalBalance);
// collect current balances:
$currentBalance = Steam::bcround($finalBalance[$currency->code] ?? '0', $currency->decimal_places);
$openingBalance = Steam::bcround($openingBalance ?? '0', $currency->decimal_places);
$virtualBalance = Steam::bcround($account->virtual_balance ?? '0', $currency->decimal_places);
$debtAmount = $account->meta['current_debt'] ?? null;
// TODO this currency conversion must not be happening here.
// set some pc_ default values to NULL:
$pcCurrentBalance = null;
$pcOpeningBalance = null;
$pcVirtualBalance = null;
$pcDebtAmount = null;
// convert to primary currency if needed:
if ($this->convertToPrimary && $currency->id !== $this->primary->id) {
Log::debug(sprintf('Convert to primary, from %s to %s', $currency->code, $this->primary->code));
$converter = new ExchangeRateConverter();
$pcCurrentBalance = $converter->convert($currency, $this->primary, $date, $currentBalance);
$pcOpeningBalance = $converter->convert($currency, $this->primary, $date, $openingBalance);
$pcVirtualBalance = $converter->convert($currency, $this->primary, $date, $virtualBalance);
$pcDebtAmount = null === $debtAmount ? null : $converter->convert($currency, $this->primary, $date, $debtAmount);
}
if ($this->convertToPrimary && $currency->id === $this->primary->id) {
$pcCurrentBalance = $currentBalance;
$pcOpeningBalance = $openingBalance;
$pcVirtualBalance = $virtualBalance;
$pcDebtAmount = $debtAmount;
}
// set opening balance(s) to NULL if the date is null
if (null === $openingBalanceDate) {
$openingBalance = null;
$pcOpeningBalance = null;
}
return [ return [
'id' => (string) $account->id, 'id' => (string) $account->id,
'created_at' => $account->created_at->toAtomString(), 'created_at' => $account->created_at->toAtomString(),
@@ -162,17 +122,17 @@ class AccountTransformer extends AbstractTransformer
'primary_currency_decimal_places' => $this->primary->decimal_places, 'primary_currency_decimal_places' => $this->primary->decimal_places,
// balances, structured for 6.3.0. // balances, structured for 6.3.0.
'current_balance' => $currentBalance, 'current_balance' => $account->meta['balances']['current_balance'],
'pc_current_balance' => $pcCurrentBalance, 'pc_current_balance' => $account->meta['balances']['pc_current_balance'],
'opening_balance' => $openingBalance, 'opening_balance' => $account->meta['balances']['opening_balance'],
'pc_opening_balance' => $pcOpeningBalance, 'pc_opening_balance' => $account->meta['balances']['pc_opening_balance'],
'virtual_balance' => $virtualBalance, 'virtual_balance' => $account->meta['balances']['virtual_balance'],
'pc_virtual_balance' => $pcVirtualBalance, 'pc_virtual_balance' => $account->meta['balances']['pc_virtual_balance'],
'debt_amount' => $debtAmount, 'debt_amount' => $account->meta['balances']['debt_amount'],
'pc_debt_amount' => $pcDebtAmount, 'pc_debt_amount' => $account->meta['balances']['pc_debt_amount'],
'current_balance_date' => $date->toAtomString(), 'current_balance_date' => $date->toAtomString(),
'notes' => $account->meta['notes'] ?? null, 'notes' => $account->meta['notes'] ?? null,
@@ -247,15 +207,10 @@ class AccountTransformer extends AbstractTransformer
return [$creditCardType, $monthlyPaymentDate]; return [$creditCardType, $monthlyPaymentDate];
} }
private function getOpeningBalance(Account $account, string $accountType): array private function getOpeningBalance(Account $account, string $accountType): ?string
{ {
$openingBalance = null;
$openingBalanceDate = null; $openingBalanceDate = null;
// $pcOpeningBalance = null;
if (in_array($accountType, ['asset', 'liabilities'], true)) { if (in_array($accountType, ['asset', 'liabilities'], true)) {
// grab from meta.
$openingBalance = $account->meta['opening_balance_amount'] ?? null;
$pcOpeningBalance = null;
$openingBalanceDate = $account->meta['opening_balance_date'] ?? null; $openingBalanceDate = $account->meta['opening_balance_date'] ?? null;
} }
if (null !== $openingBalanceDate) { if (null !== $openingBalanceDate) {
@@ -265,15 +220,9 @@ class AccountTransformer extends AbstractTransformer
} }
$openingBalanceDate = $object->toAtomString(); $openingBalanceDate = $object->toAtomString();
// NOW do conversion.
// if ($this->convertToPrimary && null !== $account->meta['currency']) {
// $converter = new ExchangeRateConverter();
// $pcOpeningBalance = $converter->convert($account->meta['currency'], $this->primary, $object, $openingBalance);
// }
} }
return [$openingBalance, $openingBalanceDate]; return $openingBalanceDate;
} }
private function getInterest(Account $account, string $accountType): array private function getInterest(Account $account, string $accountType): array