Morris Solutions
Designed, not built2026

One view of money arriving through several providers, entities and currencies

An organisation taking money through several payment providers, across more than one entity and currency, with no single view of what came in or what it cost.

Architecture and data model complete; not built. This page describes a design, not a running system.

The problem

Money arrives through several payment providers. The organisation runs more than one legal entity. Some of it is in another currency. Every provider reports fees differently, and the accounting ledger sees the net figure days later.

The result is that nobody can answer three ordinary questions: what came in this month across everything, what did it actually cost us in fees, and what does the next quarter look like. Each provider’s own dashboard answers for that provider alone, and reconciling them into the ledger is somebody’s manual week.

What it does

Pulls transactions, fees and payouts from every provider, normalises them into one shape, converts to a reporting currency, and reconciles the result against the accounting ledger — surfacing what it cannot match rather than pretending everything reconciled.

Cash flow by entity and by provider, fee analysis per transaction, currency exposure, and trend-based forecasting on top.

How it’s built

Four strictly sequential layers: ingestion, normalisation, storage, presentation. Each knows only about the one below it.

One connector per provider, fully isolated, each responsible for its own auth, pagination, rate limiting and retry. A provider outage or an API change degrades one connector rather than the pipeline.

Everything lands in a single normalised transaction table, and every view is a straightforward select over it.

The decisions that mattered

The ledger stays the system of record. This reads and reconciles; it never writes back. A reporting layer that can also mutate the books is a reporting layer nobody can trust.

Gross, fee and net are stored separately, not derived. Fee transparency per transaction is one of the main things this exists to provide, and providers report fees inconsistently enough that recomputing them from the other two is unreliable.

Store the rate, not just the converted amount. Every amount carries its base-currency equivalent alongside the exchange rate and the date it was taken, so a figure reported last quarter still reproduces this quarter.

Deduplicate on the provider’s own transaction ID. The same payment can arrive twice — once by scheduled pull, once by webhook. Matching on amount and date instead will silently discard legitimate same-value transactions.

Reconciliation is exception-based. Settlement timing differs from transaction timing, providers batch their payouts, and currency conversion means amounts rarely match to the cent. The engine matches on a window of date, amount tolerance and reference, then surfaces a queue of what it could not resolve for a human to work.

Outcome

Not built. The architecture, the normalised transaction model and the reconciliation approach are complete and documented, phased so that the first two modules deliver a working read-only view before the ledger integration — the piece carrying the most uncertainty — is scoped in detail.

Built with
PostgresServerless connectorsReactNetlify

Want something like this for your business?

Tell me how this works for you today and where it gets stuck.