Управление сложностью при доработке типовых конфигураций

17.04.20

Задачи пользователя - Адаптация типовых решений

Описан пример доработки типовой конфигурации 1С:ERP Управление предприятием с помощью подсистемы Модель объекта.

Со сложностью при разработке новых объектов метаданных с большим количеством зависимостей между реквизитами отлично справляется подсистема Модель объекта. Но может ли она помочь при доработке типовых объектов метаданных? На мой взгляд может. Для примера рассмотрим доработку документа "Заказ клиента" в типовой конфигурации 1С:ERP Управление предприятием версии 2.4.11.93

В этой конфигурации для зависимостью между реквизитами используется набор общих модулей, начинающихся с ОбработкаТабличнойЧасти

Для определения зависимостей между реквизитами используется понятие действия, которые описаны в общем модуле в виде процедур, а при изменении реквизита от которого зависят другие необходимо передать в общий модуль упорядоченный список действий. Например при изменении количества упаковок в строке табличной части "Товары":

	СтруктураДействий.Вставить("ПересчитатьКоличествоЕдиниц");
	СтруктураДействий.Вставить("ПересчитатьСуммуНДС", СтруктураПересчетаСуммы);
	СтруктураДействий.Вставить("ПересчитатьСуммуСНДС", СтруктураПересчетаСуммы);
	СтруктураДействий.Вставить("ПересчитатьСумму");
	СтруктураДействий.Вставить("ПересчитатьСуммуСУчетомРучнойСкидки", Новый Структура("Очищать", Ложь));
	СтруктураДействий.Вставить("ПересчитатьСуммуСУчетомАвтоматическойСкидки", Новый Структура("Очищать", Истина));
	СтруктураДействий.Вставить("ЗаполнитьДубликатыЗависимыхРеквизитов", ЗависимыеРеквизиты());

Недостатки такого подхода очевидны:

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

2. Если мы хотим добавить в табличную часть новый реквизит который зависит от количества упаковок нам нужно добавить новое действие в набор общих модулей и добавить это действие во все списки где явно или не явно меняется реквизит "Количество упаковок". И так для каждого реквизита

В качестве примера рассмотрим следующую задачу. Необходимо в заказ клиента выводить цену и стоимость закупки каждого товара. Соответственно мы добавляем в табличную часть 3 реквизита "Цена закупки", "Валюта закупки", "Стоимость закупки". Кроме того необходима возможность изменять количество в заказе клиента из новой обработки и не хочется при добавлении новых действий поставщиком типовой конфигурации вносить какие либо изменени в новую обработку

Для решения данной задачи необходимо сделать следующее:

1. Описать все зависимости реквизита "КоличествоУпаковок" в модуле модели, одновременно удаляя их из списка действий:

// Документ.ЗаказКлиента.Форма.ФормаДокумента
&НаСервере
Процедура ПриЧтенииСозданииНаСервере()
	// +МОД. Модель объекта
	глМодель_ПриЧтенииСозданииНаСервере(ЭтаФорма);
	// -МОД
	// ...
КонецПроцедуры

// +МОД. Модель объекта
&НаКлиенте
Функция Модель_ОбработатьДействия(КонтекстИзменений) Экспорт
	Возврат Модель_ОбработатьДействияСервер(КонтекстИзменений);
КонецФункции // -МОД

// +МОД. Модель объекта
&НаСервере
Функция Модель_ОбработатьДействияСервер(КонтекстИзменений)
	Возврат глМодель_ОбработатьДействия(КонтекстИзменений, ЭтаФорма);
КонецФункции // -МОД

&НаКлиенте
Процедура ТоварыКоличествоУпаковокПриИзменении(Элемент)
	// ...
	// +МОД. Модель объекта
	МОД_ОбщегоНазначенияКлиентСервер.УдалитьТиповыеОбработчикиСтроки(СтруктураДействий);
	глМодель_ПриИзмененииРеквизитовСтроки(ЭтаФорма, глМодель_ТекущиеДанные(Элемент), глМодель_ИмяРеквизита(Элемент), КэшированныеЗначения);
	// -МОД
	ОбработкаТабличнойЧастиКлиент.ОбработатьСтрокуТЧ(ТекущаяСтрока, СтруктураДействий, КэшированныеЗначения);
КонецПроцедуры

// ОбщийМодуль.ОбработкаТабличнойЧастиКлиентСервер
// +МОД. Модель объекта
Процедура МОД_ОбработатьСтрокуТЧ(ТекущаяСтрока, СтруктураДействий, КэшированныеЗначения) Экспорт
	#Если Клиент Тогда
	ОбработкаТабличнойЧастиКлиент.ОбработатьСтрокуТЧ(ТекущаяСтрока, СтруктураДействий, КэшированныеЗначения);
	#Иначе
	ОбработкаТабличнойЧастиСервер.ОбработатьСтрокуТЧ(ТекущаяСтрока, СтруктураДействий, КэшированныеЗначения);
	#КонецЕсли
КонецПроцедуры // -МОД

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

// ОбщийМодуль.МОД_ОбщегоНазначенияКлиентСервер
Процедура УдалитьТиповыеОбработчикиСтроки(СтруктураДействий) Экспорт
	СтруктураДействий.Удалить("ПересчитатьКоличествоЕдиниц");
	СтруктураДействий.Удалить("ПересчитатьСуммуНДС");
	СтруктураДействий.Удалить("ПересчитатьСуммуСНДС");
	СтруктураДействий.Удалить("ПересчитатьСумму");
	СтруктураДействий.Удалить("ПересчитатьСуммуСУчетомРучнойСкидки");
	СтруктураДействий.Удалить("ПересчитатьСуммуСУчетомАвтоматическойСкидки");
КонецПроцедуры

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

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

// Документ.ЗаказКлиента.Форма.ФормаДокумента
// +МОД. Добавление стоимости закупки
&НаКлиенте
Процедура ТоварыМОД_ЦенаЗакупкиПриИзменении(Элемент)
	глМодель_ПриИзмененииРеквизитовСтроки(ЭтаФорма, глМодель_ТекущиеДанные(Элемент), глМодель_ИмяРеквизита(Элемент), КэшированныеЗначения);
КонецПроцедуры // -МОД

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

// ОбщийМодуль.Модель_Документ_ЗаказКлиента
Процедура ПриВыполненииОбработчиковСтроки(КонтекстИзменений, ДанныеСтроки) Экспорт
	Объект = глМодель_Данные(КонтекстИзменений);
	
	Если глМодель_ВыполнятьОбработчикСтроки(КонтекстИзменений, ДанныеСтроки, "МОД_СтоимостьЗакупки", "КоличествоУпаковок,МОД_ЦенаЗакупки,МОД_ВалютаЗакупки", "_Сервер_") Тогда
		#Если НЕ Клиент ИЛИ ТолстыйКлиентОбычноеПриложение Тогда
		Если ЗначениеЗаполнено(ДанныеСтроки.МОД_ВалютаЗакупки) Тогда
			СтруктураКурса = РаботаСКурсамиВалют.ПолучитьКурсВалюты(ДанныеСтроки.МОД_ВалютаЗакупки, Объект.Дата);
			СтруктураКурсаДокумента = РаботаСКурсамиВалют.ПолучитьКурсВалюты(Объект.Валюта, Объект.Дата);
			
			ДанныеСтроки.МОД_СтоимостьЗакупки = ДанныеСтроки.КоличествоУпаковок * РаботаСКурсамиВалютКлиентСервер.ПересчитатьПоКурсу(ДанныеСтроки.МОД_ЦенаЗакупки, СтруктураКурса, СтруктураКурсаДокумента);
		Иначе
			ДанныеСтроки.МОД_СтоимостьЗакупки = 0;
		КонецЕсли;
		#КонецЕсли
	КонецЕсли;
	// ...
КонецПроцедуры

Вот собственно и все.

 

Помимо того, что новая зависимость будет работать в форме, количество в документе Заказ клиента можно менять извне без перечисления всех обработчиков. Например:

ДокументОбъект = глМодель_НачатьИзменения(Ссылка)

Для Каждого СтрокаТЧ Из ДокументОбъект.Товары Цикл
	глМодель_ИзменитьРеквизитСтроки(ДокументОбъект, СтрокаТЧ, "КоличествоУпаковок", НовоеКоличество[СтрокаТЧ.НомерСтроки]);
КонецЦикла;

глМодель_ЗавершитьИзменения(ДокументОбъект)

Если поставщик добавить новые зависимости для реквизита Количество упаковок, их будет достаточно описать в процедурах МОД_ОбщегоНазначенияКлиентСервер.УдалитьТиповыеОбработчикиСтроки и МОД_ОбщегоНазначенияКлиентСервер.ПриВыполненииТиповыхОбработчиковСтроки. Остальной код останется без изменений

См. также

Табличная часть в доп. реквизитах и формирование таблиц в шаблоне docx для 1С:ДО 3.0

Адаптация типовых решений Платформа 1С v8.3 1С:Документооборот Россия Платные (руб)

Расширение конфигурации для «1С:Документооборот КОРП», редакция 3.0. позволяет: 1.использовать произвольные табличные части в качестве дополнительных реквизитов к документу; 2 использовать произвольные табличные части в шаблонах в формате docx для автоматического заполнения таблиц.

29400 руб.

29.06.2023    4653    9    5    

18

Расширение для 1С:УНФ. Автоматическое снятие резервов в Заказах покупателей

Логистика, склад и ТМЦ Адаптация типовых решений Платформа 1С v8.3 1С:Управление нашей фирмой 1.6 1С:Управление нашей фирмой 3.0 Россия Управленческий учет Платные (руб)

Чтобы не допустить путаницы с обещаниями клиентам и для четкого контроля исполнения заказов мы используем резервирование товаров. Мы доработали УНФ, чтобы она автоматически отменяла старые резервы и не мешала эффективно продавать.

7200 руб.

02.08.2023    3062    4    0    

20

Создать на основании - своя кнопка (БСП). Проблема двух подменю Создать на основании

БСП (Библиотека стандартных подсистем) Адаптация типовых решений Платформа 1С v8.3 1С:ERP Управление предприятием 2 Бесплатно (free)

Понадобилось в подменю "Создать на основании" добавить свою команду, которая открывает обработку. В процессе доработок появилась проблема двух подменю "Создать на основании". В статье о том, как решились проблемы.

01.03.2024    1691    dimanich70    8    

14

Доработка отчета "Связанные документы" (структура подчиненности) для вывода объектов из любого расширения

Адаптация типовых решений Платформа 1С v8.3 1С:Управление торговлей 11 Россия Абонемент ($m)

Доработка типового отчета "Связанные документы" позволяет просто и быстро расширять состав объектов для построения структуры подчиненности документов, используя объекты основной конфигурации и любых расширений.

1 стартмани

27.10.2023    2109    19    avmartynov    14    

44

Печать непроведенных документов для УТ, КА, ERP. Настройка печати по пользователям, документам и печатным формам

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    2244    25    progmaster    8    

3
Оставьте свое сообщение