1С 7.7, нейросеть и легаси: как я научил старую обработку понимать маркировку, таможенные декларации и «коробки»

от автора

1С 7.7 сегодня живет в странном статусе: платформа давно не новая, типовые решения на ней уступили место 1С 8, но в реальном бизнесе старые базы продолжают работать. Часто это сильно доработанные конфигурации, которые годами закрывали конкретные процессы компании, и переписать их «на восьмерку» быстро не получается. С нейросетями похожая история: для 1С 8 примеров, обсуждений и готовых фрагментов заметно больше, а код под 7.7 они пишут менее уверенно. Синтаксис вроде знакомый, но объектная модель, запросы, периодические реквизиты и старые приемы работы отличаются. Поэтому использовать нейросеть для 7.7 можно, но не как автопилот, а как помощника, которому обязательно нужны реальные файлы, описание метаданных и проверка человеком.

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

У меня была как раз такая задача: внешняя обработка для 1С 7.7 загружала XML-файлы универсального передаточного документа в документ «Приходная накладная». Нужно было доработать ее под реальные файлы поставщиков.

На руках были два XML-файла с реальной выгрузкой, из которых потом и должна была идти загрузка. Формат у таких файлов стандартный, но стандартный не значит простой: много вложенных узлов, атрибуты на разных уровнях, отдельные блоки для продавца, товаров, маркировки, налогов, таможенных деклараций и страны происхождения. Разбирать это вручную можно, но времени ушло бы заметно больше. Я просто передал оба XML-файла нейросети вместе с текущим модулем, и она с первого раза правильно нашла, откуда брать основные реквизиты: наименование товара, количество, цену, артикул, контрольные идентификационные знаки, номер декларации, код и название страны.

Сразу оговорюсь: нейросеть не «сделала все сама». Я использовал GPT-5.5, давал ей контекст, примеры XML, описание реквизитов и текущий модуль на встроенном языке 1С, а дальше мы шаг за шагом доводили обработку до нужного поведения.

Еще один бытовой момент: прямой связи между средой, где я работал с нейросетью, и модулями 1С у меня не было. Я разрабатывал в Codex, но сам модуль внешней обработки в 1С жил отдельно. Поэтому приходилось заниматься обычным копипастом: фрагменты из модуля переносить в диалог с нейросетью, затем готовые куски кода возвращать обратно в 1С и проверять уже там. Это не очень удобно, зато быстро работает, если держать под рукой исходный модуль, XML-примеры и описание реквизитов.

Что уже было

На старте обработка уже умела загружать базовый универсальный передаточный документ:

  • поставщик искался по идентификационному номеру налогоплательщика;

  • если поставщик не найден, создавался новый контрагент;

  • товар искался по полному наименованию;

  • если товар не найден, создавалась новая номенклатура;

  • контрольный идентификационный знак маркировки из XML-файла попадал в реквизит строки «Кюар»;

  • если у товара было 10 контрольных идентификационных знаков, создавалось 10 строк по 1 штуке;

  • если маркировки не было, создавалась одна строка с общим количеством.

Для простого документа этого хватало. Но на реальных XML-файлах почти сразу всплыли детали, которые в первой версии не учитывались: разные единицы измерения, артикулы, грузовые таможенные декларации, страна происхождения и ситуации, когда один товар надо разбивать на несколько строк.

Как выглядел первый запрос к нейросети

Я не стал просить «доработай загрузку универсального передаточного документа». Такой запрос слишком общий. Вместо этого дал файлы и короткое техническое задание:

Доработать только код. Есть файл описания реквизитов, XML с загружаемыми данными и модуль на встроенном языке 1С с уже сделанным кодом.

Уже сделано: загрузка из XML в приходную накладную. Товар ищем по СокрЛП(ПолнНаименование), если не находим — создаем новый в корне справочника «Номенклатура». Поставщик ищется по идентификационному номеру налогоплательщика, если нет — создается новый. В XML <КИЗ> попадает в приходной в «Кюар».

Доработать: единица измерения бывает не только с кодом 796. Если в товаре XML есть АртикулТов, добавить в номенклатуру «Артикул». В приходе бывает грузовая таможенная декларация: НомерДТ, код страны и название страны. Декларация идет на определенное количество товара. Один товар может быть 10 штук с одной декларацией или 10 штук с одной декларацией и 5 штук с другой — тогда в приходе должны быть две строки.

Такой формат сработал лучше, чем абстрактное описание. Особенно для 1С 7.7, где нельзя полагаться на типовые названия реквизитов: в одной базе это ПолнНаименование, в другой — что-то еще, а табличная часть может быть доработана годами эксплуатации.

Отдельно я всегда пишу «доработать только код». Причина простая. В 1С в XML-форматах могут храниться не только данные обмена, но и внутренние вещи: формы, описания метаданных, части конфигурации. Такие форматы специфичные, не всегда публично описаны и плохо подходят для генерации «на глаз». Если не ограничить задачу, нейросеть может начать править XML-теги или предлагать изменения XML-частей кодовой базы 1С. Для 1С 7.7 это особенно опасно: ошибка в таком фрагменте может привести не к синтаксической ошибке в модуле, а к повреждению структуры, которую потом сложно восстановить. Поэтому правило простое: XML можно читать как источник данных и как справочник по структуре, но менять нужно только модуль с кодом.

При этом первый вариант от нейросети не был идеальным. Она пыталась решать часть задач слишком прямолинейно: где-то предлагала хардкодинг, где-то конструкции в стиле «найти по коду» или «найти по наименованию» без нормального использования запросов, хотя в существующем модуле поиск по справочникам уже был сделан через объект Запрос. Я отдельно указал на это и попросил переписать в том же стиле, через запросы 1С 7.7. Через пару минут GPT-5.5 перестроила код: появились отдельные функции поиска по коду, по наименованию и создания элемента справочника, уже без лишнего хардкода и ближе к тому, как был написан исходный модуль.

Единица измерения: не всегда 796

В старом коде единица измерения для новой номенклатуры была фактически захардкожена:

ЕдиницаИзм = НайтиЕдиницуИзмеренияПоКоду("796");

Код 796 — это «штука». Но в XML-файле может прийти, например, коробка:

<СведТов НаимЕдИзм="кор" ОКЕИ_Тов="..." КолТов="10" ...>

Если молча загрузить это как штуки, учет будет неправильным: 10 коробок превратятся в 10 штук. Поэтому я попросил учесть единицу из XML-файла.

Поэтому из строки товара стали читать и код, и наименование:

КодЕдиницы = АтрибутXML(УзелТовара, "ОКЕИ_Тов");НаименованиеЕдиницы = АтрибутXML(УзелТовара, "НаимЕдИзм");Товар = ПолучитьИлиСоздатьНоменклатуру(Наименование,КодЕдиницы,НаименованиеЕдиницы,Артикул);

Дальше логика такая:

  1. Ищем единицу по КодЕдин.

  2. Если не нашли — ищем по наименованию.

  3. Если не нашли и в XML-файле есть данные — создаем новую единицу.

Фрагмент функции:

ЕдиницаИзм = НайтиЕдиницуИзмеренияПоКоду(КодЕдиницы);Если ПустоеЗначение(ЕдиницаИзм) = 0 ТогдаВозврат ЕдиницаИзм;КонецЕсли;ЕдиницаИзм = НайтиЕдиницуИзмеренияПоНаименованию(НаименованиеЕдиницы);Если ПустоеЗначение(ЕдиницаИзм) = 0 ТогдаВозврат ЕдиницаИзм;КонецЕсли;Спр = СоздатьОбъект("Справочник.КодыЕдиниц");Спр.Новый();Если НаименованиеЕдиницы <> "" ТогдаСпр.Наименование = НаименованиеЕдиницы;ИначеСпр.Наименование = КодЕдиницы;КонецЕсли;Спр.КодЕдин = КодЕдиницы;Спр.Записать();

После этого найденная или созданная единица записывается в периодический реквизит номенклатуры ЕдиницаИзм.

Отдельный вопрос про «кор»

После первой правки я отдельно спросил:

«кор» — в файле есть такая единица, а у нас её нет в справочнике. Какие есть предложения?

Вариантов было несколько:

  • подменять неизвестную единицу на «шт»;

  • создать единицу автоматически;

  • завести таблицу соответствий и коэффициенты пересчета.

Подменять на «шт» я отбросил сразу. Это удобно только до первой инвентаризации. Таблица соответствий с коэффициентами — самый правильный вариант для сложного обмена, но в текущих XML-файлах не было информации вроде «1 кор = 12 шт». Значит, автоматически пересчитать коробки в штуки корректно нельзя.

Остановились на простом и честном варианте: если в XML-файле пришла единица и ее нет в справочнике, обработка создает ее и сообщает об этом пользователю.

Артикул из XML-файла

Артикул в одном из файлов приходил в ДопСведТов:

<ДопСведТов АртикулТов="ASX5010-5" КодТов="ASX5010-5" ПрТовРаб="1">

В код добавили чтение атрибута:

УзелДопСведТов = УзелТовара.ВыбратьУзел("ДопСведТов");Артикул = АтрибутXML(УзелДопСведТов, "АртикулТов");

При создании новой номенклатуры все просто:

Спр.Артикул = Артикул;

Но для уже найденного товара нужна аккуратность. Если в XML-файле артикул пустой, нельзя затирать значение в базе. Поэтому обновление сделали только при непустом артикуле:

Если Артикул <> "" ТогдаЕсли СпрНом.Артикул <> Артикул ТогдаСпрНом.Артикул = Артикул;СпрНом.Записать();КонецЕсли;КонецЕсли;

Мелочь, но именно на таких мелочах часто ломаются загрузки: один поставщик прислал артикул, другой не прислал, и в базе внезапно пусто.

Грузовая таможенная декларация и страна происхождения

Дальше дошли до грузовой таможенной декларации. В XML-файле она лежит в СвДТ:

<СвДТ КодПроисх="156" НомерДТ="10702070/270426/5157184"/>

А название страны — в другом узле:

<ДопСведТов ПрТовРаб="1"><КрНаимСтрПр>КИТАЙ</КрНаимСтрПр></ДопСведТов>

По описанию конфигурации нашли справочник ГТД. У него есть реквизиты Страна, цифровойкод и КодСтран. Для кода страны используется справочник СтраныКод.

Функция получения или создания грузовой таможенной декларации получилась такой:

Функция ПолучитьИлиСоздатьГТД(НомерГТД, КодСтраны, НаименованиеСтраны)НомерГТД = ОбрезатьСтроку(НомерГТД, 50);Если НомерГТД = "" ТогдаВозврат "";КонецЕсли;ГТД = НайтиГТДПоНомеру(НомерГТД);Если ПустоеЗначение(ГТД) = 0 ТогдаВозврат ГТД;КонецЕсли;Страна = ПолучитьИлиСоздатьСтрану(КодСтраны, НаименованиеСтраны);Спр = СоздатьОбъект("Справочник.ГТД");Спр.Новый();Спр.Наименование = НомерГТД;Спр.Страна = ОбрезатьСтроку(НаименованиеСтраны, 100);Спр.цифровойкод = ОбрезатьСтроку(КодСтраны, 10);Если ПустоеЗначение(Страна) = 0 ТогдаСпр.КодСтран = Страна;КонецЕсли;Спр.Записать();Возврат Спр.ТекущийЭлемент();КонецФункции

Что такое «ОбрезатьСтроку "? Дело в том, что строка полученная из файла, может быть разного размера. А когда ищем по наименованию, или запросом, то для 1С 7.7 надежнее привести её длину к реально используемой в текущей базе данных.

А процедура добавления строки прихода получила еще один параметр:

Процедура ДобавитьСтрокуПрихода(Док, Товар, Количество, Цена, Сумма, НДС, Кюар, ГТД)Док.НоваяСтрока();Док.Товар = Товар;Док.Количество = Количество;Док.Цена = Цена;Док.Сумма = Сумма;Док.НДС = НДС;Док.Кюар = ОбрезатьСтроку(Кюар, 35);Если ПустоеЗначение(ГТД) = 0 ТогдаДок.ГТД = ГТД;КонецЕсли;КонецПроцедуры

Когда один товар надо разбить на несколько строк

Отдельная неприятность — один товар, но несколько грузовых таможенных деклараций.

Например:

  • товар один;

  • общее количество — 15;

  • 10 штук относятся к одной грузовой таможенной декларации;

  • 5 штук — к другой.

В приходной накладной это уже не одна строка, а две. Количество понятно, но еще надо распределить сумму и НДС. Для промежуточных строк использовали пропорцию:

СуммаСтроки = Окр(СуммаБезНДС * КоличествоСтроки / Количество, 2);НДССтроки = Окр(СуммаНДС * КоличествоСтроки / Количество, 2);

А последней строке отдавали остаток:

СуммаСтроки = СуммаБезНДС - СуммаРазнесено;НДССтроки = СуммаНДС - НДСРазнесено;

Это обычный прием, чтобы не потерять копейки из-за округления.

Что делать с контрольными идентификационными знаками

Контрольные идентификационные знаки уже были реализованы до этих правок: каждый код маркировки создавал отдельную строку с количеством 1.

Эту часть трогать было рискованно. Поэтому логика осталась прежней, но к каждой строке добавилась грузовая таможенная декларация:

Кюар = ТекстXML(КодыКИЗ.ПолучитьУзел(НомерКИЗ));ГТД = ГТДДляЕдиницы(УзлыГТД,НомерКИЗ + 1,Количество,НаименованиеСтраны);ДобавитьСтрокуПрихода(Док, Товар, 1, Цена,СуммаСтроки, НДССтроки,Кюар, ГТД);

Получилось так: если товар маркирован, в документе по-прежнему будет строка на каждую единицу. Но теперь эта строка несет не только контрольный идентификационный знак, а еще и правильную грузовую таможенную декларацию.

Что проверял после правок

Нейросеть ускорила работу, но код все равно пришлось проверять обычным способом.

Я смотрел:

  • совпадают ли имена реквизитов с описанием конфигурации;

  • есть ли в базе нужные справочники: КодыЕдиниц, ГТД, СтраныКод;

  • не остались ли старые вызовы функций после изменения сигнатур;

  • не сломалась ли логика контрольных идентификационных знаков;

  • не затирается ли артикул пустым значением из XML-файла;

  • сходится ли баланс Функция/КонецФункции, Процедура/КонецПроцедуры, Если/КонецЕсли;

  • нет ли конструкций, которые могут быть сомнительны для 1С 7.7.

Старые среды не любят лишней смелости. Если можно написать проще и понятнее, лучше так и сделать.

Где нейросеть помогла, а где нет

Больше всего нейросеть помогла в рутине:

  • быстро прочитала большой модуль на встроенном языке 1С;

  • нашла места, куда встроить новую логику;

  • помогла сопоставить узлы XML-файла с реквизитами конфигурации;

  • набросала функции поиска и создания справочников;

  • подсказала варианты для отсутствующих единиц измерения.

Но учетные решения она за меня не принимала. Например, вопрос «создавать ли кор как новую единицу или пересчитывать в штуки» нельзя решить только по коду. Тут нужно понимать, как склад ведет остатки и что реально означает количество в документах поставщика.

В этом и есть нормальная роль нейросети в такой задаче: не заменить разработчика, а снять часть механической работы и быстрее довести до обсуждаемых вариантов.

Итог

После доработки обработка стала учитывать больше реальных случаев:

  • единицы измерения берутся из XML-файла;

  • отсутствующие единицы создаются автоматически;

  • АртикулТов попадает в номенклатуру;

  • создаются и заполняются грузовые таможенные декларации;

  • подтягивается страна происхождения;

  • строки разбиваются по грузовым таможенным декларациям;

  • контрольные идентификационные знаки и грузовые таможенные декларации работают вместе.

Вывод получился практический: нейросеть полезна в legacy-разработке, если давать ей не только задание, но и контекст — код, примеры данных, описание метаданных и ограничения. Тогда она действительно экономит время. Но проверка, учетная логика и ответственность за результат остаются на человеке.

ссылка на оригинал статьи https://habr.com/ru/articles/1047296/