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