Case study · Systems
DealerIQ: dealership records and forecasting
A FastAPI and Next.js dealership system that keeps orders and inventory in one ledger, then adds forecasts, anomaly detection and lead scores as well as alerts.

Role
SRS author · full-stack build · analytics pipeline
Timeline
Phases 0-10 complete · software v1.0.0 on 12 Jul 2026
Stack
FastAPI · Next.js 15 · PostgreSQL · statsforecast analytics
Output
Dealership SoR + forecasting / intel / alerts · live demo
DealerIQ is a dealership system of record for orders, inventory and customers as well as leads. It also forecasts demand, detects unusual stock and scores leads as well as opens alerts. It builds on the domain work from my 2022 NaserSalem internship.
/home/ahmdmshazly/dealeriq at commit fe7db219 (15 July 2026). Values labelled as paper artifacts come from the committed benchmark leaderboard. Behaviour described in words comes from the screens captured on the same date and reproduced below. Demo KPIs are synthetic and do not represent a dealership's books. Ledger: backups/dealeriq-numbers-ledger.2026-07-15.md.Try the live demo
Open dealeriq.ahmdmshazly.me (Vercel UI; API on the same origin via /api). The seed includes Admin, Manager and Sales as well as Analyst roles. All data is synthetic.
manager1@dealeriq.dev · password SeedUser123!. The Manager role can access the sales and operations dashboards. The ledger documents a separate demo password for admin@dealeriq.dev, which can access user and audit screens.Demo security configuration, verified 15 July 2026: TLS on the public host, a health endpoint returning 200 and a CORS allow-list containing the UI origin as well as password login for all four roles after a production synthetic seed (~15k orders and 6k leads). The EC2 API may be stopped to reduce cost, which returns 502. Digest email does nothing without SMTP configuration.

Why build the successor
In 2022 I shipped a Django and PostgreSQL sales-and-inventory system for NaserSalem Motors. It kept records in one ledger and gave each role the reports it needed. DealerIQ retains that foundation and adds intermittent-demand forecasting and anomaly detection as well as alerts.
Dealership demand is often sparse and bursty, with weeks of zeros followed by several sales. Methods designed for "smooth series" can perform poorly on that pattern. DealerIQ places forecasting, inventory classification and anomalies as well as alerts over the same orders and units ledger, with role-based access for dealership staff.
Record, forecast and detect as well as alert from the same ledger.
What it does, in plain language
Staff record customers, leads and stocked units as well as orders under role permissions. Nightly or on demand, jobs classify each demand series, pick a champion forecast, score inventory risk by ABC/XYZ, aging and reorder point as well as flag anomalies, then rank the lead funnel and open alerts where rules fire. Managers read dashboards; analysts trigger runs; admins own users, permissions and the audit log as well as the alert thresholds. Every screen reads the same PostgreSQL ledger, so a forecast, an alert and a report all trace back to the same orders and units rather than to a spreadsheet someone kept on the side.
Screens with synthetic data
These figures were captured from the live demo after a production synthetic seed and, where noted, an analytics run. They contain no real customer data.








Configuration, audit and reporting
The remaining screens are the control surface rather than the daily workflow. They were captured on the same 15 July 2026 pass, signed in as Admin. Alert thresholds, the user roster and the audit trail as well as the monthly report are where the system explains itself to whoever has to trust it.




The loop
LOOP 01 · RECORD
Orders, units, leads, customers
PostgreSQL is the single ledger. Role-based permissions (Admin · Manager · Sales · Analyst) gate who can create, approve or see margin.
LOOP 02 · FORECAST
Champion per series
Demand series are classified as smooth, intermittent and erratic as well as lumpy. Rolling-origin cross-validation selects a method for each series against Seasonal Naive, using the same pipeline as the paper benchmark.
LOOP 03 · INTELLIGENCE
Inventory + anomalies + leads
Inventory jobs publish ABC/XYZ, reorder points and aging/survival risk as well as anomaly scores. Lead scoring ranks the funnel so Sales call the right people first.
LOOP 04 · ALERT
Rules that open work
Six built-in rules open acknowledgable alerts for stock reorder, aging, sales anomalies, forecast stockouts and discount approval as well as idle leads. Thresholds and role subscriptions are stored per rule and versioned.
LOOP 05 · DECIDE
Dashboards and reports
Managers see sales vs forecast and model heat; analysts trigger runs; admins own users and the audit log. The monthly report scores forecasts against what actually sold. The UI never invents a parallel truth outside the ledger.
Three decisions worth defending
Most of this system is ordinary CRUD done carefully. Three choices are not, and they are the ones I would take into a review.
- The report refuses to score what it cannot score yet. Achieved accuracy is measured out of sample against what actually sold, and it is kept apart from the cross-validation numbers used to pick a model. When no series has enough forecast history, the panel says so instead of showing the backtest figure and calling it accuracy (Fig. 13).
- Duplicate customers warn but never block. A matching phone or email raises a notice and still writes the record (FR-030). A dealership has families sharing one number and buyers who return under a second address, so the person at the desk knows things the validator does not.
- The model watches itself. One of the six rules is
lead_score_drift, with a population stability index threshold of 0.25. If the lead-score distribution drifts away from what the model was fitted on, that opens an alert like any stock or aging problem (Fig. 10).
What was measured
Python tests · API + analytics packages
Vitest cases passed · 3 files at fe7db219
CI job · 19 named steps in the workflow
benchmark series · paper leaderboard artifact
At commit fe7db219: 214 Python test functions across apps/api and packages/analytics; Vitest 8/8 green in apps/web; nineteen Next.js routes and about 24.6k lines of app and package TypeScript and Python; one GitHub Actions ci job with nineteen named steps. A scoped run over packages/analytics reported 92% line coverage across its 104 tests. The Phase 10 paper leaderboard (committed artifact, not a live dealership KPI) reports champion vs Seasonal Naive win rates of 88.4% on intermittent series (n=86) and 94.9% overall (n=198).
Those numbers describe the code. The next four describe one full pass of the analytics and alert jobs against the production synthetic seed on 15 July 2026, which held 15,202 orders and 6,000 leads across 12 users.
line coverage · packages/analytics
ROC-AUC · lead scoring on the seeded funnel
alerts opened · six rules on one run
LOC · apps + packages TypeScript and Python
The inventory job published 66 intelligence rows, 236 unit risks and 267 series anomalies as well as 291 transaction anomalies. Lead scoring wrote 230 scores at ROC-AUC 0.889 and PR-AUC 0.866. The alert job opened 852 alerts: 62 reorder, 98 aging, 558 anomaly and 13 forecast stockout as well as 121 idle leads. The alert badge in Fig. 13 shows that same 852. These are the counts from one run, not a steady-state rate.
What this page will not claim
The repository is private, so there is no source link. NFR-005's "retry once with backoff" for jobs is not implemented. Four conformal-interval methods measured 59-63% empirical coverage against a nominal 80% interval; native-interval methods measured roughly 78-97%. The paper reports the undercoverage and the n_windows=2 default.
DealerIQ is not multi-tenant SaaS or a claim to replace a dealership management system. The demo does not contain real profit-and-loss data. No achieved forecast accuracy is shown, because at capture time no series had enough forecast history to score; that is the honest state of a system seeded that week rather than a hidden failure. Digests require SMTP, and the EC2 API may be stopped to reduce cost. Only credentials verified on the live demo appear above.
Spec DIQ-SRS-001 · CHANGELOG v1.0.0 (12 July 2026) · phases 0-10 complete.