Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Investbrain API capabilities #56

Merged
merged 13 commits into from
Jan 28, 2025
8 changes: 8 additions & 0 deletions app/Http/ApiControllers/Controller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace App\Http\ApiControllers;

abstract class Controller
{
//
}
48 changes: 48 additions & 0 deletions app/Http/ApiControllers/HoldingController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace App\Http\ApiControllers;

use App\Models\Holding;
use App\Models\Portfolio;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use App\Http\Requests\HoldingRequest;
use App\Http\Resources\HoldingResource;
use HackerEsq\FilterModels\FilterModels;
use App\Http\ApiControllers\Controller as ApiController;

class HoldingController extends ApiController
{
public function index(FilterModels $filters)
{

$filters->setQuery(Holding::query());
$filters->setScopes(['myHoldings']);
$filters->setEagerRelations(['market_data', 'transactions']);
$filters->setSearchableColumns(['symbol']);

return HoldingResource::collection($filters->paginated());
}

public function show(Portfolio $portfolio, string $symbol)
{

Gate::authorize('readOnly', $portfolio);

$holding = $portfolio->holdings()->symbol($symbol)->firstOrFail();

return HoldingResource::make($holding);
}

public function update(HoldingRequest $request, Portfolio $portfolio, string $symbol)
{

Gate::authorize('fullAccess', $portfolio);

$holding = $portfolio->holdings()->symbol($symbol)->firstOrFail();

$holding->update($request->validated());

return HoldingResource::make($holding);
}
}
21 changes: 21 additions & 0 deletions app/Http/ApiControllers/MarketDataController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace App\Http\ApiControllers;

use App\Models\MarketData;
use Illuminate\Http\Request;
use App\Http\Resources\MarketDataResource;
use App\Http\ApiControllers\Controller as ApiController;

class MarketDataController extends ApiController
{
public function show(Request $request, string $symbol)
{

return MarketDataResource::make(
MarketData::getMarketData($symbol)
);
}
}
58 changes: 58 additions & 0 deletions app/Http/ApiControllers/PortfolioController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace App\Http\ApiControllers;

use App\Models\Portfolio;
use Illuminate\Support\Facades\Gate;
use HackerEsq\FilterModels\FilterModels;
use App\Http\Resources\PortfolioResource;
use App\Http\Requests\PortfolioRequest;
use App\Http\ApiControllers\Controller as ApiController;

class PortfolioController extends ApiController
{
public function index(FilterModels $filters)
{
$filters->setQuery(Portfolio::query());
$filters->setScopes(['myPortfolios']);
$filters->setEagerRelations(['users', 'transactions', 'holdings']);
$filters->setFilterableRelations(['holdings.symbol']);
$filters->setSearchableColumns(['title', 'notes']);

return PortfolioResource::collection($filters->paginated());
}

public function store(PortfolioRequest $request)
{
$portfolio = Portfolio::create($request->validated());

return PortfolioResource::make($portfolio);
}

public function show(Portfolio $portfolio)
{
Gate::authorize('readOnly', $portfolio);

return PortfolioResource::make($portfolio);
}

public function update(PortfolioRequest $request, Portfolio $portfolio)
{
Gate::authorize('fullAccess', $portfolio);

$portfolio->update($request->validated());

return PortfolioResource::make($portfolio);
}

public function destroy(Portfolio $portfolio)
{
Gate::authorize('fullAccess', $portfolio);

$portfolio->delete();

return response()->noContent();
}
}
58 changes: 58 additions & 0 deletions app/Http/ApiControllers/TransactionController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace App\Http\ApiControllers;

use App\Models\Transaction;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use HackerEsq\FilterModels\FilterModels;
use App\Http\Requests\TransactionRequest;
use App\Http\Resources\TransactionResource;
use App\Http\ApiControllers\Controller as ApiController;

class TransactionController extends ApiController
{
public function index(FilterModels $filters)
{

$filters->setQuery(Transaction::query());
$filters->setScopes(['myTransactions']);
$filters->setSearchableColumns(['symbol']);

return TransactionResource::collection($filters->paginated());
}

public function store(TransactionRequest $request)
{
Gate::authorize('fullAccess', $request->portfolio);

$transaction = Transaction::create($request->validated());

return TransactionResource::make($transaction);
}

public function show(Transaction $transaction)
{
Gate::authorize('readOnly', $transaction->portfolio);

return TransactionResource::make($transaction);
}

public function update(TransactionRequest $request, Transaction $transaction)
{
Gate::authorize('fullAccess', $transaction->portfolio);

$transaction->update($request->validated());

return TransactionResource::make($transaction);
}

public function destroy(Transaction $transaction)
{
Gate::authorize('fullAccess', $transaction->portfolio);

$transaction->delete();

return response()->noContent();
}
}
15 changes: 15 additions & 0 deletions app/Http/ApiControllers/UserController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace App\Http\ApiControllers;

use Illuminate\Http\Request;
use App\Http\Resources\UserResource;
use App\Http\ApiControllers\Controller as ApiController;

class UserController extends ApiController
{
public function me(Request $request)
{
return UserResource::make($request->user());
}
}
1 change: 0 additions & 1 deletion app/Http/Controllers/ConnectedAccountController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use App\Models\User;
use App\Models\ConnectedAccount;
use Illuminate\Support\MessageBag;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Blade;
use Laravel\Socialite\Facades\Socialite;
Expand Down
6 changes: 3 additions & 3 deletions app/Http/Controllers/Controller.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?php

namespace App\Http\Controllers;

abstract class Controller
{
//
}
}
1 change: 0 additions & 1 deletion app/Http/Controllers/InvitedOnboardingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use App\Models\User;
use App\Models\Portfolio;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class InvitedOnboardingController extends Controller
{
Expand Down
5 changes: 2 additions & 3 deletions app/Http/Controllers/PortfolioController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Models\Holding;
use App\Models\Portfolio;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;

class PortfolioController extends Controller
{
Expand All @@ -22,9 +23,7 @@ public function create()
*/
public function show(Request $request, Portfolio $portfolio)
{
if ($request->user()->cannot('readOnly', $portfolio)) {
abort(403);
}
Gate::authorize('readOnly', $portfolio);

$portfolio->load(['transactions', 'holdings']);

Expand Down
14 changes: 14 additions & 0 deletions app/Http/Requests/FormRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest as BaseFormRequest;

class FormRequest extends BaseFormRequest
{

public function requestOrModelValue($key, $model): mixed
{
return $this->request->get($key) ?? $this->{$model}?->{$key};
}
}
24 changes: 24 additions & 0 deletions app/Http/Requests/HoldingRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace App\Http\Requests;

use App\Http\Requests\FormRequest;

class HoldingRequest extends FormRequest
{

/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{

$rules = [
'reinvest_dividends' => ['sometimes', 'boolean']
];

return $rules;
}
}
30 changes: 30 additions & 0 deletions app/Http/Requests/PortfolioRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace App\Http\Requests;

use App\Http\Requests\FormRequest;

class PortfolioRequest extends FormRequest
{

/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{

$rules = [
'title' => ['required', 'string', 'min:5', 'max:255'],
'notes' => ['sometimes', 'nullable', 'string'],
'wishlist' => ['sometimes', 'nullable', 'boolean'],
];

if (!is_null($this->portfolio)) {
$rules['title'][0] = 'sometimes';
}

return $rules;
}
}
Loading