Finance Operations

How Techparser Built a Multi-Currency Expense Panel That Never Converts at a Guess

Techparser built a multi-currency expense panel that records spend per currency and reports a total and category breakdown for each, never converting.

Client
Techparser product build
Industry
Finance Operations
Timeline
Built, available for deployment
Team
1 senior full-stack engineer

Want results like these?




Results

12 currencies
Spend recorded in any of twelve currencies
2 SQL functions
One totals per currency, one by category
5/10 MB
Image and PDF receipt size caps

The problem

Techparser built an internal panel for recording company expenses in any of twelve currencies, with categories, receipts and an analytics page that shows the total and a category breakdown for every currency in use. Admins manage users, categories and currencies, while editors record expenses. There is no row-level security in this database, so every server action has to check permissions itself. Receipts are private financial documents that must never become public files, and amounts have to stay exact.

Adding amounts in different currencies together, or converting them at a guessed rate, produces totals nobody can reconcile. One missed permission check would let anyone read or change company spending, and a careless file path would leak receipts. The money maths, the access checks and the receipt handling each had to be right on their own.

What Techparser built

  • Two SQL functions do the analytics, one totalling spend per currency and the other breaking a single currency down by category, so no figure is ever added across currencies and every number reconciles.
  • Amounts are fixed-precision decimals that must be positive, with at most two decimal places and no future dates, checked in both the form and the database, and currencies come from a reference table rather than free text.
  • A currency, category or user still referenced by a recorded expense cannot be deleted; the database refuses and the panel explains why, so history never loses its labels.
  • An edge check keeps signed-out users out and non-admins away from admin pages, and every server action then re-reads the user's role from the database before acting, so a stale or tampered session cannot raise permissions.
  • Sessions are signed tokens in HTTP-only cookies, passwords are hashed with bcrypt, the post-login redirect only accepts paths on the site, and the first admin is created from the command line rather than a public page.
  • Receipts are stored outside anything the web server publishes and served by one route that requires a session, confirms the file belongs to a recorded expense, and tells browsers never to cache it.
  • Only images up to 5 MB and PDFs up to 10 MB are accepted, each saved under a random name per expense, with every path resolved against the storage root so it cannot escape it and a failed save removing the upload.
  • Expenses record who added, changed and deleted them and when; deleting hides a row instead of erasing it, and a partial index keeps the active list fast.
  • All queries go through one server-only connection pool with placeholders for every value, including the dynamically built filters, so user input is never stitched into SQL.

Decisions that mattered

Totals that reconcile, never a guessed conversion

Adding amounts across currencies, or converting them at a guessed rate, produces totals nobody can reconcile later. Techparser refused to convert at all. The analytics run in two SQL functions: one totals spend per currency, the other breaks a single currency down by category, and no figure is ever summed across currencies. Amounts themselves are fixed-precision decimals, positive, with at most two decimal places and no future dates, checked in both the form and the database. The result is a panel where every number on the page traces back to an exact, recorded amount in its own currency.

Permission checked twice, because the database won't

This database has no row-level security, so nothing stops a query by itself; the application is the only guard. Rather than trust one checkpoint, Techparser used two. An edge check keeps signed-out users out and non-admins away from admin pages before a page even loads. Then every server action re-reads the user's role from the database before it acts, so a stale or tampered session cannot raise anyone's permissions. Sessions are signed tokens in HTTP-only cookies, passwords are bcrypt hashed, and the first admin is created from the command line, never a public sign-up page.

Receipts that cannot leak

Receipts are private financial documents, so a careless file path would expose company spending. Techparser kept them out of reach by design. Files are stored outside anything the web server publishes and served by a single route that requires a session, confirms the file belongs to a recorded expense, and tells browsers never to cache it. Uploads are limited to images up to 5 MB and PDFs up to 10 MB, each saved under a random name, and every path is resolved against the storage root so it cannot escape. A failed save deletes the orphaned file.

Outcome

The panel is built and available for deployment. It records company expenses in any of twelve currencies with categories and receipts, and its analytics page shows the total and a category breakdown for every currency in use, with admins managing users, categories and currencies and editors recording spend.

Because the analytics never add across currencies, every total on the page reconciles against exact recorded amounts, and nothing still in use can be deleted, so history keeps its labels. Permissions are re-checked in every server action rather than trusted from the session, and receipts stay outside the public folder behind a session-checked route. Soft deletes and an append-only record of who changed what mean the spending history can be audited without losing anything.

Questions about this project

What technology stack does the Expense tracker use?
The panel is built on the Next.js App Router with PostgreSQL for data and Tailwind CSS for the interface. The analytics run as two SQL functions in the database, one per-currency total and one category breakdown. Queries go through a single server-only connection pool with placeholders for every value, sessions are signed tokens in HTTP-only cookies, and passwords are hashed with bcrypt.
How does the panel keep multi-currency totals that actually reconcile?
By never converting. Amounts are recorded in their own currency as fixed-precision decimals, positive, with at most two decimal places, validated in both the form and the database. The analytics run in two SQL functions, one totalling spend per currency and one breaking a currency down by category, and no figure is ever added across currencies. Every number on the page traces back to an exact recorded amount.
Can Techparser build a multi-currency expense panel like this for us?
Yes. Techparser built this panel end to end: per-currency analytics in SQL, exact decimal amounts, permission checks in every server action, private receipt handling and a full audit trail, all on the Next.js App Router and PostgreSQL. The same approach fits any internal finance tool where totals must reconcile and access and documents have to stay locked down. Book a call to discuss what you need built.