gifts2017

Вывод остатка товаров на складе в документ Реализация товаров и услуг (для конфигурации Управление Торговлей 11.2 / 11.3)

Опубликовал Алексей Че (dklp) в раздел Программирование - Практика программирования

Пример динамического изменения (добавления) данных в табличной части формы стандартного документа из внешней обработки с использованием типа команды "ЗаполнениеФормы".

Информация для пользователей:

Сразу объясню, зачем это нужно, ведь при использовании стандартной обработки подбора товара (через меню Заполнить -> Подобрать товары) остаток товара на складе и так отображается. Но если, скажем, вы заполняете документ путем загрузки данных из внешнего файла (например, из Excel-заявки покупателя), то в этом случае складские остатки уже не отображаются, и при попытке записать документ могут вылезать сообщения о том, что какой-то товар недоступен. Приходится выискивать эти позиции товара и удалять из документа, поэтому было бы неплохо видеть сразу, что именно и где удалять. Еще, например, если товара осталось мало, и менеджеру нужно уменьшить запрашиваемое покупателем количество (чтобы и других покупателей не обделить), то было бы неплохо сразу в документе видеть, сколько в данный момент всего есть товара на складе. В общем, наши девчонки меня очень просили - я сделал. Может, кому-нибудь ещё пригодится.

Как это работает:
Если вам нужно быстро отобразить остатки, вы нажимаете на кнопку Заполнение -> Показать остаток товара на складе, и в уже открытую таблицу с товарами добавляется колонка, куда будет выведен доступный остаток товара на складе по каждой позиции номенклатуры из таблицы. Через меню Все действия -> Изменить форму вы можете найти группу элементов Заполнение, выбрать для неё Вид -> Группа кнопок, перетащить кнопку в удобное для вас место на форме документа. Там же можно переименовать заголовок новой колонки, передвинуть её в нужное вам место таблицы. Эти настройки сохранятся для всех последующих документов.

Подключение внешней обработки:
В меню НСИ и администрирование -> Настройка параметров системы -> Печатные формы, отчеты и обработки -> Отчеты и обработки -> Дополнительные отчеты и обработки нажимаете кнопку Создать, после чего автоматически откроется окно, где нужно будет указать путь к файлу обработки. Затем нужно снять галочку Показывать в списках и нажать на кнопку Записать и закрыть (то есть обработка вывода остатков будет вызываться только из самого документа "Реализация товаров и услуг", в списках документов - она не нужна).


Информация для разработчиков:

Я решил выложить код обработки, потому что при написании его столкнулся с трудностями, и надеюсь новичкам (таким же как и я) этот материал поможет разобраться с тем, как работает обработка заполнения объекта с типом команды ЗаполнениеФормы. В сети есть куча материала на тему, как заполнять объекты через ВызовКлиентскогоМетода. Лично для меня эталонной стал вот эта публикация: http://infostart.ru/public/84119/. Но там есть масса ограничений при работе с формой владельца. Так, в форме владельца не получится динамически создать новые реквизиты и элементы формы, применить условное оформление и т.п. (не говоря уже о том, что нужно создавать "невидимую" форму обработки и уже из модуля этой формы обращаться к форме владельца).

Частично можно было решить вопрос (в моем случае вопрос с динамическим добавлением на форму документа "Реализация товаров и услуг" новых реквизитов и элементов) через переопределение стандартных процедур создания форм в общем модуле МодификацияКонфигурацииПереопределяемый. Ваш код в этом модуле, по-идее, не должен затираться при обновлении конфигурации, но всё равно нужно было править типовую конфигурацию. Многие стараются этого избегать. Если интересно, можете почитать здесь: http://infostart.ru/public/424358/.

А вот тип команды обработки ЗаполнениеФормы является большим шагом вперед и позволяет работать непосредственно с контекстом формы самого документа на сервере прямо из модуля объекта внешней обработки. Никаких дополнительных форм при этом создавать не нужно. Обращение к форме происходит через параметр ПараметрыВыполнения.ЭтаФорма. Это позволяет на лету менять форму владельца, добавлять новые реквизиты, элементы и заполнять уже существующие (при использовании ВызовКлиентскогоМетода нельзя было на сервере обратиться к форме владельца - свойство ЭтоФорма.ВладелецФормы было на сервере недоступно, и передавать на сервер можно было только объект формы).

Единственный минус в том, что тип команды ЗаполениеФормы реализован в новых БСП и доступен только в свежих релизах типовых конфигураций. Хотя "новый" - это понятие, вообще говоря, условное. Я так думаю, что этот материал сам по себе уже далеко не новый. Все спецы давно в курсе, конечно. Но я адресую эту публикацию в первую очередь новичкам, потому что повторюсь: на форумах куча древних веток на тему заполнения объектов, а из свеженького - совсем мало. Секрет что ли какой-то?

Вообще, очень рекомендую отыскать в сети последнюю версию БСП. Там в архиве идет демонстрационная база, где можно наглядно посмотреть как реализованы обработки заполнения объектов, и не только. А при желании можно их выгрузить во внешний файл, и слегка подправив код, использовать как свои собственные. Правда, приходится следить за тем, чтобы версия БСП не отставала от той, которая внедрена в типовой конфигурации, и если после очередного обновления обработка слетит, быстро подправить её, указав более свежую версию БСП. Надеюсь, я ничего не напутал.  В этом, конечно, есть недостаток в плане универсальности.

Кстати, узнать какую версию БСП использует ваша типовая конфигурация можно в режиме Конфигуратора: Общие -> Общие модули -> ОбновлениеИнформационнойБазыБСП.
 
Теперь перехожу от слов к делу. Ниже представлен код модуля объекта внешней обработки создания и заполнения колонки складских остатков в табличной части Товары документа "Реализация товаров и услуг":

// возвращает сведения о внешней обработке
Функция СведенияОВнешнейОбработке() Экспорт
	
	// здесь я указываю актуальную версию БСП, которую ипользует типовая конфигурация 
	ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.3.2.53");

	ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиЗаполнениеОбъекта();
	ПараметрыРегистрации.Версия = "1.0";
	ПараметрыРегистрации.Назначение.Добавить("Документ.РеализацияТоваровУслуг");
	ПараметрыРегистрации.БезопасныйРежим = Ложь;
	
	НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
	НоваяКоманда.Представление = НСтр("ru = 'Показать остаток товара на складе'");
	НоваяКоманда.Идентификатор = "ПоказатьОстатки";
	
	// указываю тип команды "ЗаполнениеФормы" вместо "ВызовКлиентскогоМетода" 	
	НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыЗаполнениеФормы();
	НоваяКоманда.ПоказыватьОповещение = Ложь;
	НоваяКоманда.Скрыть = Истина;
	
	Возврат ПараметрыРегистрации;
	
КонецФункции

// непосредственно код выполнения команды обработки
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения, ПараметрыВыполнения) Экспорт
	
	Если ИдентификаторКоманды = "ПоказатьОстатки" Тогда
		
		// собственно, это и есть форма владельца (то есть форма документа назначения, в котором выполняется обработка)
		// её можно изменять на лету (динамически добавлять новые реквизиты и заполнять уже существующие, 
		// программно применять условное оформление и т.п.)
		// причем без необходимости назойливой проверки записанности данных перед вызовом обработки
		
		Форма = ПараметрыВыполнения.ЭтаФорма;
		
		// дальше рассматривается пример динамического создания и заполнения новой информационной колонки в табличной части Товары 
		// для отображения текущих остатков товара на складе 
		
		// создаем новый реквизит отбъекта и соответствующий ему элемент формы
		Если Форма.Элементы.Найти("ТоварыОстатки") = Неопределено Тогда 
			
			Реквизиты = Новый Массив; 
			Реквизиты.Добавить(Новый РеквизитФормы("Остатки", Новый ОписаниеТипов("Число"), "Объект.Товары" , "Доступно на складе", Ложь)); 
			Форма.ИзменитьРеквизиты(Реквизиты); 
	
			НовыйЭлементФормы = Форма.Элементы.Добавить("ТоварыОстатки", Тип("ПолеФормы"), Форма.Элементы.Товары); 			
			НовыйЭлементФормы.Вид = ВидПоляФормы.ПолеВвода; 
			НовыйЭлементФормы.ТолькоПросмотр = Истина;
			НовыйЭлементФормы.ПутьКДанным = "Объект.Товары.Остатки";
			
		КонецЕсли;

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

		// код, конечно, требует оптимизации, потому что каждый раз в цикле обращаться с запросом к регистру неправильно
		// лучше, наверное, сначала сформировать массив всех строк номенклатуры, выполнить один запрос и потом уже его в цикле обрабатывать
		// но для наглядности пусть остается пока так
		
	КонецЕсли;
	
КонецПроцедуры

// вспомогательная функция запроса к регистру накопления ТоварыНаСкладах
Функция ПолучитьОстатокТовараИзРегистра(Номенклатура)
	
	Запрос = Новый Запрос;
	Запрос.Текст ="
		|	ВЫБРАТЬ
		|		ТоварыНаСкладахОстатки.Номенклатура,
		|		ЕСТЬNULL(ТоварыНаСкладахОстатки.ВНаличииОстаток, 0) - ЕСТЬNULL(ТоварыНаСкладахОстатки.КОтгрузкеОстаток, 0) КАК Остаток
		|	ИЗ 
		|		РегистрНакопления.ТоварыНаСкладах.Остатки( , Номенклатура = &Номенклатура) КАК ТоварыНаСкладахОстатки";
		
	Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
	Выборка = Запрос.Выполнить().Выбрать();
	
	Если Выборка.Следующий() Тогда
        Возврат Выборка.Остаток;
    Иначе 
        Возврат 0;
	КонецЕсли;    
	
КонецФункции 

Примечание:
Код самой обработки (той, что выложена для скачивания) немного отличается от представленного выше. Туда добавлено условие отбора по складу в запросе, а также немного форматирования и всякой мелочи. Например, если товара нет на складе, то выводится текстовая строка "<нет на складе>" вместо пустых полей, колонка с остатками добавляется не в конец таблицы, а вставляется сразу за колонкой Количество, изменен цвет текста и т.п.

Скачать файлы

Наименование Файл Версия Размер
ВыводОстатковВДокументеРТУ(ЗаполнениеФормы) 14
.epf 5,95Kb
30.04.16
14
.epf 5,95Kb Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Антон Антонович (Ramir555) 10.05.16 08:37
Добрый день, спасибо за статью. Не подскажите, зачем НоваяКоманда.Скрыть = Истина?

В описание нашел

Признак того, что это служебная команда. Если установить в значение Истина, то команда скрывается в карточке дополнительного объекта.


Но так и не понял о каком объекте идет речь, что истина что ложь все равно отображается и в форме документа. Вы для чего её используете?
2. Алексей Че (dklp) 10.05.16 13:08
(1) Ramir555, думаю, в данном конкретном случае можно эту строку кода вообще выкинуть. разницы никакой. я сам так и не разобрался, в каком месте этот параметр скрывает команду
3. Sergey Ermakov (yandesi) 11.10.16 16:01
Нужна такая же для УНФ 1.6.7
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа