Vivek Jalondhara. All writing

AI / ML

Missing Prices Need a Review State, Not a Zero

By Vivek Jalondhara · 5 min read
Published

Model missing vendor prices explicitly so an empty cell remains a review task and a genuine zero retains its meaning.

A blank price cell and an explicitly supplied zero carry different information. Collapsing both into zero makes a tidy table, but it removes the question a reviewer needs to answer. That mistake can travel from an import preview into project pricing without producing a type error.

This educational Sheet Parser example follows one narrow rule: preserve missing values until someone resolves them. The proposed state model and synthetic rows illustrate a design choice rather than a claim about the application's private implementation.

Define what the source actually says

Imagine three rows: a speaker priced at 1200.00, a sample labelled 0.00, and a microphone whose price cell is empty. Preserve the original text for each row. An empty cell might mean unavailable pricing, a value inherited from a header, or a layout the parser misunderstood. None of those interpretations follows automatically from the absence itself.

Choose an explicit representation for an unknown amount. In this example it is null, accompanied by a reason and a source reference. An omitted property is a different contract case: it may indicate an incomplete response. JSON Schema distinguishes a null value from an absent property, so describe both required fields and their allowed values.

Normalise formatting without inventing content

Use separate stages for reading raw text and validating a canonical value. The first stage can retain a blank string, whitespace, or a dash exactly as received. A documented normalisation rule may convert some of those inputs to missing, but a dash should not acquire that meaning unless the sheet's convention supports it.

Keep decimal amounts as validated decimal text at this boundary. Avoid a truthiness check that treats numeric zero as absent, and avoid a fallback expression that turns an invalid parse into a default amount. The useful outcome of failed interpretation is a named review reason attached to the original source.

Track several missing fields together

An amount can be present while its currency or selling unit is unresolved. Returning only the first problem forces the reviewer through repeated save-and-fail cycles. Collect the missing fields so the interface can present one coherent task: confirm the amount, currency, and unit against the source.

The small function below assumes its input has already passed runtime shape validation. It deliberately checks for null, not every possible invalid string. That keeps responsibilities visible: input validation establishes the representation, this function classifies incompleteness, and the review workflow decides whether the interpreted value is supported.

Make review visible in the table

Render a missing amount as a labelled state such as Price needs review. Keep that label distinct from the formatted display of a supplied zero. A tooltip alone is insufficient for someone scanning rows or using a keyboard; the status and source action should be reachable in the ordinary reading flow.

Let a reviewer compare the raw row and nearby header before entering a replacement. Preserve the original extraction alongside the correction. If the reviewer confirms that no price is available, offer an explicit unresolved or unavailable outcome rather than forcing them to enter a number to clear the queue.

Keep incomplete drafts out of accepted pricing

Define what the next stage accepts. A draft with all three fields present is ready for review in this example; presence alone does not make the values accurate. An acceptance operation must still apply the application's access rules and verify the reviewed draft revision.

A project can display that its requested item has no accepted price yet. This is more informative than showing a total that silently includes a manufactured zero. Any partial total needs a clear incomplete state so a reader understands that some selected items are excluded from the calculation.

Exercise the difference with tiny fixtures

Test a null amount, the string 0.00, a missing currency, and a complete row with an ambiguous unit in the underlying document. The classifier should report only structural incompleteness; the ambiguous unit remains a separate semantic review case. Also test that a correction does not erase the original source text.

This design produces more visible review states than a default-filled table. That is useful information rather than a parsing failure to hide. The next improvement is to reduce avoidable ambiguity in supported sheet formats while retaining an honest representation for the cases the application cannot resolve.

Classify completeness without replacing unknown values

The canonical input has already been runtime-validated: each field contains non-empty valid text or null. A ready-for-review result does not authorise acceptance.

Illustrative example · TypeScript · Simplified for explanation

type Draft = {
  amount: string | null;
  currency: string | null;
  unit: string | null;
};

function reviewState(draft: Draft) {
  const fields = ["amount", "currency", "unit"] as const;
  const missing = fields.filter(field => draft[field] === null);
  return {
    state: missing.length ? "needs-information" : "ready-for-review",
    missing,
  };
}

reviewState({ amount: "0.00", currency: "INR", unit: "each" });
// { state: "ready-for-review", missing: [] }
How the example fits together
  1. Preserve source text
  2. Validate the canonical shape
  3. Identify missing information
  4. Review before acceptance

Conceptual flow for the example above.

Tradeoff to keep in mind

Explicit missing states require interface and workflow decisions. They preserve uncertainty, but they cannot determine whether a supplied zero is commercially correct.

Related project: Sheet Parser →

References & further reading

Related posts