# POS refunds & returns

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 drawermerchantYesNo capYesAdminYesNo
capYesmanagerYes50%Yesstaff (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.