Part 5 of 7 · Inventory reorder bot series ~5 min read

How a reorder gets approved

A draft lands in the owner’s Slack DM at 8:03am. House Blend beans are down to 58, and the bot has drafted an order for 120 bags. There are three buttons: Approve, Edit, Skip. What happens when one gets tapped? The honest answer is “it depends which one.” This post walks through the three things the owner can do with a draft — approve, edit, skip — and how the order state and the audit trail stay in sync. The one rule that never bends: nothing is ordered without a human tap.

Key takeaways

  • Three actions per draft: approve (send to the supplier, mark on-order), edit (change first), skip (do nothing this round).
  • Approve sends the PO email to the supplier via SES and flips the item to on-order.
  • Edit opens a modal to change quantity, supplier, or note before anything is sent.
  • Skip leaves the item alone — the bot re-checks tomorrow and may draft again.
  • Nothing is ever ordered without a human tap. Every action writes an audit row.

Three actions on the draft

Three actions on the draft purchase order A diagram showing one input on the left flowing through a small interactive Slack panel, then branching into three action paths. Far left: a "Draft in Slack DM" box showing a typical draft purchase order — item name, suggested quantity, unit cost, line total, supplier — with three Slack-button placeholders below: Approve, Edit, Skip. The owner taps one button. The middle column shows the three branches. Branch one, Approve: a Function URL Lambda sends the purchase-order email to the supplier's ordering address via SES outbound, flips the item's status in the ir-orders DynamoDB table to on-order with the quantity and an expected-delivery date computed from the supplier lead time, and writes an approved event to the audit trail. The item won't be drafted again until the delivery lands. Branch two, Edit: opens a Slack modal pre-filled with the quantity, supplier, and an optional note; the owner adjusts any field and hits Send; the Function URL Lambda then runs the same Approve path with the edited values, so the corrected order is what goes to the supplier. Branch three, Skip: writes a skip row to ir-orders so the draft is dismissed for now; the item's status returns to normal and the next daily check re-evaluates it — if it's still low tomorrow, a fresh draft goes out. The right side shows the convergence: every action writes a row to the ir-audit DynamoDB table with timestamp, item id, action, by-user, and notes. A note at the bottom: nothing is ordered without a human tap — Approve and Edit both send; Skip never does. Draft in Slack DM item, qty, cost, supplier [Approve] [Edit] [Skip] Action 1 Approve • PO email sent to supplier via SES outbound • Item flips to on-order • Expected date computed Action 2 Edit • Modal: qty, supplier, optional note • Send runs the Approve path with edited values Action 3 Skip • Draft dismissed for now — nothing is ordered • Next check re-evaluates — may draft again Audit trail DynamoDB ir-audit timestamp · item_id action · by-user notes Nothing is ordered without a human tap — Approve and Edit both send; Skip never does.
Fig 5. Three actions per draft, three different effects. Approve sends the PO and marks the item on-order. Edit changes the order first, then sends. Skip orders nothing and lets the bot re-check tomorrow. Every action writes to the audit trail.

Action 1: approve (the most common)

The owner looks at the draft — 120 bags of House Blend at $4.20 to Bayside Roasters, on hand 58, sells about 8 a day — and it’s exactly right. They tap Approve.

The button submits to a Function URL Lambda. Three things happen, in order. First, the purchase-order email is sent to the supplier’s ordering address via SES outbound, formatted from that supplier’s template with the item, quantity, unit cost, line total, and any standing instructions. Second, the item’s row in ir-orders is flipped from pending to on-order, with the approved quantity and an expected-delivery date computed from the supplier’s lead time (today + 5 days for Bayside). Third, an action: approved row is written to ir-audit with the user, timestamp, supplier, quantity, and total.

Tomorrow’s check reads ir-orders, sees the item is on-order, and lands at stocked regardless of the on-hand count — no duplicate draft while the delivery is in transit. When the order arrives and the count goes back up (via a physical count or the POS lane), the status flips to received and the item rejoins the normal cycle, ready to be drafted again the next time it dips.

Action 2: edit (the small correction)

Sometimes the draft is nearly right but not quite. The owner knows a promotion is coming and wants 200 bags, not 120. Or they want to switch this one order to the backup roaster because Bayside is mid-holiday. Or they want to add a note to the supplier (“please split into two deliveries”). They tap Edit.

Edit opens a small Slack modal pre-filled with the quantity, the supplier, and an empty note field. The owner changes whatever they like — the modal still enforces the pack-size rounding and the order cap from Part 4, so an edit can’t sneak past the guardrails — and hits Send. From there, the Function URL Lambda runs the exact same path as Approve, but with the edited values: the PO email goes to the (possibly changed) supplier with the (possibly changed) quantity and the note appended, the item flips to on-order, and the audit row records action: edited along with what changed from the original draft. Edit is just Approve with a detour through a form — the order that goes out is the one the owner actually wants.

Action 3: skip (the “not now”)

Sometimes the right answer is to order nothing. Maybe a big delivery is already on a truck and the sheet hasn’t caught up. Maybe the owner is discontinuing the item. Maybe they just counted the back room and there’s plenty after all. They tap Skip.

Skip writes a row to ir-orders marking the draft dismissed and returns the item’s status to normal. Nothing is ordered. The next daily check re-evaluates the item from scratch — so if it really is still low tomorrow, a fresh draft goes out, and the owner isn’t permanently blinded to a real shortage just because they skipped once. To avoid nagging, the rules doc has a skip_cooldown_days setting (default 1): after a skip, the bot waits the cooldown before drafting that item again, so a deliberate skip isn’t immediately undone. An urgent item ignores the cooldown — a genuine stockout risk is exactly when you want to be re-prompted.

If the owner skips an item repeatedly, the weekly digest flags it: “skipped 4 times in a row — is the reorder point wrong?” A pattern of skips usually means a number in the sheet (sales rate, buffer, or the point override) needs adjusting, and the digest is where that surfaces.

Every action is logged, every order is traceable

The ir-audit table records every approve, edit, and skip with the user who took the action, the timestamp, and a snapshot of the order before and after. If a wrong order goes out (wrong quantity, wrong supplier), the snapshot shows exactly what was sent and by whom, so a follow-up call to the supplier to cancel or amend is backed by a clear record rather than a guess. The audit row is also what the monthly summary reads to report spend by supplier and orders by approver.

This kind of traceability matters because an order is money leaving the business. The next time anyone asks “why did we order 200 bags of beans in May,” the answer is one row away: who approved it, when, off which draft, with what numbers in front of them. That’s the difference between a system you trust with real purchasing and one you don’t.

Next post: the cost breakdown. The whole pipeline above runs in coffee-money territory at SMB volume; Part 6 explains exactly where the dollars go and why the daily check dominates the bill.

All posts