Skip to main content

Returns & Refunds (Advanced)

Goal​

Give customers a return request form in My Account and give the shop a queue to work through: approve or reject a request, record the return shipment, exchange messages with the customer, and issue the refund through WooCommerce. Requests are numbered and tracked through their own status.

Tier and entitlement​

FieldValue
TierPremium
Entitlement keyreturns-advanced
Admin tabrma
Module keyreturns-advanced
Settings prefixaiowc_rma_

Hooks register only when aiowc_module_enabled_returns-advanced is true and the licence permits the returns-advanced entitlement.

The request lifecycle​

A customer raises a request against one of their orders, choosing a reason and the items involved. The statuses used by Service/RMAService.php are pending, approved, rejected, shipped and received, plus the refunded end state.

  • A request is refused if the order is older than return_window_days.
  • With require_approval on, the request starts pending; the shop approves or rejects it. Approval opens a ship_back_window_days window for the customer to return the goods.
  • Tracking details recorded against the request move it to shipped, then received.
  • The refund is created with WooCommerce's own wc_create_refund(). With auto_refund on it is issued automatically; otherwise the shop triggers it.
  • restocking_fee_default is applied when the request is created.

Each request gets a number of the form RMA-<date>-<random>.

What is not wired​

Two services exist in the module but have no caller anywhere in it, so their behaviour is not reachable in this release:

ServiceIntended behaviourState
Service/LabelService.phpWrites a printable HTML return label into the uploads directoryNo caller, and no REST route exposes it
Service/ExchangeService.phpResolves a return as an exchange rather than a refundNo caller

Four settings are declared but never read: allow_exchange and allow_store_credit (the resolutions they describe are not implemented), notify_admin_email, and rma_number_prefix — the RMA number generator hardcodes the RMA prefix rather than reading the setting.

Settings​

Read through ModuleSettings with the aiowc_rma_ prefix; defaults are ReturnsAdvancedModule::DEFAULTS.

SettingDefaultMeaningConsumed
return_window_days30Days after an order that a return may be requestedYes
ship_back_window_days14Days after approval to return the goodsYes
require_approvaltrueWhether a request waits for the shop before proceedingYes
auto_refundfalseWhether the refund is issued without a manual stepYes
restocking_fee_default0.0Fee applied when a request is createdYes
allow_exchangetrueIntended to offer exchange as a resolutionNo
allow_store_credittrueIntended to offer store credit as a resolutionNo
notify_admin_emailemptyIntended recipient for shop noticesNo
rma_number_prefixRMAIntended prefix for the RMA numberNo — the prefix is hardcoded

Admin screens​

There are two.

  • The plugin's admin tab rma. It lists requests by status, opens one to read and reply to its message thread, approves, rejects, records tracking and issues the refund, manages return reasons, and carries the settings form.
  • A separate WordPress admin menu page, registered by Frontend/AdminHandler.php on admin_menu, with its own form posting to admin_post_aiowc_rma_action.

Database schema​

Created by Schema/ReturnsSchema.php at schema version 1.0.0.

TableHolds
{prefix}aiowc_returns_adv_requestsThe request: order, customer, RMA number, reason, resolution, status
{prefix}aiowc_returns_adv_itemsThe order lines being returned
{prefix}aiowc_returns_adv_messagesThe message thread between customer and shop
{prefix}aiowc_returns_adv_reasonsConfigurable return reasons

REST endpoints​

Namespace aiowc/v1. All responses use the shared envelope.

Customer​

MethodPathPurposeRequired argsPermission
POST/rma/createRaise a request; also accepts reason_id, resolution, customer_noteorder_id, itemsSigned in
GET/rma/myThe customer's own requests—Signed in
GET/rma/{id}Read one requestidOwner or manager
POST/rma/{id}/messagePost a message on the threadid, messageOwner or manager
GET/rma/reasonsList active return reasons—Rate-limited public read

Shop​

Permission: manage.

MethodPathPurposeRequired args
GET/rma/admin/requestsList requests, filterable by status, paginated—
POST/rma/{id}/approveApprove a request, with an optional noteid
POST/rma/{id}/rejectReject a request, with an optional noteid
POST/rma/{id}/trackingRecord the return shipmentid, carrier, number
POST/rma/{id}/refundIssue the WooCommerce refundid
POST/rma/reasonsCreate a reason; also accepts slug, requires_evidence, sort_order, is_activelabel
PATCH/rma/reasons/{id}Update a reasonid
DELETE/rma/reasons/{id}Delete a reasonid
GET/rma/settingsRead settings—
PUT / PATCH / POST/rma/settingsUpdate settings—

WooCommerce and WordPress integration​

My Account​

HookEffect
initRegisters the aiowc-returns account endpoint
query_varsRegisters the endpoint's query variable
woocommerce_account_menu_itemsAdds the Returns menu item
woocommerce_account_aiowc-returns_endpointRenders the returns tab, which honours return_window_days when listing eligible orders

Admin​

HookEffect
admin_menuRegisters the standalone WordPress admin page
admin_post_aiowc_rma_actionHandles that page's form submission

Shortcode​

ShortcodePurpose
[aiowc_returns]Renders the returns interface outside My Account

No block is registered. Refunds go through WooCommerce's own wc_create_refund(), so they are handled by whatever gateway the order used; the plugin ships no payment provider of its own.

Background jobs​

Both run on the WordPress cron scheduler, daily.

HookPurpose
aiowc_rma_expireCloses requests whose ship-back window has passed
aiowc_rma_remindersReminds about requests left pending, and about approved requests not yet shipped, using its own day thresholds

Entitlement limits​

The returns-advanced entitlement gates the module as a whole. The return and ship-back windows are shop settings, not licence limits, and no cap on requests is implemented.