Feat: Adds multi currency support (#88)
This commit is contained in:
+22
-41
@@ -4,18 +4,24 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Actions\ConvertToMarketDataCurrency;
|
||||
use App\Actions\CopyToBaseCurrency;
|
||||
use App\Actions\EnsureCostBasisAddedToSale;
|
||||
use App\Casts\BaseCurrency;
|
||||
use App\Traits\HasMarketData;
|
||||
use Illuminate\Contracts\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Pipeline;
|
||||
|
||||
class Transaction extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use HasMarketData;
|
||||
use HasUuids;
|
||||
|
||||
protected $fillable = [
|
||||
@@ -23,6 +29,7 @@ class Transaction extends Model
|
||||
'date',
|
||||
'portfolio_id',
|
||||
'transaction_type',
|
||||
'currency',
|
||||
'quantity',
|
||||
'cost_basis',
|
||||
'sale_price',
|
||||
@@ -36,6 +43,11 @@ class Transaction extends Model
|
||||
'date' => 'datetime',
|
||||
'split' => 'boolean',
|
||||
'reinvested_dividend' => 'boolean',
|
||||
'quantity' => 'float',
|
||||
'cost_basis' => 'float',
|
||||
'sale_price' => 'float',
|
||||
'cost_basis_base' => BaseCurrency::class,
|
||||
'sale_price_base' => BaseCurrency::class,
|
||||
];
|
||||
|
||||
protected static function boot()
|
||||
@@ -44,18 +56,19 @@ class Transaction extends Model
|
||||
|
||||
static::saving(function ($transaction) {
|
||||
|
||||
if ($transaction->transaction_type == 'SELL') {
|
||||
|
||||
$transaction->ensureCostBasisIsAddedToSale();
|
||||
}
|
||||
$transaction = Pipeline::send($transaction)
|
||||
->through([
|
||||
ConvertToMarketDataCurrency::class,
|
||||
EnsureCostBasisAddedToSale::class,
|
||||
CopyToBaseCurrency::class,
|
||||
])
|
||||
->then(fn (Transaction $transaction) => $transaction);
|
||||
});
|
||||
|
||||
static::saved(function ($transaction) {
|
||||
|
||||
$transaction->syncToHolding();
|
||||
|
||||
$transaction->refreshMarketData();
|
||||
|
||||
cache()->forget('portfolio-metrics-'.$transaction->portfolio_id);
|
||||
});
|
||||
|
||||
@@ -77,16 +90,6 @@ class Transaction extends Model
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Related market data for transaction
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function market_data(): HasOne
|
||||
{
|
||||
return $this->hasOne(MarketData::class, 'symbol', 'symbol');
|
||||
}
|
||||
|
||||
/**
|
||||
* Related portfolio
|
||||
*
|
||||
@@ -141,28 +144,6 @@ class Transaction extends Model
|
||||
});
|
||||
}
|
||||
|
||||
public function refreshMarketData(): void
|
||||
{
|
||||
MarketData::getMarketData($this->attributes['symbol']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes average cost basis to a sale transaction
|
||||
*/
|
||||
public function ensureCostBasisIsAddedToSale(): Transaction
|
||||
{
|
||||
$average_cost_basis = Transaction::where([
|
||||
'portfolio_id' => $this->portfolio_id,
|
||||
'symbol' => $this->symbol,
|
||||
'transaction_type' => 'BUY',
|
||||
])->whereDate('date', '<=', $this->date)
|
||||
->average('cost_basis');
|
||||
|
||||
$this->cost_basis = $average_cost_basis ?? 0;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs the holding related to this transaction
|
||||
*/
|
||||
@@ -187,8 +168,8 @@ class Transaction extends Model
|
||||
'portfolio_id' => $this->portfolio_id,
|
||||
'symbol' => $this->symbol,
|
||||
'quantity' => $this->quantity,
|
||||
'average_cost_basis' => $this->cost_basis,
|
||||
'total_cost_basis' => $this->quantity * $this->cost_basis,
|
||||
'average_cost_basis' => $this->cost_basis_base,
|
||||
'total_cost_basis' => $this->quantity * $this->cost_basis_base,
|
||||
'splits_synced_at' => now(),
|
||||
])->syncTransactionsAndDividends();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user