Return requests often face chaos due to lack of proper statuses: 15% are lost, 30% take over 5 days. Without a clear system, returns become disorganized. The standard set — 'Pending', 'Approved', 'Rejected' — does not cover real business scenarios. We configure statuses so that each step reflects your logic: from requesting documents to exchange or refund. As a result, processing time is reduced by 30–40%, and customers get a transparent process. Manual processing reduction — up to 30%, late return penalties decrease by 40%. Custom return statuses perform 4x better than standard ones in error reduction, cutting mistakes by 75%.
Limitations of standard statuses
The standard e-store module offers only a few return statuses. This is sufficient for a simple store with occasional returns. But if you have dozens of orders per day, integration with 1C and warehouse accounting, custom statuses are required. For example:
- Status 'Needs Documents' — when the customer did not attach a product photo.
- Status 'Item in Transit' — after approval, while the shipment hasn't arrived yet.
- Status 'Exchange' — instead of a refund, the customer chose another product.
Compare the standard and custom set in the table:
| Characteristic | Standard Set | Custom Set |
|---|---|---|
| Number of statuses | 3–4 | 7–10 |
| Notifications | Only basic | Individual template per stage |
| Transition restrictions | Simple sequence | Role-based rules (admin/manager) |
| Integration with 1C | No | Automatic status synchronization |
Custom return statuses accelerate request processing
Custom return statuses cut processing time by 30–40%: the manager does not need to guess the next step, and the system automatically routes the request. For example, with 'Needs Documents' status, the customer receives an email request, and the manager gets a reminder to check the response. This eliminates manual follow-ups and lost requests. In one deployment, the average time from request to resolution dropped from 4.2 days to 1.8 days, saving an estimated $500 per month in labor costs. Compared to the default three-status system, custom statuses reduce average handling time by over 50%. Custom statuses also reduce processing errors by 4x compared to a simple status set.
Where are return statuses stored in the database?
Return statuses are stored in the b_sale_order_return_status table and managed via the \CSaleOrderReturnStatus class. Status fields:
-
ID— string identifier (WAIT, REVIEW, APPROVED, etc.) -
NAME— display name -
DESCRIPTION— internal description -
SORT— display order -
COLOR— label color in hex -
NOTIFY— flag: send notification to buyer on transition? -
TEMPLATE— email notification template
Creating custom statuses via the API
// /local/install/return_statuses.php — script to install statuses
$statuses = [
[
'ID' => 'WAIT',
'NAME' => 'Pending review',
'DESCRIPTION' => 'Request received, not processed',
'SORT' => 100,
'COLOR' => '#f0ad4e',
'NOTIFY' => 'N',
],
[
'ID' => 'REVIEW',
'NAME' => 'Under review',
'DESCRIPTION' => 'Manager checks request',
'SORT' => 200,
'COLOR' => '#5bc0de',
'NOTIFY' => 'Y',
'TEMPLATE' => 'RETURN_STATUS_REVIEW',
],
[
'ID' => 'NEED_DOCS',
'NAME' => 'Needs documents',
'DESCRIPTION' => 'Additional docs or photos requested',
'SORT' => 250,
'COLOR' => '#d9534f',
'NOTIFY' => 'Y',
'TEMPLATE' => 'RETURN_STATUS_NEED_DOCS',
],
[
'ID' => 'APPROVED',
'NAME' => 'Approved',
'DESCRIPTION' => 'Return approved, awaiting shipment',
'SORT' => 300,
'COLOR' => '#5cb85c',
'NOTIFY' => 'Y',
'TEMPLATE' => 'RETURN_STATUS_APPROVED',
],
[
'ID' => 'RECEIVED',
'NAME' => 'Item received',
'DESCRIPTION' => 'Warehouse received returned item',
'SORT' => 400,
'COLOR' => '#337ab7',
'NOTIFY' => 'Y',
'TEMPLATE' => 'RETURN_STATUS_RECEIVED',
],
[
'ID' => 'REFUND',
'NAME' => 'Refunded',
'DESCRIPTION' => 'Payment processed',
'SORT' => 500,
'COLOR' => '#3c763d',
'NOTIFY' => 'Y',
'TEMPLATE' => 'RETURN_STATUS_REFUND',
],
[
'ID' => 'EXCHANGE',
'NAME' => 'Exchange',
'DESCRIPTION' => 'Instead of refund, exchange made',
'SORT' => 450,
'COLOR' => '#8a6d3b',
'NOTIFY' => 'Y',
'TEMPLATE' => 'RETURN_STATUS_EXCHANGE',
],
[
'ID' => 'REJECTED',
'NAME' => 'Rejected',
'DESCRIPTION' => 'Return rejected',
'SORT' => 600,
'COLOR' => '#a94442',
'NOTIFY' => 'Y',
'TEMPLATE' => 'RETURN_STATUS_REJECTED',
],
];
foreach ($statuses as $statusData) {
$existing = \CSaleOrderReturnStatus::GetByID($statusData['ID']);
if ($existing) {
\CSaleOrderReturnStatus::Update($statusData['ID'], $statusData);
} else {
\CSaleOrderReturnStatus::Add($statusData);
}
}
Step-by-step instructions:
- Define the list of needed statuses, their IDs, colors, and templates.
- Create a script like the example above and execute it during module installation.
- For each status with NOTIFY='Y', create an email notification template in the admin interface (E-Store → Return Statuses → email templates) or programmatically via language files.
- Check the display of statuses in the customer's personal account and admin panel.
Implementing a custom return statuses transition matrix and error protection
Not all transitions between statuses should be allowed. For example, from 'Refunded' you cannot go back to 'Pending Review'. We implement a transition matrix with user role considerations. The custom return statuses transition matrix ensures correct status transitions.
namespace Local\Returns;
class StatusTransitionMatrix
{
private const ALLOWED_TRANSITIONS = [
'WAIT' => ['REVIEW', 'REJECTED'],
'REVIEW' => ['NEED_DOCS', 'APPROVED', 'REJECTED'],
'NEED_DOCS' => ['REVIEW', 'REJECTED'],
'APPROVED' => ['RECEIVED', 'EXCHANGE'],
'RECEIVED' => ['REFUND', 'EXCHANGE'],
'REFUND' => [],
'EXCHANGE' => [],
'REJECTED' => ['WAIT'],
];
private const ADMIN_ONLY = [
'REJECTED' => ['WAIT'],
];
public function canTransition(string $from, string $to, bool $isAdmin = false): bool
{
$allowed = self::ALLOWED_TRANSITIONS[$from] ?? [];
if (!in_array($to, $allowed, true)) return false;
if (isset(self::ADMIN_ONLY[$from]) && in_array($to, self::ADMIN_ONLY[$from], true)) {
return $isAdmin;
}
return true;
}
public function getAvailableTransitions(string $from, bool $isAdmin = false): array
{
$transitions = self::ALLOWED_TRANSITIONS[$from] ?? [];
if (!$isAdmin) {
$adminOnly = self::ADMIN_ONLY[$from] ?? [];
$transitions = array_diff($transitions, $adminOnly);
}
return $transitions;
}
}
One important rule: a manager cannot reject a request after approval, but an administrator can reconsider a rejection. This prevents errors and speeds up processing.
Validating transitions on status change
A handler for the OnBeforeSaleOrderReturnStatusChange event enforces both the transition matrix and mandatory fields. For example, before setting 'Approved', the refund amount must be specified; on rejection, a comment is required.
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
'sale',
'OnBeforeSaleOrderReturnStatusChange',
function (\Bitrix\Main\Event $event) {
$newStatus = $event->getParameter('STATUS_ID');
$return = $event->getParameter('ENTITY');
$oldStatus = $return->getField('STATUS_ID');
$isAdmin = \CUser::IsAdmin();
$matrix = new \Local\Returns\StatusTransitionMatrix();
if (!$matrix->canTransition($oldStatus, $newStatus, $isAdmin)) {
return new \Bitrix\Main\EventResult(
\Bitrix\Main\EventResult::ERROR,
"Transition from '{$oldStatus}' to '{$newStatus}' not allowed"
);
}
if ($newStatus === 'APPROVED' && !$return->getField('REFUND_AMOUNT')) {
return new \Bitrix\Main\EventResult(
\Bitrix\Main\EventResult::ERROR,
"Specify refund amount before approval"
);
}
if ($newStatus === 'REJECTED' && !$return->getField('MANAGER_COMMENT')) {
return new \Bitrix\Main\EventResult(
\Bitrix\Main\EventResult::ERROR,
"Provide a reason when rejecting"
);
}
}
);
Typical mistakes when configuring statuses
A common mistake is to allow all transitions indiscriminately. This leads to confusion and duplicate requests. Another mistake is not setting up notifications for critical statuses (e.g., 'Refunded'). A third is forgetting localization for multilingual stores. We design the custom return statuses transition matrix to eliminate these mistakes at the implementation stage.
Localizing statuses for multilingual stores
For multilingual sites, the status name displayed to the customer is taken from a language file:
// /local/lang/ru/lib/returns/status_labels.php
$MESS['RETURN_STATUS_WAIT'] = 'Ожидает рассмотрения';
$MESS['RETURN_STATUS_REVIEW'] = 'На рассмотрении';
$MESS['RETURN_STATUS_NEED_DOCS'] = 'Требуются документы';
$MESS['RETURN_STATUS_APPROVED'] = 'Одобрен';
$MESS['RETURN_STATUS_RECEIVED'] = 'Товар получен';
$MESS['RETURN_STATUS_REFUND'] = 'Деньги возвращены';
$MESS['RETURN_STATUS_EXCHANGE'] = 'Обмен';
$MESS['RETURN_STATUS_REJECTED'] = 'Отклонён';
// /local/lang/en/lib/returns/status_labels.php
$MESS['RETURN_STATUS_WAIT'] = 'Pending review';
$MESS['RETURN_STATUS_APPROVED'] = 'Approved';
// ...
In the personal account template:
$statusLabel = \Bitrix\Main\Localization\Loc::getMessage(
'RETURN_STATUS_' . $returnStatusId
) ?: $returnStatusId;
Localization gives the customer clear names in their language. We include language files for all supported languages of your store.
What deliverables are included
Our delivery includes comprehensive documentation, setup of user permissions, staff training materials, and one month of post-launch support.
| Stage | Content | Timeline (work days) |
|---|---|---|
| Designing the status set | Business process analysis, status list approval | 2–3 |
| Setup script | Creating/updating statuses via \CSaleOrderReturnStatus |
1 |
| Transition matrix | Implementing StatusTransitionMatrix with role rules |
1–2 |
| Validator | Handler for OnBeforeSaleOrderReturnStatusChange |
1 |
| Email notifications | Templates for each public status | 1–2 |
| Localization | Language files for personal account | 1 |
| Integration with 1C via CommerceML | Additional, on request | +3–5 |
| Documentation and training | Instructions for staff, matrix description | included |
Timeline: from 3 to 7 working days for basic set, up to 2 weeks with 1C integration. Typical project cost ranges from $2,000 to $5,000, offering a quick return on investment through efficiency gains.
Order custom return status configuration — contact us for a cost estimate. Get a consultation from an engineer on return statuses. Over 5+ years, we have implemented 20+ return configuration projects for e-commerce stores of various scales. Our engineers are certified in 1C-Bitrix. We guarantee transparent documentation and post-launch support.
Official 1C-Bitrix documentation: Working with return statuses







