Как запретить изменение документа «Поступление товаров и услуг», если по нему уже оформлены продажи?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

В процессе работы с программами 1С часто возникает ситуация, когда пользователи пытаются изменить или удалить строки в проведенном документе Поступление товаров и услуг за прошлый период. Если товары из этого поступления уже были проданы (списаны со склада или реализованы конкретные партии), любое изменение документа-первоисточника приводит к искажению себестоимости, появлению отрицательных остатков или сбоям в цепочке партионного учета. Проанализируем, как правильно защитить систему от подобных действий штатными и программными средствами.

Метод 1. Использование штатных механизмов конфигураций

Прежде чем писать код, стоит рассмотреть готовые функциональные возможности типовых решений 1С:

  1. Установка даты запрета редактирования: Самый простой и надежный способ — запретить изменять документы задним числом. Установите дату запрета на вчерашний день или конец прошлого месяца/квартала. В таком случае пользователи не смогут редактировать документы поступления без специальных прав.
  2. Использование документа «Корректировка поступления»: Если поставщик прислал исправленные документы, правильным методическим решением будет проведение документа Корректировка поступления в текущем периоде, вместо исправления оригинального проведённого документа.
  3. Настройка дополнительных прав пользователей: В конфигурациях (например, УТ 10.3 или УПП 1.3) доступно ограничение прав, запрещающее пользователям редактирование проведенных документов.

Метод 2. Программная блокировка формы документа при открытии

Если необходимо запретить редактирование только тех документов поступления, по которым уже есть фактические движения расхода товаров, разберем программную проверку при открытии формы.

Посмотрим на алгоритм: при открытии формы проведенного документа выполняется запрос к регистру накопления (например, ПартииТоваровНаСкладах или ТоварыНаСкладах). Если по партионному документу найдены движения с видом Расход, переводим форму в режим «Только просмотр».

Пример реализации в обработчике события ПриОткрытии формы документа:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |	ПартииТоваров.Регистратор КАК ДокументСписания
    |ИЗ
    |	РегистрНакопления.ПартииТоваровНаСкладах КАК ПартииТоваров
    |ГДЕ
    |	ПартииТоваров.ДокументОприходования = &ДокументОприходования
    |	И ПартииТоваров.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)";

Запрос.УстановитьПараметр("ДокументОприходования", ЭтотОбъект.Ссылка);

РезультатЗапроса = Запрос.Выполнить();
Если НЕ РезультатЗапроса.Пустой() Тогда
    ЭтаФорма.ТолькоПросмотр = Истина;
    Предупреждение("По данному поступлению уже выполнены списания товаров! Изменение документа запрещено.");
КонецЕсли;

Метод 3. Проверка перед записью или удалением строк табличной части

Ограничения только на уровне формы недостаточно, так как документ может быть изменен программно или снят с проведения из списка. Чтобы полностью перекрыть возможность изменения проведённых партий, разберем подписку на событие ПередЗаписью документа или обработку события ПередУдалением табличной части.

Рассмотрим порядок действий при проверке перед записью:

  1. Проверяем, проведен ли документ и изменился ли состав/количество номенклатуры (сравниваем табличную часть объекта в памяти и данные из базы по ссылке).
  2. Собираем список товаров, по которым уменьшилось количество или которые были полностью удалены.
  3. Выполняем запрос к партионному регистру и проверяем, списывалась ли данная партия после даты документа.
  4. Если обнаружен расход, устанавливаем Отказ = Истина и выводим понятное пользователю сообщение.

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


Если Не Отказ И ЭтотОбъект.Проведен Тогда
    УстановитьПривилегированныйРежим(Истина);
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |	ПартииТоваров.Номенклатура
        |ИЗ
        |	РегистрНакопления.ПартииТоваровНаСкладах КАК ПартииТоваров
        |ГДЕ
        |	ПартииТоваров.ДокументОприходования = &Ссылка
        |	И ПартииТоваров.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)";
        
    Запрос.УстановитьПараметр("Ссылка", Ссылка);
    
    Если НЕ Запрос.Выполнить().Пустой() Тогда
        Отказ = Истина;
        Сообщить("Нельзя изменить или отменить проведение поступления: по созданной партии уже есть движения реализации!");
    КонецЕсли;
КонецЕсли;

Важные технические нюансы реализации

При внедрении программных проверок проанализируем следующие ограничения и особенности платформы 1С:

  1. Работа с RLS (права на уровне записей): Если у пользователя ограничены права доступа, обычный запрос к регистру списаний может вернуть пустой результат из-за RLS. Проверку движений обязательно нужно выполнять с вызовом функции УстановитьПривилегированныйРежим(Истина).
  2. Защита от отмены проведения: Проверку наличия списанных партий необходимо размещать не только в событиях записи, но и в процедуре ОбработкаОтменыПроведения модуля документа.
  3. Проверка связанных документов (Критерии отбора): Для ускорения проверки вместо запроса к регистру можно использовать платфоменный механизм КритерииОтбора.СвязанныеДокументы. Если дерево подчиненности содержит проведенные реализации или возвраты, блокируем редактирование.
  4. Применение расширений: В современных конфигурациях доработку логики перед удалением или записью рекомендуется выносить в расширение конфигурации, чтобы сохранить типовую конфигурацию на поддержке.
← На главную