From raw ledger exports to a reconciled, forecast cash position.
A medallion pipeline with a config-driven categorization engine and a hybrid forecasting layer, surfaced to Finance through an Ontology-backed console. This page documents every layer and the test cases that hold each one in place.
Overview
medallion + writebackThe system turns raw bank and GL transaction exports into three deliverables: a reconciled monthly cash-flow statement, a twelve-month forward forecast, and a cash-position view with Days Cash on Hand. Each is served to Finance through the Cash Console.
Two design decisions shape everything downstream. First, categorization is data, not
code — rules and overrides live in writeback-enabled datasets that Finance edits from the
UI, and a change re-triggers the build chain without a deployment. Second, the
actual/forecast boundary is a single derived value: last_actual, the maximum
month present in cashflow_monthly. Every downstream transform reads it rather
than carrying its own cut-off, so the boundary can never disagree with itself.
Layer map
read top to bottomlast_actualIngestion — Bronze
parse & mergeFinance drops Excel and CSV exports into two media sets. Each parser handles real-world spreadsheet mess — preamble rows above the header, inconsistent types, dotted column names — and writes a typed dataset. Parsed uploads are then unioned with a static historical dataset and deduplicated.
Datasets
bronzeUniqueIDR-01.Cleaning — Silver
clean_transactionsStandardises types and dates, deduplicates, and joins cash transactions to their GL distribution context. This is where the accounting correctness lives.
Transformations
silversign, signed_amount, cash_date = coalesce(post date, issue date), status, recon_dateCategorization — Silver
the semantic heartMaps every transaction to a cash-flow parameter using a rules engine read from the LIVE config datasets at build time. No categorization logic is hardcoded, which is what allows Finance to re-categorize without a code change.
Rule cascade
first match winsR-04 exist to catch.Aggregation — Gold
actuals backboneDaily and monthly nets per parameter and direction. cashflow_monthly is the
backbone: the forecast models train on it, the enriched statement builds from it, and its
maximum month defines last_actual for the whole platform.
Datasets
goldForecasting
hybrid ensembleDemand-driven series get machine learning; scheduled outflows get deterministic calendar models. Mixing the two is deliberate — a model has nothing useful to learn about a payroll run that occurs every second Wednesday, and a calendar has nothing useful to say about patient payment volume.
Model branches
forecast layerlast_actual + 12
so all parameters share one forecast window.Statement & position — Gold
what Finance readsDatasets
goldlast_actual merged with forecast beyond it into one continuous series; each row tagged is_actual and forecast_method, with actual-versus-forecast variance computedConfig writeback
config as dataTwo writeback-enabled LIVE datasets are authoritative for categorization. Seed versions are produced from a SQL definition, but the app writes user edits back through Ontology actions into the LIVE datasets, and the categorize transform reads LIVE.
The loop
writebackR-05 asserts on build timestamps rather
than trusting the trigger.Ontology & application
semantic layerObject types & console
servingOrchestration
build & triggerMechanics
operationsTest catalogue
unit · integration · regressionEvery case names what it asserts and why it matters — a test whose purpose is not obvious gets deleted the first time it fails inconveniently. Regression cases are tied to failure modes that have occurred or to invariants that are expensive to discover broken.