Skip to content

feat: complete fullstack investment manager challenge - #5

Open
vinicastrolima wants to merge 36 commits into
Coderockr:mainfrom
vinicastrolima:development
Open

feat: complete fullstack investment manager challenge#5
vinicastrolima wants to merge 36 commits into
Coderockr:mainfrom
vinicastrolima:development

Conversation

@vinicastrolima

Copy link
Copy Markdown

Overview

This pull request delivers the fullstack Investment Manager challenge, including a documented JSON API and a responsive SPA based on the supplied Figma reference.

Highlights

  • Investment creation, listing, details and full withdrawal
  • Compound gains of 0.52% per completed month
  • Age-based taxation applied only to investment gains
  • Withdrawn balances frozen at the settlement date
  • Token authentication and owner-level authorization
  • Paginated investment listing with date and owner filters
  • Queued creation and withdrawal notification emails
  • Responsive desktop and mobile layouts
  • Loading, empty, validation and error states

Technical decisions

  • Laravel 13 API running with PHP-FPM and Nginx
  • Vue 3, TypeScript, Vite, Pinia and TanStack Query
  • PostgreSQL for application persistence
  • Brick Money and BCMath for deterministic financial calculations
  • Layered backend architecture with domain services, DTOs, actions and repositories
  • Laravel Sanctum for decoupled Bearer-token authentication
  • Database queues and Mailpit for local email delivery
  • Docker Compose and Make targets for a reproducible development environment
  • Frontend and backend configured for independent deployment

Quality assurance

  • 63 backend tests with Pest
  • 5 frontend unit tests with Vitest
  • 2 critical browser journeys with Playwright
  • PHPStan/Larastan level 6
  • Laravel Pint, ESLint and TypeScript checks
  • Production frontend build validated

The Playwright scenarios cover:

  1. Registration, investment creation and compounded balance validation
  2. Withdrawal preview, taxation and final settlement

Running the project

make up
Available services:
SPA: http://localhost:5173/
API: http://localhost:8080/
API documentation: http://localhost:8080/docs/api
Mailpit: http://localhost:8025/
Demo credentials:
demo@coderockr.test
password
Validation commands
make test
make e2e
make lint
Additional build instructions, architectural decisions, dependencies and screenshots are documented in the README.

…v config

- Multi-stage PHP 8.4 image (pdo_pgsql, bcmath, intl, zip, opcache, pcntl)
- php-fpm + nginx, Postgres 17, Mailpit, queue worker and Vite dev server
- Makefile 'up' brings the whole stack up, migrates and seeds in one command
- Configure Laravel env for Postgres, Mailpit and CORS (FRONTEND_URL)
Production: laravel/sanctum (Bearer token auth), brick/money (exact money),
spatie/laravel-data (typed DTOs). Dev: pestphp/pest, dedoc/scramble (OpenAPI),
larastan (static analysis). Publishes API routes and personal_access_tokens.
- config/cors.php: allow only the SPA origin (FRONTEND_URL), token mode
- config/investments.php: monthly gain rate + tax brackets as exact strings
- pint.json (strict_types baseline applied repo-wide) and phpstan.neon (Larastan lvl 6)
- Dockerfile: add pdo_sqlite for the in-memory test suite
- gitignore local planning notes
Pure, framework-free domain: GainRate/TaxBracket/InvestmentStatus, ElapsedMonths
(complete-month counting with last-day rule), GainCalculator (month-by-month
compounding, HALF_UP each step) and TaxCalculator (tax on gains by age bracket),
all backed by brick/money for exact cents. 37 unit tests cover the challenge
vectors (1000@6mo -> 1031.61/31.61; gains 200 -> tax 45.00) and edge cases.
FormRequests + API Resources cover validation/serialization idiomatically, so
laravel-data was redundant. laravel/pao corrupts stdout via
its stream filter here, so tests run on Pest's standard reporter.
Migration + Investment model (money stored as integer cents via a MoneyCast
adapter, status enum, withdrawal snapshot columns), owner relationship + Sanctum
HasApiTokens on User, an InvestmentRepository contract with an Eloquent
implementation, and a factory with active/withdrawn states.
Actions (Create/Withdraw/List) behind thin controllers; InvestmentCalculator
facade over the domain; FormRequests enforce the date/amount rules; API Resource
computes expected balance/gains (or the frozen withdrawal); Sanctum token auth;
owner-only Policy; domain exceptions mapped to 409/422. Withdrawal-preview keeps
tax math server-side. 21 feature tests cover create/view/withdraw/list/pagination.
Markdown Blade templates for investment created/withdrawn, sent to the owner via
queued Mailables and dispatched from domain events. The withdrawal e-mail renders
the full taxed breakdown. Blade is used here for templating without coupling the
UI; Mailpit catches everything in dev. Tests assert queueing and rendering.
DatabaseSeeder creates a demo user (demo@coderockr.test) with active investments
in each tax bracket, one already-withdrawn investment, and a second owner to make
per-owner scoping visible. Covered by a feature test.
Scramble serves interactive docs at /docs/api and the raw spec at /docs/api.json;
configured title/version/description and Bearer-auth documentation. The generated
OpenAPI 3.1 spec is committed to api/docs/openapi.json (regenerate with 'make docs').
Tailwind v4 (Vite plugin) with light/dark tokens, '@' path alias, ESLint (vue-ts)
+ Prettier, Vitest, and the supporting npm scripts. Removes the Vite starter cruft.
Fetch-based API client with Bearer injection and 401 handling, Pinia auth/ui
stores (token persisted, class-based dark mode), Vue Router with auth guards,
the app shell/header, currency & date composables, and login/register pages.
TanStack Query hooks (paginated list with keepPreviousData, detail, debounced
withdrawal preview, create/withdraw mutations); investment cards, status badges,
paginator and a withdraw dialog with a live taxed-net preview; list/detail/create
pages with loading, empty and error states.
The worker can start before migrations create the jobs table; a restart policy
lets it recover and drain queued notification e-mails to Mailpit.
Dashboard (light + dark), investment detail, the live taxed withdrawal preview,
the Scramble API docs and a caught notification e-mail in Mailpit.
Setup/run instructions, architecture, business rules, third-party library
rationale, API docs links, tests/quality, screenshots and design notes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant