Part 2 of 7 · Return and RMA handler series ~6 min read

How a return request gets checked

Before a single label is printed, the system has to answer one question honestly: is this return even allowed? This post is about that step alone — how a request is matched to its original order and run through a short list of plain-code policy checks, and what happens, deliberately, when one of them fails.

Key takeaways

  • A request is matched to its original order first — by order number, or by the customer’s email and the item.
  • Eligibility is a short list of plain-code checks: return window, non-returnable flags, prior returns, and condition.
  • Every check must pass. There is no “probably fine” — a single fail stops the return.
  • A fail is declined with the exact reason, or escalated to a person where policy says a human should decide.
  • No model runs here. The rules come from your written policy doc and are applied as code.

The question before the label

It’s tempting to issue a label the moment someone asks for one — it feels like good service. But a label issued for a return you don’t actually owe is a cost you’ve volunteered for: the postage, the handling, and often the refund at the end of it. The job of this stage is to answer one question honestly before any of that happens: is this return allowed under your own policy? Everything downstream — the RMA, the label, the tracking, the refund-or-replace decision — assumes the answer is yes, so this is the gate that protects the rest.

The stage is a single Lambda, rmar-eligibility, and it’s the first task in the state machine. It does two things in order: find the order the request is about, then run the policy checks against it.

Finding the order

A return request carries whatever the customer typed: ideally an order number, but sometimes just “the boots I bought last month.” The stage looks first for an order number in the request — the cleanest signal — and matches it against the orders mirrored from your Drive sheet. If there isn’t one, it falls back to the customer’s email plus the item described. A confident single hit moves on; an ambiguous one (several orders that could fit) or no match at all is escalated to a person rather than guessed, because every check that follows depends on having the right order underneath it.

The checks, in plain code

With the order in hand, the stage runs the policy as a short list of deterministic checks. Each is a clear pass or fail, and the request only proceeds if every one passes.

The eligibility stage: find the order, run four plain-code checks, and either clear or decline the return A top-to-bottom flow. At the top, a “Return request” box carrying the order, item, and reason. An arrow down leads to “Find the order”, which reads from a “Policy & orders” source box on the right holding the return window, the flags, and the rules. An arrow down leads into a container labelled “Eligibility checks — plain code” holding four checks in sequence: in the return window, not flagged non-returnable, not already returned, and declared condition allowed. An arrow down from the container reaches a decision box, “All checks pass?” If any check fails, the flow goes left to “Declined or escalated, with the exact reason”. If every check passes, the flow goes right to “Cleared, on to RMA and label”. A note at the bottom states that no model runs here; the rules come from the written policy and are applied as code. Return request order + item + reason Find the order number, or email + item Policy & orders window, flags, rules Eligibility checks — plain code In the return window Not flagged non-returnable Not already returned Declared condition allowed All checks pass? fail pass Declined or escalated with the exact reason Cleared → RMA & label (Part 3) No model runs here. The rules come from your written policy and are applied as code.
Fig 2. The eligibility gate. Find the order, run four plain-code checks against the policy, and either clear the return or decline it with the exact reason. One fail is enough to stop it.

What each check actually does

  • In the return window. The window runs from delivery, not from purchase, so the stage takes the delivery date carried on the order and compares it to today against the window in the policy — commonly 30 days. A boot delivered nine days ago passes; one delivered 40 days ago fails, and the decline says exactly that: “returns close 30 days after delivery; this was delivered on 12 May.”
  • Not flagged non-returnable. Some items can’t come back at all — final-sale, hygiene items once opened, perishables, custom-made goods. The catalogue carries a non-returnable flag per item; if it’s set, the return stops here with the reason named, rather than a label going out for something you’d never accept.
  • Not already returned. The returns table is checked for an existing return on the same order line. This is what stops a customer — or an honest mistake — opening a second return on an item that’s already been refunded or replaced once.
  • Declared condition allowed. The request asks the customer to state the condition (unopened, opened, faulty). The policy says which conditions you accept for which reasons — a change-of-mind return may need to be unopened, while a faulty item can come back used. A condition the policy doesn’t allow for the stated reason is flagged for a person rather than auto-declined, because “faulty” deserves a human read.

Why this stays plain code

There’s an obvious temptation to let a model read the request and judge eligibility “intelligently.” It’s the wrong tool here. Eligibility is a question with a right answer that your policy already defines: the date is either inside the window or it isn’t, the flag is either set or it isn’t. A model would add cost, latency, and a small but real chance of waving through a return it shouldn’t — or declining one it should — for reasons you can’t audit. Plain code against a written policy gives you the opposite: every decision is explainable, every decline cites the rule it failed, and changing a rule is a doc edit. The only place judgement genuinely helps — the phrasing of the decline email, or a borderline “faulty” claim — is handed to a model for words or to a person for the call, never to a model for the verdict.

Design rules for the eligibility stage

  • Order first, checks second. Everything depends on matching the right order; an unsure match escalates rather than guesses.
  • Every check must pass. There is no partial credit — a single fail stops the return.
  • Decline with the reason. A rejected return names the rule it failed, in words the customer can act on.
  • The window runs from delivery. The clock starts when the customer got the item, not when they paid.
  • Faulty gets a human. A condition the policy can’t auto-accept is escalated, not auto-declined.
All posts