Order Cancellation

Order Cancellation Approvals — User Guide

This explains what the cancellation approval workflow does today, who's involved, and exactly what happens for every combination of action and document type. Everything described here is built and working — this is not an aspirational spec.


What problem this solves

Cancelling a Sales Order touches a lot of other teams' work: manufacturing might already have a Work Order running, fulfillment might have stock reserved or a delivery in motion, and accounts may owe the customer a refund. Cancellation now only actually happens once everyone whose work is affected has explicitly said "yes, this is fine," or the system has determined automatically that there's nothing risky to sign off on.


Who's involved

Role What they do
Requestor Anyone with a role allowed to raise cancellations (configured by an admin). Starts the request and clicks Submit — there's no separate "send for approval" step; Submit itself decides whether approval is needed.
Manufacturing approver Acts on Work Order rows (and, through them, the linked Material Request).
Fulfillment approver Acts on stock-side Material Request rows and draft Delivery Plan rows.
Accounts approver Approves/rejects the refund leg, if a refund is involved (no dedicated action button yet — see "What's not built yet").
Admin Configures, once, which roles approve what — see "One-time setup" below.

An approver only sees the rows that belong to them: their role, and (for warehouse-bound categories) their warehouse — see "Who can see/act on what" for the exact rule, which is more permissive than you might expect.


One-time setup (admin)

Open Order Cancellation Configuration and set:

  1. Requestor Roles — who can create an Order Cancellation and submit it.
  2. Approval Routes — for each Warehouse Group (a parent/group warehouse in your warehouse tree), which category (Manufacturing or Fulfillment — your call) it falls under, and which role approves it. Every warehouse nested under that group routes the same way. To let more than one role approve the same group, add another row with the same Warehouse Group and Category, just a different role.
  3. Accounts Approver Roles — who approves the refund leg. Not tied to a warehouse.
  4. Fulfillment Approver Roles (Store Transfers) — who approves a Store→FC stock transfer Material Request. Unlike Approval Routes above, you do not list warehouses here at all — which warehouses count as "Store" for a given order is worked out automatically from that order's own Order Profile (its Stock Warehouses, minus Excluded Warehouses, minus the profile's own Fulfillment Centre) every time a request is built, so this never needs updating as branches open, close, get renamed, or get restructured. Just list the role(s) — e.g. Fulfillment User — that should be able to approve these.
  5. Fulfillment Approval Delta (Days) — see "Automatic, no-approval cancellations" below. 0 is a valid, intentional value — it means "skip approval if the required-by date is today or later and nothing has shipped yet," which is the most permissive setting. There is no "off" value; if you never want automatic skipping, set this very high (e.g. 9999) so the condition is effectively never met.
  6. Notify Approvers on Request — leave this on so approvers get notified automatically.

Double-check warehouse names carefully when filling in Approval Routes — they must match the warehouse's exact stored name, including the company-abbreviation suffix Frappe appends (e.g. ... - FT). A route pointing at a name that doesn't exactly match any real warehouse silently never fires for anyone — there's no error, it just never routes. Use the dropdown picker rather than typing the name by hand.


The requestor's journey

  1. Before creating a new request: only one Order Cancellation can be open against a given Sales Order at a time. If one is already Draft, Pending Approval, or Rejected-and-not-yet-fixed for this order, you can't start a second one — you'll get a clear error naming the request already in progress. Go finish or fix that one instead (see step 6 for what to do with a Rejected request).
  2. Create an Order Cancellation against the Sales Order. It starts in Draft status.
  3. Use Fetch → Items to pull the order's lines, adjust revised_qty per row (0 drops the line; a higher number than original is allowed — orders can grow, not just shrink), set a delivery_date per row if you want to override the original order's date for that line, and set refund_amount if one applies. If the order is also shipping to or billing a different address, set Revised Billing Address and/or Revised Shipping Address — the dropdown only offers addresses already linked to this customer. Leave either blank to keep the original order's address exactly as it was.

    If you're only changing the address and not touching any item's quantity, that's all this request will ever need — no approvals get routed at all, and submitting applies the new address straight onto the existing order without cancelling or replacing it (see "Address-only updates" below).

    Need to add an item that doesn't exist yet as a specific variant (e.g. the customer is upgrading to a different fabric/size of a sofa that's already on the order)? Click Add Variant, below the items table. Pick the item template, choose a value for each attribute the dialog asks for, and click Add Variant — it reuses an existing variant with that exact combination if one already exists, otherwise creates a new one on the spot, then adds it as a normal row. From there it behaves exactly like any other row — set its revised_qty, delivery_date, warehouse, etc. as usual. Any row you add or edit this way has its delivery_date checked against that item's configured delivery lead time — you can't set a date sooner than the item could actually be fulfilled by; saving will tell you the earliest valid date if you try.

  4. Click Submit — there's no separate "Send for Approval" step; Submit itself works out what needs to happen:

    • If nothing linked to the Sales Order actually needs a decision (see "Automatic, no-approval cancellations" below for what gets skipped), the cancellation goes through immediately — this is the step that actually cancels the original Sales Order and creates the revised one.
    • Otherwise, you'll see a message naming how many stakeholders need to sign off, and status moves to Pending Approval instead — nothing is cancelled yet. Behind the scenes this is the point where the system scans everything linked to the Sales Order and creates one approval row per document that actually needs a decision.

    Note on Work Orders specifically: only the Work Order(s) for the item(s) you're actually reducing/dropping need a real decision from Manufacturing. A Work Order for an item you left completely unchanged is automatically carried forward with no approval needed at all — see "Unchanged items' Work Orders resolve themselves" below. Standalone stock Material Requests (not tied to a Work Order) don't have this automatic handling yet — one for an unchanged item can still end up needing a decision even though its item isn't changing.

  5. Wait for approvers to act (see their journey below).
  6. Once every row is resolved (Approved/Unlinked/Cancelled — not Rejected, not still Pending), click Submit again. This time it goes through for real, cancelling the original Sales Order and creating the revised one. If you click Submit again while approvals are still outstanding, you'll just see a clear message telling you how many are left — nothing breaks.
  7. If anything was Rejected, or a Work Order is still attached to the Sales Order, submission is blocked with a clear error telling you what to resolve first. If a row was Rejected and you want to try again after making changes (e.g. removing the item an approver rejected, or fixing whatever they objected to), use the Reset & Retry button that appears on a Rejected request — it clears every approval decision recorded so far on this document and lets you resubmit it fresh, once you've made your edits. You do not need to (and can't, per step 1) create a new Order Cancellation to try again.

The approver's journey

Each approver opens the relevant Pending Cancellation Item row (or the linked document itself, for Work Order) and sees action buttons specific to what kind of document it is. There is no generic "Approve" button anywhere in this flow — every action is named for what it actually does, because approving is never just a status flag, it always does (or deliberately doesn't do) something real to the document.

Every row now shows the Item it's actually about (in the list view and on the row itself), so you don't have to open the linked document to know which product a given Work Order or Material Request row concerns. A row that genuinely spans more than one item (a Delivery Note/Plan touching several) shows a readable list of item names instead of a single item.

A Work Order only ever shows up here at all if its item is genuinely being reduced or dropped by the request. One for an item left completely unchanged never appears in this list — not Pending, not resolved, not at any status — see "Unchanged items' Work Orders resolve themselves" further down for what happens to it instead.

These buttons live both on the Work Order form itself (under the Cancellation group) and on the row's own Pending Cancellation Item form. They apply whether the Work Order is still draft or already submitted — manufacturing sometimes starts work before a Sales Order is confirmed, so a Work Order may exist in draft at the time of cancellation, and it gets a row and these same buttons just like a submitted one would.

  • Unlink — detaches the Work Order from this Sales Order (it stays alive, keeps producing) and does the same to its raw-material Material Request(s). Any Stock Reservation Entry for the same order/item is still cancelled — there's no way to "detach" a reservation, only release it. If this item is manufactured, the Material Request moving the finished item from the manufacturing unit to the Fulfillment Centre is left completely untouched and continues as normal — it's already producing/delivering stock regardless of which Sales Order it ends up serving, so Unlink doesn't detach it the way it does the raw-material request. The Work Order's row is stamped Unlinked.
  • Approve Cancellation Request — if the Work Order is submitted, cancels it outright; if it's still draft, it's deleted instead (a draft was never submitted, so there's nothing to cancel). Its linked Material Request(s) follow the same shape: cancelled if submitted, deleted if still draft — in either case, unless that Material Request also serves other Sales Orders, in which case it's left alive (just detached) to avoid disrupting those other orders. Stock Reservation Entries are cancelled either way, in both the draft and submitted case. Both rows stamped Cancelled.
  • Reject — touches nothing at all. The Work Order, its Material Request, everything stays exactly as-is. Both rows stamped Rejected, which blocks the whole Order Cancellation from being submitted.

A previous Sales Order an Unlinked Work Order was detached from is kept on the Work Order itself (a "Previous Sales Order" field), purely for traceability — it's not a live link, nothing reads it automatically. A deleted draft Work Order has no such record, since the document itself no longer exists.

Standalone Material Request rows — Approve Cancellation Request / Reject

This is for stock-side Material Requests (Material Transfer / Material Issue / Purchase / Customer Provided — anything that isn't a Manufacture type tied to a Work Order). A Store→FC stock transfer lands here too — who can approve it is whoever holds a Fulfillment Approver Roles (Store Transfers) role from setup step 4 above, not a warehouse-specific setup per branch.

  • Approve Cancellation Request — cancels the Material Request (same "don't disrupt other Sales Orders" fallback as the WO path) and cascades to cancel any Stock Reservation Entry for the same order and item. Row stamped Cancelled.
  • Reject — touches nothing. Row stamped Rejected, blocking submit.

If a Manufacture-type or Material Transfer-type Material Request is tied to a Work Order — draft or submitted — it has no independent buttons at all — acting on the Work Order's row handles it automatically, and if more than one Material Request is tied to the same Work Order, all of them follow along together. This is deliberate: a Work Order and everything feeding it must always move together — Unlink the Work Order and every coupled Material Request is unlinked with it; approve its cancellation and every coupled Material Request is cancelled with it.

Draft Delivery Plan rows — Remove / Reject

  • Remove — strips this Sales Order's rows out of the (still-draft) Delivery Plan entirely. The Delivery Plan itself stays in draft for its other orders. Row stamped Unlinked. Remove will refuse if any item on this Sales Order still exists in the revised order (its revised quantity is above zero) — that item continues to need fulfillment, so it can't be silently dropped from the plan. Resolve it on the Delivery Plan itself first, or wait until the item is actually being dropped from the order, before Remove will succeed.
  • Reject — touches nothing. Row stamped Rejected, blocking submit.

There's no "Approve Cancellation Request" option here because a draft document was never submitted — there's nothing to cancel, only to remove from.

If you try to submit a Delivery Plan that contains a Sales Order with an open (draft) Order Cancellation, submission is blocked immediately with an error naming the offending order and OC. Resolve or cancel the OC request before including that order in a Delivery Plan.

Delivery Note (draft) and Accounts (refund) rows — no dedicated button yet

These rows still use the old, plain status field — see "What's not built yet."


Who can see/act on what

  • Role match is required: you must hold one of the roles configured for that row's category/warehouse.
  • Warehouse restriction follows standard Frappe rules: if you have zero warehouse User Permissions set up at all, you can act on every warehouse's rows (you're simply unrestricted). If you have any warehouse User Permission, you're narrowed down to only those specific warehouses. This means you don't need a User Permission set up just to get started — only set one up once you actually need to restrict someone to specific warehouses.
  • System Manager / Administrator bypass all of the above and see/act on everything, everywhere.

Automatic, no-approval cancellations

Two situations never need a human at all:

  1. Stock Reservation Entries never get an approval row, full stop. They're simply released (cancelled) automatically when the Order Cancellation is finally submitted — or earlier, as a side effect of acting on the Work Order or Material Request row that's driving the item, or of a stock Material Request auto-skipping approval entirely (see below) — released immediately in that case too, not held until final submission.
  2. Stock-side Material Requests skip approval entirely — auto-cancelled the moment the request is sent for approval, no row ever created — when both of these are true:

    • No Stock Entry has been raised against it yet (nothing has actually started moving), and
    • Its earliest "Required By" date is on or after cancellation date + Fulfillment Approval Delta (Days) from your configuration.

    If either condition fails — something's already moving, or the date is too close — a normal approval row is created instead.

Manufacture-type Material Requests (the ones tied to a Work Order) never get this automatic treatment — they always go through the Work Order's row, since the Work Order itself needs a human decision regardless.

  1. Payment documents are detached, not cancelled or destroyed, the moment the Sales Order is actually cancelled. Any Payment Request or in-store payment transaction (card/UPI/POS) tied to the order is unlinked — the document itself, and any payment it already collected, stays exactly as it was, just no longer pointing at the cancelled order. If the customer already paid and that payment was applied to this order, the payment is released back to an unallocated advance rather than being cancelled — the money always stays represented in the system, never lost, and is automatically re-applied to the revised order once it's confirmed. None of this happens at all if the revision fails to submit (see "What happens if the revised order can't be submitted" below) — the original order, including its payments, is untouched in that case.

What can't be cancelled through this flow at all

These are hard blocks — they stop you from even creating/saving a draft Order Cancellation, no approval can route around them:

  • A submitted Sales Invoice exists against the Sales Order. Use the Sales Invoice → Out of Stores route instead. (A draft Sales Invoice has no effect at all — it's invisible to this flow either way.)
  • The Sales Order is part of a submitted Delivery Plan. It needs to be removed from that plan by whoever owns it before a cancellation can even be drafted. (A draft Delivery Plan does not block — see "Draft Delivery Plan rows" above, it gets a normal approval row with a Remove action.)

You'll get a specific error naming exactly which of these applies.

There's also a submit-time-only block: if a submitted Work Order is still attached to the Sales Order when you try to submit (because nobody used Unlink or Approve Cancellation Request on it yet), submission is blocked with a message pointing you to that action.

There's also a Delivery Plan-side block: submitting a Delivery Plan is blocked if any of its Sales Orders has an open (draft) Order Cancellation in progress. You must either resolve/cancel that OC first, or use the Remove action on the OC side to strip the order from the plan.


What happens if a Work Order is submitted after the cancellation was routed for approval

Manufacturing sometimes submits a Work Order after a cancellation request has already been routed for approval (i.e. after the requestor's Submit click already moved it to Pending Approval). When that happens, the system catches it automatically: the moment the Work Order is submitted, it checks whether the linked Sales Order already has an open cancellation in progress. If it does, a new approval row is immediately created for that Work Order and the manufacturing approver is notified — exactly as if it had been picked up during the original scan. No one needs to do anything manually.


What happens if the revised order can't be submitted

Submitting the Order Cancellation builds a revised order with the updated items and confirms it fully before anything about the original order is touched. If that revision fails for any reason — a pricing error, a missing field, not enough available stock to carry a surviving item's reservation forward (see below) — the whole submission fails outright, and the original Sales Order is left completely untouched: still submitted, still holding its own items and stock reservations, exactly as it was before you clicked Submit. You'll see the error naming what went wrong; nothing is silently patched over or substituted, and there's no "restored original" order to look for — the original was never cancelled in the first place. Fix whatever the error describes and submit again.

What happens if the original order can't be fully retired

Once the revised order is confirmed submitted, the system moves on to retiring the original — cancelling whatever's still attached to it and releasing its payments. This is a different, later step than the one above, and by this point the revised order already exists and can't be undone. If something here fails (a document attached to the original refuses to cancel, a payment can't be released), you'll see an error titled "Manual Follow-Up Needed", and a plain-language comment explaining exactly what happened is added to both the Order Cancellation and the revised order's Activity/Comments timeline — so the issue is never silent, even if you don't see the error message at the time. In this situation the revised order is always still fully traceable back to the original it replaces (that link is set the moment the revision is confirmed submitted, before this retirement step even starts), but the original itself may need manual attention — check the comment for specifics and involve an administrator if needed.

Stock reservations carry forward automatically

If an item survives into the revised order (its revised_qty is above zero) and had stock reserved for it on the original order, that reservation is re-created on the revised order automatically — you don't need to manually re-reserve stock for items that were never meant to be affected by this cancellation. If there genuinely isn't enough available stock to carry a reservation forward (e.g. it was sold elsewhere in the meantime), submission fails outright with a clear error naming the shortfall, rather than silently under-reserving or dropping the reservation — see "What happens if the revised order can't be submitted" above.

Work Orders follow their item onto the revised order

A Work Order that was Unlinked during approval — meaning its item survives and Manufacturing confirmed it should carry forward — is automatically re-attached to the revised order once it's created, pointing at that item's new row there. You don't need to manually re-link it afterward; it's no longer left permanently detached the way it used to be.

Unchanged items' Work Orders resolve themselves

If you reduce or drop one item out of several, the Work Orders for the other items — the ones you left completely untouched — never need a Manufacturing decision at all, and never appear anywhere in the Pending Cancellation Item list. They're automatically detached the moment the request is routed, and any raw-material Material Request tied to them follows along the same way — with nothing ever created for either document, at any status. A manufactured item's finished-goods transfer to the Fulfillment Centre is, again, left alone entirely — same as the manual Unlink case above. Only the item(s) you're actually reducing show up as something Manufacturing needs to act on. This — combined with "Work Orders follow their item onto the revised order" above — means reducing one item out of three no longer means asking Manufacturing to make a decision about the other two, or even seeing that anything happened to them: they're carried forward automatically, invisibly, and only ever show up correctly linked to the revised order once it exists.

This automatic handling is specific to Work Orders (and whatever Material Request is tied to them). A standalone stock Material Request — one not tied to any Work Order — doesn't get this treatment yet; if it's attached to the Sales Order, it can still end up needing a real decision even when its own item isn't the one changing.

Address-only updates

If every item's quantity is left exactly as it was — nothing added, nothing dropped, nothing reduced — and you've only set a revised billing/shipping address, submitting this request doesn't cancel or replace the Sales Order at all. The address is applied directly onto the existing order, nothing linked to it needs approving, and Submit goes through immediately regardless of what Work Orders, Material Requests, or anything else is still attached — none of it is at risk, because the order itself never changes identity.


What's not built yet

  • Delivery Note (draft) rows and Accounts (refund) rows still use the old plain status dropdown — there's no dedicated action button for them, so approving is bookkeeping only. The real effect on those documents happens later, automatically, when the Order Cancellation is finally submitted (the underlying cancel-everything-still-linked cascade catches them).
  • Material Requests are not automatically re-linked the way Work Orders now are — a Material Request Unlinked alongside its Work Order stays detached even after the Work Order itself is re-attached to the revised order. Only the Work Order follows automatically today.
  • A raw-material Material Request coupled to a Work Order may not actually get cancelled when you Approve Cancellation Request on the Work Order — a known, pre-existing matching issue means this can silently do nothing to the Material Request in that specific case (found during testing; not yet fixed). If you approve a Work Order's cancellation and notice its Material Request is still active afterward, that's this issue — check and cancel it manually for now.
  • Standalone stock Material Requests for an unchanged item don't get the automatic hands-off treatment Work Orders now get — see "Unchanged items' Work Orders resolve themselves" above.
  • Notification when a cancellation is routed for approval depends on the "Notify Approvers on Request" setting and on a matching, warehouse-eligible user actually existing — if nobody's been set up for a category yet, nobody gets notified (but the row still exists and still blocks submit).

Naming

Order Cancellation documents are named POC-DDMMYY-##### (e.g. POC-230626-00001 for the first request raised on 23 June 2026) — the counter keeps incrementing, it does not reset daily.

The revised Sales Order created when a cancellation goes through gets an ordinary new name from its usual naming series — not the -1-suffixed "amended" name Frappe normally gives an amended document. This is a deliberate trade-off: giving it that traditional amendment name would require cancelling the original order before the revision is even built and confirmed, which is exactly the risk this app avoids (see "What happens if the revised order can't be submitted"). The revised order still records which order it replaces (its "Amended From" field) and which Order Cancellation created it — just not in its own name.

Discard
Save
This page has been updated since your last edit. Your draft may contain outdated content. Load Latest Version

On this page

Review Changes ← Back to Content
Message Status Space Raised By Last update on