. */ declare(strict_types=1); namespace FireflyIII\Transformers; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use JsonException; use Symfony\Component\HttpFoundation\ParameterBag; /** * Class AccountTransformer */ class AccountTransformer extends AbstractTransformer { protected AccountRepositoryInterface $repository; /** * * AccountTransformer constructor. * */ public function __construct() { $this->parameters = new ParameterBag(); $this->repository = app(AccountRepositoryInterface::class); } /** * Transform the account. * * @param Account $account * * @return array * @throws FireflyException * @throws JsonException */ public function transform(Account $account): array { $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'); // get account role (will only work if the type is asset. $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); $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; $zoomLevel = (int)$location->zoom_level; } // no order for some accounts: $order = $account->order; if (!in_array(strtolower($accountType), ['liability', 'liabilities', 'asset'], true)) { $order = 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(app('steam')->balance($account, $date), $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' => [ [ 'rel' => 'self', 'uri' => '/accounts/' . $account->id, ], ], ]; } /** * @param Account $account * * @param string $accountType * * @return string|null */ private function getAccountRole(Account $account, string $accountType): ?string { $accountRole = $this->repository->getMetaValue($account, 'account_role'); if ('asset' !== $accountType || '' === (string)$accountRole) { $accountRole = null; } return $accountRole; } /** * TODO duplicated in the V2 transformer. * * @return Carbon */ private function getDate(): Carbon { $date = today(config('app.timezone')); if (null !== $this->parameters->get('date')) { $date = $this->parameters->get('date'); } return $date; } /** * @param Account $account * * @return array * @throws FireflyException * @throws JsonException */ private function getCurrency(Account $account): array { $currency = $this->repository->getAccountCurrency($account); // only grab default when result is null: if (null === $currency) { $currency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup); } $currencyId = (string)$currency->id; $currencyCode = $currency->code; $decimalPlaces = $currency->decimal_places; $currencySymbol = $currency->symbol; return [$currencyId, $currencyCode, $currencySymbol, $decimalPlaces]; } /** * @param Account $account * @param string|null $accountRole * @param string $accountType * * @return array */ private function getCCInfo(Account $account, ?string $accountRole, string $accountType): array { $monthlyPaymentDate = null; $creditCardType = null; if ('ccAsset' === $accountRole && 'asset' === $accountType) { $creditCardType = $this->repository->getMetaValue($account, 'cc_type'); $monthlyPaymentDate = $this->repository->getMetaValue($account, 'cc_monthly_payment_date'); } if (null !== $monthlyPaymentDate) { // try classic date: if (10 === strlen($monthlyPaymentDate)) { $monthlyPaymentDate = Carbon::createFromFormat('!Y-m-d', $monthlyPaymentDate, config('app.timezone'))->toAtomString(); } if (10 !== strlen($monthlyPaymentDate)) { $monthlyPaymentDate = Carbon::parse($monthlyPaymentDate, config('app.timezone'))->toAtomString(); } } return [$creditCardType, $monthlyPaymentDate]; } /** * @param Account $account * @param string $accountType * * @return array * * TODO refactor call to get~OpeningBalanceAmount / Date because it is a lot of queries. */ private function getOpeningBalance(Account $account, string $accountType): array { $openingBalance = null; $openingBalanceDate = null; if (in_array($accountType, ['asset', 'liabilities'], true)) { $amount = $this->repository->getOpeningBalanceAmount($account); $openingBalance = $amount; $openingBalanceDate = $this->repository->getOpeningBalanceDate($account); } if (null !== $openingBalanceDate) { $openingBalanceDate = Carbon::createFromFormat('Y-m-d H:i:s', $openingBalanceDate, config('app.timezone'))->toAtomString(); } return [$openingBalance, $openingBalanceDate]; } /** * @param Account $account * @param string $accountType * * @return array */ private function getInterest(Account $account, string $accountType): array { $interest = null; $interestPeriod = null; if ('liabilities' === $accountType) { $interest = $this->repository->getMetaValue($account, 'interest'); $interestPeriod = $this->repository->getMetaValue($account, 'interest_period'); } return [$interest, $interestPeriod]; } }