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

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

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

И так добавим на форму (рис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 Документ не доступен на редактирование

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

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

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

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

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

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

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

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

&НаКлиенте
Процедура ПодразделениеВыпускаПриИзменении(Элемент)
	
	Если Элемент.ТекстРедактирования = "" Тогда
		СбросПараметровСписка();	
	КонецЕсли;	
	
КонецПроцедуры

&НаСервере
Процедура СбросПараметровСписка(); 
	
	СписокДокументовДляРедактирования.Параметры.Элементы[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;
		НовыйЭлемент.Записать();	
		Ссылка = НовыйЭлемент.Ссылка;	
	Иначе	
		Выборка.Следующий();
		Ссылка = Выборка.Ссылка;
	КонецЕсли; 
	
	Возврат Ссылка;
	
Конецфункции	

Комментарии (2)


  1. BarakAdama
    17.10.2025 13:43

    Сергей, в одной из предыдущих ваших статей я уже просил не использовать хаб Habr для статей не про сам сайт. Просьба была проигнорирована(


  1. bku41
    17.10.2025 13:43

    Двойственное ощущение. С одной стороны, за рефакторинг подобного "кода" мне неплохо платят. С другой, даже за деньги неприятно в этом ковыряться.

    Извините, но вы демонстрируете полное непонимание того, как это в принципе работает.

    Какой, к черту, текст редактирования для ссылочного поля?