3 min readby Muhammad Mohtashim Husnain

Month-end fleet reports from a portal in one click

How a Flask app replaced days of spreadsheet work by pulling the operations portal once per period and recalculating every report from cached data.

Month-end reporting at Ashwheelz, a transport and equipment-rental group in Saudi Arabia, went from about three working days of spreadsheet work to one click plus a review. Here is how. The finance team used to spend those days exporting grids from the operations portal into Excel: trips, contract invoices, fuel, maintenance, driver salaries, visas. Then they rebuilt gross profit per vehicle by hand. Every month the formulas drifted a little.

The shape of the fix

The portal has no API, but it has a web session. The app logs in the way a person does (user, password, and a two-factor code the user types in, never stored), pulls every grid for the period once, and keeps the raw rows in a cache. Every report is then a pure calculation over those rows.

That one decision, cache raw rows and recalculate, made the rest easy:

  • Change a driver's salary in settings and every report updates without touching the portal again.
  • Add a fixed expense and pick which vehicles share it; the per-vehicle cost column changes instantly.
  • Verify an overtime sheet someone emailed in and compare it to the computed one.

The maths finance actually cares about

Gross profit per vehicle is:

(monthly contract amount + call-out trip revenue)
− (salary + kilometre pay + fixed cost share + maintenance + fuel + visa)

The traps were all in the inputs, not the formula. Contract invoices are per client and service type, but trips are per vehicle. The invoice says "Flatbed", the trips say "Truck Head"; both are the same vehicle category. So contract revenue is allocated to trips by (client, vehicle category), with a fallback so money never silently disappears when a category has no trips that month.

What changed for the team

Month-end went from days to one click plus a review. The first month, overtime matched the manual sheets to the minute, which is the moment the team stopped keeping the old spreadsheet open "just in case".

How the portal is read without an API

The operations portal is a web application with grids: trips, contract trips, fixed invoices, vehicle expenses, customers, the asset-income report. Each grid takes a page size parameter, so one request per grid per period returns everything. The app logs in with the finance user's credentials and the two-factor code they type into the dashboard. The code is used once and never written to disk; the session cookie is kept so the next period does not need a new code until it expires.

Two details decide whether this works for months rather than weeks:

  • Column lookup by header name, not position. The portal added a "Vendor" column one month and every positional parser would have shifted. Reading by header text means a new column is simply ignored.
  • HTML entities in names. Client names come through as A & B Transport. Matching those against the sales report failed until every cell was unescaped on the way in.

What "verified to the minute" means

Overtime is where finance trusts a system or does not. The company rule is a rolling 60-minute window per trip, Saturday duty counted from 12:00 to 16:00, and a public holiday counted as a whole day. The first month, the app's coordinator overtime was compared line by line with the sheet a coordinator had prepared by hand. The differences were all explained by the sheet using one-per-clock-hour rounding and a call-out-only filter, both of which the official rules do not have. Once the rules were confirmed in writing, the sheet was retired.

That is the order to do it in: compute, compare against the human result, explain every difference, then switch. Not the other way round.

What the finance team does now

  1. Open the app on the first working day. Click "Load period data". Wait about two minutes while the eight datasets come in.
  2. Check the three settings that change month to month: new drivers, salary changes, new fixed expenses.
  3. Export the Asset Income workbook in the layout they have always used. The cuts for 1–10 and 1–20 come from the same data.

The full case study, with screens, is on the Accounting Management System page. If you run a fleet in Pakistan or the Gulf and this sounds familiar, the fleet dashboard service page describes the engagement.