Как сохранить и заблокировать цены в «Заказе покупателя» после их утверждения?

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

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

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

Анализ проблемы и выбор инструментария

Рассмотрим исходную ситуацию: у нас есть две внешние обработки. В первой происходит выбор цен и их утверждение, во второй — работа с самим заказом. Основная техническая сложность заключается в том, что колонка Цена_ТипЦены на форме заказа не является реквизитом табличной части. Это значит, что при закрытии формы данные в этой колонке не сохраняются в базе данных.

Для решения этой задачи мы можем пойти двумя путями:

  1. Добавление реквизитов в метаданные: создание нового реквизита в табличной части Товары документа Заказ покупателя.
  2. Использование независимого регистра сведений: хранение утвержденных цен и признака блокировки во внешней таблице, связанной с заказом.

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

Шаг 1. Создание независимого регистра сведений

Для того чтобы данные «пережили» закрытие формы и были доступны в разных обработках, нам понадобится создать независимый регистр сведений (назовем его УтвержденныеЦеныЗаказов). Его структура должна позволять однозначно идентифицировать строку документа.

Рекомендуемая структура регистра:

Шаг 2. Реализация механизма утверждения в первой обработке

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

Рассмотрим пример кода для записи данных в регистр:


Процедура КомандаУтвердитьЦены(Команда)
    ЗаказОбъект = Объект.ЗаказПокупателя.ПолучитьОбъект();
    
    // Создаем набор записей регистра для конкретного заказа
    НаборЗаписей = РегистрыСведений.УтвержденныеЦеныЗаказов.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.Заказ.Установить(Объект.ЗаказПокупателя);
    
    Для Каждого СтрокаТЧ Из Объект.ТаблицаТоварыОбработки Цикл
        НоваяЗапись = НаборЗаписей.Добавить();
        НоваяЗапись.Заказ = Объект.ЗаказПокупателя;
        НоваяЗапись.КлючСвязи = СтрокаТЧ.НомерСтроки; // Или специальный идентификатор
        НоваяЗапись.Цена = СтрокаТЧ.Цена_ТипЦены;
        НоваяЗапись.Утверждено = Истина;
    КонецЦикла;
    
    НаборЗаписей.Записать();
    Сообщить("Цены успешно зафиксированы в регистре.");
КонецПроцедуры

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

Шаг 3. Отображение и блокировка во второй обработке (или форме заказа)

Теперь выясним, как «перекачать» эти данные обратно в форму документа и запретить их редактирование. При открытии формы документа нам нужно прочитать данные из регистра и заполнить ту самую программную колонку Цена_ТипЦены.

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

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


Процедура ПриОткрытииФормыДокумента()
    // Запрос к регистру для получения всех утвержденных цен по этому заказу
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   УтвержденныеЦены.КлючСвязи,
        |   УтвержденныеЦены.Цена,
        |   УтвержденныеЦены.Утверждено
        |ИЗ
        |   РегистрСведений.УтвержденныеЦеныЗаказов КАК УтвержденныеЦены
        |ГДЕ
        |   УтвержденныеЦены.Заказ = &Ссылка";
    
    Запрос.УстановитьПараметр("Ссылка", ЭтотОбъект.Ссылка);
    РезультатЗапроса = Запрос.Выполнить().Выгрузить();
    
    // Кэшируем данные в переменной модуля формы (Соответствие)
    мУтвержденныеЦены = Новый Соответствие;
    Для Каждого Стр Из РезультатЗапроса Цикл
        мУтвержденныеЦены.Вставить(Стр.КлючСвязи, Стр.Цена);
    КонецЦикла;
    
    // Если заказ утвержден, блокируем редактирование цен в ТЧ
    Если РезультатЗапроса.Количество() > 0 И РезультатЗапроса[0].Утверждено Тогда
        ЭлементыФормы.Товары.Колонки.Цена.ТолькоПросмотр = Истина;
        ЭлементыФормы.Товары.Колонки.Цена_ТипЦены.ТолькоПросмотр = Истина;
    КонецЕсли;
КонецПроцедуры

Шаг 4. Обработка события вывода строк

Чтобы наша колонка (которая не является реквизитом) заполнялась актуальными данными из нашего кэша, используем событие ПриВыводеСтроки (для обычных форм):


Процедура ТоварыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    // Ищем цену в нашем соответствии по номеру строки или ключу
    УтвержденнаяЦена = мУтвержденныеЦены.Получить(ДанныеСтроки.НомерСтроки);
    
    Если УтвержденнаяЦена <> Неопределено Тогда
        ОформлениеСтроки.Ячейки.Цена_ТипЦены.УстановитьТекст(УтвержденнаяЦена);
        
        // Дополнительно можно визуально выделить утвержденные строки
        ОформлениеСтроки.Ячейки.Цена_ТипЦены.ЦветФона = ЦветаСтиля.ЦветФонаУтвержденнойЗаписи;
    КонецЕсли;
КонецПроцедуры

Почему не стоит использовать временное хранилище или хранилище настроек?

В ходе обсуждения на форуме предлагались варианты с ВременнымХранилищем и ХранилищемНастроек. Проанализируем, почему для данной задачи они подходят плохо:

Дополнительные рекомендации по сопровождению

Разберем несколько важных моментов, которые обеспечат стабильность решения:

  1. Очистка мусора: Чтобы регистр УтвержденныеЦеныЗаказов не разрастался бесконечно, в модуле объекта ЗаказПокупателя в процедуре ПередЗаписью добавьте проверку. Если документ помечается на удаление, необходимо программно удалять записи из регистра, связанные с этим заказом.
  2. Контроль характеристик: Если в вашем учете используется номенклатура с характеристиками, обязательно добавьте Характеристику в измерения регистра. В противном случае утвержденная цена для «Красного дивана» может ошибочно примениться к «Синему дивану», если оператор изменит строку в заказе.
  3. Защита на уровне модуля: Чтобы опытный пользователь не смог обойти блокировку в форме, добавьте проверку в процедуру ПередЗаписью самого документа. Если в регистре стоит флаг Утверждено, сравните текущие цены в ТЧ документа с данными в регистре. При расхождении — отменяйте запись с выводом ошибки.

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

← На главную