Skip to main content
Algoramming Systems Ltd. logoAlgoramming
HomeAbout
ProjectsBlogsCareersContact
Let's Talk
01Next move

Software that works quietly, every single day.

Ready to build something people stick with?

Send the brief, bullet points are fine. We reply within one business day with a plain-English next step. NDA on request.

Start a projectBook a 30-min call
Studio signalAccepting briefs
Reply
≤ 1 business day
Discovery
Free 30-min call
Engagement
Fixed scope or retainer
Timezone overlap
6+ hours, any region
support@algoramming.comDhaka · GMT (UTC+6)
Reply in one business day
NDA on request
Plain-English scoping note
Senior team, end-to-end
Algoramming Systems Ltd.

An independent product studio in Dhaka, designing and engineering custom software, mobile, and web apps for ambitious teams worldwide.

Innovation in every step

Company

  • About us
  • Services
  • Projects
  • Blogs
  • Careers
  • Contact
  • Book Meeting

Services

  • Custom software
  • Mobile apps
  • Web applications
  • UI/UX design
  • Product consultation
  • Tech partnership
  • Maintenance & support

Get in touch

  • House #12, Road #02, Dag #1677
    Merul Badda, Anandanagar
    Dhaka-1212, Bangladesh
    Open in Maps →
  • +880 1400 629698
  • WhatsApp us
  • support@algoramming.com

Hire dedicated developers

Hire Flutter developersHire Next.js developersHire React developersHire backend developersHire full-stack developersHire product designersHire DevOps engineers
Hire Flutter developersHire Next.js developersHire React developersHire backend developersHire full-stack developersHire product designersHire DevOps engineers

New posts, in your inbox

We send a short email whenever we publish a new field note or ship a studio update. No fixed schedule, no filler, unsubscribe in one click.

Working with teams in

  • DhakaBangladeshBST
  • DubaiUAEGST
  • DohaQatarAST
  • MansfieldUSAEST
  • Mexico CityMexicoCST
  • MonfalconeItalyCET
  • MelbourneAustraliaAEST
  • VarnaBulgariaEET

© 2022-2026 Algoramming Systems Ltd.All rights reserved.

Privacy PolicyTerms and ConditionsSitemap
Home/Projects/Building a Ledger-Driven Equipment Management System for a City Corporation Fleet
Case study

Building a Ledger-Driven Equipment Management System for a City Corporation Fleet

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.

Algoramming Systems Ltd. logo
Engagement by
Algoramming Systems Ltd.
CMS20264 metrics shipped
Building a Ledger-Driven Equipment Management System for a City Corporation Fleet
6
Platforms
18
Feature modules
5
Role tiers
1 year
In production

The problem

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.

Our approach

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.

The outcome

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.

The business problem

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:

  • Keep an authoritative registry of every vehicle and piece of equipment, classified by a real category taxonomy and linked to its assigned driver.
  • Track spare-parts and consumables inventory with true on-hand quantities. Not a number someone typed in, but one that can never drift away from the actual movements.
  • Record procurement (who we bought from, under which document, at what price) and turn each purchase into stock.
  • Issue parts and fuel to specific vehicles through maintenance job cards, and make issuance depend on approval.
  • Give every record an audit trail and enforce role-based access, so a data-entry operator cannot do what only an owner should.
  • Run on the office desktop, on the web, and on a phone in the yard from a single build.
  • Produce printable, shareable statements (per vehicle, per vendor, per stock item, per job card) for offline sign-off and government record-keeping.

The solution at a glance

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)
18feature modules 320Dart files 6platforms 5role tiers 2switchable backends
One repeatable module contract, applied about 18 times, running unchanged on six platforms.

Architecture

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.

The double-entry ledger, the heart of the product

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.

Procurementvendor purchase document Stockthe shelf, as a balance Vehiclethe machine consuming Debit stock in Credit stock out Fuelsame path, instant vendor to vehicle On-hand = sum of debits, minus sum of active credits worked out by a Postgres view, never stored in a column
Procurement debits stock, an approved job card credits it out to a vehicle, and fuel reuses the same two primitives.
  1. Stock in (Debit). When a procurement document is filled, each purchased line item becomes a StockEntity and a paired transaction: FileProcurement to Stock, Debit, flagged isSystemGenerated, tagged with the "Stock Add Voucher". This is inventory arriving.
  2. Stock out (Credit). When a job card issues parts to a vehicle, each part becomes a transaction: Stock to Vehicle, Credit, carrying the job-card id, the vehicle context, and the timestamp. This is inventory being consumed.
  3. Fuel uses the same pattern with no special table: a refuel creates a Fuel-typed stock item bought from a fixed "instant vendor," then credits it straight to the specific vehicle.

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.

One stock balance, read three ways from the same ledger Spent (approved job cards) Held (reserved, not yet approved) Left (still on the shelf)
Approving a card flips its transactions from held to spent. No separate reservation table exists.

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.

Engineering challenges worth telling

The interesting work was in the seams, where a mobile app, a live Postgres backend, and a strict accounting model meet.

Working out inventory instead of storing it

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.

Approval-gated consumption

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.

Pushing aggregation into the database

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.

One module contract, eighteen times

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.

One codebase, six platforms, one PDF pipeline

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.

Runtime backend switching

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.

Built for accountability, the field, and the fiscal year

Discoverability was not the goal here. Accountability and everyday usability in a public-sector setting were, and they shaped the schema and the interface.

  • Audit by construction: every master-data and ledger row carries 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.
  • Fiscal-year native: stock carries a 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.
  • Bilingual and responsive: the interface ships English and বাংলা (Bengali) and adapts between a persistent desktop layout and a mobile drill-down, because the same records are entered at a desk and checked on a handset.
  • Bulk onboarding: CSV import for both vehicles and stock resolves foreign keys (categories, brands, units, stock types) against the live configuration as the file comes in, so an existing fleet register can be loaded without hand-entering thousands of rows.

Governance, access, and control

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.

Ownerabove the assignable roles, cannot be demoted in-app Adminmanages users and roles Managerruns day-to-day operations Operatorenters records and movements Disposeconfined to settings only
Access is checked at the route level. An out-of-scope role sees an access-denied page, not the feature.
  • Role hierarchy: a five-tier user model (Owner, Admin, Manager, Operator, Dispose) drives what each account can see and do. The Owner sits above the assignable roles (cannot be listed or demoted through the interface), Owners and Admins manage other users' roles, and the lowest tier is confined to settings only.
  • Route-level gating: access is enforced at the application shell. Every screen declares which roles may reach it, and an out-of-scope role is shown an access-denied page rather than the feature.
  • Subscription/licence gate: the shell also checks an active payment for the current period. When it lapses, the app diverts to a payment page, keeping the deployment licensed and accounted for.
  • Approval workflow as control: because inventory consumption only becomes real on job-card approval, "who can approve" is itself a meaningful control point over spend.
  • Records that stand on their own: any view can be exported as a signed-off PDF statement, giving the corporation a self-contained paper trail that lives outside the app.

Results

  • One system of record for a city corporation's equipment operation (vehicles, drivers, vendors, procurement, inventory, fuel, and maintenance), replacing scattered spreadsheets and paper files.
  • Inventory that cannot silently drift, because on-hand quantity is calculated from an append-only ledger rather than an editable number.
  • Spend and stock that reconcile on their own, with reserved-versus-spent, running balances, and per-sub-category budgets computed in the database.
  • True cross-platform reach (desk, web, and field) from a single Flutter codebase, with printable statements for offline government record-keeping.
  • A predictable, extensible architecture where a whole new domain (fuel) was added by composing existing primitives instead of rebuilding.

Tech stack

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.


Frequently asked questions

What is DNCC EMS?

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.

Why build inventory on a double-entry ledger instead of storing quantities?

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.

How does maintenance consume parts, and how is it controlled?

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.

Does it really run on all platforms from one codebase?

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.

How is access controlled?

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.

What technologies power it?

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.

Key takeaways

  • Model movements, not balances. Storing an append-only ledger and working out inventory and value in the database buys integrity you cannot get from an editable quantity column.
  • Let the database do the aggregation. Views and RPC functions kept running balances, budgets, and last-used lookups fast and correct over mobile networks, and off the client.
  • A single module contract adds up. One repeatable model/api/provider/view slice made the codebase predictable and let a whole new domain (fuel) ship by composing existing parts.
  • Controls belong in the workflow. Tying inventory consumption to job-card approval turned "who signs off" into the real spend control, with no separate reservation system needed.

Want a system of record like this for your fleet or operation? Get in touch with Algoramming.

Project facts
Industry
CMS
Year
2026
Metrics
4 shipped
Services behind this
  • Custom Software Development
  • Web Application Design and Development
  • Mobile App Design and Development
Share this
Like what you see?

Start a similar project.

Send the brief. We reply within one business day with a plain-English next step. NDA on request.

Start a project
“What the client said
(4.5)
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.
Abul Hasnat Md. Ashraful Alam, portrait
Abul Hasnat Md. Ashraful Alam
Chief Executive Engineer, DNCC
More work

Other case studies from the studio.

All projects
Building an AI-Native CMS That Writes, Illustrates, and Publishes Its Own SEO Content01 · Related
SaaS, CMS·2026

Building an AI-Native CMS That Writes, Illustrates, and Publishes Its Own SEO Content

How 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
From Storefront to Doorstep: How Algonize Gives Multi-Branch Businesses One Real-Time Command CenterFeatured
Retail, E-commerce, Restaurants, Food Service, SME , SAAS, ERP, CRM,·2026

From Storefront to Doorstep: How Algonize Gives Multi-Branch Businesses One Real-Time Command Center

Algonize 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
Digitising a City’s Waste Weighbridges: The DSCC Waste Management System03 · Related
CMS·2026

Digitising a City’s Waste Weighbridges: The DSCC Waste Management System

How 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 study
Liked this work?

Bring us a problem, not just a brief.

We will reply in plain English within one business day, NDA on request. Discovery call is free.

Start a conversationOr browse more case studies