POS refunds & returns

Markdown

View as Markdown

POS refunds & returns

A clean refund is two events at once: money goes back to the customer, and stock comes back into your warehouse. LaunchMyStore POS keeps both halves honest with a paired cash-movement + inventory-movement ledger.

What counts as a refund

Any time a customer returns goods and you give value back. Sources of value:

  • Cash refund — cash leaves the drawer.
  • Card refund — reverses the original card charge through the payment provider.
  • Store credit / gift card — issues new credit instead of cash.
  • Mixed — e.g., $20 cash + $30 store credit.

Each refund is tied to an original order line. You cannot refund more than the order’s remaining refundable amount.

How to process a refund

  1. Open POS → Orders.
  2. Find the order. Tap it.
  3. Tap Refund (only visible to staff with the Refund permission).
  4. Pick which line items and quantities to refund.
  5. Choose the refund destination — cash, card, or store credit.
  6. Tick Restock returned items if the goods are coming back into inventory (default: on).
  7. Confirm.

If the original tender was cash and your refund destination is cash, the drawer pops via the cash-kick cable.

Restocking via InventoryMovement

When you mark items as restocked, the backend writes a row into the InventoryMovements table:

{
  type: 'refund_restock',
  quantity: 2,
  delta: +2,           // positive: stock returns
  channel: 'pos',
  warehouseId: '<shift warehouse>',
  orderId: '<original order>',
  productId, variantId,
  reason: 'Customer returned'
}

Stock returns to the same warehouse the shift was opened against. If the shift had no warehouseId, the global product / variant counter is incremented instead.

Skip the “restock” checkbox for damaged goods. The refund still posts, but no InventoryMovement is written — the goods are now in your shrinkage column, not on the shelf.

Cash movement on the shift

If the refund destination is cash, the system also writes a CashMovement:

{
  shiftId: '<current open shift>',
  type: 'refund',
  amount: 49.99,
  orderId: '<original order>',
  reason: 'Customer returned'
}

This pulls down your expectedCash for the day so the drawer balances at close. Card refunds don’t affect cash — they touch the card processor and reduce the day’s card-tender total instead.

Partial refunds

Refund any subset of the original order — one out of three items, half a quantity, or a custom amount.

The original order’s refundedAmount increments on each partial. When it reaches the order total, the order is fully refunded. You can’t refund more than what’s remaining.

Card refund flow

For card-tender orders processed through a supported provider:

  1. The refund request is sent to the original processor (Stripe, your in-house gateway, etc.).
  2. The processor reverses the charge.
  3. POS updates the order’s paymentStatus to refunded or partially_refunded.
  4. If you ticked restock, the InventoryMovement still fires.

Card refunds typically take 5–10 business days to land back on the customer’s statement — that’s the bank’s clock, not ours.

Permissions per staff role

RoleCan refund?Max discountOpen drawer
merchantYesNo capYes
AdminYesNo capYes
managerYes50%Yes
staff (cashier)No10%Yes

A cashier returning goods needs to call a manager over — the Refund button is hidden for the staff role. This is enforced both client-side (button absent) and server-side (refund API returns 403).

Issuing store credit instead

If your store offers store credit / gift cards, set the refund destination to Store credit. The system issues a new gift-card code for the refund amount and emails / SMSes it to the customer. No cash leaves the drawer, no card charge is reversed.

Exchanges

An exchange is a refund + a new sale in one motion. POS handles it via the Exchange button on the order — pick the returning items, then add the replacement items to the cart. The price difference is the new cash/card/credit transaction.

Common issues

  • Refund button missing — your role lacks the Refund permission. Have a manager process it, or have the merchant promote your role.
  • Inventory not coming back — the “Restock returned items” box was unchecked. You can fire a manual inventory adjustment to fix it.
  • Card refund “pending” for days — that’s the processor’s clearing window. Check the order’s payment provider log.
  • Variance shows positive after a refund — you marked the refund as cash in POS but actually didn’t take cash out of the drawer. Reverse it via paid_out.

FAQ

Does refunding a POS order also restock inventory?

Yes, when you tick the “Restock returned items” checkbox (default on). The system writes a refund_restock InventoryMovement that signs delta = +quantity and increments stock at the shift’s warehouse.

Can I refund a POS order from the admin instead of the register?</h3

Yes — the admin Orders page has a Refund action with the same options. The cash side is handled differently: if no shift is open at the register, a cash refund from admin marks the order refunded but doesn’t debit any drawer. Reconcile with a paid_out on the next shift.

What if the customer paid with split tenders?

You can refund per tender. $30 of a $50 order paid as $20 cash + $30 card can refund $20 to cash and $10 to card (or any split that sums to the refund amount).

Can a cashier override the refund block?

No. The no-refund rule is enforced server-side. Even calling the API directly from a cashier token returns 403.

Where do I see the day’s refund total?

On the Z-report at shift close, in the Tender totals section — refunds appear as negative entries per tender. The InventoryMovements log under Reports → Stock movements shows the goods-side detail.

Can I refund without selecting an original order?

No. Every refund must point at an order — that’s how the ledger stays balanced. If a customer brings something back without a receipt, take down the SKU and issue store credit via an admin-side adjustment instead of routing it through refunds.


Was this article helpful ?