В процессе работы с системой 1С:Предприятие, особенно при корректировке старых данных или в специфических сценариях, нам часто приходится сталкиваться с обязательной проверкой заполнения реквизитов. Например, когда необходимо откорректировать документы годовалой давности, установив нулевые суммы и цены, типовая конфигурация может выдавать ошибки из-за того, что поля Цена и Сумма в табличной части являются обязательными для заполнения. В таких случаях прямое изменение свойств конфигурации нежелательно, так как это усложняет процесс обновления. В этой статье мы подробно разберем, как решить эту проблему, используя расширение конфигурации и программный подход. При необходимости можно воспользоваться готовым расширением для проведения документов с нулевыми ценами в УТ 11.
Наша задача заключается в том, чтобы отключить обязательную проверку заполнения для реквизитов Товары.Цена и Товары.Сумма в документе "Корректировка приобретения" в конфигурации 1С:Управление торговлей 11.4. Мы будем использовать расширение конфигурации, чтобы не снимать основную конфигурацию с поддержки.
Давайте рассмотрим, какие есть способы отключить проверку заполнения реквизитов в 1С. Существует два основных подхода:
Наиболее подходящим инструментом для решения нашей задачи является процедура ОбработкаПроверкиЗаполнения, расположенная в модуле объекта документа. Эта процедура вызывается при интерактивной записи объекта (то есть, когда пользователь нажимает "Записать" или "Провести"), перед тем как объект будет записан в базу данных. Важно отметить, что при программной записи объектов средствами встроенного языка эта процедура обычно не вызывается, если только мы явно не имитируем интерактивную запись.
В процедуру ОбработкаПроверкиЗаполнения в качестве одного из параметров передается массив ПроверяемыеРеквизиты. Этот массив содержит имена всех реквизитов, для которых настроена обязательная проверка заполнения. Если мы удалим из этого массива имена нужных нам реквизитов, то система проигнорирует их при проверке. Для реквизитов табличных частей, таких как Цена и Сумма в таблице Товары, имена указываются в формате "ИмяТабличнойЧасти.ИмяРеквизита", например, "Товары.Цена".
Давайте разберем процесс решения нашей задачи по шагам.
Прежде всего, нам необходимо создать расширение конфигурации и добавить в него нужный нам документ. Этот шаг стандартен для любой доработки через расширение:
Теперь нам нужно добавить процедуру ОбработкаПроверкиЗаполнения в модуль объекта документа "Корректировка приобретения", но уже в контексте нашего расширения. Для этого мы будем использовать аннотацию &Перед.
&Перед. Эта аннотация указывает, что наш код должен быть выполнен *перед* выполнением одноименной процедуры в основной конфигурации. Это позволяет нам модифицировать массив ПроверяемыеРеквизиты до того, как типовая логика начнет его обрабатывать.Первая версия кода, которая была предложена автором темы, выглядела так:
&Перед("ОбработкаПроверкиЗаполнения")
Процедура РасшО_ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
// Вставить содержимое метода.
ПроверяемыеРеквизиты.Удалить(ПроверяемыеРеквизиты.Найти("Товары.Цена"));
ПроверяемыеРеквизиты.Удалить(ПроверяемыеРеквизиты.Найти("Товары.Сумма"));
КонецПроцедуры
Эта доработка уже позволяет решить задачу. При записи документа, когда вызывается ОбработкаПроверкиЗаполнения, наш код срабатывает первым. Он находит элементы массива ПроверяемыеРеквизиты с именами "Товары.Цена" и "Товары.Сумма" и удаляет их из списка. Таким образом, к моменту выполнения типовой процедуры эти реквизиты уже не числятся в списке обязательных к проверке, и система не выдает ошибок.
Хотя предложенное решение работает, оно имеет определенный потенциальный недостаток, на который справедливо указали участники форума. Что произойдет, если в будущих обновлениях конфигурации реквизит "Товары.Цена" или "Товары.Сумма" будет переименован или вовсе удален? В этом случае функция ПроверяемыеРеквизиты.Найти(...) вернет значение Неопределено, и попытка вызвать метод Удалить() для Неопределено приведет к ошибке выполнения. Нам нужно сделать наш код более надежным.
Давайте улучшим код, добавив проверку на существование реквизита в массиве ПроверяемыеРеквизиты перед попыткой его удаления. Это исключит возможность возникновения ошибки в случае изменения или отсутствия реквизита.
Вот улучшенный и более безопасный вариант кода:
&Перед("ОбработкаПроверкиЗаполнения")
Процедура РасшО_ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
// Для реквизита "Товары.Цена"
РеквизитЦена = ПроверяемыеРеквизиты.Найти("Товары.Цена");
Если РеквизитЦена <> Неопределено Тогда
ПроверяемыеРеквизиты.Удалить(РеквизитЦена);
КонецЕсли;
// Для реквизита "Товары.Сумма"
РеквизитСумма = ПроверяемыеРеквизиты.Найти("Товары.Сумма");
Если РеквизитСумма <> Неопределено Тогда
ПроверяемыеРеквизиты.Удалить(РеквизитСумма);
КонецЕсли;
КонецПроцедуры
В этом коде мы сначала ищем элемент в массиве ПроверяемыеРеквизиты с помощью метода Найти(). Результат поиска присваиваем временной переменной (например, РеквизитЦена). Затем мы проверяем, не является ли эта переменная Неопределено. Только если элемент был найден (то есть, РеквизитЦена <> Неопределено), мы выполняем его удаление из массива. Такой подход значительно повышает стабильность и устойчивость нашего расширения к изменениям в основной конфигурации.
Важно понимать, что предложенный подход отключает проверку заполнения для *всего столбца* "Цена" и "Сумма" в табличной части "Товары" документа "Корректировка приобретения". Это означает, что ни одна строка в этой табличной части не будет проверяться на заполнение этих полей. Для нашей изначальной задачи (корректировка старых документов с нулевыми суммами) это является приемлемым решением.
Однако, могут возникнуть ситуации, когда требуется выборочное отключение проверки. Например, если нам нужно отключать проверку только для строк, где "Статья расходов" имеет определенное значение "N", или при других более сложных условиях. В таком случае, простое удаление реквизитов из массива ПроверяемыеРеквизиты будет недостаточным, так как оно отменяет проверку для всех строк без исключения. Для гибкой настройки правил проверки по условиям подойдёт расширение для настраиваемого контроля обязательности реквизитов в документах УТ 11.
Для реализации выборочной проверки нам потребуется более сложная логика. Вот несколько вариантов, которые можно рассмотреть:
&Вместо: Аннотация &Вместо полностью замещает собой типовую процедуру. Это дает полный контроль над процессом проверки заполнения. Мы могли бы перенести весь код типовой процедуры ОбработкаПроверкиЗаполнения в наше расширение, а затем уже внутри него добавить свою логику выборочной проверки. Однако, это значительно усложняет доработку и увеличивает риск ошибок при обновлениях, так как при каждом обновлении типовой конфигурации нам придется сверять и, возможно, адаптировать весь код процедуры. Поэтому для простых случаев, как наш, &Перед является более безопасным выбором.&Вместо, мы можем полностью контролировать, какие ошибки показывать пользователю. Мы можем сами перебрать строки табличной части, проверить нужные реквизиты по своим условиям, а в случае незаполнения добавить сообщение об ошибке с помощью метода Сообщить() или передать Истина в параметр Отказ, чтобы предотвратить запись документа.В нашем случае, когда необходимо отключить проверку *полностью* для этих реквизитов, подход с &Перед является оптимальным по простоте и безопасности.
Для более стандартизированного и универсального подхода к удалению реквизитов из массива ПроверяемыеРеквизиты, особенно если таких реквизитов много, можно рассмотреть использование функций из Библиотеки стандартных подсистем (БСП). В общем модуле ОбщегоНазначения существует процедура УдалитьНепроверяемыеРеквизитыИзМассива, которая предназначена для безопасного удаления реквизитов из массива МассивРеквизитов, проверяя их наличие перед удалением.
Пример использования (если бы мы имели доступ к этому модулю в расширении и процедура была бы экспортной):
&Перед("ОбработкаПроверкиЗаполнения")
Процедура РасшО_ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
МассивУдаляемыхРеквизитов = Новый Массив;
МассивУдаляемыхРеквизитов.Добавить("Товары.Цена");
МассивУдаляемыхРеквизитов.Добавить("Товары.Сумма");
// Предполагается, что ОбщегоНазначения.УдалитьНепроверяемыеРеквизитыИзМассива доступна
// в контексте расширения или была заимствована соответствующим образом
ОбщегоНазначения.УдалитьНепроверяемыеРеквизитыИзМассива(ПроверяемыеРеквизиты, МассивУдаляемыхРеквизитов);
КонецПроцедуры
Такой подход делает код более чистым и использует уже проверенные решения. Однако, необходимо убедиться, что соответствующая процедура БСП доступна и может быть вызвана из расширения.
Предложенное решение по отключению обязательной проверки заполнения реквизитов Товары.Цена и Товары.Сумма с помощью расширения и доработанной процедуры ОбработкаПроверкиЗаполнения является адекватным и рабочим для поставленной задачи. Мы выяснили, что наиболее надежный способ заключается в индивидуальной проверке наличия каждого реквизита в массиве ПроверяемыеРеквизиты перед его удалением. Это значительно снижает риски ошибок при будущих обновлениях или изменениях в конфигурации.
Давайте подытожим ключевые моменты, которые мы рассмотрели:
&Перед позволяет нам безопасно изменить поведение типовой процедуры, не переписывая весь ее код.&Вместо, но с пониманием сопутствующих рисков.Всегда помните, что любое изменение в конфигурации, даже через расширение, требует тщательного тестирования. Убедитесь, что ваше решение не вызывает нежелательных побочных эффектов в других частях системы.