Как запретить редактирование Заказа поставщику, если по нему уже создано Поступление товаров и услуг в 1С:УПП?

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

В процессе разработки в системе 1С:УПП (Управление производственным предприятием) часто возникает задача по обеспечению целостности данных. Одной из таких задач является запрет на изменение или перепроведение документа ЗаказПоставщику, если на его основании уже были введены и проведены документы ПоступлениеТоваровУслуг. Это необходимо для того, чтобы пользователи не могли изменить условия сделки (цены, количество, номенклатуру), когда фактическая поставка уже отражена в учете.

Рассмотрим, почему стандартный подход через проверку реквизита «не срабатывает», и разберем корректные способы реализации этой логики.

Почему не работает прямая проверка реквизита

Разберем ситуацию, с которой столкнулся автор темы. Попытка обратиться к реквизиту ДокументПоступления внутри модуля объекта ЗаказПоставщику обречена на провал по техническим причинам. Проанализируем структуру метаданных УПП: в этой конфигурации связь между заказом и поступлением реализована «снизу вверх». Это означает, что документ Поступление товаров и услуг хранит в себе ссылку на Заказ поставщику (в шапке или в табличной части Товары), но сам заказ «не знает» о своих подчиненных документах на уровне простых реквизитов.

Следовательно, код типа Если ЗначениеЗаполнено(ДокументПоступления) не имеет смысла, так как такого поля в объекте заказа просто не существует. Для решения задачи нам необходимо использовать другие механизмы платформы 1С.

Способ 1. Использование запроса к базе данных

Самый надежный и распространенный метод — это выполнение запроса к таблице документов ПоступлениеТоваровУслуг. Нам нужно выяснить, существуют ли в базе документы поступления, которые ссылаются на наш текущий заказ. Проанализируем пример кода, который следует разместить в процедуре ПередЗаписью модуля объекта документа ЗаказПоставщику:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)

    // Если идет загрузка данных, проверку пропускаем
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

    // Проверку выполняем только при записи существующего документа
    Если ЭтоНовый() Тогда
        Возврат;
    КонецЕсли;

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

    Запрос.УстановитьПараметр("ТекущийЗаказ", Ссылка);

    РезультатЗапроса = Запрос.Выполнить();

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

КонецПроцедуры

В данном примере мы проверяем табличную часть Товары, так как в УПП заказ обычно указывается именно там. Важно отметить использование ПЕРВЫЕ 1 — нам не нужен список всех поступлений, достаточно факта наличия хотя бы одного проведенного документа.

Способ 2. Анализ движений в регистрах накопления

Как справедливо заметили участники обсуждения на форуме, «верняк» — это проверка остатков или оборотов по регистрам. В УПП за выполнение заказов отвечает регистр накопления ЗаказыПоставщикам. Когда оформляется поступление, этот регистр делает движение «Расход», тем самым закрывая потребность по заказу.

Выясним причину, почему этот способ может быть предпочтительнее: он учитывает не только прямые документы поступления, но и другие операции, которые могли закрыть заказ (например, закрытие заказов специальной обработкой). Однако, если задача стоит жестко — реагировать именно на документ поступления, то лучше использовать первый способ.

Рассмотрим логику запроса к регистру:

  1. Обращаемся к виртуальной таблице Обороты регистра ЗаказыПоставщикам.
  2. Фильтруем по измерению ЗаказПоставщику.
  3. Проверяем наличие оборота по расходу.

Способ 3. Использование критериев отбора

В платформе 1С существует объект метаданных КритерииОтбора. В типовых конфигурациях, таких как УПП, часто присутствует критерий СвязанныеДокументы. Мы можем программно получить список всех документов, которые связаны с нашим заказом, не написав ни одной строки сложного SQL-подобного кода.

Посмотрим на пример использования этого механизма:


СписокСвязанныхДокументов = КритерииОтбора.СвязанныеДокументы.Найти(Ссылка);
Для Каждого ТекДокумент Из СписокСвязанныхДокументов Цикл
    Если ТипЗнч(ТекДокумент) = Тип("ДокументСсылка.ПоступлениеТоваровУслуг") Тогда
        // Проверяем, проведен ли документ
        Если ТекДокумент.Проведен Тогда
            Сообщить("Обнаружено проведенное поступление: " + СокрЛП(ТекДокумент));
            Отказ = Истина;
            Прервать;
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

Этот метод удобен тем, что он автоматически анализирует все связи, прописанные в метаданных, включая и шапку, и все табличные части документов поступления.

Дополнительные рекомендации и UX

Проанализируем ситуацию с точки зрения пользователя. Если мы просто пропишем Отказ = Истина в ПередЗаписью, пользователь сможет открыть форму, долго вносить изменения и только в самом конце, при попытке сохранить, получит ошибку. Это вызывает раздражение.

Для улучшения взаимодействия рекомендуем выполнить следующие шаги:

Таким образом, мы рассмотрели несколько вариантов решения задачи. Выбор конкретного метода зависит от архитектурных предпочтений разработчика, но наиболее производительным и «чистым» для конфигурации УПП считается запрос к табличной части документов поступления или использование критериев отбора.

← На главную