DarkRiDDeR15 мин

Миграция Bitrix-поля: проверить сохранение, чтение и обратимость

BitrixДанные

Проблема миграции Bitrix-поля проявляется после успешного ответа API. Запись получила ID, но телефон оказался пустым, email изменил регистр, а повторный запуск создал второе значение. Цена ошибки — не только испорченная строка. Дальше ломается поиск, уведомление или связь с внешней системой, а восстановить исходное состояние трудно, потому что команда сохранила только факт «update вернул успех».

Полевой разбор должен проверять три операции: сохранить mapping, прочитать результат тем же смыслом и повторить вход без дубля. Для каждого поля нужно различить отсутствующее значение и явную очистку. Это особенно важно при переходе от массивов Bitrix к canonical объекту: старое имя можно удалить из кода, но нельзя удалить смысл значения до окончания проверки.

Сначала таблица mapping

Документация CUser перечисляет поля пользователя, включая PERSONAL_PHONE, EMAIL, идентификатор и время изменения. Для проекта это отправная точка, а не готовая схема: рядом могут быть пользовательские поля, обработчики события и внешний XML_ID. Запишите для каждого значения источник, формат, пустое состояние и обратное представление. Если поле не переносится, причина должна быть явной.

Нормализация должна быть идемпотентной: одинаковый вход при повторном запуске даёт одинаковый canonical результат. Для телефона это может быть trim без изменения номера, для email — lowercase, если бизнес-правило считает регистр незначимым. Нельзя применять общую нормализацию ко всем полям: комментарий пользователя, парольный хэш и XML_ID имеют разные правила.

Цикл проверки миграции Bitrix-поля: mapping входа, нормализация, запись, повторное чтение и контроль повторного запуска.
Схема показывает, что успешный вызов записи — только середина проверки. Нужны read-back и повторяемость результата.
Полевой контракт переноса поля
ПолеLegacy-значениеCanonical-значениеПроверка
ТелефонPERSONAL_PHONE, пробелы допустимыphone, trimmed stringread-back и формат
EmailEMAIL, исходный регистрemail, lower-caseвалидность и отсутствие дубля
IDID пользователяexternalIdодинаковая запись при retry
Пустотанет ключа или пустая строкаmissing или clearдва разных теста
СвязьXML_IDexternalIdдвусторонний mapping

Учебная нормализация без Bitrix-сервера

Ниже запускается локальная функция преобразования одного объекта. Она сохраняет legacy-копию, создаёт canonical поля и возвращает признак обратимости. Это не подмена миграционного запуска: результат показывает, как тестировать mapping до подключения API. В интеграционном коде следующая проверка должна сравнить canonical объект с read-back из Bitrix.

import { migrateUserFields } from './upgrade-2027-02.mjs';

const input = {
  ID: 17,
  PERSONAL_PHONE: ' +7 900 000-00-00 ',
  EMAIL: 'User@Example.TEST',
  XML_ID: 'crm-17',
};

console.log(migrateUserFields(input));
// canonical.phone === '+7 900 000-00-00'
// canonical.email === 'user@example.test'
// reversible === true

Ожидаемый результат показывает две отдельные операции: пробелы убраны у телефона, регистр email нормализован, а исходные поля остаются в legacy snapshot. Snapshot нужен для теста и отката преобразования, но не должен случайно отправляться обратно в новый API. В production-модуле его заменит журнал безопасного mapping без персональных значений.

Пустое поле и отсутствующее поле

Разница между {} и { PERSONAL_PHONE: "" } часто теряется в универсальном merge. Первый объект может означать «не менять телефон», второй — «очистить телефон». Если миграция смешивает эти случаи, повторный запуск удалит данные, которые не должны были меняться. В тестовой матрице должны быть оба входа и ожидаемое действие на стороне Bitrix.

Внешняя валидация тоже не должна менять значение молча. PHP filter_var может помочь проверить email, но решение о допустимости адреса принадлежит контракту приложения. Неверный email лучше остановить до update, чем сохранить пустую строку и потом считать ответ API доказательством успеха. Для телефона нужны отдельные правила: длина, допустимые символы и локальный формат.

Действия по порядку

  1. Составить mapping table и отдельно назвать missing, empty, invalid и unchanged для каждого поля.
  2. Запустить нормализацию на локальном наборе с пробелами, разным регистром, пустым и неверным значением.
  3. В тестовой среде записать одну запись по стабильному ID или XML_ID, затем выполнить read-back.
  4. Сравнить смысловые поля, время изменения, события и внешний идентификатор; не ограничиваться HTTP/API success.
  5. Повторить тот же запуск и убедиться, что новая запись не появилась и canonical результат не изменился.

Ограничения и следующий шаг

Локальная функция не знает о правах, событиях и особенностях конкретной версии Bitrix. Read-back может вернуть представление, отличное от входа: формат телефона, timezone или пустое значение иногда нормализуются сервером. Восстановление должно учитывать транзакцию и сохранённую связь, а не просто повторно отправлять старый объект.

Следующий шаг — взять одно поле, для которого есть внешний XML_ID, и прогнать полный цикл на небольшой выборке: mapping, запись, read-back, повтор и отчёт по расхождениям. Пока расхождения не классифицированы, расширять миграцию на весь набор рискованно. Проверяемость одного поля ценнее широкого запуска с неясным результатом.

Проверяемые источники

  • Главный модуль: CUser — документация 1С-Битрикс — версия и дата: документация API, проверена 31 July 2026; класс доступен с версии 3.0.6. Применение: Официальный список полей CUser используется для примера PERSONAL_PHONE, EMAIL, ID и XML_ID. Граница: Документация не знает пользовательские поля, события и фактические данные проекта.
  • PHP Manual: filter_var — версия и дата: PHP Manual, актуальная страница, проверена 31 July 2026. Применение: PHP Manual используется для проверки допустимости входного email перед записью. Граница: filter_var не определяет бизнес-правила, Bitrix-формат и гарантию сохранения поля.
  • CModule::IncludeModule — документация 1С-Битрикс — версия и дата: документация API, проверена 31 July 2026; CModule с версии 3.0.1. Применение: Подключение модуля упомянуто как проверка интеграционной границы до записи. Граница: Страница не подтверждает права и настройки конкретной среды.