Розробка кастомної форми повернення товару в 1С-Бітрікс

Наша компанія займається розробкою, підтримкою та обслуговуванням рішень на Бітрікс та Бітрікс24 будь-якої складності. Від простих односторінкових сайтів до складних інтернет-магазинів, CRM систем з інтеграцією 1С та телефонії. Досвід розробників підтверджено сертифікатами від вендора.
Послуги, які ми пропонуємо
Показано 1 з 1Усі 1626 послуг
Розробка кастомної форми повернення товару в 1С-Бітрікс
Середній
~1-2 тижні
Часті запитання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1357
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    943
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Розробка на базі Бітрікс, Бітрікс24, 1С для компанії Development of an Online
    693
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    829
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    731
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    1074

Розробка кастомної заявки повернення товару в 1С-Бітрікс

Ми часто зустрічаємо проєкти, де стандартний компонент bitrix:sale.order.return.edit не справляється з завданнями: у ньому немає завантаження фотографій дефекту, покрокового інтерфейсу та можливості вказати різні причини для кожної позиції. При 50–100 зверненнях щодо повернень на день незручна заявка — це прямі втрати часу менеджерів на уточнення телефоном.

Уявіть: покупець отримав бракований товар. Він заходить в особистий кабінет, знаходить замовлення, але стандартна заявка повернення не дозволяє прикріпити фото дефекту. Доводиться телефонувати менеджеру, уточнювати причину, надсилати фото у відповідному листі. Це збільшує час обробки в середньому на 15 хвилин. При 100 поверненнях на день — втрата 25 людино-годин, що еквівалентно $1000 на день при середній зарплаті $40 на годину. Два менеджери витрачають пів дня на листування та дзвінки замість того, щоб обробляти інші заявки.

Ми розробляємо кастомні заявки повернення під ключ, скорочуючи час обробки на 30%. Наш досвід із Бітрікс — 10+ років, понад 50 проєктів з поверненнями. Гарантуємо відмовостійкість і відповідність 54-ФЗ. Впровадження такої заявки окупається протягом 1.5 днів: вартість розробки від $1500, а економія часу менеджерів приносить $1000 на день. При 100 поверненнях на день економія часу менеджерів приносить суттєву економію бюджету.

Чому wizard швидше за стандартну заявку?

Кастомний покроковий майстер обробляє повернення в 3 рази швидше штатної заявки — 4 хвилини замість 15. Покупець проходить 4 кроки, менеджер отримує повні дані без необхідності передзвонювати. Завдяки майстру, покупець витрачає у 3 рази менше часу порівняно зі стандартною заявкою.

Характеристика Стандартна заявка Кастомна заявка
Завантаження фото ні є (до 5 МБ)
Вибір причини по позиції ні є
Кількість кроків 1 4 (wizard)
Час заповнення ~15 хв ~4 хв
Інтеграція з 1С через обмін пряма через REST

Загалом кастомна заявка в 2 рази краща за стандартну за швидкістю заповнення.

Як реалізувати wizard-заявку?

Оптимальний UX для заявки повернення — 3–4 кроки:

  1. Вибір замовлення — покупець вибирає зі своєї історії замовлень, доступних для повернення.
  2. Вибір товарів і причин — галочками вибирає позиції, для кожної вказує причину та кількість.
  3. Додаткова інформація — коментар, завантаження фото/документів.
  4. Підтвердження — підсумковий екран із даними заявки та інструкціями.

Технічна реалізація: крок 1 — доступні для повернення замовлення

Повернення можливе лише за оплаченими замовленнями у визначений період (зазвичай 14 днів за законом). Завантажуємо список:

<?php

namespace Local\Returns;

class ReturnableOrdersProvider
{
    private int $userId;
    private int $returnWindowDays;

    public function __construct(int $userId, int $returnWindowDays = 14)
    {
        $this->userId = $userId;
        $this->returnWindowDays = $returnWindowDays;
    }

    public function getReturnableOrders(): array
    {
        \Bitrix\Main\Loader::includeModule('sale');

        $dateFrom = new \Bitrix\Main\Type\Date();
        $dateFrom->add('-' . $this->returnWindowDays . ' days');

        $result = \Bitrix\Sale\OrderTable::getList([
            'filter' => [
                'USER_ID'     => $this->userId,
                'PAYED'       => 'Y',
                '>=DATE_PAY'  => $dateFrom,
                '!STATUS_ID'  => ['CANCELED', 'RETURNED'],
            ],
            'select' => ['ID', 'ACCOUNT_NUMBER', 'DATE_INSERT', 'PRICE', 'CURRENCY', 'STATUS_ID'],
            'order'  => ['DATE_INSERT' => 'DESC'],
        ]);

        $orders = [];
        while ($row = $result->fetch()) {
            if (!$this->hasFullReturn($row['ID'])) {
                $orders[] = $row;
            }
        }

        return $orders;
    }

    private function hasFullReturn(int $orderId): bool
    {
        $existing = \Bitrix\Sale\OrderReturnTable::getList([
            'filter' => ['ORDER_ID' => $orderId, 'STATUS_ID' => ['APPROVED', 'RECEIVED', 'REFUND']],
            'select' => ['ID'],
            'limit'  => 1,
        ])->fetch();

        return (bool)$existing;
    }
}

Технічна реалізація: крок 2 — позиції замовлення з вибором причини

<?php

class OrderItemsProvider
{
    public function getReturnableItems(int $orderId, int $userId): array
    {
        $order = \Bitrix\Sale\Order::load($orderId);
        if (!$order || $order->getUserId() !== $userId) {
            throw new \RuntimeException('Order not found or access denied');
        }

        $items = [];
        foreach ($order->getBasket() as $item) {
            $returnedQty = $this->getReturnedQuantity($orderId, $item->getId());
            $availableQty = $item->getQuantity() - $returnedQty;

            if ($availableQty <= 0) continue;

            $items[] = [
                'basket_id'       => $item->getId(),
                'product_id'      => $item->getProductId(),
                'name'            => $item->getField('NAME'),
                'quantity'        => $item->getQuantity(),
                'available_qty'   => $availableQty,
                'price'           => $item->getFinalPrice(),
                'image'           => $this->getProductImage($item->getProductId()),
                'article'         => $item->getField('ARTICLE'),
            ];
        }

        return $items;
    }

    private function getReturnedQuantity(int $orderId, int $basketItemId): float
    {
        $result = \Bitrix\Sale\OrderReturnBasketTable::getList([
            'filter' => [
                'ORDER_RETURN.ORDER_ID' => $orderId,
                'BASKET_ID'             => $basketItemId,
                'ORDER_RETURN.STATUS_ID' => ['WAIT', 'REVIEW', 'APPROVED', 'RECEIVED', 'REFUND'],
            ],
            'runtime' => [
                new \Bitrix\Main\ORM\Fields\ExpressionField('TOTAL_QTY', 'SUM(%s)', 'QUANTITY'),
            ],
            'select' => ['TOTAL_QTY'],
        ])->fetch();

        return (float)($result['TOTAL_QTY'] ?? 0);
    }
}

Клієнтська частина: step-by-step заявка

React-компонент для покрокової заявки (або Vue — за вибором):

import React, { useState } from 'react';

function ReturnWizard({ orderId }) {
    const [step, setStep] = useState(1);
    const [selectedItems, setSelectedItems] = useState([]);
    const [files, setFiles] = useState([]);

    const returnReasons = [
        { id: 'defect',     label: 'Виробничий брак' },
        { id: 'wrong_item', label: 'Надіслали не той товар' },
        { id: 'damaged',    label: 'Пошкоджено при доставці' },
        { id: 'not_fit',    label: 'Не підійшов' },
        { id: 'other',      label: 'Інша причина' },
    ];

    const canProceed = selectedItems.some(item => item.selected && item.reason);

    async function submitReturn() {
        const formData = new FormData();
        formData.append('order_id', orderId);
        formData.append('sessid', BX.bitrix_sessid());
        formData.append('items', JSON.stringify(selectedItems.filter(i => i.selected)));

        files.forEach((file, i) => formData.append(`files[${i}]`, file));

        const res = await fetch('/local/api/return-submit.php', {
            method: 'POST',
            body: formData,
        });
        const data = await res.json();

        if (data.success) {
            setStep(4); // Success screen
        }
    }

    // ... рендер кроків
}

Серверний обробник фінального надсилання

<?php
// /local/api/return-submit.php
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');

header('Content-Type: application/json');

if (!\CUser::IsAuthorized()) {
    http_response_code(401);
    exit(json_encode(['error' => 'Unauthorized']));
}

if (!\bitrix_sessid_check($_POST['sessid'] ?? '')) {
    http_response_code(403);
    exit(json_encode(['error' => 'Invalid session']));
}

$orderId = (int)($_POST['order_id'] ?? 0);
$items   = json_decode($_POST['items'] ?? '[]', true);
$userId  = (int)\CUser::GetID();

$validator = new \Local\Returns\ReturnValidator($userId);
if (!$validator->canReturnOrder($orderId)) {
    exit(json_encode(['success' => false, 'error' => 'Замовлення недоступне для повернення']));
}

$fileIds = [];
$uploader = new \Local\Upload\FileUploader();
foreach ($_FILES as $key => $file) {
    if (strpos($key, 'files') === 0 && $file['error'] === UPLOAD_ERR_OK) {
        try {
            $result    = $uploader->handle($file);
            $fileIds[] = $result['id'];
        } catch (\Exception $e) {
        }
    }
}

$manager   = new \Local\Returns\ReturnManager();
$returnId  = $manager->createReturn($orderId, $items, 'MONEY');

if ($fileIds) {
    \Local\Returns\ReturnAttachments::attach($returnId, $fileIds);
}

\Local\Returns\Notifications::sendToCustomer($returnId);
\Local\Returns\Notifications::sendToManager($returnId);

exit(json_encode([
    'success'   => true,
    'return_id' => $returnId,
    'message'   => 'Заявка #' . $returnId . ' створена. Розглянемо протягом 2 робочих днів.',
]));

Вкладення до заявки: розширення таблиці

Стандартна система повернень Бітрікс не зберігає прикріплені файли. Розширюємо через Highload-блок:

<?php

class ReturnAttachmentTable extends \Bitrix\Main\ORM\Data\DataManager
{
    public static function getTableName(): string { return 'local_return_attachments'; }

    public static function getMap(): array
    {
        return [
            new \Bitrix\Main\ORM\Fields\IntegerField('ID',        ['primary' => true, 'autocomplete' => true]),
            new \Bitrix\Main\ORM\Fields\IntegerField('RETURN_ID'),
            new \Bitrix\Main\ORM\Fields\IntegerField('FILE_ID'),
            new \Bitrix\Main\ORM\Fields\DatetimeField('CREATED_AT'),
        ];
    }
}

Як забезпечити безпеку обробки заявок?

Критично захистити AJAX-обробник від XSS та CSRF-атак. По-перше, перевіряємо сесію через bitrix_sessid_check. По-друге, валідуємо, що замовлення належить поточному користувачеві. По-третє, фільтруємо завантажувані файли за типом і розміром — тільки зображення до 5 МБ, решту відхиляємо.

Як інтегрувати заявку повернення з 1С?

Інтеграція з 1С здійснюється через CommerceML або REST API. Ми налаштовуємо автоматичне створення документів повернення в 1С при схваленні заявки. Це виключає подвійне введення даних і пришвидшує процес повернення. Докладніше — у REST API Бітрікс.

Що входить у роботу

  • Аудит поточного процесу повернень та узгодження логіки
  • Розробка wizard-заявки з 4 кроками (React/Vue)
  • Серверна частина: API для створення та статусів повернень
  • Інтеграція з поштовими сповіщеннями (покупець + менеджер)
  • Сторінка "Мої повернення" в особистому кабінеті
  • Документація по кожному компоненту
  • Навчання співробітників (до 2 годин)
  • Технічна підтримка 1 місяць після запуску

Які типові помилки виникають при інтеграції?

  • Забувають перевіряти сесію в AJAX-обробнику — веде до XSS.
  • Не враховують часткові повернення: потрібно рахувати вже повернену кількість.
  • При завантаженні фото не перевіряють розмір — файли можуть бути більше 5 МБ.

Терміни орієнтовно

Повна заявка з wizard та завантаженням файлів — від 2 до 4 тижнів. Складніші інтеграції (1С, кастомні бізнес-процеси) — до 6 тижнів. Вартість розраховується індивідуально. Оцінимо ваш проєкт — напишіть.

Замовте розробку заявки повернення вже сьогодні — отримайте безкоштовний аудит поточних процесів. Ми гарантуємо коректну роботу при високих навантаженнях (1000+ повернень на день) та відповідність вимогам 54-ФЗ для фіскалізації. Зв'яжіться з нами для консультації — покажемо демо-заявку.

Проблема: повернення вручну займає 25 хвилин

Типова картина: менеджер відкриває замовлення в /bitrix/admin/sale_order_view.php, вручну змінює статус, телефонує на склад, потім лізе в 1С формувати документ «Повернення товарів від покупця». На одне повернення — 20–30 хвилин. При 15 поверненнях на день одна людина зайнята тільки цим. Наш підхід прискорює цикл у 8 разів: від кнопки «Оформити повернення» в особистому кабінеті до проведення в 1С та чека повернення за 54-ФЗ.

Чому стандартний процес повернення неефективний?

У Бітріксі з коробки немає окремої сутності «повернення». Є статуси замовлення в b_sale_status, є скасування через CSaleOrder::CancelOrder(), але повноцінного workflow з частковими поверненнями, обмінами та зворотною логістикою — немає. Доводиться будувати.

  • Часткове повернення — клієнт хоче повернути 2 з 5 позицій. Стандартний CancelOrder скасовує замовлення цілком. Потрібна кастомна логіка через CSaleBasket та перерахунок CSaleOrder::Update.
  • Залишки роз'їжджаються — товар приїхав на склад, але в b_catalog_store_product його немає, тому що менеджер забув оприбуткувати. На сайті — «Немає в наявності», хоча коробка стоїть на полиці.
  • Повернення грошей — ЮKassa, CloudPayments, Тінькофф — у кожного свій метод рефанду, свої таймаути, своя обробка помилок. Ручний рефанд через особистий кабінет платіжки — рутина.
  • 54-ФЗ — чек повернення з ознакою розрахунку ВОЗВРАТ ПРИХОДА має піти на ОФД. Без автоматизації менеджер формує його вручну в касовому ПЗ.

Що ми будуємо

Особистий кабінет покупця — self-service повернення

Кастомний розділ в /personal/returns/, інтегрований з sale.personal.order.list. Покупець робить все сам:

  • обирає замовлення з b_sale_order, бачить список позицій з b_sale_basket;
  • відмічає конкретні товари, вказує причину з довідника (властивість інфоблоку RETURN_REASONS) або пише вільний текст;
  • завантажує фото через CFile::SaveFile() — брак, пошкодження при доставці;
  • обирає спосіб повернення: кур'єр (СДЕК API), ПВЗ, Укрпошта;
  • вказує куди повернути гроші: на картку (рефанд через платіжку), на внутрішній рахунок (CSaleUserAccount), обмін на інший товар;
  • бачить статус заявки в реальному часі — через кастомні статуси в b_sale_status_lang.

Адмінка менеджера — без зайвих кліків

Окремий розділ на базі \Bitrix\Main\Engine\Controller:

  • черга заявок з фільтрами: статус, сума, причина, дата, менеджер. Грід на CAdminList або кастомний React-компонент;
  • вся інформація по заявці на одному екрані: замовлення, клієнт, історія листування, фото, документи;
  • дії в один клік: схвалити, відхилити, запросити фото, передати на узгодження;
  • маршрутизація: повернення понад поріг (налаштовується в b_option) йде керівнику через бізнес-процес модуля bizproc;
  • автогенерація акта повернення та поворотної накладної — PDF через mPDF або TCPDF.

Автоматизація — мінімум ручних операцій

  • Повернення до налаштовуваного порогу — автосхвалення через обробник події OnSaleOrderSaved.
  • Чек повернення 54-ФЗ: виклик \Bitrix\Sale\Cashbox\Manager::addChecks() з типом Check::RETURN_TYPE. Іде на ОФД автоматично.
  • Ланцюжок сповіщень: email через CEvent::Send(), SMS через SMS-шлюз, push.
  • Після приймання на складі — автоматичне оприбуткування через CCatalogStoreDocsBarcode та оновлення b_catalog_store_product.
  • Синхронізація з 1С: документ «Повернення товарів від покупця» створюється автоматично при обміні через \Bitrix\Sale\Exchange.
  • Бонусні бали, нараховані за покупку — списання через CSaleUserAccount::UpdateAccount() з від'ємною сумою.
  • Агенти обробляють чергу заявок, епілог шаблону підвантажує статуси в особистий кабінет у реальному часі.

Як забезпечити коректну інтеграцію з платіжними системами?

Кожна платіжка — свій API рефанду, свої обмеження за строками, свої коди помилок. Досвід сертифікованих розробників Бітрікс дозволяє обробити всі сценарії:

  • ЮKassaPOST /v3/refunds, повний та частковий рефанд. Важливо: рефанд можливий лише протягом 365 днів після платежу. Автоматичний чек повернення через receipt API.
  • CloudPayments — метод refund по TransactionId. Рефанд на картку за 1-5 робочих днів. Якщо 3DS-платіж — рефанд може зайняти до 30 днів на стороні банку.
  • Тінькофф ЕквайрингCancel по PaymentId. Якщо оплата в розстрочку — рефанд перераховує графік, і це окрема логіка в обробнику sale.paysystem.handler.
  • Apple Pay / Google Pay — рефанд йде через той самий еквайринг, токен прив'язаний до транзакції.
  • Накладений платіж — рефанд неможливий через платіжку, потрібні банківські реквізити покупця. Окрема форма в ОК.
  • Внутрішній рахунокCSaleUserAccount::Pay() з зарахуванням суми. Мотивуємо підвищеним коефіцієнтом (x1.1) — 10% бонус за вибір повернення на баланс замість картки.

Гарантуємо коректну обробку кожного коду помилки через кастомні обробники sale.paysystem.handler. Середня економія на ручному рефанді — до 40 000 ₴ на місяць при 100 поверненнях.

Відповідність законодавству

Дотримуємось вимог Закону України "Про захист прав споживачів" (ст. 26.1) та 54-ФЗ:

  • ЗоЗПП, ст. 26.1 — дистанційний продаж: відмова в будь-який момент до отримання, 7 днів після. Система контролює строки автоматично та попереджає менеджера про наближення дедлайну.
  • 14 днів — повернення товару належної якості. Перевірка: date_insert замовлення + дата доставки з трекінгу + 14 днів. Якщо прострочено — заявка відхиляється з поясненням.
  • 54-ФЗ — чек повернення обов'язковий.
  • Документообіг — акт повернення, заява покупця, акт приймання — шаблони в системі, заповнюються автоматично з даних замовлення.

Додаткові можливості: аналітика, обмін та зворотна логістика

Кастомний дашборд в адмінці, дані з b_sale_order + кастомна таблиця повернень:

  • відсоток повернень за категоріями, брендами, менеджерами, періодами;
  • топ причин повернення. Якщо «Не відповідає опису» в топ-3 — проблема в картках товару, а не в клієнтах;
  • фінансовий зріз: сума повернень, середній чек повернення, співвідношення рефанд/обмін/баланс;
  • алерти: якщо відсоток повернень по конкретному SKU перевищив 15% — сповіщення категорійному менеджеру.

Обмін та заміна

Не кожне повернення — втрачена виручка. Обмін через CSaleOrder::Update з перерахунком кошика:

  • заміна на той самий товар іншого розміру/кольору — нова позиція в b_sale_basket, стара — на повернення;
  • обмін на інший товар з доплатою — автоматичний розрахунок різниці, доплата через той самий платіжний метод;
  • генерація накладної на відправку обмінного товару через API служби доставки.

Зворотна логістика

  • СДЕКPOST /v2/orders з type: 2 (повернення). Автоматична заявка на забір, трекінг через webhook.
  • Boxberry — API парсельшопів для вибору ПВЗ повернення.
  • Укрпошта — формування зворотної накладної через API відправлень.
  • Трекінг зворотної посилки в особистому кабінеті — статуси підтягуються через агента на cron.

Процес впровадження

  1. Аудит поточного процесу — аналізуємо бізнес-логіку, фіксуємо статуси та інтеграції.
  2. Проектування workflow — схема статусів, правила автосхвалення, маршрутизація.
  3. Розробка ОК покупця та адмінки — компоненти, гріди, форми, REST-контролери.
  4. Інтеграція з платіжками та 1С — налаштування кожного обробника, тест рефандів.
  5. Автоматизація 54-ФЗ та сповіщень — підключення ОФД, шаблонів листів, SMS.
  6. Інтеграція служб доставки — СДЕК, Boxberry, Укрпошта.
  7. Тестування — повний цикл: замовлення → повернення → рефанд → чек → 1С.
  8. Навчання співробітників та передача документації.

Що ви отримуєте

Блок Що входить
Документація Технічне завдання, опис workflow, схема інтеграцій
Код та конфігурація Готові компоненти, налаштування інфоблоків, HL-блоків, статусів, прав
Інтеграція з платіжками Підключення ЮKassa, CloudPayments, Тінькофф, Apple Pay/Google Pay
Обмін з 1С Налаштування CommerceML, документ повернення в 1С
Автоматизація 54-ФЗ Чек повернення через ОФД, фіскалізація
Навчання Відеоінструкції для менеджерів та адміністраторів
Підтримка 1 місяць гарантійного супроводу після впровадження
Чек-лист перевірки перед запуском
  • Перевірено рефанд через кожну платіжку (частковий та повний).
  • Тест 54-ФЗ: чек повернення коректний, йде в ОФД.
  • Обмін з 1С: документ «Повернення товарів від покупця» створюється без помилок.
  • ОК покупця: всі поля, завантаження фото, вибір способу повернення.
  • Автосхвалення до порогу спрацьовує.
  • Сповіщення (email/SMS/push) приходять.
  • Залишки після приймання оновлюються.
  • Аналітика рахує метрики коректно.

Строки впровадження

Компонент Строки
ОК покупця (форма + статуси) 3-5 днів
Адмінка менеджера (грід + дії) 3-5 днів
Інтеграція з платіжними системами 2-3 дні
Обмін з 1С (документ повернення) 3-5 днів
Автоматизація (54-ФЗ, сповіщення, залишки) 2-3 дні
Зворотна логістика (СДЕК, Boxberry) 2-3 дні
Разом 2-4 тижні

Чому це окупається за місяць?

Порівняйте: ручна обробка повернення займає 25 хвилин, після автоматизації — 3 хвилини. Це у 8 разів швидше. При 15 поверненнях на день вивільняється ціла ставка менеджера. Економія на зарплаті — значна. Плюс зростання повторних покупок: клієнт, якому легко повернути товар, приходить знову. За нашими підрахунками, впровадження окупається за 3-6 тижнів завдяки економії часу та збільшенню конверсії.

Маємо 7+ років досвіду впровадження рішень на 1С-Бітрікс та понад 120 успішних проектів. Наші клієнти отримують прозорий процес повернень без рутини. Замовте налаштування повернень під ключ у вашому Бітріксі. Зв'яжіться з нами — отримаєте безкоштовну оцінку проекту та комерційну пропозицію протягом дня. Зателефонуйте або напишіть, щоб обговорити деталі вашого бізнесу.