Lorixen.
EN

An Undo Window for Bulk Category Moves in a Product Admin

A bulk category move is easy to start and awkward to reverse. Someone selects forty products, picks a new category, confirms, and later realises the target was wrong. This article proposes, conditionally, an undo window that works from a record of what moved. It does not rely on rolling back the database.

What the undo window would and would not be

The proposal is a time-limited action that restores products to the category they held before a specific batch. It would be built from a ledger, not from a transaction. That distinction matters. A database rollback undoes everything since a point in time, including unrelated edits by other people. A ledger-based undo would touch only the products the batch moved, and only when it is safe to do so.

The feature should never be described to staff as a guarantee. The interface wording could be: "Undo restores products from this batch that have not been changed since."

The primary artifact: the movement ledger

If adopted, each bulk move would write one row per product at the moment of the change.

Field Purpose
batch_id Groups all rows from one confirmation
product_id Identifies the product
category_before Category held immediately before the move
category_after Category the batch assigned
position_before Sort position inside the old category, if the catalogue uses one
moved_by, moved_at Who and when
undo_state pending, undone, skipped_conflict, or expired

The rows must be written in the same operation as the move, so a move without a ledger entry cannot exist.

The undo boundary

The boundary is the rule that decides, per row, whether undo may act. A cautious version:

  1. Undo applies only while the batch is inside its window, for example until the editor leaves the session or a configured period ends. The length is a decision for the team.
  2. For each row, undo proceeds only if the product's current category still equals category_after.
  3. If the current category differs, because someone moved it again, the row becomes skipped_conflict and is reported, never overwritten.
  4. Undo itself writes new ledger rows, so an undo can be inspected and is not silent.

Branching choices

If the catalogue has a product deleted after the move, mark the row skipped_conflict with a reason of missing product. If the old category has since been deleted, do not recreate it; stop that row and report it. If a product is in several categories, the ledger should record the full set before and after, or the team should decide to exclude multi-category products from bulk moves entirely.

Hypothetical worked example

Imagine a batch of six products moved from "Fittings" to "Adapters". Afterwards, a colleague manually moves product 4 to "Clearance", and product 6 is deleted. The editor presses undo. The expected result: products 1, 2, 3 and 5 return to "Fittings". Product 4 is skipped as a conflict because it is now in "Clearance". Product 6 is skipped as missing. The summary reads "4 restored, 2 not restored", with the two reasons listed.

Undo-boundary tests

A team could require these before accepting the feature:

  • Undo immediately after a move restores every product to category_before.
  • Undo after a single product was re-moved by someone else leaves that product untouched and reports it.
  • Undo after the window closes does nothing and states why.
  • Pressing undo twice does not move anything the second time.
  • A batch that failed partway only has ledger rows for products actually moved.
  • Undo of one batch does not alter products from a different batch.
  • Sort position is restored only where the position slot is still unambiguous; otherwise the product is appended and the report says so.

Stop conditions

Pause the rollout if any test shows undo overwriting a later human edit, if ledger rows can be missing for moved products, or if the summary count disagrees with the rows changed.

Acceptance check

A reviewer should be able to take any batch id and, from the ledger alone, state what each product was, what it became, and what undo did to it. If that cannot be answered, the ledger is not yet sufficient.

Sources

    WhatsAppLet’s talk