'datetime', 'password' => 'hashed', 'admin' => 'boolean', 'options' => 'json', ]; } public function portfolios() { return $this->belongsToMany(Portfolio::class)->withPivot(['owner', 'full_access', 'invite_accepted_at']); } public function daily_changes() { return $this->hasManyDeep(DailyChange::class, ['portfolio_user', Portfolio::class]); } public function holdings(): HasManyDeep { return $this->hasManyDeep(Holding::class, ['portfolio_user', Portfolio::class]) ->withMarketData() ->withPerformance(); } public function transactions(): HasManyDeep { return $this->hasManyDeep(Transaction::class, ['portfolio_user', Portfolio::class]) ->withMarketData() ->withAggregate('portfolio', 'title') ->selectRaw(' CASE WHEN transaction_type = \'SELL\' THEN COALESCE(transactions.sale_price - transactions.cost_basis, 0) ELSE COALESCE(market_data.market_value - transactions.cost_basis, 0) END AS gain_dollars'); } public function getCurrency(): string { return Arr::get($this->options, 'display_currency') ?? config('investbrain.base_currency'); } public function getLocale(): string { $available_locales = Arr::pluck(config('app.available_locales'), 'locale'); return Arr::get($this->options, 'locale') ?? request()->getPreferredLanguage($available_locales) ?? config('app.locale'); } public function setOption(mixed $key, string $value): self { $options = is_array($key) ? $key : [$key => $value]; $this->user->options = array_merge($this->user->options ?? [], $options); return $this; } }