Crm 26.1450.0–26.1700.0: права на настройку без админства, белый список обработчиков печати и RequirementProvider
Ломающее обновление
Удалены или изменены публичные API — прикладной код может перестать работать.
В коробочный Битрикс24 пришли четыре версии CRM: 26.1450.0, 26.1500.0, 26.1600.0 и 26.1700.0. Настройку CRM можно раздать по семи правам, а RequirementProvider возвращает стадии, на которых поле обязательно. Обновление закрывает дыры в правах, но сначала проверьте обработчики печати и оплаты, копии шаблонов и вызовы canEditCommonView().
Новое
Раздайте настройку CRM без админства (26.1600.0)
У CRM и у каждого цифрового рабочего места в ролевой модели появились семь операций: воронки, стадии, поля, удаление полей, общие представления, шаблоны БП и типы смарт-процессов. Флага нет, полное право на настройку стоит над ними как суперправо. Их спрашивают CCrmStatus::Check*Permission, REST crm.dealcategory.* и crm.type.*, crm.entity.editor, crm.kanban и страницы полей и БП.
Своя страница настроек с проверкой isCrmAdmin() не пустит того, кому штатный интерфейс настройку разрешил. Методы UserPermissions::configuration() ждут ConfigurationCallSite, перечень штатных точек проверки, а класс Configuration помечен @internal. Для общих представлений есть entityEditor()->canEditCommonView().
Разрешите наблюдателям редактировать (26.1600.0)
Право «Изменение наблюдателями» (OBSERVERS_WRITE) появилось у сделок, лидов, контактов, компаний, смарт-процессов и смарт-счетов, а где есть стадии, оно задаётся по стадиям. Наблюдатель карточки сможет её менять, даже если роль записи не даёт.
Изначально право выключено, даже в пресете «полный доступ».
Спросите, на каких стадиях поле обязательно (26.1700.0)
RequirementProvider из V2\Public отдаёт настройку «обязательно со стадии» без ручного разбора атрибутов поля. Нужно право «Управление полями». Чтение идёт без кеша и не создаёт ни стадий, ни настроек полей.
<?php declare(strict_types=1);
use Bitrix\Crm\V2\Public\Entity\Field\RequirementException;
use Bitrix\Crm\V2\Public\Entity\Field\RequirementMode;
use Bitrix\Crm\V2\Public\EntityType;
use Bitrix\Crm\V2\Public\Provider\Field\RequirementProvider;
use Bitrix\Main\Engine\CurrentUser;
use Bitrix\Main\Loader;
Loader::requireModule('crm');
function describeDealFieldRequirement(string $fieldId, int $categoryId, int $userId): string
{
try {
$requirement = RequirementProvider::forEntityType(EntityType::deal(), $userId)
->get($fieldId, $categoryId);
} catch (RequirementException $e) {
return 'Нет ответа: ' . $e->getError()->value; // ACCESS_DENIED, FIELD_NOT_FOUND…
}
if ($requirement->isGloballyRequired()) {
return 'Обязательно всегда';
}
return match ($requirement->getMode()) {
RequirementMode::All => 'Обязательно на всех стадиях',
RequirementMode::Stages => 'Обязательно на стадиях: ' . implode(', ', $requirement->getRequiredStageIds()),
RequirementMode::None => 'Не обязательно',
};
}
echo describeDealFieldRequirement('UF_CRM_CONTRACT_NO', 0, (int)CurrentUser::get()->getId());
Реквизиты получили в 26.1600.0 свой RequisiteProvider и команды вроде AddRequisiteCommand. На запрет провайдер отвечает тем же NotFoundException, что и на отсутствие записи.
Роботы, письма, документы
Робот «Создать реквизит» (CrmCreateRequisiteActivity, 26.1600.0) возвращает RequisiteId, Status (created, found или error) и ErrorMessage. Пока выключен флаг CreateRequisiteBizprocActivity, робота не видно.
В редакторе почтовых шаблонов crm.mail_template.editor (26.1700.0) есть вложения с Диска, плейсхолдеры и CoPilot. Ссылку на него строит MailTemplateEditorProvider::getCreateUrl($siteId), доступ проверяет isAvailable($userId).
В генераторе документов у товара появились вес и габариты (WEIGHT, LENGTH, WIDTH, HEIGHT), у платежа и отгрузки TOTAL_WEIGHT (26.1700.0).
REST 3.0 растёт за флагами
За флагом RestV3CrudDeal в 26.1500.0–26.1600.0 добавились адреса и реквизиты, aggregate, пользовательские поля field.custom.*, справочники crm.dictionary.* и раскладки карточки detailPageLayout.*. За RestV3WebForm с 26.1500.0 живёт CRUD веб-форм crm.form.*, в 26.1700.0 к нему добавились activate, deactivate и validate. С 26.1600.0 crm.form.update ждёт updatedTime, с 26.1700.0 удаление активной формы ждёт confirmed: true. Оба флага выключены, включение на стенде показано в прошлом разборе.
Что заметят пользователи
- «Недавние клиенты» в селекторах разложены по разделам: классическая CRM, каждое цифровое рабочее место, свои компании (26.1500.0).
- AI-заполнение полей выключается для типа сущности, отдельные поля можно из него исключить (26.1500.0).
- Канбан смарт-процессов, предложений и смарт-документов после сброса фильтра показывает финальные стадии (26.1700.0).
Что сломается
Перенесите свои обработчики печати и оплаты (26.1500.0)
Печать предложений и старых счетов CRM принимает только белый список: семь штатных quote_br...quote_ua из /bitrix/php_interface/include/sale_payment/ и девять bill...billua из /bitrix/modules/sale/handlers/paysystem/. Для оплаты подходят системный обработчик из /bitrix/modules/sale/handlers/paysystem/<code>/handler.php или REST-обработчик. Свои шаблоны печати, обработчики в /local/php_interface/include/sale_payment/ и кастомные платёжки на публичной странице оплаты счёта отклоняются с COULD NOT FIND PAYMENT SYSTEM ACTION FILE! или CRM_PAYSYSTEM_HANDLER_NOT_ALLOWED.
Пересоберите копии шаблонов
Из crm в 26.1500.0 удалено 469 PNG, штатные CSS и шаблоны ссылаются на новые WebP. Копии шаблонов и стилей crm.* со ссылками на *.png получат 404.
crm.deal_category.list, crm.config.measure.list, crm.currency.list и crm.config.locations.list.v2 переписаны на гриды V2 (26.1600.0), и копии их шаблонов перестанут работать. У crm.deal_category.list удалены component.php, ajax.php и script.js шаблона, в arResult другие ключи (grid, GRID_ID, CATEGORY_COUNT, QUANTITY_LIMIT).
Поле бронирования ресурсов в CRM-форме с 26.1450.0 отправляет серверу sourceType: 'crm-webform', formId, sec и fieldCode, а шаблон crm.webform.fill передаёт в JS 'sec' => $arParams['SECURITY_CODE'] ?? ''. В копии шаблона без sec и в своих формах с бронированием слоты окажутся пустыми.
Серверную половину фикса в calendar мы разобрали отдельно.
Проверьте код вокруг прав на настройку (26.1600.0)
EntityEditor::canEditCommonView(?int $entityTypeId, ?int $categoryId) требует оба аргумента, без них будет ArgumentCountError. Если карточки нет, передавайте null, право проверится для всей CRM:
<?php declare(strict_types=1);
use Bitrix\Crm\Service\Container;
use Bitrix\Main\Loader;
Loader::requireModule('crm');
$userId = (int)\Bitrix\Main\Engine\CurrentUser::get()->getId();
$categoryId = 0;
$editor = Container::getInstance()->getUserPermissions($userId)->entityEditor();
$canEditDealCard = $editor->canEditCommonView(\CCrmOwnerType::Deal, $categoryId);
$canEditAnyCard = $editor->canEditCommonView(null, null);
Удалён публичный Kanban::isCrmAdmin(). crm.kanban заполняет $arResult['ACCESS_CONFIG_PERMS'] по праву на стадии воронки. Проверьте кастомные шаблоны канбана и наследников Kanban.
CCrmStatus::Update() при ошибке StatusTable::update возвращает false, раньше возвращал $ID.
Колл-листы видят только автор и админ (26.1500.0, 26.1600.0)
REST crm.calllist.list показывает не-админу только его списки. select, filter и order принимают лишь ID, DATE_CREATE, CREATED_BY_ID, WEBFORM_ID и ENTITY_TYPE_ID, а start=-1 больше не снимает лимит. С 26.1600.0 CallList::createWithId() по умолчанию бросает SystemException('Access Denied', 403) всем, кроме автора и админа, а crm.calllist.items.get на чужой список отвечает «Call list is not found».
Передайте gridId в действия панели грида (26.1500.0)
У всех Component\EntityList\Grid\Panel\Action\* в конструкторе появился обязательный string $gridId, местами в середине списка параметров. Id элементов панели получили суффикс грида (action_assigned_by_id_<gridId>), и JS, который ищет их по старым id, ничего не найдёт. У абстрактного FrontIntegration::onClickAddHandler() добавился параметр array $analyticsContext = [], наследник со старой сигнатурой упадёт с фаталом.
Проверьте остальное
ActivityTable(26.1500.0):RESULT_VALUEсталfloat, и строго типизированный код, который ждётint, упадёт.PROVIDER_PARAMSбольше не'serialized' => trueи читается черезunserialize()сallowed_classes => false, объекты внутри станут__PHP_Incomplete_Class.Activity\Mail\Message::getSignature($email, $name)(26.1700.0) берёт подписи из\Bitrix\Main\Mail\Sender::prepareUserMailboxesWithSignatures(), а в main 26.800.0 такого метода нет. Пока main не обновится,getSignature()отдаёт пустую строку для любого адреса, а уgetSenderList()пустое полеsignature. С новым main пустая строка останется для адреса, которого нет среди отправителей пользователя. Protected-хелперыgetGeneralSignature(),loadSignatureMap(),resolveSignature()иresolveSignatureTemplate()удалены.Visit::getVkProfile()удалён (26.1700.0),crm.activity.visitбольше не сохраняетVK_PROFILEв мультиполеWEB/VK.- Сопоставление пользовательских полей при конвертации пересобрано (26.1700.0): совместимость сверяется по значимым настройкам вроде min/max и regexp, значения списков переносятся по тексту, старые карты конвертации пересчитываются. Из лида могут переходить другие поля.
Закрытые дыры
- 26.1450.0: анонимный эндпоинт бронирования считал занятость по присланной клиентом конфигурации.
- 26.1500.0: печать подключала
payment.phpпоACTION_FILEбез проверки; коррекцию чека мог провести любой авторизованный;crm.calllist.listотдавал чужие списки;RequisiteLink::listAction()не проверял владельца;PROVIDER_PARAMSдел десериализовался с объектами. - 26.1600.0: очистка HTML в
crm.invoice.add/updateне работала;crm.calllist.items.getне проверял владельца; групповые действия задевали нечитаемые элементы. - 26.1700.0: подписи «Да» и «Нет» булевых полей выводились в HTML без экранирования.
Deprecated
Activity\Mail\Message::getSignature()(26.1700.0). Замена —Message::getSenderList(), плоский список отправителей CRM с полемsignature. Полный список даст\Bitrix\Main\Mail\Sender::prepareUserMailboxesWithSignatures(), когда метод появится в main.Attribute\FieldAttributeManager::processPhaseModification()ничего не делает (26.1500.0), диапазоны «обязательно со стадии» менеджер пересчитывает сам.Copilot\CallScriptMaintenance\Dispatcher::SYSTEM_USER_ID, жёсткую единицу, заменяетgetSystemUserId()(26.1500.0).
БД
b_crm_ai_field_fill_exclusion(26.1500.0): поля, исключённые из AI-заполнения, по одной строке наUSER_FIELD_ID. Строки удалённого поля чистит обработчикmain:OnAfterUserTypeDelete.b_crm_call_list: индексIX_B_CRM_CALL_LIST_CREATED_BY_ID_ID (CREATED_BY_ID, ID)под фильтр по автору (26.1500.0).- Новая колонка
b_crm_webform.DATE_MODIFY(26.1600.0) при каждом обновлении формы без явного значения становится текущим временем, а если оно не больше прежнего, прибавляет секунду. Это значениеcrm.form.updateждёт вupdatedTime. b_crm_automated_solution(26.1600.0):VIBE_ID,IS_VIBE_ENABLEDиVIBE_CREATION_TOKENдля стартовой страницы цифрового рабочего места на Landing Vibe, за флагомAutomatedSolutionVibe.
Мелочи и находки
- Загрузчик
crm.site.form.jsберёт ключ кэша изappVersion, времени изменения бандла, поэтому новая форма доходит до внешних сайтов сразу после обновления, а не через сутки (26.1450.0). - Фильтр «Лид закрыт» в канбане раньше всегда давал
!STATUS_SEMANTIC_ID = P, в 26.1700.0 его починили.
Устаревшие и удалённые API в этой версии
| Символ | Статус | Чем заменять |
|---|---|---|
Bitrix\Crm\Activity\Mail\Message::getSignature()
|
Deprecated |
Bitrix\Crm\Activity\Mail\Message::getSenderList()
|
Bitrix\Crm\Attribute\FieldAttributeManager::processPhaseModification()
|
Deprecated | — |
Bitrix\Crm\Copilot\CallScriptMaintenance\Dispatcher::SYSTEM_USER_ID
|
Deprecated |
Bitrix\Crm\Copilot\CallScriptMaintenance\Dispatcher::getSystemUserId()
|
Bitrix\Crm\Kanban::isCrmAdmin()
|
Удалено | — |
Bitrix\Crm\Activity\Provider\Visit::getVkProfile()
|
Удалено | — |
Bitrix\Crm\Feature\Entity\FeatureRepository::getById()
|
Удалено |
Bitrix\Crm\Feature\Entity\FeatureRepository::has(), Bitrix\Crm\Feature\Entity\FeatureRepository::isEnabled()
|
Bitrix\Crm\Stage\DefaultProcessColorGenerator
|
Удалено |
Bitrix\Crm\Stage\DefaultColorGenerator
|
Bitrix\Crm\V2\Public\Command\Address\SetLeadAddressCommand
|
Удалено |
Bitrix\Crm\V2\Public\Command\Address\SaveAddressCommand
|
Bitrix\Crm\V2\Public\Command\Address\DeleteLeadAddressCommand
|
Удалено |
Bitrix\Crm\V2\Public\Command\Address\DeleteAddressCommand
|
Bitrix\Crm\V2\Public\Provider\Address\LeadAddressProvider
|
Удалено |
Bitrix\Crm\V2\Public\Provider\Address\EntityAddressProvider
|
Bitrix\Crm\V2\Public\Entity\Address\LeadAddress
|
Удалено |
Bitrix\Crm\V2\Public\Entity\Address\Address
|