How Algoramming built DNCC EMS, a cross-platform equipment-management platform on Flutter and Supabase that runs a city corporation's vehicles, spare-parts inventory, procurement, fuel, and maintenance job cards on one double-entry ledger, from any device.

Dhaka North City Corporation ran its vehicles, heavy machinery, spare parts, fuel, drivers, and maintenance on scattered manual records and spreadsheets. Stock could be spent twice, running balances never reconciled, and no one could audit where a part or a taka of budget really went across a large public-sector fleet.
Algoramming built a cross-platform Flutter and Supabase app that stores every stock movement as a double-entry transaction. Procurement debits inventory, an approved job card or a refuel credits it, and Postgres views plus RPC functions work out stock levels, running balances, and budgets straight from that one ledger.
DNCC now runs one accountable, auditable system of record on six platforms from a single codebase. Nothing on the shelf is spent twice, balances reconcile on their own, and staff get role-based access, fiscal-year tagging, printable PDF statements, and a bilingual English and Bangla interface over a full audit history.
TL;DR (answer-first summary): Algoramming built DNCC EMS, a cross-platform platform on Flutter and Supabase that runs the Dhaka North City Corporation's equipment operation from one codebase on six platforms (Android, iOS, Web, Windows, macOS, Linux). It covers vehicles and heavy machinery, spare-parts inventory, vendor procurement, fuel, drivers, and maintenance job cards. The core idea is simple: instead of storing "how many parts are on the shelf," the system stores every movement as a double-entry transaction and works out stock levels, running balances, and budgets from that ledger inside Postgres. Procurement debits inventory, an approved job card or a refuel credits it, and nothing on the shelf can be spent twice. The outcome is an accountable, auditable system of record with role-based access, fiscal-year tagging, printable statements, and a bilingual (English and বাংলা) interface.
A city corporation runs a large, expensive, constantly-moving fleet: waste trucks, excavators, road rollers, generators, and the long tail of spare parts, tyres, batteries, lubricants, and fuel that keeps them running. Managing that on spreadsheets and paper files produces the same failures everywhere. Nobody can say with confidence how many filters are actually in the store, which vehicle consumed them, whether a repair was approved before parts went out, or how much of this year's budget is already committed.
The corporation needed one system that could:
Algoramming delivered DNCC EMS, a Flutter application backed by Supabase, organized as about 18 feature modules across roughly 320 Dart files, running unchanged on all six Flutter target platforms. It is not a thin CRUD front-end over a database. Its centre of gravity is a double-entry inventory-and-value ledger. Every other module is either a way to write transactions into that ledger or a way to read worked-out totals back out of it.
| Capability | What it does |
|---|---|
| Equipment registry | Every vehicle and machine, classified Category then Sub-Category, with brand, registration, engine/chassis, capacity, source-of-fund, and an assigned driver |
| Ledger-driven inventory | On-hand quantity is calculated from transactions, never stored, so stock cannot silently drift |
| Procurement to stock | A vendor purchase document turns each line item into stock plus a system-generated "stock-in" debit |
| Job cards | Maintenance work orders that consume parts against a vehicle; consumption only counts once the card is approved |
| Fuel management | Refuelling per vehicle, built on the same stock and ledger primitives, with no bolt-on table |
| Statements | Print, share, or export PDF statements scoped to any vehicle, vendor, stock item, or job card |
| Access & audit | Five-tier role hierarchy, per-row creator/updater stamps, and a subscription/licence gate |
| Dashboards | Fleet drill-down (vehicles per category) plus transaction-value charts (daily, monthly, annual) |
DNCC EMS runs on Flutter with Riverpod 3 for state, Beamer for declarative URL-based routing, and Supabase (Postgres, Auth, Storage) for the backend. It follows a strict, repeatable feature-module convention. Every module under lib/src/modules/ splits into model/ (the entity, its JSON mapping, its PostgREST join spec, and its search query), api/ (a thin class of Supabase CRUD calls), provider/ (Riverpod notifiers: one for the paginated list, one for the add/edit form), and view/ (the responsive page plus its components). Because every module (vehicle, driver, vendor, stock, job card) mirrors the exact same shape, the codebase is predictable and easy to extend. Learn one slice and you know all of them.
A single navigation registry (the drawer enum) is the source of truth for the menu, mapping each feature to an icon, title, and route. Beamer guards handle the whole session flow declaratively. An unauthenticated user is sent to login, a logged-in user is bounced off the login screen, and a global maintenance flag can divert the whole app to a maintenance page. Auth changes simply re-run the guards.
Supabase provides Postgres, Auth (email and password plus an OTP-based password-recovery flow), and Storage (avatars and attachments). The heavy lifting of aggregation lives inside the database as SQL views and RPC functions, not in the client. On-hand quantities, running balances, per-vehicle budgets, and last-used dates are all computed by Postgres and sent down ready to render.
One deliberate operational decision: the same build can point at two backends, a production and a development Supabase project, switched at runtime from a saved local flag, with no rebuild. Local device preferences (theme, locale, date/time format, the environment flag) are the only thing stored on the device, in Hive. All domain data stays server-side and is fetched live with debounced search and infinite-scroll pagination.
This is the idea everything else is built around. Most inventory apps store a quantity column and change it in place. DNCC EMS does not trust a stored number. It stores movements and works the number out.
Every movement is a row in one transactions table. Each row moves value between two general-ledger account types (FileProcurement, Stock, or Vehicle) in a direction that is either a Debit or a Credit.
StockEntity and a paired transaction: FileProcurement to Stock, Debit, flagged isSystemGenerated, tagged with the "Stock Add Voucher". This is inventory arriving.Stock to Vehicle, Credit, carrying the job-card id, the vehicle context, and the timestamp. This is inventory being consumed.On-hand quantity is a worked-out view: sum of debits minus sum of active credits. A companion running-balance view produces a per-stock "intotal" column so the stock book reads like a real ledger. Two RPC functions handle the rest of the maths server-side. One returns {budget, spend, hold} for a sub-category's stock value, and the other returns each part's last-used and last-held date for a given vehicle.
The detail that makes it trustworthy: a job card's consumption transactions are created inactive and only flip to active when the card is approved. Un-approved work is visible but does not yet count against inventory, so parts can be reserved (held) without being spent, and the "left versus hold" split comes straight out of the same ledger.
Approving or un-approving a card re-writes its transactions' active flag and refreshes the stock levels everywhere they appear. The whole system therefore has one source of truth for both inventory and money, and every screen (a vendor, a vehicle, a single stock item, a job card) is just that one ledger filtered to the entity you are looking at, with a one-tap PDF statement of exactly what you filtered.
The interesting work was in the seams, where a mobile app, a live Postgres backend, and a strict accounting model meet.
Storing a quantity is easy and wrong. It drifts the moment two writes race or a correction is fumbled. We modelled stock as an append-only ledger and computed on-hand levels in Postgres views (stock_with_left_quantity, transaction_stock_summary). The payoff is integrity, because the displayed number is always a pure function of the recorded movements. The trade-off is that every "stock" read is really a small join-and-aggregate, so we hydrate stock rows with their calculated left/hold and their originating transaction in one coordinated fetch rather than many round-trips.
Field reality is that parts get requested before a repair is signed off. Rather than a separate reservations system, we used a single isActive flag on the consumption transactions and tied it to the job card's approval state. "Reserved but not spent" and "spent" become the same ledger, read two ways, which is why the dashboards can show committed-versus-available budget with no extra bookkeeping tables.
Doing running balances, per-vehicle budgets, and last-used lookups on the client would mean shipping the whole ledger to a phone. Instead we wrote them as SQL views and RPC functions and enabled Postgres aggregates for the REST layer. The client asks a focused question ("budget, spend, and hold for this sub-category") and gets a small JSON answer back. Fast over mobile networks, and correct because the maths lives next to the data.
We committed to a single vertical-slice recipe (model, api, provider, view) with an identical list-provider pattern (debounced search, typeahead, infinite scroll, a nested pagination provider) and applied it to every entity. That discipline is why the team could add an entire Fuel module late in the project by composing the existing stock and transaction primitives instead of building new infrastructure.
The same statements have to print from a Windows desktop in the office and share from a phone in the yard. File handling is very different between web and native, so the PDF layer branches cleanly. Native builds write generated statements into a managed on-device directory tree, web triggers a browser download behind a conditional import, and sharing and printing route through the platform's own sheets. The document templates themselves (transaction statement, job-card sheet) are shared across all targets.
Government rollouts need a safe way to demo and test against non-production data. Rather than maintain separate build flavours, we made the Supabase target a saved runtime setting. One flag flips the URL and key between the production and development projects on next launch, so a single installed app can move between environments without a new binary.
Discoverability was not the goal here. Accountability and everyday usability in a public-sector setting were, and they shaped the schema and the interface.
creator, updater, created, and updated stamps, and the interface can resolve those ids back to the actual staff member who touched the record. Every change has a name and a time attached.fiscalia (fiscal-year) tag worked out automatically, so inventory and spend can be read against the government budgeting calendar rather than an arbitrary rolling window.Because the platform is the operational record for public assets, control was a first concern. A five-tier role hierarchy drives what each account can see and do, enforced at the application shell rather than trusted to the interface alone.
Framework: Flutter (Material, Dart 3), running on Android, iOS, Web, Windows, macOS, and Linux from one codebase.
State & routing: Riverpod 3 (Notifier and AsyncNotifier family providers with debounced search and infinite scroll), Beamer (declarative URL routing with auth and maintenance guards).
Backend: Supabase, using Postgres, Auth (email/password plus OTP recovery), Storage (avatars and attachments), Row-Level Security, and SQL views and RPC functions for server-side aggregation (on-hand quantity, running balance, budgets, last-used).
Local & media: Hive CE (device settings, theme, and locale only), image_picker, image_cropper, file_picker, and fast_cached_network_image.
Reporting & UX: Syncfusion charts (dashboards), pdf, printing, and csv (statements and bulk import), flutter_typeahead, flutter_easyloading, and bilingual English/বাংলা localization.
DNCC EMS (Dhaka North City Corporation Equipment Management System) is a cross-platform application built by Algoramming that manages a city corporation's vehicles and heavy equipment, spare-parts inventory, procurement, fuel, drivers, and maintenance job cards in one system, on a single shared double-entry ledger.
Because a stored quantity drifts. By recording every movement as a transaction (procurement debits stock, an approved job card or refuel credits it) and working out on-hand levels in the database, the displayed quantity is always a pure function of real movements and can never diverge from reality on its own.
A job card issues parts against a specific vehicle as ledger transactions. Those transactions are created inactive and only count against inventory once the job card is approved, so parts can be reserved without being spent, and approval is a real control point over spend.
Yes. It is a single Flutter codebase targeting Android, iOS, Web, Windows, macOS, and Linux. Platform-specific concerns such as file handling for PDF statements branch internally, while the domain logic and interface are shared.
A five-tier role hierarchy (Owner, Admin, Manager, Operator, Dispose) governs what each account can reach, enforced at the application shell, and a subscription/licence check gates access for the current period. Every record also carries creator, updater, and timestamp stamps for an audit trail.
Flutter and Dart on the front end (with Riverpod for state and Beamer for routing), Supabase (Postgres, Auth, Storage, RLS, SQL views, and RPC functions) for data and server-side aggregation, Hive for local settings, and Syncfusion, pdf, and csv for dashboards, statements, and bulk import.
model/api/provider/view slice made the codebase predictable and let a whole new domain (fuel) ship by composing existing parts.Want a system of record like this for your fleet or operation? Get in touch with Algoramming.
We developed our DNCC vehicle equipment management system with this company, and our experience has been very good. Their professional approach and work process truly impressed us. We have been using the software for almost a year, and it has helped us manage our equipment and stock records in a much more organized way. Their after-sales support has also been very helpful, and the team is friendly and supportive, making it easy for our staff to use the software smoothly with proper guidance.
01 · RelatedHow we built the AI-native CMS behind algoramming.com, a Next.js 16 and Supabase platform that researches, writes, illustrates and publishes long-form SEO articles to four social networks every night, with a human in control by choice.
Read case study
FeaturedAlgonize is the cloud ERP, CRM and POS platform built in Dhaka for multi-branch retail shops, restaurants and delivery businesses. This case study shows how one real-time dashboard unifies sales, inventory, riders, loyalty and accounting across Android, iOS, macOS and the web.
Read case study
03 · RelatedHow Algoramming built an offline-first, weighbridge-integrated waste management platform for Dhaka South City Corporation: a Flutter ecosystem that reads live scale weights, prints tamper-resistant slips, and syncs across transfer stations even when the network drops.
Read case studyWe will reply in plain English within one business day, NDA on request. Discovery call is free.