Loading...
Chingola, Zambia · +260 969 787 323
Webmail Support All systems operational Operational
Sempya Systems
Logistics

Transport & logistics on Sempya CloudERP

A haulage fleet lives or dies on driver licences, fuel cost, overload fines and border delays — and the same fleet's earthmoving contract lives or dies on shift availability and tyre-and-tooth wear instead. Here's how Mukuba Haulage & Logistics — one of our eighteen industry reference companies — runs both on CloudERP, gaps included.

A haulage fleet lives or dies on driver licences, fuel cost, overload fines and border delays — and the same fleet's earthmoving contract lives or dies on shift availability and tyre-and-tooth wear instead. Here's how Mukuba Haulage & Logistics — one of our eighteen industry reference companies — runs both on CloudERP, gaps included.

For a haulier, the fleet isn't just an asset on the books — it's most of the business, and most of the risk. Mukuba Haulage & Logistics Ltd, an Ndola-based cross-border operator running the Copperbelt corridors to Dar es Salaam, Durban and Walvis Bay, is one of our eighteen fictional reference companies. Its fleet also runs a Copperbelt earthmoving contract alongside the trucks — a genuinely different operational world, covered further down. Rather than describe either in general terms, we built out the trucks, the excavator-and-dump-truck pair, the drivers and operator, and a real trip's and a real shift's worth of transactions on our demo site, and worked through what actually goes wrong for an operator like this — then mapped each pain point to what CloudERP does about it today, and what it doesn't yet.

The fleet register isn't just an asset list

Every truck on Mukuba's demo fleet — BAF 4410, BAE 1187, BAD 2232, BAD 2231 — is a CloudERP Asset, depreciating on the books like any other fixed asset. But a truck's real maintenance burden isn't calendar depreciation, it's the workshop schedule: service intervals, breakdowns, parts consumed. That's a separate module, Asset Maintenance, with its own team and task calendar. On the demo, BAF 4410's quarterly service is deliberately sitting Overdue — a due date five days in the past, sitting on Mukuba Workshop Team's task list exactly the way a real missed service would.

The more interesting case is BAE 1187's breakdown at Nakonde: brake pads and an air filter consumed at the border, seven and a half hours of downtime, K 4,350 in repair cost. That's an Asset Repair record, not a maintenance task — a different document for the "something broke unexpectedly" case versus the "this was scheduled" case — and it pulls real stock from Mukuba's parts inventory (BRK-SCN, FLT-AIR-FL) via a Stock Entry the same way a Sales Invoice would, so the workshop's parts usage shows up in stock valuation automatically, not as a side ledger someone reconciles later.

Honest gap: there's no native link from an Asset Maintenance schedule to actual odometer readings, so a real fleet still needs someone to notice the truck has done 20,000km, not just that a quarter has passed. Mileage-triggered service intervals aren't a CloudERP feature today.

Drivers are Employees with an extra layer, not a separate world

CloudERP's fleet records (Vehicle, Driver) are part of its HR module, and by default they're not scoped to a company — a real gap for anyone running multiple legal entities, which we closed by adding a company field to both before building out Mukuba's data, so a truck or driver can't leak across tenant boundaries. Each driver is also an Employee first: Kennedy Mulenga (Senior Driver, license valid to 2027) and Brian Chansa (Driver) both exist as full HR records, which is what lets a trip advance or an expense claim reference them directly, instead of a fleet-only "driver" record that HR and finance can't see.

Brian's license is the deliberate story here: it expires in 20 days. On paper that's just a date field, but it's a CloudERP Notification firing 30 days before expiry_date — the same mechanism, and the same 30-day window, we use for the compliance documents below. One notification design, two different real-world triggers.

Compliance tracking: road tax, fitness, insurance — the feature we built for this post

This is genuinely new, not something CloudERP already had lying around. A standard accounting system has nowhere to put a road tax renewal date or a fitness certificate, so we built a small custom doctype, Vehicle Compliance, against a specific complaint: a haulier losing a truck to a police stop at Kasumbalesa because someone missed a renewal date is a real, recurring cost, and "check the folder" isn't a system.

Each Vehicle Compliance record ties a document (Road Tax, Fitness Certificate, Insurance, COMESA Carrier Licence, COMESA Yellow Card, Cross-Border Permit) to a vehicle, an issue date and an expiry date, with the file itself attachable. Mukuba's demo fleet carries eight of these, deliberately mixed: BAF 4410's fitness certificate expires in 15 days, BAE 1187's road tax expired 10 days ago, the rest sit comfortably valid — so a fleet manager glancing at the list sees exactly the mixture a real audit would turn up, not a wall of green.

This now ships as part of sempya_fleet, our own installable module — a new tenant picks it up automatically, not a bespoke build each time.

Trip advances and expense claims — the part that actually broke, and how it's supposed to work

A driver on a Ndola–Dar run doesn't submit fuel receipts from the road; he's handed a trip advance before he leaves and reconciles it after. CloudERP's native flow is: an Employee Advance (Kennedy's run, K 18,500) gets submitted, then genuinely paid — a bank/cash Journal Entry, the disbursement itself, not just an approval — before an Expense Claim can settle against it. Skip the payment step and the system correctly refuses the claim: an advance that was only approved, never paid, has nothing "unclaimed" to allocate.

On Mukuba's demo trip, that K 18,500 was paid out, then settled against K 9,200 in border/transit charges and K 9,350 in driver subsistence — K 18,550 total, K 50 more than the advance. That K 50 residual becomes a real payable to Kennedy, sitting open on the Expense Claim rather than disappearing into a rounding error — a small, true-to-life detail: trip advances are rarely exact.

Both the advance and the claim tag CloudERP's Project doctype (Trip: Ndola - Dar es Salaam (Aug 2026)), alongside the trip's Sales Invoice, Purchase Invoice and the route itself (more on that below), so the whole trip's economics land in one place — and, because CloudERP runs payroll and HR alongside the accounts, the Project's own gross margin genuinely folds the driver's Expense Claim into the cost side, not just sales and purchase costs. Run the numbers on this actual trip — K 29,363 billed, K 23,490 in fuel, K 18,550 in border fees and subsistence — and the honest answer is a loss of K 12,677 once the full trip is counted, not a comfortable margin with an asterisk. That's the software doing its job: a trip that looked fine on the invoice looks very different once the road costs land on the same P&L line.

Fuel: the cost line that actually decides whether a route is worth running

Fuel is the single biggest variable cost in this business, and it's easy to track badly — a fuel card statement nobody reconciles against a specific truck. CloudERP's Vehicle Log doctype exists for exactly this: date, odometer, litres, price, supplier, one entry per fill-up. BAF 4410's three fill-ups on this trip (Ndola depot, a Tanzanian border-town top-up at Tunduma, then a fill before Dar) feed straight into a built-in report, Vehicle Expenses, that breaks fuel and service cost down per truck — no custom reporting work, the report already existed in CloudERP, it just had nothing to show until real logs existed.

The route itself, not just the invoice for it

Everything above tags a trip as an accounting object, but a haulier also needs the route as an operational one: which truck, which driver, which stops, how far. That's CloudERP's Delivery Trip doctype — BAF 4410 and Kennedy Mulenga, departure logged, two stops in sequence (the Nakonde/Tunduma border, then Dar es Salaam port) each with its own distance and address, marked Completed once the truck actually arrived. This is also the honest peg for the GPS story below: the route structure — stops, sequence, distance — already exists natively; what's missing is a live position feeding it automatically instead of a dispatcher typing it in after the fact.

Overload fines are a real cost, and now a real ledger entry

Every corridor into Tanzania runs through TANROADS weighbridges enforcing the East African Community's 56-tonne gross vehicle mass limit — Tanzania has held thousands of trucks under that law, and a single overload can cost the operator into five figures. Standard CloudERP has nowhere to put a weighbridge ticket, so we built one: a Weighbridge Ticket doctype recording the vehicle, station, weighed mass against that vehicle's own legal limit, and the fine. BAF 4410 weighed in 2,200kg over the limit at the Tunduma weighbridge on this trip — a real K 3,500 fine, posted through a Journal Entry into a dedicated Fines and Penalties account and tagged with the same Vehicle dimension used for per-truck P&L above, so an overload fine shows up exactly where it belongs: against the truck and the trip that earned it, not lost in a general expense line.

Border dwell time is unbilled revenue until someone tracks it

Kasumbalesa and Nakonde/Tunduma are both notorious for multi-day queues — Kasumbalesa alone has stranded over a thousand trucks at a time during congestion spikes. The cost isn't just standing time, it's revenue a haulier is entitled to but never bills, because nobody has timestamps. We built a Border Crossing Log doctype capturing arrival and clearance time per border post, the clearing agent used, and the documents handed over. On this trip, BAF 4410 sat at Nakonde/Tunduma for 54 hours against a 24-hour contractual free allowance — 30 hours of genuine detention. That excess becomes a real Sales Invoice line, Border Standing/Detention Charges, billed straight to the customer and tagged to the same trip Project: K 24,000 in revenue that a paper process would have quietly written off as "just how the border is."

Both, like Vehicle Compliance, ship as part of sempya_fleet now too.

Tyres wear out on a schedule fuel doesn't tell you about

After fuel, tyres are the biggest variable cost a haulier carries, and the real money is in retreading — a worn casing sent for a retread comes back at a fraction of a new tyre's cost, but only if someone tracks which casing is on which wheel and how many lives it's had. We built a Tyre doctype for exactly that: serial number, brand, wheel position (steer, drive or trailer, by axle), casing state, and a movement log recording every Fit, Remove, Rotate, Send for Retread and Return from Retread. One of BAF 4410's trailer tyres, a Dunlop SP320, proves the point directly: bought new for K 9,500, ran 90,000km on the steer axle, retreaded for K 3,200, then ran a second life on a trailer position — K 12,700 total cost over 190,000km, K 0.0668 per km. Steer positions wear faster and cost more per km than a trailer retread; the system doesn't just store the number, it's the reason a fleet manager can actually see that.

When something goes wrong, the claim has to go somewhere too

Vehicle Compliance tracks a policy's expiry date. It says nothing about what happens after an actual accident. We built a Vehicle Incident doctype for the gap between those two: police report number, third-party involvement, and a claim section tracking the insurer, the claim reference, and its status from Draft through to Settled. BAF 4410's real story here is a reversing collision at the Tunduma truck park — a Tanzanian-registered pickup, a K 185,000 repair bill, a K 18,500 excess, and K 166,500 recovered from the insurer four days later. That recovery isn't just a note in a claim file: it's a real Journal Entry, tagged to the same Vehicle dimension as everything else, so the accident's true net cost to that specific truck is visible on its own ledger, not buried in a general insurance expense line.

Per-truck profitability, not just per-trip

A single Project margin answers "was this trip worth it." It doesn't answer "which truck in the fleet is actually making money" across dozens of trips. For that, CloudERP uses an Accounting Dimension targeting Vehicle — once set up, it adds a vehicle field across every accounting document (invoices, journal entries, expense claims) and their resulting ledger entries, so a truck's revenue and cost roll up continuously, not just for one tagged Project. Proof from this same data: query the ledger by vehicle and BAF 4410 (running this trip) shows K 71,403 in turnover against BAE 1187 (sitting at the workshop after Kasumbalesa) showing K 4,350 in repair cost and nothing else that week — two trucks, two genuinely different pictures, from one dimension applied consistently across the books.

Mukuba also runs earthmoving on the pit — same fleet, different work

Cross-border haulage isn't the only work a Copperbelt fleet does. Mukuba also contracts an excavator-and-dump-truck pair — a Komatsu PC1250 (EX-02) and a Caterpillar 745 articulated dump truck (ADT-07) — to strip waste rock on an open-pit mining contract, and that's a genuinely different operational world from a Ndola–Dar run: no odometer, no border post, no route. What matters here is the shift.

We built a Shift Production Record doctype around exactly that: one record per machine per shift, capturing hour-meter readings (this equipment runs on engine hours, not kilometres — Vehicle Log needed a new field for that), load count, material type, source pit and destination dump, and every delay logged with a start and end time. One real day shift on ADT-07 proves the whole chain: 38 loads at 39 tonnes each, paired with EX-02 loading at Pit A, hauling 1.6km to Waste Dump 2 — 1,482 tonnes, 559 BCM, computed automatically from the material's own density, not typed in by hand.

The number that actually matters to a mine contractor isn't tonnes moved, it's availability — and the mining industry has four distinct, commonly-confused ways of measuring it, all computed correctly from the same shift record: Mechanical Availability (92.68% on this shift — was the machine mechanically sound?), Physical Availability (93.75% — was it available against the roster?), Use of Availability (84.44% — did we actually use what was available?), and Effective Utilisation (79.17% — the honest bottom line). A blast-clearance standby, a hydraulic hose failure, a crib break and a refuelling queue are all logged as separate delay entries with their own reasons, so the four numbers come apart cleanly instead of collapsing into one vague "downtime" figure — exactly the distinction a mine owner's own contract terms usually turn on.

That shift also settles a real invoice. A Contract doctype holds the agreed rate — K 35 per BCM for this waste-stripping work — and the shift record computes its own revenue directly from it: K 19,573.75 for that one shift, no separate billing spreadsheet required. This is the revenue side the haulage business never needed, because a haulage trip already has its own Sales Invoice; a shift-based earthmoving contract doesn't, until something ties tonnes moved to a rate.

Two more things wear out on a mine site that don't apply to a road truck at all. Ground-engaging tools — bucket teeth, cutting edges, grader blades — are a real cost category on par with tyres, so we generalised the tyre lifecycle pattern into a Wear Part doctype: EX-02's bucket carries one tooth still in service (no cost-per-hour yet, because its lifecycle isn't finished) and one already worn out and scrapped after 880 hours at K 3,900 — K 4.4318 per hour, the ground truth a maintenance budget needs and rarely has. And because operating a digger or a haul truck requires a real Mines Safety Department certificate, not just a driving licence, we extended the same expiry-tracking pattern from Vehicle Compliance to people: an Operator Competency record per employee per equipment class, with its own 30-day warning before the certificate lapses.

Like everything else in this post, these ship as part of sempya_fleet too — but this remains genuinely a different operational world from the haulage side. A route-and-border mindset doesn't transfer to a pit-and-shift one, which is exactly why this needed its own doctypes rather than forcing Delivery Trip to do double duty.

When Mukuba doesn't own the machine, or doesn't need it that week

A contract earthmoving operator rarely owns exactly the right fleet for every job. Mukuba doesn't own a grader, but haul roads still need maintenance; and its own excavator sits idle between shifts on a smaller contract. Both directions are the same underlying problem — equipment moving in or out of the fleet for a fixed period at an agreed rate — so we built one Equipment Rental doctype that handles both, not two.

Renting in: a Caterpillar 140M grader, hired from Kafue Plant Hire Ltd for 14 days to maintain the Pit A access road, at K 4,200 a day — K 58,800, posted as a real Purchase Invoice the moment the machine went back. Renting out: EX-02 itself, idle for three shifts between Mukuba's own contract work, hired to Mufulira Quarry & Crushing Ltd for face clean-up at K 6,500 a shift — K 19,500, posted as a real Sales Invoice, tagged to the same Vehicle dimension as everything else EX-02 does. The system won't let you rent out equipment you don't own — try it without a Vehicle on a "Rented Out" record and it refuses, which is a small guard but exactly the kind of mistake a spreadsheet won't catch.

GPS and telematics — Coming Soon, not vapourware

We're not going to pretend a fleet system is complete without live vehicle tracking, so we're saying plainly where this sits: GPS/telematics integration is on our roadmap, not yet scoped. It's a real project we already have lined up — pulling live position, mileage and possibly fuel data from a telematics provider into the same fleet records described above — not a feature we're quietly deciding to skip. If your fleet already runs a telematics box and you want that data landing next to service history and compliance dates in one place, that's exactly the conversation to have with us now, while it's still being scoped.

Fully onboarded, and transacting

Mukuba went through the same review and sign-off workflow described in our opening balances post, then kept moving: a real quotation, order, invoice and payment on the selling side, a real purchase order, supplier bill and payment on the buying side, and — because its South African creditors for fuel, tyres and tolls are Rand-denominated — a month-end exchange rate revaluation catching the Rand's movement against the Kwacha since those bills were first raised. Cross-border freight is also zero-rated for VAT, which flips the usual position on its head: instead of owing VAT, Mukuba is owed a refund by ZRA, sitting as a debit rather than the credit most businesses carry.

Get in touch if fleet compliance, driver advances or cross-border accounting is closer to your own business than a standard trading company.

Business email
Your own domain, hosted in Zambia
K 55/mailbox/mo, ex-VAT

Migration from Google or Microsoft included, backed up nightly.

See business email →
← All blog posts