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