← Back to work

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.

∑
Source of the numbers. Engineering counts come from /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.

⇢
Manager login (verified 15 July 2026). Email 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.

DealerIQ login screen on the live demo host.
Fig. 01: Login at dealeriq.ahmdmshazly.me (captured 15 July 2026).

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.

Manager dashboard with sales vs forecast chart and top/bottom models.
Fig. 02: Manager dashboard with sales, forecasts, models and inventory as well as alert summaries.
Customers screen with a new-customer form above a table of seeded customers showing name, phone, email, city and source.
Fig. 03: Customers. A duplicate phone or email warns the clerk and still writes the record (FR-030).
Orders list with negotiated price, discount and margin as well as delivered status.
Fig. 04: Orders move including draft and submission, approval as well as delivery.
Leads funnel table with status badges and action buttons.
Fig. 05: Leads funnel with role-scoped ownership and status transitions.
Current lot inventory listing for the dealership.
Fig. 06: Current lot inventory from the seeded vehicle-units ledger.
Analytics page listing champion forecasts vs Seasonal Naive by series.
Fig. 07: Per-series champion models compared with Seasonal Naive after a forecast run.
Inventory intelligence ABC/XYZ heatmap and anomaly explorer.
Fig. 08: ABC/XYZ heatmap, aging and reorder as well as anomalies after an inventory run.
Alerts notification center with rule and severity filters.
Fig. 09: Alerts from the six built-in rules (FR-061).

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.

Alert Rules table listing six rules with severity badges, JSON parameters, a version column and enabled toggles.
Fig. 10: Thresholds and role subscriptions live in data, not in code. Every rule carries a version and each change is audit-logged (FR-065).
Admin users table listing seeded Admin, Manager, Sales, and Analyst accounts.
Fig. 11: Admin controls for creating, deactivating and unlocking as well as assigning users.
Audit log table with when, actor, action, entity and IP columns, filtered by action.
Fig. 12: An append-only record of logins, failed attempts, password changes and role edits (FR-080/081).
Monthly report for June 2026 showing total revenue, total margin, an achieved forecast accuracy panel and alert breakdowns by rule and severity.
Fig. 13: The monthly report keeps achieved accuracy separate from training-time cross-validation and says plainly when it cannot score yet.

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

0

Python tests · API + analytics packages

0

Vitest cases passed · 3 files at fe7db219

0

CI job · 19 named steps in the workflow

0

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.

0%

line coverage · packages/analytics

0

ROC-AUC · lead scoring on the seeded funnel

0

alerts opened · six rules on one run

0k

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.

✓
Check the work. Sign in at dealeriq.ahmdmshazly.me with the Manager credentials above, or read about the 2022 NaserSalem system. Treat the live application as current if this page falls behind.

Spec DIQ-SRS-001 · CHANGELOG v1.0.0 (12 July 2026) · phases 0-10 complete.