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

17.04.20

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

 

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

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

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

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

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

См. также

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

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

29400 руб.

29.06.2023    7112    19    13    

28

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

Расширение позволяет вывести в табличном документе факсимиле печати и подписей и/или вывести произвольную картинку из прикреплённых файлов организации для 1С УТ 11.5, КА 2.5, ERP 2.5, УНФ 3, Розница 3. Вывод факсимиле возможен в табличные документы УПД, УКД, Счёт-фактура, ТОРГ-12 и другие. Возможно настроить вывод для любых типовых макетов (Акт сверки, М-15, ТТН), для этого потребуется отредактировать макет и разместить на нём картинки с установленными именами. Редактирование осуществляется через типовой механизм в пользовательском интерфейсе.

3500 руб.

07.02.2023    7851    85    17    

42

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

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

7200 руб.

02.08.2023    4962    19    1    

36

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

Маленькая заметка (в трех разных масштабах) для тех, кто часто видит окно при входе в ЗУП «Новые сообщения для расшифровки по 1С-Отчетность», которое появляется через 60 секунд после запуска программы, как раз когда вы уже добрались до интересующей вас формы и начали в ней что-то активно делать:

1 стартмани

17.06.2024    4093    48    Znata_PI    6    

14

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

Каждый из нас сталкивается с ситуацией, когда какой-нибудь менеджер показывает свой Excel и рассказывает, как он что-то из 1С копирует в него, снабжает пояснениями, выделяет цветом и т.д. и т.п. Заканчивается все просьбой сделать вот чтобы также было в 1С. И оказывается такой человек (почти с гарантией) либо лучшим продажником, либо каким-то важным, за все отвечающим, - на ком все держится.

2 стартмани

22.04.2024    5838    dimanich70    15    

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