The engine
Charges in exact decimals, with the drafting kept outside
Everything on this page is computed in Python against exact decimals. No language model is in this path, which is what makes a charge defensible when a carrier disputes it six weeks later.
Chargeable weight
A rule, not a number
Four modes, four different answers for the same carton. A single divisor constant misprices three of them.
| Mode | Rule | Charged | Determined by |
|---|---|---|---|
| Air | Volumetric at 6000 cm³/kg | 176.000 kg | volumetric weight |
| Courier | Volumetric at 5000 cm³/kg | 211.200 kg | volumetric weight |
| Ocean LCL | Weight or measure, 1 cbm = 1000 kg | 1,056.000 kg | measurement |
| Road | Actual gross weight | 90.000 kg | gross weight |
The engine resolves the rule from the mode rather than applying a divisor it was configured with once. It also records which quantity won — "volumetric weight", "measurement", "gross weight" — and that phrase travels onto the charge line and into the console beside the figure.
That last part matters more than it sounds. When a carrier bills 176 kg for a 90 kg consignment, the question the operations manager has to answer is not whether the number is right but why it is right, and the answer needs to be next to it rather than in somebody’s head.
The arithmetic gate
Nothing renders if it does not tie
Before anything is drafted, the engine cross-foots what it computed. Charge lines have to sum to the stated total. Cargo item weights have to sum to the manifest gross weight. Container tare plus cargo has to equal the declared verified gross mass within tolerance. Duty heads have to sum to the declared total, and revenue less cost has to equal the stated margin.
If any of those does not hold, the job ends in a state that is not a failure — it is the software working — and it names the container and the amount it is out by. Nothing renders. There is no bypass flag anywhere in the software, not a parameter and not a setting, and the build fails if somebody adds one.
The verified gross mass check is the one that surprises people. A container whose declared mass disagrees with the computed sum of cargo, dunnage and tare beyond tolerance is a stop condition rather than a warning, because under SOLAS a box without a correct verified mass does not load — and a stow plan built on a wrong one is a safety problem rather than a billing one.
Arithmetic
Exact decimals, end to end
Money is an exact decimal in the database, in the engine and in the browser, and the arithmetic layer raises on a floating-point number rather than coercing one. By the time a float arrives the precision is already gone, so the fix belongs upstream at the parser rather than in a rounding step at the end.
The difference is not theoretical. A freight invoice with several hundred lines, each carrying a surcharge computed as a percentage of a base, accumulates a residual in floating point that is small enough to look like a rounding artefact and large enough to stop the invoice tying. A residual that small is worse than a large one, because nobody investigates it.
Every amount also carries its currency. There are no bare amounts anywhere in the schema, and adding two different currencies raises rather than silently coercing — a rule that sounds pedantic until a USD ocean freight and an INR terminal handling charge end up in the same total.
Tariffs
Rates are data, not code
Rate contracts, tariff lines, surcharge formulas and free-time rules are effective-dated rows loaded from reviewed, checksummed sources. A tariff is resolved by charge code, lane, mode, container type, commodity and the date the shipment moved — and specificity wins, so a line naming this container type beats a generic one and a mid-contract rate increase supersedes the base rate without either being edited.
A lane with no contract in force on that date is refused. It is never rated from an expired sheet, because that produces a figure of exactly the right shape and the wrong amount, which is the version of this failure nobody catches until the customer queries the invoice.
You can also read what will be applied before anything runs. The tariff that would be resolved for a lane on a date, the exchange rate that would be used and from which source, and the free-time rule that would govern a box at a given port are all readable in advance rather than discovered in the output.
Demurrage and detention
Slab arithmetic over a real calendar
Free time, then tiers that escalate, with weekend and port-holiday treatment that differs by port and by carrier. The engine computes against the port’s own calendar rather than a generic working week, because a terminal that treats a public holiday as a free day and one that does not produce different invoices for the same box.
The accrual runs on when the event happened, not on when the message about it arrived. A gate-out that reaches the system four days late still started the clock when the container actually left the terminal. Both timestamps are kept; every accrual uses the first.
Demurrage — the box still inside the terminal — and detention — the box outside it and not yet returned — are computed separately because they are different clocks with different free periods, and a system that conflates them under-reports one of them.
Currency
Three rates, one shipment, no contradiction
The carrier invoices at its own tariff rate. The bank settles at a market rate. Customs assesses at the rate notified under section 14 of the Customs Act, which moves fortnightly and matches neither. All three are correct for their own purpose, and a shipment can carry all three at once.
So there is no function in this engine that converts an amount to a currency. Every conversion takes an explicit rate that names its source and its effective date, and those three values land on the row that was produced. A converted amount with no source recorded is blocked by the provenance validator rather than rendered.
A date with no rate on file for that source is refused. It is never converted at the nearest available rate, because assessing at last fortnight’s notified rate is a wrong declaration rather than an approximation.
Incoterms
Which party bears the charge is a term, not a convention
A shipment has two sides — what you bought and what you sold — and the Incoterm decides where the line falls. On a CIF shipment the main carriage and the insurance sit with the seller; on FOB they do not. On DDP the import duty does too, which is the term most often agreed casually and most expensive to get wrong.
So apportionment reads the agreed term rather than a house convention. There is no default Incoterm anywhere in the software: a shipment without one is refused at the edge, because guessing one moves money between two parties who did not agree to it.
The shipment margin is then revenue less cost, cross-footed before it is shown. A margin that does not equal the difference between its own two totals is a blocked job rather than a number on a dashboard.
Ingestion
Nothing is dropped silently
Packing lists, commercial invoices, carrier invoices, rate sheets, gate logs, EDI status messages and carrier tracking events are parsed row by row. Parsed plus rejected plus duplicate has to equal the rows submitted, and that is a contract the software checks rather than a claim it makes.
An unrecognised format is an error, not an empty result. A truncated EDI message fails naming the segment and the position rather than returning zero milestones, and a rating run over zero parsed rows would tie perfectly and produce a settlement statement showing nothing owed — which is why it is refused instead.
Every rejected row is kept exactly as the file wrote it, with the reason it was refused, and the rejected list is a screen in the console rather than a line in a log nobody reads.
Provenance
Every amount traces to a tariff line
An amount reaches a rendered document from a charge line or it does not appear. Each charge line carries the tariff line that rated it, the dated contract that tariff belongs to, the exchange rate and source if it was converted, and the imported row underneath.
A figure a drafting model wrote into a cargo description or a claim letter, with no charge line behind it, blocks the render. That is enforced by a validator rather than by a prompt asking the model to behave, and the separation is enforced structurally as well: the build fails if the computation layer can even import the model client.
In the console this is a chain you can walk. Click an amount on a bill of lading and you get the charge line, the tariff, the contract it came from with its effective dates, and the row in the file somebody uploaded.
In one place
Everything the engine refuses to do
The stops, collected. A reader evaluating this page is really asking whether they are real, so they are worth listing together.
- Render a document whose figures do not cross-foot
- Rate a lane with no contract in force on the day it moved
- Convert a currency without recording the rate, its source and its effective date
- Convert at the nearest available rate when the right one is missing
- Assume a volume when a packing list carries neither dimensions nor cubic metres
- Apply a single volumetric divisor across modes that price differently
- Let an amount reach a rendered document without a charge line behind it
- Put a tariff heading it proposed onto a declaration nobody confirmed
- Issue a bill of lading while a prior original is neither surrendered nor voided
- Accept a booking that matched a denied-party list without a named override
- Return an empty result for a file it could not parse
- Offer a flag that turns any of the above off
Bring a carrier invoice you disagreed with
The fastest way to judge a rating engine is to point it at an invoice somebody already argued about, with the contract that was supposed to govern it. Send us those two and we will show you what it does with them.
Get in touch
Talk to the people building it
No chatbot and no ticket queue. Tell us what your operation actually looks like — the modes you move, whether you clear your own customs, and roughly how many shipments a month — and someone who works on the software will reply.
info@legosphere.com