I tried to go through support for this but I’ve been told (possibly by an LLM) that this is the only way to report bugs - my original report there contains specifics around which customers are affected - if you are able to find that ticket you’ll have more details.
I work for Groundplan, which integrates with ServiceM8 via the API. Since May 22, for some customers, we’ve been observing POST /jobmaterial.json returning 400 “inc-tax and ex-tax prices are inconsistent.” on submissions that declare their values as tax-exclusive. The validator’s arithmetic implies it is ignoring the displayed_amount_is_tax_inclusive flag we send.
In every observed failure, the returned X exactly equals submitted_price / (1 + 0.10) — the validator strips a 10% tax from our submitted value as if it were tax-inclusive, despite our flag saying it is not.
A failing request body (shape, with generic values):
{
“active”: 1,
“cost”: “62.00”,
“displayed_amount”: “80.60”,
“displayed_amount_is_tax_inclusive”: “0”,
“displayed_cost”: “62.00”,
“job_uuid”: “”,
“name”: “”,
“price”: “80.60”,
“quantity”: “1.00”,
“sort_order”: “100”,
“uuid”: “”
}
Response:
{
“errorCode”: 400,
“message”: “inc-tax and ex-tax prices are inconsistent. Expected price [73.27].”
}
80.60 / 1.10 = 73.27 exactly. price equals displayed_amount, both declared as tax-exclusive via the flag. My understanding of displayed_amount_is_tax_inclusive field is that if I set it to 0, the displayed_amount is tax exclusive, therefore it should match the price.
When testing against our own ServiceM8 account with an identical request shape (price == displayed_amount, displayed_amount_is_tax_inclusive “0”, body uuid set, no material_uuid), POST /jobmaterial.json accepts the submission in every configuration we’ve been able to construct:
- against a fresh row;
- against an existing row whose stored displayed_amount_is_tax_inclusive is “1” from a prior API call;
- against an existing row whose stored displayed_amount_is_tax_inclusive is “1” from creation via the ServiceM8 web UI;
- regardless of whether the catalogue material referenced has price_includes_taxes 0 or 1.
In each case the row is updated, the stored displayed_amount_is_tax_inclusive flips to “0”, and stored price/displayed_amount update to the submitted values. The validator does not fire.
The failures are limited to specific ServiceM8 accounts. We cannot reproduce the rejection in our own account using the same body shape, so it appears to only affect certain accounts, or possibly certain materials. There seems to be a correlation between customers who have reported this problem and the use of integrations to drive materials/bundles, in particular Burdi and Xero.
I’d really appreciate some attention on this issue as it’s currently affecting customers of both our companies and holding them up from performing quotes. I suspect it might be a change to how data comes in from integrations, or possible we’ve just been doing it wrong the whole time and it only just started validating it? Either way would love to know.
Thanks
(Alex Gilleran, posting under Frederico’s account)