Skip to content

bhavya-ops21/finance-backend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Finance Dashboard Backend

A backend system for managing financial records with role-based access control. Built with FastAPI and PostgreSQL.

I built this as a screening assignment for Zorvyn. The goal was to create a clean, well-structured backend that handles real-world concerns like authentication, role-based permissions, data validation, and dashboard-level aggregations.


What this does

Different people in an organisation need different levels of access to financial data. A junior employee shouldn't be able to delete records. A manager should be able to see summaries but not necessarily manage users. This backend handles all of that cleanly.

There are three roles:

  • Viewer — can browse records and see the dashboard. Nothing else.
  • Analyst — can create and update records on top of everything a viewer can do.
  • Admin — full access. Can manage users, change roles, and delete records.

Tech stack

  • FastAPI — fast, modern Python web framework with automatic docs
  • PostgreSQL — relational database
  • SQLAlchemy (async) — talks to the database using Python instead of raw SQL
  • JWT via python-jose — stateless authentication tokens
  • Passlib + bcrypt — passwords are hashed, never stored as plain text
  • Pydantic v2 — validates every request automatically

Getting it running

1. Clone the repo

git clone <your-repo-url>
cd finance-backend

2. Create a virtual environment

python3 -m venv venv
source venv/bin/activate

3. Install dependencies

pip install -r requirements.txt

4. Set up PostgreSQL

psql postgres

Then run these inside psql:

CREATE DATABASE finance_db;
CREATE USER finance_user WITH PASSWORD 'finance123';
GRANT ALL PRIVILEGES ON DATABASE finance_db TO finance_user;
\c finance_db
GRANT ALL ON SCHEMA public TO finance_user;
\q

5. Create a .env file in the root folder

DATABASE_URL=postgresql+asyncpg://finance_user:finance123@localhost:5432/finance_db
SECRET_KEY=supersecretkey123changethisinproduction
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30

6. Start the server

uvicorn app.main:app --reload

7. Open the interactive docs

http://127.0.0.1:8000/docs

FastAPI generates this automatically. You can test every endpoint directly from the browser — no Postman needed.


How authentication works

  1. Register a user at POST /auth/register
  2. Login at POST /auth/login — you get back a JWT token
  3. Click Authorize in the docs page and paste the token
  4. All future requests will automatically include it

Tokens expire after 30 minutes. Roles are checked on every protected endpoint using FastAPI's dependency injection system.


Access control at a glance

Action Viewer Analyst Admin
View records Yes Yes Yes
Create records No Yes Yes
Update records No Yes Yes
Delete records No No Yes
View dashboard Yes Yes Yes
Manage users No No Yes

API endpoints

Authentication

  • POST /auth/register — create a new user
  • POST /auth/login — login and receive a JWT token

Users

  • GET /users/me — see your own profile
  • GET /users/ — list all users (admin only)
  • PATCH /users/{id} — update role or deactivate a user (admin only)

Financial Records

  • POST /records/ — create a new record (analyst and admin)
  • GET /records/ — list all records with optional filters
  • GET /records/{id} — fetch one specific record
  • PATCH /records/{id} — update a record (analyst and admin)
  • DELETE /records/{id} — soft delete a record (admin only)

Dashboard

  • GET /dashboard/summary — total income, total expenses, net balance
  • GET /dashboard/categories — breakdown by category
  • GET /dashboard/recent — last 5 transactions
  • GET /dashboard/trends — month by month income and expense totals

Filtering and pagination

The records list endpoint supports query parameters so the frontend can filter without loading everything:

GET /records/?type=income
GET /records/?category=Salary
GET /records/?start_date=2026-01-01&end_date=2026-04-30
GET /records/?skip=0&limit=10

A few design decisions worth mentioning

Soft deletes — records are never permanently removed. When something is deleted, we just set is_deleted = True and hide it from all responses. This means data can be recovered if needed and nothing is lost by accident.

Database-level aggregations — the dashboard doesn't load all records into Python and loop through them. It uses SQL GROUP BY and SUM directly, which is much faster as data grows.

Role guards as reusable dependencies — access control is handled through FastAPI's Depends() system. A single function like require_admin can be dropped into any endpoint. No repeated if/else checks everywhere.

Passwords never leave the system — the response schemas are designed so that even the hashed password is never included in any API response.


Assumptions made

  • New users are viewers by default — an admin must manually upgrade them
  • The .env file is never committed to version control
  • All dashboard endpoints require login but no specific role
  • Pagination defaults to 10 records per page, max 100

Project structure

finance-backend/
├── app/
│   ├── main.py          ← entry point, table creation on startup
│   ├── core/
│   │   ├── config.py    ← reads .env settings
│   │   ├── security.py  ← password hashing and JWT logic
│   │   └── deps.py      ← reusable auth and role guards
│   ├── models/          ← database table definitions
│   ├── schemas/         ← request and response shapes
│   ├── routers/         ← API endpoints
│   ├── services/        ← business logic
│   └── db/              ← database connection and base class
├── .env
├── requirements.txt
└── README.md

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages