AWRA OpsHub Search
AWRA Field 06 screens 12 min read

Both Numbers, Side by Side

A queued approval that lost a race gets refused, and the operator has to decide whether to throw away their own capture. That decision needs both numbers on one screen, and it needs a live connection to be worth anything.

Written by
AWRA OpsHub TeamOperations Insights
Issued
Build
Initial

Two people approve the same transfer. One of them is in a yard with no signal, so their approval waits in a queue. By the time it lands, the movement has already been rejected by somebody at a desk. The queued copy is refused — correctly — and now the person holding the phone has to decide what to do with a capture they made in good faith.

For a long time all we could tell them was the classification: somebody else already decided this. Which is true, and is an instruction to discard, and answers none of the questions that matter. Decided how? By whom? On what grounds? A person is about to destroy their own record of what they saw, and they are being asked to do it on a sentence.

The screen the sentence could not replace

What that decision needs is not better wording. It is the two things that disagree, on one screen, labelled.

What this device captured What the server holds now
Decision Approve Rejected
Decided by A named colleague
Quantity 40 36
Captured Yesterday, 16:20 Updated this morning
Two columns. The left is what this device captured, with its own timestamp. The right is what the server holds now, which is why the screen needs a live connection. Only rows that genuinely disagree are marked.
Two columns, labelled for what they are. Neither claims to be what the record looked like at capture — nothing records that.

Now the decision is ordinary. If the movement was rejected for a reason that no longer holds, that is a conversation with a colleague rather than a discard. If the quantity has moved because stock genuinely moved, discarding is right and the operator can see why.

Never ask somebody to destroy a record on the strength of a sentence when you could show them both versions.

It needs a connection, and it says so

This is the one screen in the offline queue that refuses to work offline, and the refusal is the point. The entire claim of the right-hand column is here is what the server has now. A cached copy cannot make that claim: it would put a second stale number beside the operator's own and label it as the truth, which is a worse outcome than showing nothing.

So with no connection the screen says so and offers nothing. Not a greyed-out table, not a cached approximation. A sentence explaining that the comparison needs a live connection, and the same sentence again when the connection comes back and it can be fetched.

Five things the fetch can conclude

Outcome What it means What the operator does
Ready Both columns, side by side Reads the disagreement and decides.
Unsupported This kind of entry has no comparison, and the reason is named Falls back to the classification and the record itself.
Offline The claim cannot be made right now Waits for a connection. Nothing is guessed at.
Gone The record no longer exists on the server This is itself the answer — the one that means discard.
Error The fetch failed Retries. A failure to look is not evidence of anything.
Five outcomes. Ready shows both columns. Unsupported names why there is no comparison. Offline makes no claim at all. Gone is itself the answer and means discard. Error is a failure to look, which is evidence of nothing.
Only one of the five shows a table. The other four each say something specific rather than showing an empty one.

"Gone" is a result, not a failure

A record that has been deleted is the clearest possible outcome: there is nothing left for the queued write to apply to, and the only sensible action is to discard. Reporting that as an error would leave an operator retrying a fetch for a record that will never come back.

Where a comparison exists, and where it honestly does not

Nine kinds of queued entry have a comparison: the four decision families, count lines, inventory status actions, stock transfers, check-outs and point-of-sale entries. Everything else does not, and the screen says which case it is in.

One of those refusals is specific rather than generic, and it is the one worth reading twice. A check-in adds stock rather than drawing it down, so there is no balance for it to have outrun. There is nothing to compare, not because nobody has written the comparison yet, but because the disagreement this screen exists to show cannot arise. Saying that is much better than an empty table.

An empty table is the one thing it must never be

A comparison with no rows and no explanation reads as nothing changed — which is the precise opposite of what a conflict screen is for. Every case where there is nothing to show carries a sentence saying why, and that sentence is checked before a request is spent on the fetch.

Two limits, both deliberate

The first is about history. The left column is what this device captured — not a snapshot of what the server looked like at the moment of capture. Nothing records that anywhere, and reconstructing it from the payload would be a guess presented as history, which on a screen somebody uses to destroy their own record is the worst kind of thing to ship.

So where a field genuinely exists on both sides — a quantity, a counted value, a decision, a reason — the two columns are directly comparable and the row is marked as changed or not. Where it does not, the row is informational and never claims a change.

The second is about how "changed" is decided. It is computed per row by the code that understands that row, not by comparing the two strings in the table. That distinction is invisible until you see what a string comparison does to real data.

Why comparing the display text would be wrong

"Approve" against "Rejected" A real disagreement
"approve" against "approved" The same decision
40 against 40.00 The same quantity
A reason code against its label The same reason
Rows flagged as changed Only the genuine ones

Three of the four above are false alarms that a string comparison would raise, on a screen whose entire job is telling somebody which rows to look at. A conflict view that cries wolf on formatting is one people stop reading, which returns them to deciding on a sentence.

Eight lines, and the ninth

A count or a transfer can carry many lines, and checking every one against live stock is a request per line. The comparison checks the first eight and says so plainly when there are more: how many were not compared, and that only the first eight were checked.

Which is a compromise, and is stated as one. The alternative of silently comparing eight and presenting it as the whole entry would be a conflict screen that misses conflicts — exactly the failure the screen exists to prevent, dressed up as a complete answer.

Questions about conflict handling

What does an operator see when a queued action is refused?

What you will hear

"An error message."

How to read it

Ask whether it contains the server's own reason and the values that disagree. A classification alone tells somebody to discard their capture without telling them what they are discarding it in favour of.

Can I see what the record looked like when I captured it?

What you will hear

"Yes, it is all in the audit trail."

How to read it

Worth confirming, because most systems record what the device sent and not what the server held at that moment. If nobody stored it, a screen showing it is reconstructing it — which is a guess with the authority of a table.

What does the comparison show when the device is offline?

What you will hear

"It works offline like everything else."

How to read it

It cannot. The right-hand column claims to be what the server holds now, and a cached copy cannot make that claim. A vendor who says otherwise is showing a stale number labelled as current, on the screen where that matters most.

How do you decide which fields have actually changed?

What you will hear

"We compare the values."

How to read it

Compare them how? Case, formatting and codes-versus-labels all produce differences that are not disagreements, and a screen that flags them is one operators stop trusting within a week.

Our take

Every offline system eventually asks somebody to throw away work they captured in good faith, and that moment deserves more care than it usually gets. A classification is not enough — it names the situation and hides the evidence. The version worth building shows both columns, marks only genuine disagreements, states plainly which entries have no comparison and why, treats a deleted record as an answer rather than an error, and refuses to pretend it can make the claim offline. It costs one screen and it changes the conflict from a leap of faith into an ordinary decision.

More we can add to your workspace

The comparison is a per-type builder, which is what makes it extensible

Each supported entry type has its own small builder that knows what its rows mean. Adding to that set is a defined job rather than a redesign.

Every line compared, not the first eight

Batched line-level checks for long counts and transfers, so a fifty-line entry is compared whole rather than sampled.

The record as it was at capture

A server-side snapshot taken when a device fetches a record, turning the two columns into three and making the middle one real history rather than an inference.

Comparisons for more entry types

The same treatment for entry types that currently fall back to the classification, each with a builder that understands its own fields.

Resolve from the comparison itself

Adjusting the captured values to the current ones and resubmitting in place, for the conflicts where the right answer is visible on the screen.

The support map, the builders and the fetch each live in one place, so extending any of them touches a known surface rather than the queue as a whole.

Tell us where your approvals collide

Make two people decide the same thing

Approve a transfer on a phone in flight mode, reject it on the web, then reconnect. What the phone shows you at that moment is the whole of how a system treats work it has to refuse.

Talk to us about offline approvals

Frequently asked questions

What happens when somebody else decides a record before my queued approval lands?

The queued copy is refused, and the entry opens on a screen showing what your device captured beside what the server holds now — the decision, who made it, the quantities, and the times. You then discard your capture or take it up with the colleague who decided differently, with the evidence in front of you rather than a sentence describing it.

Why does the comparison need an internet connection?

Because its whole claim is "this is what the server has now", and a cached copy cannot make that claim. Showing a stale number beside your own and labelling it as current would be worse than showing nothing, so offline the screen says the comparison needs a connection and offers nothing else.

Some entries say there is no comparison. Is that a gap?

Sometimes it is a comparison nobody has written yet, and the screen says so. Sometimes it is a statement about the operation: a check-in adds stock rather than drawing it down, so there is no balance for it to have outrun and nothing to compare. Both cases carry a sentence, because an empty table with no explanation reads as "nothing changed", which is the one thing it must never mean.

What if the record has been deleted?

That is reported as its own outcome rather than as an error, because it is the clearest possible answer: there is nothing left for your queued write to apply to, so the entry should be discarded. Treating it as a failure would leave you retrying a fetch for a record that will never come back.

How do you decide which rows actually disagree?

Per row, by the code that understands that row, rather than by comparing the displayed text. "Approve" against "Rejected" is a real disagreement; "approve" against "approved", 40 against 40.00, and a reason code against its label are not. A screen that flags formatting as a conflict is one people stop reading, which puts them back to deciding on a sentence.

Does it compare every line of a large count?

The first eight, and it tells you how many were not compared. Each line costs a check against live stock, so the compromise is stated rather than hidden — silently comparing eight and presenting it as the whole entry would be a conflict screen that misses conflicts. Comparing every line in a batch is a defined piece of commissionable work.

Can I see what the record looked like when I captured it?

Not today: the left column is what your device captured, and nothing records what the server held at that moment. Reconstructing it from the payload would be a guess presented as history, on the screen where somebody decides whether to destroy their own record — so instead the two columns are what they say they are. A capture-time snapshot is one of the more requested extensions here.

Help Center

Need a quick answer while you read?

Run inventory, procurement, assets, sales, and field work with approved AWRA guidance for setup, migration, integrations, security, pricing, and support.

Search all approved AWRA public help articles.

Open Help Center