Full refund with restock.
A customer returns a $42 order in full. The unit goes back into sellable inventory. The original sale posted at $42 revenue with $9.80 COGS at branch A’s WAC. The refund must reverse all of it: debit Sales returns $42, credit Shopify clearing $42, debit Inventory $9.80, credit COGS $9.80. The unit returns to stock at $9.80, not at current WAC.
The reason matters. If you restock at current WAC, say $10.50, you have moved $0.70 of margin from the past period to the current one. Across hundreds of refunds, that is enough to make any month look better or worse than it actually was. Restocking at original cost is the only way to keep periods clean.
Full refund without restock.
Sometimes the unit is unsellable. Maybe it arrived damaged, maybe the customer kept the unit and got refunded as a goodwill gesture. The unit does not go back to stock. Revenue still reverses, but COGS does not. Instead, you book the cost as a separate expense, often Inventory write-off or Customer accommodation expense.
Journal: debit Sales returns $42, credit Shopify clearing $42, debit Inventory write-off $9.80, credit Inventory $9.80. The inventory ledger is correct (the unit is gone) and gross margin is honest (cost was incurred but goods did not return). Booking this as a normal restock would silently inflate stock counts.
Partial refund mechanics.
A $42 order had two units at $21 each. One is refunded. The other stays. Only one unit reverses revenue and COGS. Sales returns $21, COGS reversal at one unit times branch A’s WAC at the time of the original sale, restock of one unit. The remaining order still settles at $21 sales and one unit’s COGS.
Where merchants get this wrong is when the partial refund is a discount, not a return. A customer complains, you refund $5 as a courtesy. No goods come back. The $5 is a customer accommodation, not a sales return, and certainly not a COGS reversal. Booking it as a sales return overstates returns; booking it as a discount understates.
Shipping and tax on refunds.
Shopify lets you refund shipping or not. If shipping is refunded, the journal includes a debit to Shipping income (the inverse of the original Shipping income credit). If not, shipping stays as recognized income. Tax behaves similarly: if tax is refunded, it reverses against the same tax liability account it was originally credited to.
On a $124 order with $6 shipping and $9.92 sales tax (8% in a Wayfair state), a full refund with shipping reversed is debit Sales returns $99.40, debit Shipping income $6, debit Sales tax payable $9.92, credit Shopify clearing $124. If shipping is kept (a common policy on customer-initiated returns), the $6 shipping debit becomes zero and Shopify clearing reverses by only $118.
- Shipping refunded: debit Shipping income for the refunded amount
- Shipping kept: shipping income remains, only merchandise reverses
- Tax refunded: debit the same tax payable account that was originally credited
- Tax kept: tax stays as a liability, refund only covers net of tax
Restocking fees.
A restocking fee is income, not a reduction of returns. On a $42 refund with a $2 restocking fee, the refund to the customer is $40. Journal: debit Sales returns $42, credit Shopify clearing $40, credit Restocking fee income $2. COGS reverses normally if the unit restocks.
Booking the restocking fee as a credit to Sales returns understates returns and overstates net sales. Booking it as a credit to revenue is worse, because it confuses what category the money came from. The restocking fee is operationally a fee, a separate income line that helps merchants see whether their returns process is self-funding.
Refunds that span periods.
A March order is refunded in May. The original sale and COGS hit March. The reversal hits May. This is operationally normal but accounting-sensitive. Some accountants prefer to push refunds back to the original period; others recognize them in the current period. The principle is consistency.
For Shopify merchants, the cleanest approach is current-period recognition with a returns-aging report. You can see how much of current-period sales are likely to come back based on aging, and you can hold a returns reserve if material. Nonari aggregates this aging automatically so you can decide if a reserve is needed.
COD-specific refunds.
For cash-on-delivery orders (common in some markets and for marketplaces like Mercado Libre, Daraz, Jumia), the refund flow is operationally different. The courier attempts delivery, the customer refuses or returns the package, the courier returns it to your warehouse. Revenue was likely never recognized (you only post on delivery confirmation), so the reversal is much simpler: just don’t post the original revenue.
If you did post on order, you will need a true reversal: debit Sales, credit COD receivable, debit Inventory, credit COGS. The courier RTO (return to origin) report is the trigger. Nonari ingests RTO reports automatically and reverses the order without a manual entry.
Where Nonari fits.
Every Shopify refund webhook fires through Nonari. The system snapshots the original WAC at sale time on every order, so the refund reverses at the correct cost basis automatically. Partial refunds, shipping flags, tax flags, and restocking fees all flow through the same pipeline with separate accounts. RTO reversals on COD orders work the same way.
The result is that gross margin per period reflects what the warehouse actually did. Margin does not drift with refund volume. Refund-aging is a built-in report. Returns reserves can be set based on actual aging, not a guess. Most importantly, none of this requires the merchant to remember a single accounting rule.