12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- <?php
-
- namespace App\Casts;
-
- use App\Models\Banking\BankAccount;
- use App\Utilities\Currency\CurrencyAccessor;
- use App\Utilities\Currency\CurrencyConverter;
- use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
- use Illuminate\Database\Eloquent\Model;
- use UnexpectedValueException;
-
- class TransactionAmountCast implements CastsAttributes
- {
- /**
- * Static cache to persist across instances
- */
- private static array $currencyCache = [];
-
- /**
- * Eagerly load all required bank accounts at once if needed
- */
- private function loadMissingBankAccounts(array $ids): void
- {
- $missingIds = array_filter($ids, static fn ($id) => ! isset(self::$currencyCache[$id]) && $id !== null);
-
- if (empty($missingIds)) {
- return;
- }
-
- /** @var BankAccount[] $accounts */
- $accounts = BankAccount::with('account')
- ->whereIn('id', $missingIds)
- ->get();
-
- foreach ($accounts as $account) {
- self::$currencyCache[$account->id] = $account->account->currency_code ?? CurrencyAccessor::getDefaultCurrency();
- }
- }
-
- public function get(Model $model, string $key, mixed $value, array $attributes): string
- {
- // Attempt to retrieve the currency code from the related bankAccount->account model
- $bankAccountId = $attributes['bank_account_id'] ?? null;
-
- if ($bankAccountId !== null && ! isset(self::$currencyCache[$bankAccountId])) {
- $this->loadMissingBankAccounts([$bankAccountId]);
- }
-
- $currencyCode = $this->getCurrencyCodeFromBankAccountId($bankAccountId);
-
- if ($value !== null) {
- return CurrencyConverter::prepareForMutator($value, $currencyCode);
- }
-
- return '';
- }
-
- /**
- * @throws UnexpectedValueException
- */
- public function set(Model $model, string $key, mixed $value, array $attributes): int
- {
- $bankAccountId = $attributes['bank_account_id'] ?? null;
-
- if ($bankAccountId !== null && ! isset(self::$currencyCache[$bankAccountId])) {
- $this->loadMissingBankAccounts([$bankAccountId]);
- }
-
- $currencyCode = $this->getCurrencyCodeFromBankAccountId($bankAccountId);
-
- if (is_numeric($value)) {
- $value = (string) $value;
- } elseif (! is_string($value)) {
- throw new UnexpectedValueException('Expected string or numeric value for money cast');
- }
-
- return CurrencyConverter::prepareForAccessor($value, $currencyCode);
- }
-
- /**
- * Get currency code from the cache or use default
- */
- private function getCurrencyCodeFromBankAccountId(?int $bankAccountId): string
- {
- if ($bankAccountId === null) {
- return CurrencyAccessor::getDefaultCurrency();
- }
-
- return self::$currencyCache[$bankAccountId] ?? CurrencyAccessor::getDefaultCurrency();
- }
- }
|