Back to Projects

ReimburseFlow

An expense-reimbursement tool where the approval chain is configuration, not code — with OCR receipt scanning and live multi-currency baked in.

Solo build
  • FastAPI
  • React
  • Prisma
  • PostgreSQL
Cover coming soon

Every company approves expenses differently. Some want the manager to sign off first, then finance. Some want three people in a strict order. Some just want any two of five approvers to agree. The usual result is that "the approval workflow" gets hardcoded into the app, and the first company with a slightly different policy needs a code change. ReimburseFlow is built on the opposite bet: the workflow is data an admin configures, and the engine just runs whatever shape they describe.

The problem

Expense approval looks trivial until you look closely. Then it fractures into a dozen policy questions. Sequential or parallel approvers? Is the submitter's manager always first? Does a rule fire on a percentage of approvers agreeing, or does one specific person's yes auto-approve everything? Are some approvers required, so their rejection kills the whole request regardless of everyone else? Encode any single answer and you've built a tool for exactly one company. I wanted an approval engine general enough that changing the policy means editing a rule, not shipping a release.

What I built

A React front end on a FastAPI backend, with Prisma over Postgres. An employee submits an expense — description, category, amount, who paid — and either saves it as a draft or pushes it straight into the approval workflow. Managers and admins get an approval queue showing exactly the expenses awaiting their step, an expense detail view with a status progress bar, and a full audit log of who did what and when, with rejections requiring a comment.

The heart of it is the admin's rule builder. A rule can be a percentage threshold, a specific-approver auto-approve, or a hybrid of both. There's a toggle for whether the submitter's manager approves first, and a toggle that flips the approver list between sequential (1→2→3, each waiting on the last) and parallel (everyone notified at once). Each approver can be marked required — and if a required approver rejects, the expense is auto-rejected no matter what the others say. One rule is the company default; the rest sit ready for the cases that need them.

The two integrations that make it feel finished

Two features move ReimburseFlow from "form with a state machine" to something that respects the user's time.

The first is OCR. Instead of typing a receipt, you photograph it — the image goes to the Mindee receipt API and comes back as amount, currency, date, vendor, and category, pre-filled into the form and highlighted so you can see exactly what was auto-read before you confirm. And it degrades gracefully: with no API key configured, the scan page still works, it just hands you an empty form to fill in manually rather than throwing a wall in your face.

The second is multi-currency. Submit an expense in USD when the company runs in INR and it's converted at live rates automatically — and the approver sees both numbers, the original and the converted, with the rate that was used. No mental math, no "wait, what was the exchange rate that day" in the approval thread. New companies even pick their base currency from a country list pulled live at signup.

Built to be tested

Because the whole point is behavior under different policies, I seeded it to be exercised, not just admired. There are role-based test accounts across admin, managers, and employees; pre-seeded expenses sitting in every state — pending, approved, rejected, in-progress; and two ready-made rules (a sequential three-step default and a quick parallel one). You can log in as an employee, submit, then walk the approval through several managers in order and watch the state machine and audit log update at each hop. The backend ships an auto-generated Swagger UI, so every endpoint behind all of this is inspectable rather than a black box.

Where it stands

The full loop works end to end: submit (or draft), route through a configurable chain, approve or reject with a paper trail, convert currencies live, and scan receipts into the form. The obvious next step is real receipt storage — right now the attach-file UI selects a file but doesn't yet persist it — and richer reporting on top of the expense data. But the hard, differentiating part, the configurable approval engine, is done and behaving.