chore: code style
This commit is contained in:
+59
-66
@@ -2,17 +2,16 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\AiChat;
|
||||
use App\Interfaces\MarketData\MarketDataInterface;
|
||||
use App\Notifications\InvitedOnboardingNotification;
|
||||
use Carbon\CarbonPeriod;
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Interfaces\MarketData\MarketDataInterface;
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||
use App\Notifications\InvitedOnboardingNotification;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class Portfolio extends Model
|
||||
{
|
||||
@@ -30,7 +29,7 @@ class Portfolio extends Model
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
|
||||
static::saved(function ($portfolio) {
|
||||
|
||||
self::ensurePortfolioHasOwner($portfolio);
|
||||
@@ -40,7 +39,7 @@ class Portfolio extends Model
|
||||
protected $hidden = [];
|
||||
|
||||
protected $casts = [
|
||||
'wishlist' => 'boolean'
|
||||
'wishlist' => 'boolean',
|
||||
];
|
||||
|
||||
protected $with = ['users', 'transactions'];
|
||||
@@ -53,8 +52,8 @@ class Portfolio extends Model
|
||||
public function holdings()
|
||||
{
|
||||
return $this->hasMany(Holding::class, 'portfolio_id')
|
||||
->withMarketData()
|
||||
->withPerformance();
|
||||
->withMarketData()
|
||||
->withPerformance();
|
||||
}
|
||||
|
||||
public function transactions()
|
||||
@@ -77,25 +76,25 @@ class Portfolio extends Model
|
||||
return $this->morphMany(AiChat::class, 'chatable')->where('user_id', auth()->user()->id);
|
||||
}
|
||||
|
||||
public function scopeMyPortfolios()
|
||||
public function scopeMyPortfolios()
|
||||
{
|
||||
return $this->whereHas('users', function ($query) {
|
||||
$query->where('user_id', auth()->user()->id);
|
||||
});
|
||||
}
|
||||
|
||||
public function scopeFullAccess($query, $user_id = null)
|
||||
public function scopeFullAccess($query, $user_id = null)
|
||||
{
|
||||
return $query->whereHas('users', function ($query) use ($user_id) {
|
||||
$query->where('user_id', $user_id ?? auth()->user()->id)
|
||||
->where(function ($query) {
|
||||
$query->where('full_access', true)
|
||||
->orWhere('owner', true);
|
||||
});
|
||||
->where(function ($query) {
|
||||
$query->where('full_access', true)
|
||||
->orWhere('owner', true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public function scopeWithoutWishlists()
|
||||
public function scopeWithoutWishlists()
|
||||
{
|
||||
return $this->where(['wishlist' => false]);
|
||||
}
|
||||
@@ -103,7 +102,7 @@ class Portfolio extends Model
|
||||
public function setOwnerIdAttribute($value)
|
||||
{
|
||||
// enable queued jobs to create portfolios with owners
|
||||
if (!auth()->user()?->id && !$this->owner_id) {
|
||||
if (! auth()->user()?->id && ! $this->owner_id) {
|
||||
static::$owner_id = $value;
|
||||
}
|
||||
}
|
||||
@@ -115,18 +114,18 @@ class Portfolio extends Model
|
||||
|
||||
public function getOwnerAttribute()
|
||||
{
|
||||
if (!$this->relationLoaded('user')) {
|
||||
|
||||
if (! $this->relationLoaded('user')) {
|
||||
|
||||
$this->load('users');
|
||||
}
|
||||
|
||||
return $this->users->where('pivot.owner', true)->first();
|
||||
}
|
||||
|
||||
public static function ensurePortfolioHasOwner(self $portfolio)
|
||||
public static function ensurePortfolioHasOwner(self $portfolio)
|
||||
{
|
||||
// make sure we don't remove owner access
|
||||
if (!$portfolio->owner_id) {
|
||||
if (! $portfolio->owner_id) {
|
||||
$owner[static::$owner_id ?? auth()->user()->id] = ['owner' => true];
|
||||
|
||||
// save
|
||||
@@ -138,24 +137,24 @@ class Portfolio extends Model
|
||||
public function syncDailyChanges(): void
|
||||
{
|
||||
$holdings = $this->holdings()
|
||||
->join('transactions', function($join) {
|
||||
$join->on('transactions.symbol', '=', 'holdings.symbol')
|
||||
->where('transactions.portfolio_id', '=', $this->id);
|
||||
})
|
||||
->select('holdings.symbol', 'holdings.portfolio_id', DB::raw('min(transactions.date) as first_transaction_date')) // get first transaction date
|
||||
->groupBy(['holdings.symbol', 'holdings.portfolio_id'])
|
||||
->get();
|
||||
->join('transactions', function ($join) {
|
||||
$join->on('transactions.symbol', '=', 'holdings.symbol')
|
||||
->where('transactions.portfolio_id', '=', $this->id);
|
||||
})
|
||||
->select('holdings.symbol', 'holdings.portfolio_id', DB::raw('min(transactions.date) as first_transaction_date')) // get first transaction date
|
||||
->groupBy(['holdings.symbol', 'holdings.portfolio_id'])
|
||||
->get();
|
||||
|
||||
$dividends = Dividend::whereIn('symbol', $holdings->pluck('symbol'))->get();
|
||||
|
||||
|
||||
$total_performance = [];
|
||||
|
||||
$holdings->each(function($holding) use (&$total_performance, $dividends) {
|
||||
$holdings->each(function ($holding) use (&$total_performance, $dividends) {
|
||||
|
||||
$period = CarbonPeriod::create(
|
||||
$holding->first_transaction_date,
|
||||
now()->isBefore(Carbon::parse(config('investbrain.daily_change_time_of_day')))
|
||||
? now()->subDay()
|
||||
$holding->first_transaction_date,
|
||||
now()->isBefore(Carbon::parse(config('investbrain.daily_change_time_of_day')))
|
||||
? now()->subDay()
|
||||
: now()
|
||||
);
|
||||
|
||||
@@ -170,11 +169,11 @@ class Portfolio extends Model
|
||||
$dividends_earned = 0;
|
||||
$holding_performance = [];
|
||||
|
||||
foreach($period as $date) {
|
||||
foreach ($period as $date) {
|
||||
$date = $date->format('Y-m-d');
|
||||
|
||||
$close = $this->getMostRecentCloseData($all_history, $date);
|
||||
|
||||
|
||||
$total_market_value = $daily_performance->get($date)->owned * $close;
|
||||
$dividends_earned += $daily_performance->get($date)->owned * ($dividends->get($date)?->dividend_amount ?? 0);
|
||||
|
||||
@@ -182,18 +181,18 @@ class Portfolio extends Model
|
||||
$holding_performance[$date] = [
|
||||
'date' => $date,
|
||||
'portfolio_id' => $this->id,
|
||||
'total_market_value' => $total_market_value,
|
||||
'total_market_value' => $total_market_value,
|
||||
'total_cost_basis' => $daily_performance->get($date)->cost_basis,
|
||||
'total_gain' => $total_market_value - $daily_performance->get($date)->cost_basis,
|
||||
'realized_gains' => $daily_performance->get($date)->realized_gains,
|
||||
'total_dividends_earned' => $dividends_earned
|
||||
'total_dividends_earned' => $dividends_earned,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($holding_performance as $date => $performance) {
|
||||
if (Arr::get($total_performance, $date) == null) {
|
||||
|
||||
|
||||
$total_performance[$date] = $performance;
|
||||
|
||||
} else {
|
||||
@@ -207,9 +206,9 @@ class Portfolio extends Model
|
||||
}
|
||||
});
|
||||
|
||||
if (!empty($total_performance)) {
|
||||
if (! empty($total_performance)) {
|
||||
DB::transaction(function () use ($total_performance) {
|
||||
|
||||
|
||||
$this->daily_change()->upsert(
|
||||
$total_performance,
|
||||
['date', 'portfolio_id'],
|
||||
@@ -218,7 +217,7 @@ class Portfolio extends Model
|
||||
'total_cost_basis',
|
||||
'total_gain',
|
||||
'realized_gains',
|
||||
'total_dividends_earned'
|
||||
'total_dividends_earned',
|
||||
]
|
||||
);
|
||||
});
|
||||
@@ -229,10 +228,10 @@ class Portfolio extends Model
|
||||
{
|
||||
$close = Arr::get($history, "$date.close", 0);
|
||||
|
||||
if (!$close && $i < $max_attempts) {
|
||||
if (! $close && $i < $max_attempts) {
|
||||
|
||||
$i++;
|
||||
|
||||
|
||||
$date = Carbon::parse($date)->subDay()->format('Y-m-d');
|
||||
|
||||
return $this->getMostRecentCloseData($history, $date, $i);
|
||||
@@ -244,53 +243,47 @@ class Portfolio extends Model
|
||||
public function getFormattedHoldings()
|
||||
{
|
||||
$formattedHoldings = '';
|
||||
foreach($this->holdings as $holding) {
|
||||
$formattedHoldings .= " * Holding of ".$holding->market_data->name." (".$holding->symbol.")"
|
||||
."; with ". ($holding->quantity > 0 ? $holding->quantity : 'ZERO') . " shares"
|
||||
."; avg cost basis ". $holding->average_cost_basis
|
||||
."; curr market value ". $holding->market_data->market_value
|
||||
."; unrealized gains ". $holding->market_gain_dollars
|
||||
."; realized gains ". $holding->realized_gain_dollars
|
||||
."; dividends earned ". $holding->dividends_earned
|
||||
foreach ($this->holdings as $holding) {
|
||||
$formattedHoldings .= ' * Holding of '.$holding->market_data->name.' ('.$holding->symbol.')'
|
||||
.'; with '.($holding->quantity > 0 ? $holding->quantity : 'ZERO').' shares'
|
||||
.'; avg cost basis '.$holding->average_cost_basis
|
||||
.'; curr market value '.$holding->market_data->market_value
|
||||
.'; unrealized gains '.$holding->market_gain_dollars
|
||||
.'; realized gains '.$holding->realized_gain_dollars
|
||||
.'; dividends earned '.$holding->dividends_earned
|
||||
."\n\n";
|
||||
}
|
||||
|
||||
return $formattedHoldings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Share a portfolio with a user
|
||||
*
|
||||
* @param string $email
|
||||
* @param boolean $fullAccess
|
||||
* @return void
|
||||
*/
|
||||
public function share(string $email, bool $fullAccess = false): void
|
||||
{
|
||||
$user = User::firstOrCreate([
|
||||
'email' => $email
|
||||
'email' => $email,
|
||||
], [
|
||||
'name' => Str::title(Str::before($email, '@'))
|
||||
'name' => Str::title(Str::before($email, '@')),
|
||||
]);
|
||||
|
||||
$permissions[$user->id] = [
|
||||
'full_access' => $fullAccess
|
||||
'full_access' => $fullAccess,
|
||||
];
|
||||
|
||||
$sync = $this->users()->syncWithoutDetaching($permissions);
|
||||
|
||||
if (!empty($sync['attached'])) {
|
||||
if (! empty($sync['attached'])) {
|
||||
|
||||
foreach($sync['attached'] as $newUserId) {
|
||||
foreach ($sync['attached'] as $newUserId) {
|
||||
User::find($newUserId)->notify(new InvitedOnboardingNotification($this, auth()->user()));
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Un-share a portfolio
|
||||
*
|
||||
* @param string $userId
|
||||
* @return void
|
||||
*/
|
||||
public function unShare(string $userId): void
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user