gifts2017

Реализация обмена по организации в УТ

Опубликовал Айтуар Баубериков (Bajo) в раздел Администрирование - Распределенная БД (УРИБ, УРБД)

В связи с открытием филиала в другом городе возникла необходимость организации учета в конфигурации "Управление торговлей для Казахстана, ред. 3" (адаптированный аналог "Управление торговлей, ред. 11"). Как оказалось встроенного обмена по организации не оказалось, есть только "Полный". Пришлось реализовывать самому. Конечно был вариант работы через терминальное подключение и тонкий клиент, но в связи во-первых неустойчивыми каналами связи и с заделкой на будущее (большие объемы данных) решил сделать РИБ. И вот об этом моя первая статья, может поможет кому нибудь.  

Имеем следующее: Работающая информационная база на основе конфигурации "Управление торговлей для Казахстана, ред. 3", в основном используемая для торговых операций в городе А. Решили открыть филиал в городе Б. Выбирали между 3 вариантами:

1. работа в режиме управляемого приложения (тонкий клиент) (отпал из-за неустойчивого канала связи)

2. работа в терминальном режиме (отпал из-за возможного постоянного конфликта блокировок, проблемы с обновлением)

3. РИБ

Выбрали РИБ (по нашему мнению самый отлаженный и надёжный способ работы при больших нагрузках). Реализацию возложили на меня.

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

Описываю алгоритм:

1) Работа в режиме конфигуратор. Скопировал план обмена "Полный" (так как есть объекты которые должны быть только в региональных базах). Переименовал в "План обмена". Добавил реквизит "организация" с типом справочникссылка. организация

2) Откорректировал состав обмениваемых данных. В общих объектах (справочники, константы, планы видов характеристик) поставил авторегистрация=разрешить. В остальных поставил авторегистрация=запретить.

3) В общих модулях создал глобальный общий модуль "ОбменПоОрганизации" . Текст модуля в файле "Общий модуль".  Для выкладывания текст большой.

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

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

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

Функция ОпределитьТипОбъекта(Объект)
	
	Класс = Объект.Метаданные().ПолноеИмя();
	Класс = Лев(Класс, Найти(Класс, ".")-1);	
	
	Возврат Класс;
	
КонецФункции

4) Затем в объектах, где данные нужно фильтровать и объект включен в состав обмена (документы, регистры) необходимо в модулях объектов в процедуре приЗаписи добавить вызов процедуры обРегистрацияИзменений().

Если ЭтотОбъект.ОбменДанными.Получатели.АвтоЗаполнение и не ЭтотОбъект.ОбменДанными.Загрузка Тогда
        обРегистрацияИзменений(ЭтотОбъект) ;
КонецЕсли;

5) Подчиненный узел создал копированием оригинала и удалением документов, юзеров. Затем сделал рокировку планов обмена (подмена кодов узла). Установил главный узел.
6) Почистил регистрацию изменений на всякий случай. Нужно учитывать если объект хоть где-то удаляется, то он удаляется и в остальных узлах!!!
7) Затем при первоначальном начале работы подчиненного узла убрал вызов помощника настройки обмена.

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

См. также

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

Комментарии

1. Борис Разорёнов (Bor_ka) 28.08.14 14:55
Понравился подход, можно подробнее о пунктах 5,6,7?
2. Айтуар Баубериков (Bajo) 29.08.14 06:51
(1) Bor_ka, по пункту 5. В оригинале базы создал подчиненные узлы. Сделал копию выгрузив базу в *.DT. Загрузил в чистую базу. В планах обмена в новой базе удалил лишние узлы осталось только 2. Поменял коды узлов местами. Откорректировал реквизит "Организация" в соответствии с реальностью.
пункт 6. Все объекты имеют уникальный идентификатор. Если в филиале №1 в справочнике контрагенты произойдет непосредственное удаление элемента, то после обмена с центром этот объект удалится в центральной базе. Затем когда центральная база сделает обмен с филиалом №2, то объект удалится и в этой базе.
пункт 7. при развертке РИБ в типовой конфигурации при первом запуске базы автоматически запускается помощник настройки обмена. он работает косячно. я не стал разбираться, просто отключил его.

базы работают уже полгода никаких проблем с обменом.
3. Кумганбаев Самат (kumga99) 18.06.15 14:59
Калайсын,Айтуар? красавчик, буны сен енгизип един эпл ситиде?
4. Айтуар Баубериков (Bajo) 30.06.15 14:39
(3) kumga99, Жаксы. Сам как? Да эпл март кой. Кайда жумыс истеп журсин?
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа