diff --git a/app/Exports/Sheets/DailyChangesSheet.php b/app/Exports/Sheets/DailyChangesSheet.php
index 586cfb2..aa8a768 100644
--- a/app/Exports/Sheets/DailyChangesSheet.php
+++ b/app/Exports/Sheets/DailyChangesSheet.php
@@ -13,10 +13,10 @@ class DailyChangesSheet implements FromCollection, WithHeadings, WithTitle
{
return [
'Date',
- 'Portfolio',
+ 'Portfolio ID',
'Total Market Value',
'Total Cost Basis',
- 'Total Gain Loss',
+ 'Total Gain',
'Total Dividends',
'Realized Gains',
'Annotation'
@@ -28,7 +28,7 @@ class DailyChangesSheet implements FromCollection, WithHeadings, WithTitle
*/
public function collection()
{
- return auth()->user()->daily_changes;
+ return DailyChange::myDailyChanges()->get();
}
/**
diff --git a/app/Exports/Sheets/PortfoliosSheet.php b/app/Exports/Sheets/PortfoliosSheet.php
index 3116e07..f352a05 100644
--- a/app/Exports/Sheets/PortfoliosSheet.php
+++ b/app/Exports/Sheets/PortfoliosSheet.php
@@ -26,7 +26,7 @@ class PortfoliosSheet implements FromCollection, WithHeadings, WithTitle
*/
public function collection()
{
- return auth()->user()->portfolios;
+ return Portfolio::myPortfolios()->get();
}
/**
diff --git a/app/Exports/Sheets/TransactionsSheet.php b/app/Exports/Sheets/TransactionsSheet.php
index 13bfd1c..f4f1a25 100644
--- a/app/Exports/Sheets/TransactionsSheet.php
+++ b/app/Exports/Sheets/TransactionsSheet.php
@@ -2,10 +2,11 @@
namespace App\Exports\Sheets;
+use App\Models\Portfolio;
use App\Models\Transaction;
-use Maatwebsite\Excel\Concerns\FromCollection;
-use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithTitle;
+use Maatwebsite\Excel\Concerns\WithHeadings;
+use Maatwebsite\Excel\Concerns\FromCollection;
class TransactionsSheet implements FromCollection, WithHeadings, WithTitle
{
@@ -22,14 +23,7 @@ class TransactionsSheet implements FromCollection, WithHeadings, WithTitle
'Split',
'Date',
'Created',
- 'Updated',
- 'Company Name',
- 'Portfolio Title',
- 'Market Value',
- '52 Week Low',
- '52 Week High',
- 'Market Data Refresh Date',
- 'Gain/Loss Dollars'
+ 'Updated'
];
}
@@ -38,7 +32,7 @@ class TransactionsSheet implements FromCollection, WithHeadings, WithTitle
*/
public function collection()
{
- return auth()->user()->transactions;
+ return Transaction::myTransactions()->get();
}
/**
diff --git a/app/Http/Controllers/HoldingController.php b/app/Http/Controllers/HoldingController.php
index ac4a96b..1f71376 100644
--- a/app/Http/Controllers/HoldingController.php
+++ b/app/Http/Controllers/HoldingController.php
@@ -2,7 +2,6 @@
namespace App\Http\Controllers;
-use App\Models\Holding;
use App\Models\Portfolio;
use Illuminate\Http\Request;
@@ -15,14 +14,12 @@ class HoldingController extends Controller
public function show(Request $request, Portfolio $portfolio, String $symbol)
{
+ $holding = $portfolio->holdings()
+ ->with(['market_data'])
+ ->symbol($symbol)
+ ->portfolio($portfolio->id)
+ ->first();
- $holding = Holding::query()
- ->portfolio($portfolio->id)
- ->symbol($symbol)
- ->first();
-
- $market_data = $holding->market_data;
-
- return view('holding.show', compact(['portfolio', 'holding', 'market_data']));
+ return view('holding.show', compact(['portfolio', 'holding']));
}
}
diff --git a/app/Http/Controllers/PortfolioController.php b/app/Http/Controllers/PortfolioController.php
index a10dc1f..3c07a56 100644
--- a/app/Http/Controllers/PortfolioController.php
+++ b/app/Http/Controllers/PortfolioController.php
@@ -22,16 +22,17 @@ class PortfolioController extends Controller
*/
public function show(Portfolio $portfolio)
{
+ $portfolio->load(['transactions', 'holdings']);
+
// get portfolio metrics
$metrics = cache()->tags(['metrics', 'portfolio', auth()->user()->id, $portfolio->id])->remember(
'portfolio-metrics-' . $portfolio->id,
60,
function () use ($portfolio) {
- return
- Holding::query()
- ->portfolio($portfolio->id)
- ->getPortfolioMetrics()
- ->first();
+ return Holding::query()
+ ->portfolio($portfolio->id)
+ ->getPortfolioMetrics()
+ ->first();
}
);
diff --git a/app/Imports/BackupImport.php b/app/Imports/BackupImport.php
index 2b92723..c722a44 100644
--- a/app/Imports/BackupImport.php
+++ b/app/Imports/BackupImport.php
@@ -20,8 +20,10 @@ class BackupImport implements WithMultipleSheets
{
return [
'Portfolios' => new PortfoliosSheet,
- // 'Transactions' => new TransactionsSheet,
+ 'Transactions' => new TransactionsSheet,
// 'Daily Changes' => new DailyChangesSheet,
];
+
+ // Can listen for AfterSheet to run clean up afterwards
}
}
diff --git a/app/Imports/Sheets/DailyChangesSheet.php b/app/Imports/Sheets/DailyChangesSheet.php
index 1760182..e9af765 100644
--- a/app/Imports/Sheets/DailyChangesSheet.php
+++ b/app/Imports/Sheets/DailyChangesSheet.php
@@ -15,23 +15,25 @@ class DailyChangesSheet implements ToCollection, WithHeadingRow, SkipsEmptyRows
public function collection(Collection $dailyChanges)
{
- foreach ($dailyChanges->sortBy('date') as $row) {
- if ($row['user'] != auth()->user()->id) {
+ foreach ($dailyChanges as $dailyChange) {
+
+ if ($dailyChange['user'] != auth()->user()->id) {
+
throw new Exception('Can\'t do that.');
}
DailyChange::updateOrCreate([
- 'date' => $row['date'],
- 'user_id' => $row['user'],
+ 'date' => $dailyChange['date'],
+ 'portfolio_id' => $dailyChange['portfolio_id'],
],[
- 'user_id' => $row['user'],
- 'date' => $row['date'],
- 'total_market_value' => $row['total_market_value'],
- 'total_cost_basis' => $row['total_cost_basis'],
- 'total_gain' => $row['total_gain'],
- 'total_dividends_earned' => $row['total_dividends_earned'],
- 'realized_gains' => $row['realized_gains'],
- 'notes' => $row['notes'],
+ 'portfolio_id' => $dailyChange['portfolio_id'],
+ 'date' => $dailyChange['date'],
+ 'total_market_value' => $dailyChange['total_market_value'],
+ 'total_cost_basis' => $dailyChange['total_cost_basis'],
+ 'total_gain' => $dailyChange['total_gain'],
+ 'total_dividends' => $dailyChange['total_dividends'],
+ 'realized_gains' => $dailyChange['realized_gains'],
+ 'annotation' => $dailyChange['annotation'],
]);
}
}
diff --git a/app/Imports/Sheets/PortfoliosSheet.php b/app/Imports/Sheets/PortfoliosSheet.php
index e71d2d5..59b25a2 100644
--- a/app/Imports/Sheets/PortfoliosSheet.php
+++ b/app/Imports/Sheets/PortfoliosSheet.php
@@ -14,7 +14,7 @@ class PortfoliosSheet implements ToCollection, WithHeadingRow, SkipsEmptyRows
public function collection(Collection $portfolios)
{
- foreach ($portfolios->sortBy('date') as $portfolio) {
+ foreach ($portfolios as $portfolio) {
auth()->user()->portfolios()
->where(['id' => $portfolio['id']])
diff --git a/app/Imports/Sheets/TransactionsSheet.php b/app/Imports/Sheets/TransactionsSheet.php
index 646087c..6ad02ff 100644
--- a/app/Imports/Sheets/TransactionsSheet.php
+++ b/app/Imports/Sheets/TransactionsSheet.php
@@ -7,28 +7,36 @@ use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
+use Maatwebsite\Excel\Concerns\WithChunkReading;
-class TransactionsSheet implements ToCollection, WithHeadingRow, SkipsEmptyRows
+class TransactionsSheet implements ToCollection, WithHeadingRow, SkipsEmptyRows, WithChunkReading
{
// use Importable;
public function collection(Collection $transactions)
{
- foreach ($transactions->sortBy('date') as $row) {
+ foreach ($transactions as $transaction) {
- Transaction::updateOrCreate([
- 'id' => $row['id'],
- ],[
- 'id' => $row['id'],
- 'symbol' => $row['symbol'],
- 'portfolio_id' => $row['portfolio'],
- 'transaction_type' => $row['transaction'],
- 'quantity' => $row['quantity'],
- 'cost_basis' => $row['cost_basis'] ?? 0,
- 'sale_price' => $row['sale_price'],
- 'split' => $row['split'] ?? null,
- 'date' => $row['date'],
- ]);
+ Transaction::where('id', $transaction['transaction_id'])
+ ->firstOr(function () use ($transaction) {
+
+ return Transaction::make()->forceFill([
+ 'id' => $transaction['transaction_id'],
+ 'symbol' => $transaction['symbol'],
+ 'portfolio_id' => $transaction['portfolio_id'],
+ 'transaction_type' => $transaction['transaction_type'],
+ 'quantity' => $transaction['quantity'],
+ 'cost_basis' => $transaction['cost_basis'] ?? 0,
+ 'sale_price' => $transaction['sale_price'],
+ 'split' => $transaction['split'] ?? null,
+ 'date' => $transaction['date'],
+ ])->save();
+ });
}
}
+
+ public function chunkSize(): int
+ {
+ return 500;
+ }
}
diff --git a/app/Models/DailyChange.php b/app/Models/DailyChange.php
index 80cf328..a97d16e 100644
--- a/app/Models/DailyChange.php
+++ b/app/Models/DailyChange.php
@@ -37,6 +37,15 @@ class DailyChange extends Model
{
return $query->where('portfolio_id', $portfolio);
}
+
+ public function scopeMyDailyChanges()
+ {
+ return $this->whereHas('portfolio', function ($query) {
+ $query->whereHas('users', function ($query) {
+ $query->where('id', auth()->id());
+ });
+ });
+ }
public function portfolio()
{
diff --git a/app/Models/Holding.php b/app/Models/Holding.php
index 6abd830..0c776cb 100644
--- a/app/Models/Holding.php
+++ b/app/Models/Holding.php
@@ -56,7 +56,8 @@ class Holding extends Model
public function transactions()
{
return $this->hasMany(Transaction::class, 'symbol', 'symbol')
- ->where('transactions.portfolio_id', $this->portfolio_id);
+ ->where('portfolio_id', $this->portfolio_id)
+ ->withAggregate('portfolio', 'title');
}
/**
@@ -141,7 +142,7 @@ class Holding extends Model
public function scopeSymbol($query, $symbol)
{
- return $query->where('symbol', $symbol);
+ return $query->where('holdings.symbol', $symbol);
}
public function scopeWithoutWishlists($query) {
diff --git a/app/Models/Portfolio.php b/app/Models/Portfolio.php
index 41847cb..0c2a145 100644
--- a/app/Models/Portfolio.php
+++ b/app/Models/Portfolio.php
@@ -62,6 +62,13 @@ class Portfolio extends Model
return $this->hasMany(DailyChange::class);
}
+ public function scopeMyPortfolios()
+ {
+ return $this->whereHas('users', function ($query) {
+ $query->where('user_id', auth()->user()->id);
+ });
+ }
+
public function scopeWithoutWishlists()
{
return $this->where(['wishlist' => false]);
diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php
index 5fa9dbc..1e5489e 100644
--- a/app/Models/Transaction.php
+++ b/app/Models/Transaction.php
@@ -90,7 +90,6 @@ class Transaction extends Model
public function scopeWithMarketData($query)
{
$query->withAggregate('market_data', 'name')
- ->withAggregate('portfolio', 'title')
->withAggregate('market_data', 'market_value')
->withAggregate('market_data', 'fifty_two_week_low')
->withAggregate('market_data', 'fifty_two_week_high')
@@ -108,6 +107,15 @@ class Transaction extends Model
return $query->where('symbol', $symbol);
}
+ public function scopeMyTransactions()
+ {
+ return $this->whereHas('portfolio', function ($query) {
+ $query->whereHas('users', function ($query) {
+ $query->where('id', auth()->id());
+ });
+ });
+ }
+
public function refreshMarketData()
{
return MarketData::getMarketData($this->attributes['symbol']);
diff --git a/app/Models/User.php b/app/Models/User.php
index a6097d1..6a7ae1d 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -72,6 +72,7 @@ class User extends Authenticatable
{
return $this->hasManyDeep(Transaction::class, ['portfolio_user', Portfolio::class])
->withMarketData()
+ ->withAggregate('portfolio', 'title')
->selectRaw('
CASE
WHEN transaction_type = \'SELL\'
diff --git a/resources/views/holding/show.blade.php b/resources/views/holding/show.blade.php
index 4fb10b0..ee28cb8 100644
--- a/resources/views/holding/show.blade.php
+++ b/resources/views/holding/show.blade.php
@@ -7,7 +7,7 @@
>
@livewire('manage-transaction-form', [
'portfolio' => $portfolio,
- 'symbol' => $market_data->symbol,
+ 'symbol' => $holding->market_data->symbol,
])
@@ -16,7 +16,7 @@
{{ __('Market Data Age') }}:
- {{ \Carbon\Carbon::parse($market_data->updated_at)->diffForHumans() }}
+ {{ \Carbon\Carbon::parse($holding->market_data->updated_at)->diffForHumans() }}
{{ __('Forward PE') }}: - {{ $market_data->forward_pe }} + {{ $holding->market_data->forward_pe }}
{{ __('Trailing PE') }}: - {{ $market_data->trailing_pe }} + {{ $holding->market_data->trailing_pe }}
{{ __('Market Cap') }}: - ${{ Number::forHumans($market_data->market_cap ?? 0) }} + ${{ Number::forHumans($holding->market_data->market_cap ?? 0) }}
{{ __('52 week') }}: