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