Зачастую мы сталкиваемся с задачами бизнеса которые диктуют свои правила.
К примеру дабы не допустить возможность ошибки со стороны менеджера оформляющего заказ на сайте, вводятся кастомные ошибки уведомляющие его о том что одно или несколько полей были описаны не верно, как этого добиться?

В D7 существует следующий способ:

use Bitrix\Main\Event;
use App\Events\Order;
$eventManager = EventManager::getInstance();
$eventManager->addEventHandler('sale', 'OnSaleOrderBeforeSaved', [Order::class, 'BeforeOrderUpdate']);

Листинг класса Order

namespace App\Events;
use \Bitrix\Main;

class Order
{
    public static function BeforeOrderUpdate(Main\Event $event, $values)
    {
        if (Main\Context::getCurrent()->getRequest()->isAdminSection()) {
            /** @var \Bitrix\Sale\Order $order */
            $order = $event->getParameter("ENTITY");
            $isNew = $event->getParameter("IS_NEW");
            $oldFields = $event->getParameter("VALUES");
            if ($oldFields['STATUS_ID'])
            {
                return self::returnResultError('Недостаточно прав для изменения статуса заказа.', 'SALE_EVENT_ON_BEFORE_ORDER_SAVED_ERROR');
            }

        }
    }

    public static function returnResultError($message, $code = '')
    {
        return new \Bitrix\Main\EventResult(
            \Bitrix\Main\EventResult::ERROR,
            \Bitrix\Sale\ResultError::create(new \Bitrix\Main\Error($message, $code))
        );
    }
}

Давно не писал всяких полезностей и вот случилось недавно разрешить проблему в админке Bitrix, надо было переопределелить стандартную функцию зашитую в ядро, лезть куда конечно же моветон.

Функции обладают возможностью для переопределения поведения. Переопределение происходит с помощью присвоения анонимной функции переменной, которая называется так же, как и переопределяемая функция.

Обработчик навесил на события OnAdminSaleOrderEditDraggable, OnAdminSaleOrderCreateDraggable.
return array("BLOCKSET" => "OrderEdit",
"getScripts" => array('\Events\OrderEdit', "orderScripts"),
);

Сам листинг скрипта
var oldfunc = BX.Sale.Admin.OrderBuyer.showChooseBuyerWindow;
BX.Sale.Admin.OrderBuyer.showChooseBuyerWindow = function (languageId) {
var currentWindow = window.open(
'/local/tools/user_search.php?sessid='+BX.bitrix_sessid()+'&lang='+languageId+'&FN='
+BX.Sale.Admin.OrderEditPage.formId+'&FC=USER_ID',
'',
'scrollbars=yes,resizable=yes,width=840,height=500,top='+Math.floor((screen.height - 840)/2-14)+',left='+Math.floor((screen.width - 760)/2-5)
);
currentWindow.onunload = function(){
setTimeout(function() {
BX.Sale.Admin.OrderAjaxer.sendRequest(
BX.Sale.Admin.OrderEditPage.ajaxRequests.refreshOrderData(),true);
}, 1000);
}
};
//тут к примеру можно вызвать oldfunc, если нужен старый функционал

showChooseBuyerWindow — содержимое воспроизводит родителя, за исключением ссылки на скрипт поиска пользователя, таким образом можно преобразовать любой интересующий вас js представленный в админке, при этом не испытывая особых затруднений при обновлении и расширить стандартный функционал.