Как я обновлял расширения конфигурации при изменении релиза 1С:КА с 2.5.22.186 на 2.5.27.75 с помощью ИИ
Предисловие
Я — разработчик 1С, сопровождающий сильно доработанную конфигурацию «Комплексная автоматизация» редакции 2.5. Передо мной стояла задача: обновить релиз с 2.5.22.186 на 2.5.27.75, сохранив все пользовательские доработки. Конфигурация содержит основное расширение с сотнями перехваченных методов и форм.
До начала работы я зафиксировал правила обновления в файле upd.md, описывающем роли трёх версий (BASE, THEIRS, OURS) и алгоритмы слияния. Затем начал методично, модуль за модулем, проходить все изменившиеся методы.
В этой статье я расскажу, что получилось, что нет, и какую роль сыграл ИИ (Claude через opencode) на каждом этапе.
Инфраструктура
-
Платформа: 1С:Предприятие 8.3.27.1719
-
Конфигурация: Комплексная автоматизация 2.5
-
Старый релиз: 2.5.22.186
-
Новый релиз: 2.5.27.75
-
Расширение: Основное расширение, обмен с БП, дополнительные расширения.
Рабочая база содержит 47 расширений:
-
СРС_ОсновноеРасширение— наше целевое, без безопасного режима, в нём все доработки -
СРС_Временное— площадка для горячих правок (тоже без безопасного режима) -
Именно взаимодействие такого числа расширений с обновлённой конфигурацией породило основную массу runtime-ошибок, описанных ниже.
-
AVS,AVS_ИнтеграцияССайтом— модули интеграции -
PowerTools,КонтурEDI,ПИЛОТ_ТЭДО— внешние подсистемы -
Остальные 35+
EF_00_*— отраслевые расширения поставщика, все в безопасном режиме -
Инструменты:
CfeUpdater.epf 2.1.1.0,KDiff3,Git,opencodeс Claude
Структура рабочего каталога:
text
I:\sv_ka_work\upd27\ old-configuration\ # типовая до обновления (BASE) new-configuration\ # типовая после обновления (THEIRS) extension\ # расширение с доработками (OURS) after_upd\ # загруженное расширение для правки results\ # результаты слияния history.md # журнал всех действий upd.md # правила и алгоритмы
Ключевое правило: тело метода расширения с директивой &ИзменениеИКонтроль должно посимвольно совпадать с телом типового метода из NEW-конфигурации. Отличия допустимы только внутри блоков #Вставка / #КонецВставки но ни в коем случае не внутри блока #Удаление / #КонецУдаления. Для проверки использовался скрипт merge-check.ps1.
Статистика проекта
-
Всего сессий слияния: 69
-
Уникальных модулей: 37
-
Явных «0 diffs» (perfect match): 2
-
Модулей с ошибками после слияния: 13
-
Сессий исправлений: 17
-
Полных пересборок с нуля: 1
-
Runtime-ошибок, обнаруженных интерактивно: 7
-
Попыток решения проблемы ПечатьЗаданияНаОтборРазмещениеТоваров: 5 подходов
-
Дней активной работы: 2 (21–22 августа 2026)
Анализ: что получалось, что нет
Что ИИ делал отлично
1. Слияние простых перехватчиков (~60% модулей).
Я призываю не поручать ИИ все подряд, чем меньше тем лучше. Простое не только не выгодно, но от объема качество работы ИИ на мой взгляд сильно страдает. При чрезмерном доверии и недостатке внимания пользователя получилась дорогостоящая и бессовестная халтура, от которой руки опускаются. Так что простые вещи я делаю сам. Сложные поручаю ИИ под контролем для экономии времени.
Типовой сценарий: найти три файла (BASE, THEIRS, OURS), сопоставить метод, перенести #Вставка-блоки в NEW-тело, проверить merge-check.ps1. Для большинства модулей это занимало 2–3 итерации и давало чистый результат.
Пример: модуль ПулКодовМаркировкиСУЗ — метод СРС_ЗаписатьДанныеКодаМаркировки обновлён с новыми полями ПолныйКодМаркировки и ТоварнаяГруппа без единой ошибки.
2. Обнаружение переименований.
При загрузке расширения в конфигуратор платформа выдаёт ошибки на несовпадениях. ИИ анализировал NEW-конфигурацию и находил новые имена:
-
РаспределениеЗапасов.Состояние→СостояниеЗапаса(8 вхождений) -
РаспределениеЗапасовСостояния.ОстатокНаСкладе→СостоянияЗапаса.ВНаличии -
ОсобенностиУчетаНоменклатуры.Антисептики→УдалитьАнтисептики(и ещё 5 аналогичных переименований enum-значений)
3. Глобальные замены.
Команда «замени во всех модулях X на Y» выполнялась быстро и без ошибок. Например, замена ОсобенностиУчетаНоменклатуры.* → Удалить* в 6+ модулях.
4. Посекционная сборка сложных методов.
Для метода СРС_ПараметрыФормыУказанияСерий (НоменклатураСервер) — 1752 строки, 16 блоков #Вставка — ИИ разбил NEW-тело на секции по якорным строкам и собрал результат посекционно. Итог: 0 diffs с NEW, идеальное совпадение.
Что ИИ делал с трудом
1. Трёхстороннее слияние без BASE.
Модуль УправлениеОтгрузкой не имел полного BASE для трёхстороннего сравнения. ИИ пытался восстанавливать логику по двум версиям — с ошибками, потребовалась ручная корректировка.
2. Специфичные знания платформы 1С.
ИИ не всегда знал ограничения синтаксиса:
-
СГРУППИРОВАТЬ ПОсПОМЕСТИТЬв определённых контекстах вызывает ошибку -
ПЕРВЫЕ 1работает нестабильно с временными таблицами -
#Удаление+#Вставканельзя разбивать — иначе vendor-код между блоками не совпадает с NEW
Эти нюансы выяснялись экспериментально, ценой лишних итераций.
3. PowerShell.
Несколько раз команды падали из-за того, что PowerShell резолвил .Replace() во внешнюю утилиту replace.exe вместо метода .NET. Также были ошибки с кодировкой и экранированием спецсимволов.
КЛЮЧЕВОЕ ПРАВИЛО: #Удаление НЕЛЬЗЯ РАЗБИВАТЬ
Это правило оказалось самым критичным и неочевидным из всех, что были выявлены в ходе проекта.
В чём проблема
В расширении блок #Удаление помечает vendor-код, который должен быть удалён из NEW при наложении расширения. Платформа сравнивает vendor-код расширения (вне #Вставка и #Удаление) с NEW, из которого предварительно вычтено содержимое #Удаление.
Если в расширении был единый блок #Вставка / #Удаление, его нельзя разбивать при адаптации под новую конфигурацию. В противном случае появляется vendor-код между блоками, который не совпадает с NEW после вычитания.
Пример ошибки
В расширении (правильно):
text
#Вставка
Если ... Тогда ... Иначе vendor_call КонецЕсли;
#КонецВставки
#Удаление
vendor_call # удаляет дубликат из NEW
#КонецУдаления
Ошибочная адаптация (разбиение на два #Вставка):
text
#Вставка
Если ... Тогда ... Иначе
#КонецВставки
vendor_call # vendor-код между блоками — ПЛАТФОРМА НЕ ПРИМЕТ!
#Вставка
КонецЕсли;
#КонецВставки
#Удаление
vendor_call
#КонецУдаления
При разбиении vendor-код между #КонецВставки и #Вставка остаётся, а #Удаление вычитает его из NEW — получается расхождение: расширение имеет vendor-код, а NEW после вычитания — пусто.
Правильная адаптация
Скопировать EXT-структуру один-в-один (один #Вставка → один #Удаление), заменив OLD vendor-код внутри #Вставка и внутри #Удаление на NEW-формат — включая точное совпадение отступов (табуляция должна быть как в NEW, а не как в EXT).
Как проверять
Обычный merge-check.ps1 (удаление обоих #Вставка и #Удаление) даёт 0 diffs даже при ошибочной структуре. Дополнительно обязательно проверять:
-
Содержимое
#Удалениепосимвольно совпадает с соответствующим vendor-кодом NEW -
Между
#КонецВставкии#Удалениетого же логического блока нет vendor-кода (должны идти подряд) -
После
#КонецУдаленияvendor-код продолжается со следующей строки NEW (без дубликатов и пропусков)
Итог: Это правило было выведено экспериментально на модуле СчетФактура и сэкономило несколько часов отладки runtime-ошибок в других модулях.
Что не получалось совсем
1. Экспорт встроенных обработок в EPF.
Команда ibcmd недоступна в этой версии платформы. Параметр /DumpExternalDataProcessorOrReport не экспортирует встроенные обработки. LoadExternalDataProcessorOrReportFromFiles ожидает формат <ExternalDataProcessor>, а XML-дамп даёт <MetaDataObject><DataProcessor>. Приходилось экспортировать EPF вручную из конфигуратора.
2. Первая попытка нормализации дубликатов в ПечатьЗаданияНаОтборРазмещениеТоваров.
4 подхода подряд не сработали — и только на 5-м был найден верный.
Кейс: ПечатьЗаданияНаОтборРазмещениеТоваров
Самый сложный модуль проекта. Ниже — хронология всех попыток.
Контекст
Печатная форма «Задание на сбор» из РасходногоОрдераНаТовары показывает список товаров с ячейками отбора. В новой версии запрос начал возвращать 4 строки вместо 1 для каждого товара — потому что один товар размещён в 4 ячейках, а LEFT JOIN по Номенклатуре умножает строки.
Попытка 1: МИНИМУМ + СГРУППИРОВАТЬ ПО
В подзапросах ЯчейкиОстаток и ЯчейкиИнформация (4 варианта) добавлены агрегатные функции МИНИМУМ() и СГРУППИРОВАТЬ ПО Номенклатура.
Результат: ОШИБКА — синтаксическая ошибка платформы: СГРУППИРОВАТЬ несовместимо с ЛЕВОЕ СОЕДИНЕНИЕ + ПОМЕСТИТЬ в данном контексте.
Попытка 2: ПЕРВЫЕ 1 + УПОРЯДОЧИТЬ ПО
Группировка откачена, вместо неё в каждый из подзапросов добавлены ПЕРВЫЕ 1 и УПОРЯДОЧИТЬ ПО Ячейка.Наименование.
Результат: ОШИБКА — ПЕРВЫЕ 1 без СГРУППИРОВАТЬ ПО ограничивает ВЕСЬ запрос одной строкой, а не одной строкой на товар. Если в заказе 5 товаров, ячейка будет получена только для первого.
Дополнительная ошибка: PowerShell-скрипт замены создал двойной префикс. Потребовалась дополнительная правка.
Ещё ошибка: скрипт отката GROUP BY использовал паттерн, который совпал во ВСЕХ подзапросах пакета. Все GROUP BY пришлось удалять и добавлять заново точечно.
Попытка 3: РАЗЛИЧНЫЕ в финальном SELECT
Все ПЕРВЫЕ убраны, вместо них в 4 финальных SELECT добавлено РАЗЛИЧНЫЕ.
Результат: НЕ ПОМОГАЕТ — РАЗЛИЧНЫЕ не помогает, потому что строки отличаются значением поля Ячейка — для одного товара в 4 разных ячейках возвращаются 4 разные строки, и РАЗЛИЧНЫЕ считает их уникальными.
Попытка 4: убрать Ячейка из Свернуть
Поля Ячейка и ЯчейкаСправочно убраны из метода Свернуть(), а код заполнения Размещения заменён на пустую строку.
Результат: ЧАСТИЧНО — 1 строка на товар, правильные количества. Но информация о ячейке потеряна — в печатной форме колонка «Размещение» пустая. Неприемлемо для пользователей.
Попытка 5: нормализация в коде ДО Свернуть
Архитектура решения:
-
Запросы пакета НЕ трогаем — они остаются как в типовой конфигурации
-
После
лЗапрос.ВыполнитьПакет()получаемТаблицаЗначенийс размноженными строками -
Первый проход: для каждого ключа
(Номенклатура + Характеристика)находим лучшую ячейку поMAX(Остаток) -
Второй проход: всем дублям проставляем одинаковую ячейку;
Остатокобнуляем у дублей (оставляем только у первой строки) -
После нормализации вызываем
Свернуть()с полным набором полей, включаяЯчейкаиЯчейкаСправочно -
Код заполнения
Размещениевосстановлен излВыборка.Ячейка
Попытка 6: В модуле менеджера ПечатьЗаданияНаОтборРазмещениеТоваров после LEFT JOIN с СтруктураРаспоряжения добавлена нормализация данных: обход строк по ключу уникальности, для дубликатов — обнуление количественных полей. Сортировка Упорядочить ставит необнулённую строку первой. Ключевую роль в поиске решения сыграл отладчик — именно таблица значений после LEFT JOIN, полученная из отладчика, показала, что дубликаты отличаются только количественными полями, и привела к правильному решению за одну итерацию, вместо того чтобы продолжать перебирать варианты агрегации.
«Как именно помог отладчик: он показал, что строки группируются по ключу (Номенклатура + Характеристика + Заказ). В каждой группе только ОДНА строка содержит номенклатуру в Заказ, а остальные три — нет. Это сделало решение очевидным: не фильтровать (поскольку GROUP BY и DISTINCT не работают на всех полях сразу), а нормализовать — обойти строки и обнулить количественные поля для дублей.»
| # | Гипотеза | Инструмент | Результат |
|---|---|---|---|
| 1 | Лишние строки из-за LEFT JOIN |
Визуальный осмотр запроса | JOIN с СтруктураРаспоряжения множит строки — подтверждено |
| 2 | Отсеять на уровне GROUP BY |
Правка запроса | Сложно: ключ уникальности не включает все поля |
| 3 | DISTINCT в подзапросах |
Правка запроса | Не работает: DISTINCT применяется к одной колонке, не к строке |
| 4 | MAX(Количество) в агрегации |
Правка запроса | Не решает проблему дубликатов других полей |
| 5 | Ложный успех «Заказ = 2» | Единичный тест в одной базе | Тестирование преждевременно завершено |
| 6–8 | Комбинации GROUP BY + ORDER BY |
Правки, тесты | Все варианты дают побочные эффекты |
| 9 | Данные отладчика | Отладчик, анализ ТаблицаЗначений |
Установлено: дубликаты отличаются только количественными полями (Количество, КоличествоСамыхМест, Вес, Объем). LEFT JOIN создаёт по 4 строки на позицию, три из них — мусор |
Итог по модулю
| Подход | Итераций | Результат |
|---|---|---|
| Field renames | 1 | Успех |
| МИНИМУМ + ГРУППИРОВАТЬ | 2 | Ошибка платформы |
| ПЕРВЫЕ 1 + ORDER BY | 3 | Неверная логика |
| РАЗЛИЧНЫЕ | 1 | Не помогает |
| Убрать Ячейка из Свернуть | 1 | Работает, но теряет данные |
| Нормализация в коде | 1 | Успех |
| Всего | 9 |
Резюме. 9 итераций, финальное решение — одна нормализация данных. Решающий инструмент — отладчик: именно таблица значений из отладчика показала структуру дубликатов и привела к решению за один проход. Без данных отладчика мы бы продолжали перебирать варианты агрегации, не видя истинной причины. Единичный успех не равен завершению задачи — только полный цикл тестирования всех видов заданий даёт основание считать проблему решённой.
Хронология: день 1 (21 августа 2026)
Первый день — потоковая обработка модулей. 21 модуль за одну сессию. Большинство — простые перехватчики, где нужно перенести 1–3 блока #Вставка в NEW-тело.
Ключевые события дня:
-
ЗаказКлиента — дублированное присваивание настройки
РазрешитьОтгрузкуСверхЗаказа. Исправлено удалением лишней строки. -
ВзаиморасчетыСервер — сложный случай: типовой модуль был разделён на 2 (основной + локализация). Пользовательский код потребовал переноса в новую структуру.
-
ПроверкаИПодборПродукцииИС — спецсхема: BASE = старая обработка ИСМП, THEIRS = новая обработка ИС (без МП). Адаптация под новую архитектуру без
ВидПродукции. -
ФормированиеФискальныхЧековКлиент — вызов удалённой клиентской функции из расширения. Исправлено переносом вызова в серверный контекст.
-
ИнтеграцияИСМПУТ — обнаружены буквальные
\tв тексте запросов (результат предыдущей автоматической обработки). Исправлено заменой на реальные табуляции.
Хронология: день 2 (22 августа 2026)
Второй день — работа над сложными модулями и исправление ошибок, обнаруженных при загрузке расширения.
Пересборка НоменклатураСервер
Метод СРС_ПараметрыФормыУказанияСерий (1752 строки) перестроен с нуля посекционным подходом. NEW-тело разделено на секции по якорным строкам, между ними вставлены 16 блоков #Вставка из расширения. Итог: 0 diffs с NEW.
СкладыСервер
Метод СРС_ПолучитьОбъектОрдер — NEW-запрос полностью переписан поставщиком. Пользовательские блоки перенесены в новый запрос. 153 строки, 0 diffs.
СчетФактура: ошибка разбиения #Удаление/#Вставка
Критическое правило, выведенное экспериментально: блоки #Вставка и #Удаление нельзя разбивать. Если EXT содержит единый блок:
text
#Вставка
Если ... Тогда ... Иначе vendor_call КонецЕсли;
#КонецВставки
#Удаление
vendor_call
#КонецУдаления
— его нельзя разбивать на два #Вставка с vendor-кодом между ними. Платформа сравнивает vendor-код расширения (вне #Вставка) с NEW, из которого вычтено содержимое #Удаление — и при разбиении получается расхождение.
ПечатьЗаданияНаОтборРазмещениеТоваров
Полная хронология — в разделе выше. 9 итераций, 5 подходов.
В течение первых суток эксплуатации пользователи сообщили о серии ошибок в самой нагруженной форме системы — «Проверка и подбор продукции ИС». Ниже — подробная хронология.
Ошибка 1: ЕстьИерархия — не-Булево значение
Где. Форма ПроверкаИПодбор, vendor-процедура ОбработатьПолученныеДанныеТСДНаСервере, строка Если ЕстьИерархия Тогда.
Причина. Vendor-код новой конфигурации инициализирует ЕстьИерархия только в ветке Тогда условного оператора. В ветке Иначе переменная остаётся Неопределено. Между этими ветками находится #Вставка-блок расширения, который не меняет значения переменной. После выхода из #Вставка vendor-код попадает в Иначе → ЕстьИерархия не определена → следующая vendor-строка Если ЕстьИерархия Тогда падает с ошибкой «значение не Булево».
Исправление. Добавлена одна строка в #Вставка (перед #КонецВставки, в начале ветки Иначе):
bsl
ЕстьИерархия = Истина;
Ошибка 2: СоставКодаМаркировки — не-объектный тип
Где. Vendor-цикл обработки штрихкодов ТСД, сравнение ДанныеРазбора.СоставКодаМаркировки <> Неопределено.
Причина. Функция ГрупповаяОбработкаШтрихкодовИС.ВидУпаковкиИПредставлениеШтрихкодаУпрощенныйРазбор в новой конфигурации возвращает СоставКодаМаркировки типа, несовместимого со сравнением <> Неопределено на клиенте.
Исправление. В #Вставка-блоке (перед vendor-циклом обработки ТСД) добавлен обход КешДанныхРазбора:
bsl
Для Каждого КЗ Из КешДанныхРазбора Цикл
Попытка
Проверка = КЗ.Значение.ДанныеРазбора.СоставКодаМаркировки <> Неопределено;
Исключение
КЗ.Значение.ДанныеРазбора.СоставКодаМаркировки = Неопределено;
КонецПопытки;
КонецЦикла;
Критически важно: использовать то же сравнение <> Неопределено, что и vendor-код — а не = Неопределено. Иначе нормализация сбросит корректные записи, vendor пропустит ЗаполнитьЗначенияСвойств, и Номенклатура не заполнится в дереве.
Ошибка 3: Уровень — поле не обнаружено
Где. Vendor-разбор данных ТСД, обращение к СтрокаДанныхТСД.Уровень.
Причина. В новой конфигурации структура СтрокаДанныхТСД больше не содержит поля Уровень по умолчанию.
Исправление. В #Вставка перед vendor-обработкой:
bsl
Для Каждого СтрокаДанныхТСД Из ДанныеДляТСД.Штрихкоды Цикл
СтрокаДанныхТСД.Вставить("Уровень", 0);
КонецЦикла;
Ошибка 4: Объект.Ордер → СсылкаНаОрдер.Склад
Где. Блок работы с серийными номерами, обращение к складу через ордер.
Причина. Тройная:
-
Vendor переименовал
Объект.ОрдервСсылкаНаОрдер— прямая замена -
СсылкаНаОрдерможет бытьПеремещениеТоваров(нет поляСклад) — обращение падает -
СсылкаНаОрдерможет бытьРасходныйОрдерНаТовары(есть полеСклад) — должно работать
Исправление. Замена Объект.Ордер на СсылкаНаОрдер + защитная проверка перед обращением к Склад:
bsl
И СсылкаНаОрдер.Метаданные().Имя = "РасходныйОрдерНаТовары"
Ошибка 5: СРС_ЭтоНеGTIN — переписана
Причина. Старая реализация использовала запрос к регистру ШтрихкодыНоменклатуры на каждый GTIN — медленно, плюс новый конфигуратор изменил формат данных.
Исправление. Функция переписана на структурный анализ кода без запросов:
-
00*→ SSCC (не GTIN) -
0*→ GTIN с ведущим нулём -
12+ цифр после отрезания префикса → GTIN
Ошибка 6: «Заполнить по заказам и ордерам» — команды исчезли из формы накладных
Vendor полностью переработал интерфейс заполнения табличной части документов. Старые кнопки удалены, функциональность перенесена в подменю «Заполнить». Требуется либо обновление расширения с заимствованием новой формы, либо адаптация пользователей к новому интерфейсу. Вопрос оставлен на решение заказчика.
Ошибка 7: ОСУ «заполнить количество по документу» — табчасть пуста
Самая сложная ошибка. 6 итераций расследования, каждая с новым инструментом: отладчик, трассировка быстродействия, grep-анализ файлов.
Симптом. Кнопка «Заполнить количество по документу» в объёмно-сортовом учёте не заполняет марками табличную часть. Сообщение: «Объемно-сортовой учет не используется».
Итерация 1 — гипотеза GTIN. Отладчик показал: GTIN 04656759851392 успешно определяется при сканировании штрихкода, но Номенклатура в дерево маркированной продукции не попадает. Vendor-строка ЗаполнитьЗначенияСвойств не выполняется — СоставКодаМаркировки = Неопределено (следствие нормализации из Ошибки 2). Гипотеза отвергнута — проблема глубже.
Итерация 2 — нормализация. Исправлена как описано в Ошибке 2 (замена = Неопределено на <> Неопределено). Не помогло — отладчик по-прежнему не заходит в ЗаполнитьЗначенияСвойств, потому что СоставКодаМаркировки и правда Неопределено в новой конфигурации. Vendor больше не передаёт эти данные через кеш ГрупповаяОбработкаШтрихкодовИС.
Итерация 3 — поиск места заполнения Номенклатуры. Найден альтернативный путь: vendor-код заполняет Номенклатуру ПОЗЖЕ, через НайтиПоИдентификатору(ДеревоМаркированнойПродукции, ...). Но отладчик показал — процедура ОСУ (ЗаполнитьКоличествоПоДокументуОСУКлиент) работает с ПодобраннаяМаркируемаяПродукция, а не с деревом. Этот путь для ОСУ не релевантен.
Итерация 4 — попытка прямого заполнения GTIN. Добавлен код в #Вставка для заполнения GTIN в обход vendor-сравнения <> Неопределено. Не помогло — ОСУ-проверка ПоддерживаетсяОбъемноСортовойУчет всё равно отсекает все продукты.
Итерация 5 — трассировка. Решающий шаг. Трассировка показала точную картину выполнения процедуры ЗаполнитьКоличествоПоДокументуОСУКлиент:
-
228 продуктов в
ПодобраннаяМаркируемаяПродукция -
Для каждого:
ПоддерживаетсяОбъемноСортовойУчет(...)→Ложь -
Для каждого:
Продолжить(228 раз из 229 итераций) -
Причина:
СтрокаМаркируемойПродукции.ВидПродукциипуст для ВСЕХ записей -
Функция
ВидыПродукцииКлючавКонструкторИСОбщегоНазначенияКлиентСерверполучает пустойКлючВидовПродукции→ возвращает пустой результат → ОСУ не поддерживается ни для одного продукта
Итерация 6 — дубликат процедуры. Grep-анализ файла Module.bsl расширения показал: в модуле ДВЕ процедуры СРС_ЗаполнитьКоличествоПоДокументуОСУКлиент. Первая (строки 1–216 файла) — старый мусор с битой кодировкой Windows-1251, оставшийся после неудачного слияния. Вторая (строка 2915) — правильная из слияния. Платформа грузила первую — она и содержала проверку ПоддерживаетсяОбъемноСортовойУчет, обречённую на Ложь для всех продуктов без ВидПродукции.
Финальное решение. Два шага:
-
Удалены 238 строк мусора из начала файла (старая процедура + старая
СРС_ЭтоНеGTIN) -
В оставшейся правильной процедуре
СРС_ЗаполнитьКоличествоПоДокументуОСУКлиентблок vendor-проверки ОСУ и блок контроля даты ОСУ обёрнуты в#Удаление:
bsl
#Удаление
КешДатНачалаКонтроляПоОСУ = Новый Соответствие();
ДатаСеанса = НачалоДня(ОбщегоНазначенияКлиент.ДатаСеанса());
#КонецУдаления
Для Каждого СтрокаМаркируемойПродукции Из ПодобраннаяМаркируемаяПродукция Цикл
#Удаление
Если СтрокаМаркируемойПродукции.МаркируемаяПродукция
И Не КонструкторИСОбщегоНазначенияКлиентСервер.ПоддерживаетсяОбъемноСортовойУчет(
СтрокаМаркируемойПродукции.ВидПродукции, ПараметрыСканирования) Тогда
Продолжить;
КонецЕсли;
// блок контроля даты ОСУ (КешДатНачалаКонтроляПоОСУ, ДатаСеанса)
#КонецУдаления
Если ИспользоватьСерииНоменклатуры ...
Почему это корректно. Процедура ЗаполнитьКоличествоПоДокументуОСУКлиент работает на КЛИЕНТЕ, а ВидПродукции определяется на СЕРВЕРЕ при подборе номенклатуры. На момент вызова процедуры ВидПродукции всегда пуст → vendor-проверка всегда даёт Ложь → все продукты пропускаются. Удаление переносит ОСУ-контроль на серверную сторону, где ВидПродукции уже доступен.
Итоги первого периода начала эксплуатации
| Категория | Количество |
|---|---|
| Ошибки формы (Boolean, type, field) | 3 |
| Ошибки навигации по объектам (Ордер/Склад) | 1 |
| Переписанные функции (СРС_ЭтоНеGTIN) | 1 |
| Изменения интерфейса (команды заполнения) | 1 |
| Логические ошибки (ОСУ fill) | 1 |
| Дубликаты кода в модулях | 1 |
| Всего | 8 |
Все ошибки выявлены пользователями в течение суток после загрузки расширения.
Главный урок этого этапа. Слияние &ИзменениеИКонтроль даёт 0 diffs с NEW-конфигурацией — но это гарантирует только синтаксическую корректность. Runtime-поведение зависит от порядка и контекста вызова. Процедура, корректная в vendor-контексте, может быть некорректна в расширении из-за разницы в моменте доступности данных (клиент vs сервер). Трассировка быстродействия + grep-анализ исходников оказались единственным путём к обнаружению дубликата процедуры — визуальный осмотр модуля в конфигураторе дубликат не показал.
Артефакты проекта
Правила слияния (upd.md)
Файл на 314 строк, содержащий:
-
Структуру рабочего каталога и роли версий
-
10 правил слияния (основа — NEW, пользовательские блоки переносятся, сигнатуры из NEW)
-
Правило точного соответствия тела
&ИзменениеИКонтрольс NEW (0 diffs) -
Правило обработки
#Удаление— код внутри должен посимвольно совпадать с NEW -
Правило бэкапа перед изменениями
-
Правило сохранности модуля расширения
-
Инструменты:
merge-check.ps1,merge_nomenk_v6.ps1 -
Специфику модулей группы 3 (обработки) и ИСМП
Журнал действий (history.md)
Файл на 817 строк с детальным описанием каждой сессии:
-
Дата и название модуля
-
Описание выполненного изменения
-
Перечень изменённых и созданных файлов
-
Результаты статических проверок
-
Ограничения и риски
Всего 69 записей за 2 дня.
Скрипты
-
merge-check.ps1— Посимвольное сравнение тела метода с NEW (проверка 0 diffs) -
merge_nomenk_v6.ps1— Шаблон посекционной сборки метода
Результаты слияния (results/)
38 подкаталогов с результатами для каждого модуля: after_upd и backup_* файлы.
Ключевые выводы
1. Правила важнее интуиции
Файл upd.md с жёсткими правилами (0 diffs, не разбивать #Вставка/#Удаление, бэкап перед каждой правкой) сэкономил десятки часов отладки. Без него многие ошибки проявлялись бы только в runtime.
2. Проверка merge-check.ps1 обязательна
Посимвольное сравнение с NEW после каждой правки — единственный надёжный способ убедиться, что vendor-код не повреждён. 0 diffs ≠ отсутствие ошибок (есть ещё #Удаление), но не-0 diffs = гарантированная ошибка.
3. ИИ полезен, но не заменяет знание платформы
ИИ отлично справляется с рутинными слияниями (60% модулей), поиском переименований, глобальными заменами. Но специфичные ограничения платформы 1С (СГРУППИРОВАТЬ + ПОМЕСТИТЬ, ПЕРВЫЕ 1 в пакетах, структура #Вставка/#Удаление) приходилось выяснять экспериментально.
4. Инфраструктура — половина успеха
Чёткая структура каталогов (old-configuration, new-configuration, extension, after_upd, results), скрипты проверки, правила бэкапа — всё это сделало процесс воспроизводимым и позволило быстро откатывать неудачные попытки.
5. Самый сложный модуль — не тот, где много кода
НоменклатураСервер (1752 строки, 16 блоков #Вставка) был пересобран с первой попытки благодаря посекционному подходу. А ПечатьЗаданияНаОтборРазмещениеТоваров с простым запросом потребовал 9 итераций — потому что проблема была не в слиянии, а в логике (дубликаты из-за множественных ячеек).
После завершения всех слияний:
-
Проверка применимости расширения в конфигураторе
-
Выгрузка расширения в production
Результаты
Эксперимент показал, что AI-assisted upgrade типовой конфигурации 1С — это не фантастика, а рабочий инструмент уже сегодня. Да, с нюансами. Да, с ограничениями. Но 37 модулей за 2 дня с документированным процессом и воспроизводимыми результатами — это уровень.
Проект выполнен с использованием:
-
1С:Предприятие 8.3.27.1719
-
Claude (Anthropic) через opencode — для анализа, слияния и генерации кода
-
CfeUpdater.epf 2.1.1.0 — для анализа CFE-расширений
-
PowerShell + Git — для автоматизации и версионирования
-
KDiff3 — для ручного просмотра сложных конфликтов
Вступайте в нашу телеграмм-группу Инфостарт