A comprehensive full-stack application for managing financial assets, featuring a RESTful API built with FastAPI and SQLAlchemy, and a modern React frontend. Supports both SQLite (local development) and Supabase (production) databases.
Backend:
- Python 3.12.11: Modern Python with excellent performance and type hinting support
- FastAPI: Modern, fast web framework for building APIs with automatic OpenAPI documentation
- SQLAlchemy 2.0: Powerful ORM for database operations with excellent PostgreSQL and SQLite support
- Pydantic 2.5: Data validation and serialization using Python type hints
- Alembic: Database migration tool for schema versioning
- Pytest: Comprehensive testing framework with async support
- Virtual Environment: Isolated Python environment using
venvfor dependency management
Frontend:
- React 18: Modern UI library with hooks and functional components
- TypeScript: Type-safe JavaScript for better development experience
- Vite: Fast build tool and development server
- Axios: HTTP client for API communication
- Lucide React: Modern icon library for consistent UI elements
- Local Development: SQLite for fast, file-based development without external dependencies
- Production: Supabase (PostgreSQL) for scalable, cloud-hosted database with built-in features
- Migration Support: Alembic for database schema versioning and migrations
- RESTful Endpoints: Following REST conventions for predictable, intuitive API design
- Comprehensive CRUD: Full Create, Read, Update, Delete operations for all entities
- Bulk Operations: Efficient bulk asset creation from JSON data
- Filtering & Pagination: Query parameters for filtering and pagination
- OpenAPI Documentation: Auto-generated interactive API documentation
Our API follows REST architectural principles with careful attention to resource nesting:
Resource-Based URLs: Each URL represents a resource, not an action
- ✅
GET /api/v1/assets/(collection) - ✅
GET /api/v1/assets/{id}(individual resource) - ❌
GET /api/v1/get-assets/(action-based)
Purposeful Nesting Strategy: We implement exactly two levels of nesting following REST best practices:
- Level 1:
categories/{id}/subcategories- Clear parent-child containment - Level 2:
subcategories/{id}/assets- Core business relationship - Avoided:
categories/{id}/subcategories/{id}/assets- Prevents over-nesting
Nesting Principles Applied:
- Sparse Nesting: Only nest when there's genuine containment, not convenience
- Meaningful Hierarchies: Each level represents real business relationships
- Resource Independence: All resources accessible directly without forced navigation
- URL Simplicity: Prevents unwieldy URLs while maintaining functionality
HTTP Methods: Proper use of HTTP verbs for different operations
GET: Retrieve resourcesPOST: Create new resourcesPUT: Update entire resourcesDELETE: Remove resources
Status Codes: Meaningful HTTP status codes for different scenarios
200: Success201: Created404: Not found400: Bad request422: Validation error
- Category: Primary asset categories (Cash, Investment, RealEstate, OtherProperty)
- Subcategory: Asset subcategories (Cash, Cryptocurrency, Vehicle, RealEstate, Brokerage)
- Asset: Main asset entity with comprehensive financial data
- AssetHolding: Detailed asset composition breakdown
The API supports various asset types including:
- Cash: Traditional cash accounts
- Cryptocurrency: Digital currency holdings with price tracking
- Real Estate: Property investments with address and valuation data
- Vehicles: Automobile and vehicle assets
- Brokerage: Investment accounts with detailed holdings breakdown
Assets can have complex holdings with major and minor asset classes:
- Major Classes: AlternativeInvestments, PublicEquity, FixedIncome, etc.
- Minor Classes: PersonalRealEstate, UsEquity, InvestmentGradeFixedIncome, etc.
- Python 3.12.11 (recommended version)
- pip (Python package installer)
- Git (for version control)
-
Clone the repository
git clone <repository-url> cd assets
-
Create and activate virtual environment
# Create virtual environment python3.12 -m venv venv # Activate virtual environment source venv/bin/activate # On Windows: venv\Scripts\activate # Verify Python version python --version # Should show Python 3.12.11
-
Install dependencies
pip install -r requirements.txt
-
Set up environment variables
cp env.example .env # Edit .env with your configuration (optional for local development) -
Initialize the database
python scripts/init_db.py
-
Load sample data (optional)
python scripts/load_sample_data.py info/assets.json
-
Run the application
# Option 1: Using the run script python run.py # Option 2: Using uvicorn directly python -m uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
The API will be available at http://localhost:8000
- Run the frontend (optional)
# Navigate to frontend directory cd frontend # Install dependencies npm install # Copy environment file cp env.example .env.local # Start development server npm run dev
The frontend will be available at http://localhost:5173
This project includes both a REST API backend and a React frontend for a complete assets management system.
Terminal 1 - Backend:
# In the root directory
source venv/bin/activate
python run.pyTerminal 2 - Frontend:
# In the frontend directory
cd frontend
npm install
npm run devAccess the application:
- API: http://localhost:8000
- Frontend: http://localhost:5173
- API Docs: http://localhost:8000/api/v1/docs
The React frontend provides:
- Hierarchical Asset Display: Categories → Subcategories → Assets
- Real-time Data: Live updates from the API
- Responsive Design: Works on desktop and mobile
- Interactive UI: Modern, clean interface
- Total Net Worth Calculation: Automatic sum of all assets
This project uses Python's built-in venv module for virtual environment management:
# Create virtual environment (if not already created)
python3.12 -m venv venv
# Activate virtual environment
source venv/bin/activate # On Windows: venv\Scripts\activate
# Verify you're in the virtual environment
which python # Should point to venv/bin/python
# Deactivate virtual environment
deactivateImportant: Always activate the virtual environment before running any Python commands or installing packages.
Create a .env file based on env.example:
# Database Configuration
DATABASE_URL=sqlite:///./assets.db
SUPABASE_URL=your_supabase_url_here
SUPABASE_KEY=your_supabase_key_here
# Environment
ENVIRONMENT=development
# API Configuration
API_V1_STR=/api/v1
PROJECT_NAME=Assets Management API- Swagger UI:
http://localhost:8000/api/v1/docs - ReDoc:
http://localhost:8000/api/v1/redoc - OpenAPI JSON:
http://localhost:8000/api/v1/openapi.json
- API Logging Guide: LOGGING.md - Comprehensive guide to request/response logging, debugging, and monitoring
GET /api/v1/assets/- List all assets with filteringPOST /api/v1/assets/- Create a new assetPOST /api/v1/assets/bulk- Create multiple assets from JSONGET /api/v1/assets/{id}- Get asset by IDGET /api/v1/assets/by-asset-id/{asset_id}- Get asset by asset_id fieldPUT /api/v1/assets/{id}- Update assetDELETE /api/v1/assets/{id}- Delete asset
GET /api/v1/categories/- List all categoriesPOST /api/v1/categories/- Create categoryGET /api/v1/categories/{id}- Get category by IDPUT /api/v1/categories/{id}- Update categoryDELETE /api/v1/categories/{id}- Delete categoryGET /api/v1/categories/{id}/subcategories- Get all subcategories for a category
GET /api/v1/subcategories/- List all subcategoriesPOST /api/v1/subcategories/- Create subcategoryGET /api/v1/subcategories/{id}- Get subcategory by IDPUT /api/v1/subcategories/{id}- Update subcategoryDELETE /api/v1/subcategories/{id}- Delete subcategoryGET /api/v1/subcategories/{id}/assets- Get all assets for a subcategory
skip: Number of records to skip (pagination)limit: Maximum number of records to returncategory_id: Filter by category IDsubcategory_id: Filter by subcategory IDis_active: Filter by active status
Example: GET /api/v1/assets/?category_id=1&is_active=true&limit=10
The API supports nested resource queries for hierarchical data, following REST best practices for resource nesting:
GET /api/v1/categories/{category_id}/subcategories- Get all subcategories for a specific category
Example: GET /api/v1/categories/1/subcategories returns all subcategories for the Cash category
GET /api/v1/subcategories/{subcategory_id}/assets- Get all assets for a specific subcategory
Example: GET /api/v1/subcategories/1/assets returns all assets in the Cash subcategory
Our API implements exactly two levels of nesting following REST best practices:
Why Two Levels Only?
- Categories → Subcategories: Represents a clear parent-child relationship where subcategories are logically contained within categories
- Subcategories → Assets: Represents the core business relationship where assets belong to specific subcategories
- No deeper nesting: We avoid
categories/{id}/subcategories/{id}/assetsto prevent over-nesting
REST Best Practices Applied:
- Sparse Nesting Principle: We nest only when there's a genuine containment relationship, not just for convenience
- Meaningful Hierarchies: Each nested level represents a real business relationship, not just data organization
- Avoiding Deep Nesting: Prevents URLs from becoming unwieldy and maintains API usability
- Resource Independence: Assets can still be accessed directly via
/api/v1/assets/without requiring navigation through the hierarchy
Benefits of This Approach:
- Intuitive Navigation: Natural progression from broad categories to specific assets
- Performance: Shorter URLs and fewer database joins
- Maintainability: Simpler routing and easier to understand API structure
- Flexibility: Users can access resources at any level without forced navigation
Alternative Access Patterns:
- Direct asset access:
GET /api/v1/assets/?subcategory_id=1 - Direct subcategory access:
GET /api/v1/subcategories/ - Direct category access:
GET /api/v1/categories/
This design balances the convenience of hierarchical navigation with the principles of RESTful API design, ensuring our API remains both powerful and maintainable.
# Run all tests
python -m pytest
# Run with coverage
python -m pytest --cov=app --cov-report=html --cov-report=term-missing
# Run with coverage and fail if below threshold (80%)
python -m pytest --cov=app --cov-report=html --cov-report=term-missing --cov-fail-under=80
# Run specific test file
python -m pytest tests/test_assets.py
# Run with verbose output
python -m pytest -v
# Generate HTML coverage report
python -m pytest --cov=app --cov-report=html
# Open htmlcov/index.html in your browser to view detailed coverageThe project includes a Makefile for common operations:
# Show all available commands
make help
# Install dependencies
make install
# Run tests
make test
# Run tests with coverage
make test-cov
# Run tests with coverage and fail if below threshold
make test-cov-fail
# Generate HTML coverage report
make coverage-html
# Generate XML coverage report
make coverage-xml
# Start the application
make run
# Initialize database
make init-db
# Load sample data
make load-data
# Set up development environment
make dev-setup
# Frontend commands
make frontend-install # Install frontend dependencies
make frontend-dev # Start frontend development server
make frontend-build # Build frontend for production
# Clean up generated files
make cleanThe test suite includes:
- Unit Tests: Individual component testing
- Integration Tests: API endpoint testing
- Database Tests: Model and service testing
- Error Handling: Edge cases and error scenarios
Current Coverage: 82% overall coverage with detailed reporting
Coverage Reports:
- Terminal: Shows missing lines and coverage percentage
- HTML: Interactive report at
htmlcov/index.html - XML: Machine-readable report for CI/CD integration
Coverage Threshold: Tests fail if coverage drops below 80%
Tests use a separate SQLite database (test.db) that is created and destroyed for each test run.
To load the provided sample assets data:
python scripts/load_sample_data.py info/assets.jsonThis will:
- Parse the JSON asset data
- Map fields to the database schema
- Create categories and subcategories as needed
- Process complex holdings data
- Insert all assets into the database
Sample Data Includes:
- 6 different asset types: Cash, Cryptocurrency, Vehicle, Real Estate, and Brokerage
- Complex holdings structures: Detailed asset composition with major and minor asset classes
- Real-world data: Actual financial data with proper valuations and metadata
- Various asset states: Active assets with different balance types and update frequencies
Expected Output:
Loading sample data from info/assets.json...
Successfully loaded 6 assets!
- Cash Test (Cash): $5,000.00
- Crypto Test (Cryptocurrency): $416,285.75
- Vehicle Test (Vehicle): $30,000.00
- Real Estate Test (RealEstate): $800,000.00
- Investment Account (Brokerage): $47,500.00
- Test Real Estate (RealEstate): $751,200.00
The API supports bulk asset creation via the /api/v1/assets/bulk endpoint:
import requests
assets_data = [
{
"assetId": "asset-123",
"nickname": "My Investment",
"wealthAssetType": "Brokerage",
"primaryAssetCategory": "Investment",
"balanceCurrent": 10000.0,
"isActive": True
}
# ... more assets
]
response = requests.post(
"http://localhost:8000/api/v1/assets/bulk",
json=assets_data
)The project uses Alembic for database migrations:
# Create a new migration
alembic revision --autogenerate -m "Description of changes"
# Apply migrations
alembic upgrade head
# Rollback migration
alembic downgrade -1The database includes the following tables:
categories: Asset categoriessubcategories: Asset subcategoriesassets: Main asset dataasset_holdings: Detailed asset composition
# Start the development server
python -m uvicorn app.main:app --reload --host 0.0.0.0 --port 8000-
Set up Supabase project
- Create a new Supabase project
- Get your database URL and API key
-
Update environment variables
ENVIRONMENT=production DATABASE_URL=postgresql://user:password@host:port/database SUPABASE_URL=your_supabase_url SUPABASE_KEY=your_supabase_key
-
Run migrations
alembic upgrade head
-
Deploy your application
- Use your preferred deployment platform (Heroku, AWS, etc.)
- Ensure environment variables are set correctly
assets/
├── app/ # Main application code
│ ├── api/ # API routes and endpoints
│ │ └── v1/
│ │ ├── endpoints/ # Individual endpoint modules
│ │ │ ├── assets.py # Asset CRUD operations
│ │ │ ├── categories.py # Category management
│ │ │ └── subcategories.py # Subcategory management
│ │ └── api.py # API router configuration
│ ├── core/ # Core application configuration
│ │ ├── config.py # Settings and environment variables
│ │ ├── database.py # Database connection and session management
│ │ └── init_db.py # Database initialization
│ ├── models/ # SQLAlchemy database models
│ │ ├── asset.py # Asset model with comprehensive fields
│ │ ├── category.py # Category model
│ │ ├── subcategory.py # Subcategory model
│ │ └── asset_holding.py # Asset holdings breakdown model
│ ├── schemas/ # Pydantic schemas for API serialization
│ │ ├── asset.py # Asset request/response schemas
│ │ ├── category.py # Category schemas
│ │ └── subcategory.py # Subcategory schemas
│ ├── services/ # Business logic layer
│ │ └── asset_service.py # Asset management service
│ └── main.py # FastAPI application entry point
├── frontend/ # React frontend application
│ ├── src/ # React source code
│ │ ├── components/ # React components
│ │ │ ├── AssetsTable.tsx # Main assets display component
│ │ │ ├── AssetRow.tsx # Individual asset row component
│ │ │ ├── CategoryRow.tsx # Category display component
│ │ │ └── SubcategoryRow.tsx # Subcategory display component
│ │ ├── services/ # API service layer
│ │ │ └── api.ts # HTTP client and API calls
│ │ ├── utils/ # Utility functions
│ │ │ └── formatting.ts # Currency and data formatting
│ │ ├── App.tsx # Main React component
│ │ └── main.tsx # React application entry point
│ ├── public/ # Static assets
│ ├── package.json # Node.js dependencies
│ ├── vite.config.ts # Vite configuration
│ └── env.example # Frontend environment variables
├── tests/ # Test suite
│ ├── test_assets.py # Asset endpoint tests
│ ├── test_categories.py # Category endpoint tests
│ ├── test_subcategories.py # Subcategory endpoint tests
│ ├── test_main.py # Main application tests
│ └── conftest.py # Test configuration and fixtures
├── scripts/ # Utility scripts
│ ├── init_db.py # Database initialization script
│ ├── load_sample_data.py # Sample data loading script
│ └── run_tests.py # Test runner script
├── alembic/ # Database migration files
│ ├── versions/ # Migration version files
│ ├── env.py # Alembic environment configuration
│ └── script.py.mako # Migration template
├── info/ # Sample data and documentation
│ └── assets.json # Sample assets data
├── venv/ # Python virtual environment (created locally)
├── requirements.txt # Python dependencies
├── alembic.ini # Alembic configuration
├── pytest.ini # Pytest configuration
├── Makefile # Common development commands
├── run.py # Application runner script
├── env.example # Environment variables template
└── README.md # This file
Backend:
- Models: Add new models in
app/models/ - Schemas: Create Pydantic schemas in
app/schemas/ - Services: Implement business logic in
app/services/ - Endpoints: Add API routes in
app/api/v1/endpoints/ - Tests: Write tests in
tests/
Frontend:
- Components: Add new React components in
frontend/src/components/ - Services: Add API calls in
frontend/src/services/api.ts - Utils: Add utility functions in
frontend/src/utils/ - Types: Define TypeScript types in
frontend/src/types/ - Styling: Update CSS in component files or
frontend/src/App.css
Backend:
- Type Hints: All functions use Python type hints
- Docstrings: Comprehensive documentation for all functions
- Error Handling: Proper HTTP status codes and error messages
- Validation: Pydantic models for request/response validation
Frontend:
- TypeScript: Type-safe JavaScript with proper interfaces
- Component Architecture: Modular, reusable React components
- Error Handling: Graceful error states and loading indicators
- Responsive Design: Mobile-first approach with modern CSS
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Run the test suite
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
Python Version Issues:
# Check Python version
python --version
# If not Python 3.12.11, install it:
# macOS: brew install python@3.12
# Ubuntu: sudo apt install python3.12 python3.12-venv
# Windows: Download from python.orgVirtual Environment Issues:
# If virtual environment is not activated
source venv/bin/activate # On Windows: venv\Scripts\activate
# If virtual environment doesn't exist
python3.12 -m venv venv
source venv/bin/activate
pip install -r requirements.txtDatabase Issues:
# If database doesn't exist or is corrupted
rm assets.db # Remove existing database
python scripts/init_db.py # Recreate databaseImport Errors:
# Make sure you're in the project directory
cd /path/to/assets
# Make sure virtual environment is activated
source venv/bin/activate
# Reinstall dependencies
pip install -r requirements.txtPort Already in Use:
# If port 8000 is already in use
python run.py --port 8001 # Use different port
# Or kill the process using port 8000
lsof -ti:8000 | xargs kill -9Backend Only:
# Complete backend setup from scratch
git clone <repository-url>
cd assets
python3.12 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python scripts/init_db.py
python scripts/load_sample_data.py info/assets.json
python run.pyFull-Stack Setup:
# Complete full-stack setup from scratch
git clone <repository-url>
cd assets
# Backend setup
python3.12 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python scripts/init_db.py
python scripts/load_sample_data.py info/assets.json
# Frontend setup
cd frontend
npm install
cp env.example .env.local
# Run both (in separate terminals)
# Terminal 1: Backend
cd .. && source venv/bin/activate && python run.py
# Terminal 2: Frontend
cd frontend && npm run devFor production deployment to Render with Supabase, see the Deployment Guide.
Quick Deploy to Render:
- Push your code to a Git repository
- Connect the repository to Render
- Set environment variables for Supabase:
ENVIRONMENT=productionSUPABASE_URL=your_supabase_connection_stringSUPABASE_KEY=your_supabase_anon_key
- Deploy automatically using the included
render.yaml
Why Supabase for Production?
- SQLite is not suitable for production (concurrent access limitations)
- Supabase provides managed PostgreSQL with excellent performance
- Built-in authentication and real-time features
- Automatic scaling and backups
For questions or issues:
- Check the API documentation at
/api/v1/docs - Review the test cases for usage examples
- Check the logs for error details
- Verify Python version and virtual environment setup
- Create an issue in the repository
This section outlines key architectural decisions and trade-offs made during development, particularly considering the 2-hour time constraint and assessment requirements.
Decision: No authentication system implemented
Rationale:
- Assessment Scope: The requirements didn't specify authentication as a core requirement
- Time Constraints: Setting up proper auth (JWT, OAuth, user management) would consume significant development time
- Frontend Nature: The current frontend is essentially read-only, reducing security concerns
- Focus on Core Features: Prioritized demonstrating API design, data modeling, and full-stack integration
Production Considerations:
- User-Specific Data: If expanded to support user-specific assets, authentication would be mandatory
- Data Security: Without auth, all data is publicly accessible (acceptable for assessment)
- User Management: Would require additional models (User, UserSession, etc.) and associated flows
- API Security: Would need to implement proper authorization middleware and user context
Decision: SQLite for development, Supabase (PostgreSQL) for production
Trade-offs:
- ✅ Development Speed: SQLite requires no setup, enabling rapid iteration
- ✅ Production Scalability: PostgreSQL handles concurrent users and complex queries
- ❌ Complexity: Requires environment-specific configuration and migration management
- ❌ Data Consistency: Different databases might behave differently in edge cases
Decision: RESTful API with two-level nesting maximum
Trade-offs:
- ✅ Simplicity: Easy to understand and maintain
- ✅ Performance: Shorter URLs, fewer database joins
- ❌ Flexibility: Some complex queries might require multiple API calls
- ❌ Convention: Not following GraphQL patterns that some teams prefer
Decision: Simple React components without state management library
Trade-offs:
- ✅ Simplicity: Easy to understand and modify
- ✅ Performance: No additional bundle size from Redux/Zustand
- ❌ Scalability: Complex state management would be challenging
- ❌ Developer Experience: No time-travel debugging or predictable state updates
Decision: Basic HTTP status codes with simple error messages
Trade-offs:
- ✅ Simplicity: Easy to implement and understand
- ✅ Standards Compliance: Follows HTTP conventions
- ❌ User Experience: Limited error context for debugging
- ❌ Monitoring: No structured error tracking or logging aggregation
Decision: Unit and integration tests with 82% coverage
Trade-offs:
- ✅ Quality Assurance: Catches regressions and validates functionality
- ✅ Documentation: Tests serve as usage examples
- ❌ Development Speed: Writing tests takes time
- ❌ Maintenance: Tests need updates when code changes
If this application were to be expanded for production use:
-
Authentication & Authorization
- JWT-based authentication
- Role-based access control (RBAC)
- User registration and management flows
- Session management and security
-
Enhanced Security
- Input validation and sanitization
- Rate limiting and DDoS protection
- CORS configuration for production domains
- Security headers and HTTPS enforcement
-
Performance Optimization
- Database indexing strategy
- Caching layer (Redis)
- API response compression
- Frontend code splitting and lazy loading
-
Monitoring & Observability
- Structured logging with correlation IDs
- Application performance monitoring (APM)
- Error tracking and alerting
- Health checks and metrics
-
Scalability Improvements
- Database connection pooling
- Horizontal scaling considerations
- CDN for static assets
- Microservices architecture for complex domains
- Initial release
- Complete CRUD operations for assets, categories, and subcategories
- Bulk asset creation from JSON
- Comprehensive test suite
- SQLite and Supabase support
- Interactive API documentation
- React frontend with hierarchical asset display
- Full-stack application with modern UI