fix: holding calculations
This commit is contained in:
+80
-54
@@ -246,8 +246,6 @@ class Holding extends Model
|
||||
return $query->select([
|
||||
'holdings.symbol',
|
||||
'holdings.portfolio_id',
|
||||
'transactions_display.total_cost_basis',
|
||||
'transactions_display.realized_gain_dollars',
|
||||
'dividends_display.total_dividends_earned',
|
||||
])
|
||||
->groupBy([
|
||||
@@ -255,8 +253,6 @@ class Holding extends Model
|
||||
'holdings.quantity',
|
||||
'holdings.portfolio_id',
|
||||
'cr.rate',
|
||||
'transactions_display.total_cost_basis',
|
||||
'transactions_display.realized_gain_dollars',
|
||||
'dividends_display.total_dividends_earned',
|
||||
'market_data.market_value_base',
|
||||
])
|
||||
@@ -264,10 +260,10 @@ class Holding extends Model
|
||||
$join->where('cr.currency', '=', $currency);
|
||||
|
||||
if (config('database.default') === 'sqlite') {
|
||||
|
||||
$join->whereRaw("strftime('%Y-%m-%d', cr.date) = ?", [now()->toDateString()]);
|
||||
$join->whereRaw("strftime('%Y-%m-%d', cr.date) = ?", [
|
||||
now()->toDateString(),
|
||||
]);
|
||||
} else {
|
||||
|
||||
$join->on('cr.date', '=', DB::raw("'".now()->toDateString()."'"));
|
||||
}
|
||||
})
|
||||
@@ -277,16 +273,29 @@ class Holding extends Model
|
||||
->selectRaw(
|
||||
'holdings.quantity * market_data.market_value_base * COALESCE(cr.rate, 1) AS total_market_value'
|
||||
)
|
||||
->selectRaw('(
|
||||
holdings.quantity * market_data.market_value_base * COALESCE(cr.rate, 1)
|
||||
) - transactions_display.total_cost_basis as total_gain_dollars')
|
||||
->selectRaw(
|
||||
'SUM(transactions_display.realized_gain_dollars) * COALESCE(cr.rate, 1) AS realized_gain_dollars'
|
||||
)
|
||||
->selectRaw(
|
||||
'(SUM(transactions_display.total_cost_basis) / SUM(transactions_display.total_purchases)) * holdings.quantity AS total_cost_basis'
|
||||
)
|
||||
->selectRaw(
|
||||
'(
|
||||
holdings.quantity * market_data.market_value_base * COALESCE(cr.rate, 1)
|
||||
) - (SUM(transactions_display.total_cost_basis) / SUM(transactions_display.total_purchases)) * holdings.quantity AS total_gain_dollars'
|
||||
)
|
||||
->leftJoinSub(
|
||||
DB::table('transactions')
|
||||
->leftJoin('currency_rates as cr', function ($join) use ($currency) {
|
||||
$join->on('cr.date', '=', 'transactions.date')
|
||||
$join
|
||||
->on('cr.date', '=', 'transactions.date')
|
||||
->where('cr.currency', '=', $currency);
|
||||
})
|
||||
->select(['transactions.symbol', 'transactions.portfolio_id'])
|
||||
->select([
|
||||
'transactions.id',
|
||||
'transactions.symbol',
|
||||
'transactions.portfolio_id',
|
||||
])
|
||||
->leftJoinSub(
|
||||
DB::table('transactions')
|
||||
->leftJoin('currency_rates as cr', function ($join) use ($currency) {
|
||||
@@ -298,71 +307,87 @@ class Holding extends Model
|
||||
'transactions.symbol',
|
||||
'transactions.portfolio_id',
|
||||
'transactions.quantity',
|
||||
'transactions.cost_basis_base',
|
||||
'transactions.date',
|
||||
])
|
||||
->selectRaw(
|
||||
"(CASE
|
||||
WHEN
|
||||
transactions.transaction_type = 'BUY'
|
||||
OR SUM(transactions.cost_basis_base) = 0
|
||||
THEN
|
||||
COALESCE(cr.rate, 1)
|
||||
ELSE (
|
||||
SELECT
|
||||
SUM(COALESCE(cr2.rate, 1) * buy.cost_basis_base)
|
||||
/ SUM(buy.cost_basis_base)
|
||||
FROM transactions as buy
|
||||
LEFT JOIN currency_rates as cr2
|
||||
ON cr2.date = buy.date
|
||||
AND cr2.currency = '{$currency}'
|
||||
WHERE buy.symbol = transactions.symbol
|
||||
AND buy.portfolio_id = transactions.portfolio_id
|
||||
AND buy.transaction_type = 'BUY'
|
||||
AND buy.date <= transactions.date
|
||||
) END)
|
||||
AS rate"
|
||||
)
|
||||
->selectRaw(
|
||||
"CASE
|
||||
WHEN transactions.transaction_type = 'BUY'
|
||||
THEN transactions.quantity
|
||||
ELSE -transactions.quantity
|
||||
END
|
||||
AS remaining_quantity"
|
||||
)
|
||||
->selectRaw("
|
||||
(CASE
|
||||
WHEN
|
||||
transactions.transaction_type = 'BUY'
|
||||
OR SUM(transactions.cost_basis_base) = 0
|
||||
THEN
|
||||
COALESCE(cr.rate, 1)
|
||||
ELSE (
|
||||
SELECT
|
||||
SUM(COALESCE(cr2.rate, 1) * buy.cost_basis_base)
|
||||
/ SUM(buy.cost_basis_base)
|
||||
FROM transactions as buy
|
||||
LEFT JOIN currency_rates as cr2
|
||||
ON cr2.date = buy.date
|
||||
AND cr2.currency = '{$currency}'
|
||||
WHERE buy.symbol = transactions.symbol
|
||||
AND buy.portfolio_id = transactions.portfolio_id
|
||||
AND buy.transaction_type = 'BUY'
|
||||
AND buy.date <= transactions.date
|
||||
) END)
|
||||
AS rate")
|
||||
->groupBy([
|
||||
'transactions.id',
|
||||
'transactions.symbol',
|
||||
'transactions.date',
|
||||
'transactions.portfolio_id',
|
||||
'transactions.transaction_type',
|
||||
'transactions.cost_basis_base',
|
||||
'transactions.quantity',
|
||||
'cr.rate',
|
||||
]), 'cost_basis_display', function ($join) {
|
||||
$join->on('transactions.symbol', '=', 'cost_basis_display.symbol')
|
||||
->on('transactions.portfolio_id', '=', 'cost_basis_display.portfolio_id')
|
||||
->on('transactions.date', '=', 'cost_basis_display.date');
|
||||
})
|
||||
->selectRaw(
|
||||
"SUM(CASE WHEN transactions.transaction_type = 'SELL' THEN (transactions.sale_price_base - transactions.cost_basis_base) * transactions.quantity * COALESCE(cr.rate, 1) ELSE 0 END) AS realized_gain_dollars"
|
||||
]),
|
||||
'cost_basis_display',
|
||||
function ($join) {
|
||||
$join
|
||||
->on('transactions.symbol', '=', 'cost_basis_display.symbol')
|
||||
->on(
|
||||
'transactions.portfolio_id',
|
||||
'=',
|
||||
'cost_basis_display.portfolio_id'
|
||||
)
|
||||
->on('transactions.date', '=', 'cost_basis_display.date');
|
||||
}
|
||||
)
|
||||
->selectRaw(
|
||||
"SUM(CASE WHEN transactions.transaction_type = 'BUY' THEN transactions.cost_basis_base * transactions.quantity * cost_basis_display.rate END) / SUM(CASE WHEN transactions.transaction_type = 'BUY' THEN transactions.quantity END) * SUM(cost_basis_display.remaining_quantity) AS total_cost_basis"
|
||||
"CASE WHEN transactions.transaction_type = 'SELL' THEN (transactions.sale_price_base - transactions.cost_basis_base) * transactions.quantity * COALESCE(cr.rate, 1) END AS realized_gain_dollars"
|
||||
)
|
||||
->groupBy(['transactions.symbol', 'transactions.portfolio_id']),
|
||||
->selectRaw(
|
||||
"CASE WHEN transactions.transaction_type = 'BUY' THEN transactions.cost_basis_base * transactions.quantity * cost_basis_display.rate END AS total_cost_basis"
|
||||
)
|
||||
->selectRaw(
|
||||
"CASE WHEN transactions.transaction_type = 'BUY' THEN transactions.quantity END AS total_purchases"
|
||||
)
|
||||
->groupBy([
|
||||
'transactions.id',
|
||||
'transactions.symbol',
|
||||
'transactions.portfolio_id',
|
||||
'transactions.cost_basis_base',
|
||||
'transactions.quantity',
|
||||
'cost_basis_display.rate',
|
||||
'cr.rate',
|
||||
]),
|
||||
'transactions_display',
|
||||
function ($join) {
|
||||
$join->on('holdings.symbol', '=', 'transactions_display.symbol')
|
||||
$join
|
||||
->on('holdings.symbol', '=', 'transactions_display.symbol')
|
||||
->on('holdings.portfolio_id', '=', 'transactions_display.portfolio_id');
|
||||
}
|
||||
)
|
||||
->leftJoinSub(
|
||||
DB::table('dividends')
|
||||
->join('transactions as tx', function ($join) {
|
||||
$join->on('tx.symbol', '=', 'dividends.symbol')
|
||||
$join
|
||||
->on('tx.symbol', '=', 'dividends.symbol')
|
||||
->on('tx.date', '<=', 'dividends.date');
|
||||
})
|
||||
->leftJoin('currency_rates as cr', function ($join) use ($currency) {
|
||||
$join->on('cr.date', '=', 'dividends.date')
|
||||
$join
|
||||
->on('cr.date', '=', 'dividends.date')
|
||||
->where('cr.currency', '=', $currency);
|
||||
})
|
||||
->select(['dividends.symbol'])
|
||||
@@ -375,6 +400,7 @@ class Holding extends Model
|
||||
$join->on('holdings.symbol', '=', 'dividends_display.symbol');
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public function syncTransactionsAndDividends()
|
||||
|
||||
Reference in New Issue
Block a user