Обработка редактирования документов выпуска продукции, продолжаем разработку

В своей первой статье Динамические списки -программное управление я рассмотрел их использование управление запросом динамического списка и другие моменты при создании обработки "Редактирование документов выпуска", там было показано начало создания.

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

И так добавим на форму (рис1) еще один динамический список и таблицу значений, в динамический список будем отбирать материалы по определенному документу и используя механизм перетаскивание мышкой будем переносить определенные материалы в таблицу значений.

Рис1. Конструктор формы обработки
Рис1. Конструктор формы обработки

Для заполнения списка материалов по выбранному документу используем следующий код:

&НаКлиенте
Процедура ЗаполнитьДанными(Команда)

	СсылкаДокументаРедактирования = Элементы.СписокДокументовДляРедактирования.ТекущаяСтрока;
	РедактируемыйДокумент = Строка(СсылкаДокументаРедактирования) ; 
	Элементы.РедактируемыйДокумент1.ОбновитьТекстРедактирования();

	Если СсылкаДокументаРедактирования <> неопределено Тогда
		СписокМатериалов.Параметры.УстановитьЗначениеПараметра("ДокументРедактирования",СсылкаДокументаРедактирования);
		Элементы.СписокМатериалов.Обновить();
	КонецЕсли;
КонецПроцедуры

Текст запроса динамического списка "Список материалов" :

ВЫБРАТЬ
	ПроизводствоБезЗаказаМатериалыИРаботы.Номенклатура КАК Номенклатура,
	ПроизводствоБезЗаказаМатериалыИРаботы.Количество КАК Количество,
	ПроизводствоБезЗаказаМатериалыИРаботы.НомерГруппыЗатрат КАК НомерГруппыЗатратМатериалы,
	ПроизводствоБезЗаказаВыходныеИзделия.Номенклатура КАК Продукция,
	ПроизводствоБезЗаказаВыходныеИзделия.НомерГруппыЗатрат КАК НомерГруппыЗатратПродукция,
	ПроизводствоБезЗаказаМатериалыИРаботы.Номенклатура.ЕдиницаИзмерения КАК НоменклатураЕдиницаИзмерения,
	ПроизводствоБезЗаказаМатериалыИРаботы.НомерСтроки КАК НомерСтроки
ИЗ
	Документ.ПроизводствоБезЗаказа.МатериалыИРаботы КАК ПроизводствоБезЗаказаМатериалыИРаботы
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПроизводствоБезЗаказа.ВыходныеИзделия КАК ПроизводствоБезЗаказаВыходныеИзделия
		ПО ПроизводствоБезЗаказаМатериалыИРаботы.Ссылка = ПроизводствоБезЗаказаВыходныеИзделия.Ссылка
			И ПроизводствоБезЗаказаМатериалыИРаботы.НомерГруппыЗатрат = ПроизводствоБезЗаказаВыходныеИзделия.НомерГруппыЗатрат
ГДЕ
	ПроизводствоБезЗаказаМатериалыИРаботы.Ссылка = &ДокументРедактирования

Так это выглядит в приложении при нажатии кнопки "Заполнить из выбранного документа" рис2.

Рис2 Выбираем данные для редактирование
Рис2 Выбираем данные для редактирование

Подготовка данных для редактирования документа "Производство без заказа"

Удерживая клавишу Ctrl отмечаем те материалы количество которых будет редактироваться и мышкой перетаскиваем их в таблицу значений "Редактируемые данные".

И вот тут при написании кода, сталкиваешься еще с одним секретом динамического списка при перетаскивании элементов мы получаем номер строки в списке а не значение рис3-4.

Рис3. Перетаскивание элементов динамического списка
Рис3. Перетаскивание элементов динамического списка
Рис;. Массив данных получаемых при перетаскивании
Рис;. Массив данных получаемых при перетаскивании

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

Рис 5 Перетаскивание из дерева значений
Рис 5 Перетаскивание из дерева значений

Для решения этой ситуации используем следующий код в котором обращаемся к строкам динамического списка по номеру строки:

Для каждого элемент ИЗ  ПараметрыПеретаскивания.Значение Цикл
		СтрокаПереноса = Элементы.СписокМатериалов.ДанныеСтроки(элемент);
		НоваяСтрока = РедактируемыеДанные.Добавить();
		НоваяСтрока.Номенклатура = СтрокаПереноса.Номенклатура;
		НоваяСтрока.ЕдИзм = СтрокаПереноса.НоменклатураЕдиницаИзмерения;
		НоваяСтрока.КоличествоВДокументе = СтрокаПереноса.Количество;			
		НоваяСтрока.КоличествоФактическое = 0; 
		НоваяСтрока.НомерСтроки = СтрокаПереноса.НомерСтроки;
	КонецЦикла; 

В реквизит "Пояснение к исправлению" добавляем описание причин отклонения количества от переданного с бетономешалок рис6.

Рис 6 Пояснение к изменению
Рис 6 Пояснение к изменению

Запись измененных данных в документ выпуска

Осталось нажать кнопку "Редактировать выпуск" код:

&НаКлиенте
Процедура РедактироватьВыпуск(Команда)
	Подразделение = элементы.СписокДокументовДляРедактирования.ТекущиеДанные.Подразделение;
	ДокументСсылка = элементы.СписокДокументовДляРедактирования.ТекущаяСтрока;
	//РедактироватьВыпускНаСервере(Подразделение);
	ЗаписьВРегистр(Подразделение);
	РезультатДействия = РедактироватьДокументНаСервере(ДокументСсылка,Подразделение); 
	
	Если РезультатДействия = Истина Тогда
		ПоказатьОповещениеПользователя("Редактирование - " + Строка(ДокументСсылка)+ " выполнено успешно" , "Редактирование документа") ;
	Иначе
		ПоказатьОповещениеПользователя("Редактирование - " + Строка(ДокументСсылка)+ "не выполнено!!", "Редактирование документа") ;
	КонецЕсли;
	РедактируемыеДанные.Очистить();
КонецПроцедуры

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

Создаем этот регистр а также справочник в котором будут хранится номера созданных корректировок в зависимости от подразделения выпуска Рис7-8

Рис 7. Регистр
Рис 7. Регистр
Рис 8. Справочник
Рис 8. Справочник

Сам документ имеющий в комментарии слово "создан автоматически" закрыт от ручного изменения что соответствует требованиям службы безопасности рис9.

Рис9 Документ не доступен на редактирование
Рис9 Документ не доступен на редактирование

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

рис 10. Отключение панели команд списка
рис 10. Отключение панели команд списка

И добавлена лишь одна команда "Расширенный поиск" рис11

рис 11. Добавление команды на форму
рис 11. Добавление команды на форму

Можно использовать пользовательские настройки отбором и т.д.. выбирая к примеру свое подразделение но код написан для максимально простой и удобной работы пользователя с созданными фильтрами.

Если есть необходимость включения панели команд списка все таки можно часть команд отключить чтобы пользователь не повлиял на логику работы jотключив часть команд так : Рис 12

Рис12 .Установка команд списка
Рис12 .Установка команд списка

Или открыв Настройки списка - Настройки снять галочки с "Включать в пользовательские настройки" в одной из вкладок настроек, отвечающей за те или иные действия со списком: Рис 13.

Рис 13.Отключение пользовательских настроек.
Рис 13.Отключение пользовательских настроек.

Вот собственно и все! Возможно это материал кому то уменьшит время разработки если возникнет подобная задача корректировки закрытых от ручного редактирования документов выпуска.

Всем хорошего настроения и успехов!

Как и обещал привожу весь код:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	//Вставить содержимое обработчика 
	СписокМатериалов.Параметры.УстановитьЗначениеПараметра("ДокументРедактирования",Документы.ПроизводствоБезЗаказа.ПустаяСсылка());
	
КонецПроцедуры
&НаКлиенте
Процедура ПодразделениеВыпускаПриИзменении(Элемент)	
	
	ОбновлениеПараметровСписка(ПодразделениеВыпуска,ДатаДокумента);	
	
КонецПроцедуры 

&НаКлиенте
Процедура ДатаДокументаПриИзменении(Элемент)

	ОбновлениеПараметровСписка(ПодразделениеВыпуска,ДатаДокумента);
	
КонецПроцедуры


&НаСервере
Процедура ОбновлениеПараметровСписка(ПодразделениеВыпуска,ДатаДокумента); 
	
	Если ЗначениеЗаполнено(ПодразделениеВыпуска) = Ложь И ДатаДокумента = '00010101' Тогда	
		СписокДокументовДляРедактирования.Параметры.Элементы[0].Использование = Ложь;
		СписокДокументовДляРедактирования.Параметры.Элементы[1].Использование = Ложь;
		//СписокДокументовДляРедактирования.Параметры.УстановитьЗначениеПараметра("ПодразделениеВыпуска",Подразделение);
		//СписокДокументовДляРедактирования.Параметры.УстановитьЗначениеПараметра("ДатаДокумента",ДатаДокумента);
		
	ИначеЕсли ЗначениеЗаполнено(ПодразделениеВыпуска) = Истина   И ДатаДокумента = '00010101'  Тогда
		СписокДокументовДляРедактирования.Параметры.Элементы[0].Использование = Ложь;
		СписокДокументовДляРедактирования.Параметры.Элементы[1].Использование = Истина; 
		СписокДокументовДляРедактирования.Параметры.УстановитьЗначениеПараметра("ПодразделениеВыпуска",ПодразделениеВыпуска);
		//СписокДокументовДляРедактирования.Параметры.УстановитьЗначениеПараметра("ДатаДокумента",ДатаВыпуска);
		
	ИначеЕсли ЗначениеЗаполнено(ПодразделениеВыпуска) = Истина   И НЕ ДатаДокумента = '00010101'  Тогда
		СписокДокументовДляРедактирования.Параметры.Элементы[0].Использование = Истина;
		СписокДокументовДляРедактирования.Параметры.Элементы[1].Использование = Истина; 
		СписокДокументовДляРедактирования.Параметры.УстановитьЗначениеПараметра("ПодразделениеВыпуска",ПодразделениеВыпуска);
		СписокДокументовДляРедактирования.Параметры.УстановитьЗначениеПараметра("ДатаДокумента",ДатаДокумента);
		
	ИначеЕсли ЗначениеЗаполнено(ПодразделениеВыпуска) = Ложь   И НЕ ДатаДокумента = '00010101'  Тогда
		СписокДокументовДляРедактирования.Параметры.Элементы[0].Использование = Истина;
		СписокДокументовДляРедактирования.Параметры.Элементы[1].Использование = Ложь; 
		//СписокДокументовДляРедактирования.Параметры.УстановитьЗначениеПараметра("ПодразделениеВыпуска",ПодразделениеВыпуска);
		СписокДокументовДляРедактирования.Параметры.УстановитьЗначениеПараметра("ДатаДокумента",ДатаДокумента);
		
	КонецЕсли;

	Элементы.СписокДокументовДляРедактирования.Обновить();
	
КонецПроцедуры	

&НаСервере
Функция ТекстЗапросаДокументы() Экспорт
	
	ТекстЗапроса = "ВЫБРАТЬ
	|	ДокументПроизводствоБезЗаказа.Ссылка КАК Ссылка
	|ИЗ
	|	Документ.ПроизводствоБезЗаказа КАК ДокументПроизводствоБезЗаказа
	|ГДЕ
	|	ДокументПроизводствоБезЗаказа.ПометкаУдаления = &Ложь
	|	И ДокументПроизводствоБезЗаказа.Проведен = &Истина
	|{ГДЕ
	|	(ДокументПроизводствоБезЗаказа.Подразделение = &ПодразделениеВыпуска),
	|	(ДокументПроизводствоБезЗаказа.Дата МЕЖДУ НАЧАЛОПЕРИОДА(&ДатаДокумента, ДЕНЬ)),
	|	И КОНЕЦПЕРИОДА(&ДатаДокумента, ДЕНЬ))}";		
	
	Возврат ТекстЗапроса;
	
КонецФункции

&НаКлиенте
Процедура ЗаполнитьДанными(Команда)

	СсылкаДокументаРедактирования = Элементы.СписокДокументовДляРедактирования.ТекущаяСтрока;
	РедактируемыйДокумент = Строка(СсылкаДокументаРедактирования) ; 
	Элементы.РедактируемыйДокумент1.ОбновитьТекстРедактирования();

	Если СсылкаДокументаРедактирования <> неопределено Тогда
		СписокМатериалов.Параметры.УстановитьЗначениеПараметра("ДокументРедактирования",СсылкаДокументаРедактирования);
		Элементы.СписокМатериалов.Обновить();
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура Очистить(Команда)
	ОчиститьНаСервере();	
КонецПроцедуры 

&НаКлиенте
Процедура РедактируемыеДанныеПеретаскивание(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
	
	Для каждого элемент ИЗ  ПараметрыПеретаскивания.Значение Цикл
		СтрокаПереноса = Элементы.СписокМатериалов.ДанныеСтроки(элемент);
		НоваяСтрока = РедактируемыеДанные.Добавить();
		НоваяСтрока.Номенклатура = СтрокаПереноса.Номенклатура;
		НоваяСтрока.ЕдИзм = СтрокаПереноса.НоменклатураЕдиницаИзмерения;
		НоваяСтрока.КоличествоВДокументе = СтрокаПереноса.Количество;			
		НоваяСтрока.КоличествоФактическое = 0; 
		НоваяСтрока.НомерСтроки = СтрокаПереноса.НомерСтроки;
	КонецЦикла; 
КонецПроцедуры

&НаСервере
Процедура ОчиститьНаСервере() 
	
	СписокМатериалов.Параметры.УстановитьЗначениеПараметра("ДокументРедактирования",Документы.ПроизводствоБезЗаказа.ПустаяСсылка());
	Элементы.СписокМатериалов.Обновить();
	РедактируемыйДокумент =""; 
	Элементы.РедактируемыйДокумент1.ОбновитьТекстРедактирования();
	
КонецПроцедуры	

&НаКлиенте
Процедура РедактируемыеДанныеПроверкаПеретаскивания(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
	СтандартнаяОбработка = Ложь;
КонецПроцедуры

&НаКлиенте
Процедура РедактироватьВыпуск(Команда)
	Подразделение = элементы.СписокДокументовДляРедактирования.ТекущиеДанные.Подразделение;
	ДокументСсылка = элементы.СписокДокументовДляРедактирования.ТекущаяСтрока;

	ЗаписьВРегистр(Подразделение);
	РезультатДействия = РедактироватьДокументНаСервере(ДокументСсылка,Подразделение); 
	
	Если РезультатДействия = Истина Тогда
		ПоказатьОповещениеПользователя("Редактирование - " + Строка(ДокументСсылка)+ " выполнено успешно" , "Редактирование документа") ;
	Иначе
		ПоказатьОповещениеПользователя("Редактирование - " + Строка(ДокументСсылка)+ "не выполнено!!", "Редактирование документа") ;
	КонецЕсли;
	РедактируемыеДанные.Очистить();  
	
КонецПроцедуры

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

&НаСервере
Функция  РедактироватьДокументНаСервере(ДокументСсылка,Подразделение)
	
	Если Не ЗначениеЗаполнено(ДокументСсылка) Тогда
		Возврат ложь;
	КонецЕсли;
	
	ДокументОбъект = ДокументСсылка.ПолучитьОбъект();
	
	Для Каждого СтрокаТаблицы Из РедактируемыеДанные Цикл 
		СтрокаТЧ = ДокументОбъект.МатериалыИРаботы[СтрокаТаблицы.НомерСтроки-1];		
		Если СтрокаТЧ.Номенклатура = СтрокаТаблицы.Номенклатура Тогда
			СтрокаТЧ.Количество = СтрокаТаблицы.КоличествоФактическое;
			СтрокаТЧ.КоличествоУпаковок = СтрокаТаблицы.КоличествоФактическое;
		Иначе
			Сообщить("Номенклатура в строке " + СтрокаТаблицы.НомерСтроки + " не соответствует переданной номенклатуре.");
		КонецЕсли;
	КонецЦикла;
	
	Попытка
		ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
		ОбновитьНомерКорректировки(Подразделение);	
		Рез = Истина;	
		Возврат Рез;	
	Исключение
		Сообщить(ОписаниеОшибки());
		Рез = Ложь;
		Возврат Рез;
	КонецПопытки;
КонецФункции	

Функция НомерКорректировки(Подразделение)
	номер = 0;
	sps_НомераКорректировокСсылка = СсылкаНаСправочник();
	
	ЗначенияРеквизитов = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(sps_НомераКорректировокСсылка, "НомерКБ, НомерКФ,НомерКК,НомерКА");
		
	Если Подразделение.Наименование = "Бетоносмесительный цех" Тогда	
		номер ="Б" + Строка(ЗначенияРеквизитов.НомерКБ + 1);		
	ИначеЕсли Подразделение.Наименование = "Формовочный цех" Тогда	
		номер ="Ф" +   Строка(ЗначенияРеквизитов.НомерКФ + 1);
	ИначеЕсли  Подразделение.Наименование = "Кассетный цех" Тогда
		номер ="К" +   Строка(ЗначенияРеквизитов.НомерКК + 1);
	ИначеЕсли Подразделение.Наименование = "Арматурный цех" Тогда		
		номер ="А" +  Строка(ЗначенияРеквизитов.НомерКА + 1);
	КонецЕсли;
	
	Возврат Номер;
	
КонецФункции 

&НаСервере
Процедура ОбновитьНомерКорректировки(Подразделение)
	
	sps_НомераКорректировокСсылка = СсылкаНаСправочник(); 
	
	НомерОбъект = sps_НомераКорректировокСсылка.ПолучитьОбъект();
	
	Если Подразделение.Наименование = "Бетоносмесительный цех" Тогда
		НомерОбъект.НомерКБ = НомерОбъект.НомерКБ + 1;
	КонецЕсли; 
	
	НомерОбъект.Записать();
	
КонецПроцедуры 

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