Opening case study…
Opening case study…
A business analytics dashboard that turns any sales CSV into KPIs, charts and forecasts — pointed at a new dataset by editing a column mapping rather than the code.
Covers
Stack
DataPulse is written to be used rather than read. Its own documentation opens by saying so — a business owner or an examiner should be able to work the thing without opening a Python file — and that framing decides most of what follows.
The path through it is a pipeline. CSVs land in a raw folder; ingestion normalizes their headers and loads them; transformation folds several raw tables into one business-ready analytics table; the dashboard reads from that table, and forecasting hangs off the same one.
The code is layered to match. Pages render, services hold the business logic — authentication, data access, KPI calculation, forecasting — pipeline components do the loading and reshaping, configuration holds the dataset mapping, and a shared UI module owns styling and chart helpers. Each file has one job, which is what keeps a project this size legible.
Administrator
Runs the pipeline
Viewer
Reads the dashboard
Ingestion
CSV, headers normalized
Transformation
One analytics table
KPI service
Business measures
Visualization
Plotly
Forecasting
Prophet
Column mapping
Python or YAML
Assistant
Question to SQL
Supabase Postgres
Via SQLAlchemy
There are two kinds of person in the system. An administrator manages users, sets business targets, runs the pipeline and triggers forecasts; a viewer sees the dashboard and the reports and cannot reach any of that.
That split is why the settings and pipeline pages exist separately at all. Deleting data, resetting the system and changing who has access are precisely the actions you do not want one click away from a read-only dashboard.
Pages
Administrator only
Viewer
Insights
Pipeline
Services
Six pages over five service modules. The repository is public, so this list is checkable rather than asserted.
The product claim is that DataPulse works for any business, and the column mapping is what makes that true rather than aspirational. A dataset needs a date column, a value column and a unique record ID; a customer column is optional.
Pointing the application at a different business means editing that mapping — in a Python config or a YAML file, both of which are committed — so the names in the system line up with the names in the CSV. No application logic changes. It is a small idea, and it is the entire difference between a dashboard for one dataset and a dashboard for any.
Everything downstream reads the mapped names and neither knows nor cares what the source file called them. The KPIs fall out of that table: revenue, order count, average order value, and the trend across whatever date range the reader selects.
One analytics table, built from the mapped CSVs
The selected date range
KPI cards, trend charts and a downloadable CSV
Mapping, not migration
Changing which business the dashboard serves is a configuration edit, not a schema change. The mapping names which CSV column plays each role, and everything downstream — the KPI service, the charts, the forecast — reads those roles rather than the source file's own column names.
revenue ÷ orders → average order valueThe forecasting path fits Prophet to the historical series in the analytics table and renders the result beside the actuals, which is genuinely useful for the planning conversations the product is aimed at.
What the project does not do is evaluate it. There is no held-out period, no baseline to compare against, and no error metric reported anywhere. A forecast chart that looks plausible is not a measured forecast, and that distinction is the whole reason this page calls the work analytics with forecasting rather than machine learning.
That is a gap in the evidence rather than a criticism of the choice. Prophet is a reasonable tool for a small business series. It simply has not been shown to be right here — and showing it would be cheap: one held-out window and one baseline would settle the question.
What the forecast is
What it is not
There is a feature in the repository its documentation never mentions: a conversational assistant that answers questions about the data by writing SQL against it.
The flow is careful. It reads live column metadata for the analytics tables and builds a compact schema description, decides whether the question is a data question at all, asks the model for a single SELECT constrained to those tables, runs it, and then asks the model again to turn the returned rows into a sentence.
The part worth pointing at is that it does not trust the model. The prompt asks for a SELECT with no semicolons — and then the code independently checks that the statement begins with SELECT, contains none of a list of write and schema-modifying keywords, and carries no semicolon, and appends a row limit if the model did not set one. A prompt instruction is a request; the guard is what actually holds.
It is a keyword denylist and a row cap rather than a sandbox, and nothing in the repository measures how often the generated SQL answers the question asked. Both of those sit in the limits below rather than being glossed over here.
There are two automated tests. One checks a KPI calculation against known data; the other checks that the application can load data from the database.
Two is a small number, and this page says so rather than describing them as a suite. What they do cover is the seam most likely to fail silently — a KPI that quietly computes the wrong thing looks exactly like a KPI that works — so as a first test to have written, it is the right one.
Known-data KPI test
The chain names what the KPI test walks, not what it returns; its inputs and values are not reproduced here. Two tests is the entire suite — no coverage figure is claimed, and none has been measured.
The application ran on Streamlit Community Cloud against a Supabase-hosted Postgres database, reached through SQLAlchemy with the connection string supplied as an environment value. An example environment file is committed; the real one is not.
Whether that deployment is still live is unresolved, so it is not presented here as a running demo. What is reproducible is the local path: the repository carries a development container definition and a pinned requirements file, so the environment is described rather than assumed.
Browser
Streamlit Community Cloud
Application hosting
Streamlit application
Pages and services
SQLAlchemy
Connection from environment
Supabase
Managed Postgres
The repository is public, so the left column below can be checked rather than taken on trust — the structure, the mapping, the forecasting path and the SQL guards are all there to read.
The right column is where this would have to grow to be a data-science case study rather than an application one. None of it is difficult. None of it is done.
Next proof
Not a roadmap — the specific things that would turn this from an application into evidence. Each one converts a claim on this page from an assertion into a number.
A reproducible dataset published beside the work, so a reader can run it.
Checks that run with the pipeline rather than beside it.
A stated baseline for any forecast to be measured against.
Explicit forecast error, reported rather than implied.
A fixed set of questions with known answers, so accuracy is a number rather than an impression.
Tests that assert a viewer cannot reach an administrator's actions.
The repository and everything in it are public and available: the layered source, both mapping formats, the forecasting path, the assistant and the two tests.
What is not available is any evaluation, and the hosted deployment's state is unresolved. The rows below keep those apart rather than folding them into a summary that would read as finished.
Concept level, and checkable — the repository is public. The separation is not covered by any test, which the limits section states rather than hides.
The repository is public. It shows a layered application — pages, services, pipeline components, configuration and shared UI, each with one job — a configurable column mapping that onboards a new dataset without touching application logic, a Prophet forecasting path, two separated roles, and a Gemini-backed assistant that turns questions into guarded SELECT statements against the analytics schema.
Forecast quality is not evaluated anywhere: no baseline, no held-out period, no error metric. The assistant's SQL is guarded but not measured — nothing checks how often its answers are right. Two automated tests exist, which is two. Role enforcement, data provenance and whether the deployment remains live are unverified, and the contribution split between Rafay Khattak and Muhammad Umar Nadeem is not documented, so none is claimed.
The application is a single Streamlit process reading and writing a Supabase-hosted Postgres database through SQLAlchemy. Ingestion loads CSVs and normalizes their headers, transformation folds them into one analytics table, and Prophet produces the forecast from it. It was deployed through Streamlit Community Cloud; whether that deployment is still live is unresolved, so it is not presented here as a running demo.