Доработка правил конвертации ЗУП->Бух1.2: расширенный поиск физических лиц и др.

Задача: В стандартной обработке выгрузки данных из ЗиУП для Украины 2.1 в Бухгалтерию для Украины 1.2 используется поиск сотрудников и физ. лиц по коду/табельному номеру. Необходимо переделать это на поиск по ИНН.

Стандартная выгрузка из ЗиУП в Бухгалтерию для Украины замечательно подходит, если у вас одна база ЗиУП и одна база Бухгалтерии 1.2. Однако, часто, в хозяйственной деятельности предприятия задействованы несколько разных баз или ведется учет сразу по нескольким предприятиям. Или вероятна ситуация, когда в ЗУП ведется учет по нескольким организациям и необходимо добавить еще одну. В таком случае, обеспечение соответствия кодов элементов справочников в разных бухгалтерских базах становится не тривиальной задачей. В штатной версии выгрузки в Бухгалтерию 1.2 нас не устраивает:

  1. Поиск по большинству элементов справочников происходит по коду элемента. Нам необходимо сделать поиск по наименованию или, даже, более сложный поиск.
  2. Нет проверки на нужную конфигурацию и наличие организации в базе-приемнике

Проверка версии конфигурации и наличие организации

Для проверки конфигурации добавим в событие конвертации "Перед загрузкой данных":

Если Метаданные.Имя <> "БухгалтерияДляУкраины12" Тогда
	Сообщить("Данный файл предназначен для загрузки в конфигурацию ""Бухгалтерия для Украины 1.2""!", СтатусСообщения.Внимание);
	Сообщить("Ваша текущая конфигурация " + Метаданные.Имя);
	Сообщить("Загрузка отменена!",СтатусСообщения.Важное);
	Отказ = Истина
КонецЕсли;

Для проверки наличия организации будем передавать параметр "Организация" в базу-приемник и проверять его заполнение в событии конвертации "После загрузки параметров":

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

Для ПКО "Организации" обязательно нужно поставить флаг "Не создавать новый объект в приемнике, если он НЕ найден". Предполагается, что это не первоначальный обмен и такая организация в базе-приемнике уже есть.

1-1.png

Поиск организации будем проводить по коду ЕДРПОУ или наименованию организации. Поскольку в ЗУП у справочника "Организации" нет реквизита "КодЕДРПОУ", мы будем получать его с помощью программного кода и передавать в приемник в качестве параметра. В событии "Перед выгрузкой" ПКС "КодПоЕДРПОУ":

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

В событии "Поля поиска" ПКО "Организации" делаем запрос к регистру сведений "Коды организации" на предмет наличия организации с нужным кодом ЕДРПОУ. Если поиск не удачный или организаций с таким кодом больше одной (что очень странно), производим поиск по наименованию:

Если НомерВариантаПоиска = 1 тогда
	КодПоЕДРПОУ = Неопределено;
	Попытка
		КодПоЕДРПОУ = ПараметрыОбъекта["КодПоЕДРПОУ"];	
	Исключение
	КонецПопытки;
	
	Если ЗначениеЗаполнено(КодПоЕДРПОУ) Тогда
		Запрос = Новый Запрос;
		Запрос.УстановитьПараметр("Дата", ТекущаяДата());
		Запрос.УстановитьПараметр("КодПоЕДРПОУ", КодПоЕДРПОУ);
		Запрос.Текст = "
			|ВЫБРАТЬ РАЗЛИЧНЫЕ
			|	КодыОрганизацииСрезПоследних.Организация
			|ИЗ
			|	РегистрСведений.КодыОрганизации.СрезПоследних(&Дата, ) КАК КодыОрганизацииСрезПоследних
			|ГДЕ
			|	КодыОрганизацииСрезПоследних.КодПоЕДРПОУ = &КодПоЕДРПОУ
			|";
		Выборка = Запрос.Выполнить().Выбрать();
		
		Если Выборка.Количество() = 1 Тогда
			Выборка.Следующий();
			СсылкаНаОбъект = Выборка.Организация;
		КонецЕсли;
	КонецЕсли;
	
Иначе
	СтрокаИменСвойствПоиска = "Наименование";
КонецЕсли;

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

Расширенный поиск физ. лиц

По указанным выше причинам, поиск физ. лиц и сотрудников по коду справочника нас не устраивает. Самым разумным было бы искать физических лиц по коду ДРФО, а сотрудника по сопоставленному ему физ. лицу. Однако, в нашем случае, по некоторым причинам, в базе приемнике может быть несколько физических лиц с совпадающими наименованиями и кодами ДРФО. Значит нам необходимо при поиске получать сопоставленных сотрудников и проверять реквизит сотрудника "Организация". Сам алгоритм поиска следующий:

  1. Ищем физ. лица с нужными нам КодДРФО;
  2. Если их несколько, левым соединением присоединяем к таблице справочник сотрудников с отбором по организации;
  3. Если таких сотрудников несколько, проверяем реквизит сотрудника "Активность" (вариант когда сотрудник был уволен, а потом опять принят на работу);
  4. Если результатов опять несколько, накладывем отбор по наименованию сотрудника.

Для этого поиска удобно использовать алгоритм, который назовем "ПоискФизЛица":

КодПоДРФО = СвойстваПоиска["КодПоДРФО"];
ЭтоГруппа = Ложь;//СвойстваПоиска["ЭтоГруппа"];
ПометкаУдаления = СвойстваПоиска["ПометкаУдаления"];
Организация = Параметры.Организация;
Наименование = СвойстваПоиска["Наименование"];

ПродолжитьПоиск = Истина;
СсылкаНаОбъект = Справочники.ФизическиеЛица.ПустаяСсылка();
Таблица = Новый ТаблицаЗначений;
ТаблицаФизЛиц = Новый ТаблицаЗначений;

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

//Если присутствуют все необходимые поля 
//Пробуем вариант 1 - поиск по коду ДРФО
Если ПродолжитьПоиск Тогда
	//ЗАПРОС 1 
	Запрос.Текст = "
		|ВЫБРАТЬ РАЗЛИЧНЫЕ
		|	ФизическиеЛица.Ссылка,
		|	ФизическиеЛица.Наименование
		|ИЗ
		|	Справочник.ФизическиеЛица КАК ФизическиеЛица
		|ГДЕ
		|	ФизическиеЛица.ЭтоГруппа = &ЭтоГруппа
		|	И ФизическиеЛица.КодПоДРФО = &КодПоДРФО
		|	И ФизическиеЛица.ПометкаУдаления = &ПометкаУдаления
		|";

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

//Если найдено более чем одно физ. лицо с таким кодом ДРФО
Если ПродолжитьПоиск И НЕ ЗначениеЗаполнено(СсылкаНаОбъект) Тогда
	//ЗАПРОС 2
	//Проверять на NULL не надо, т. к. если сотрудник ЕСТЬ NULL - у него нет реквизита "Организация" и в выборку он не попадет
	Запрос.Текст = "
		|ВЫБРАТЬ РАЗЛИЧНЫЕ
		|	ФизическиеЛица.Ссылка,
		|	ФизическиеЛица.Наименование,
		|	СотрудникиОрганизаций.Ссылка КАК Сотрудник,
		|	СотрудникиОрганизаций.Актуальность
		|ИЗ
		|	Справочник.ФизическиеЛица КАК ФизическиеЛица
		|		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СотрудникиОрганизаций КАК СотрудникиОрганизаций
		|		ПО СотрудникиОрганизаций.Физлицо = ФизическиеЛица.Ссылка
		|ГДЕ
		|	ФизическиеЛица.ЭтоГруппа = &ЭтоГруппа
		|	И ФизическиеЛица.КодПоДРФО = &КодПоДРФО
		|	И ФизическиеЛица.ПометкаУдаления = &ПометкаУдаления
		|	И СотрудникиОрганизаций.Организация = &Организация
		|";
	
	//Выгружаем в таблицу на которую и будем накладывать отборы, чтобы не дергать базу
	Таблица = Запрос.Выполнить().Выгрузить();	
КонецЕсли;

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

	//Ищем не актуальных сотрудников
	Если НЕ ЗначениеЗаполнено(СсылкаНаОбъект) Тогда
		ОтборАктуальность = Новый Структура;
		ОтборАктуальность.Вставить("Актуальность", Ложь);
		
		СтрокиОтборАктуальность = Таблица.НайтиСтроки(ОтборАктуальность);
		
		Если СтрокиОтборАктуальность.Количество() = 1 Тогда
			СсылкаНаОбъект = СтрокиОтборАктуальность[0].Ссылка;
		КонецЕсли;
	КонецЕсли;
КонецЕсли;

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

Этот алгоритм будет задействован в событии "Поля поиска" ПКО "ФизическиеЛица":

Если СвойстваПоиска["ЭтоГруппа"] = Истина Тогда
	СтрокаИменСвойствПоиска = "Наименование, ЭтоГруппа";		
Иначе
	Если НомерВариантаПоиска = 1 тогда
		Выполнить(Алгоритмы.ПоискФизЛица);
	 	Если НЕ ЗначениеЗаполнено(СсылкаНаОбъект) Тогда
	 		СтрокаИменСвойствПоиска = "КодПоДРФО, ПометкаУдаления, ЭтоГруппа";
		КонецЕсли;
	 
	ИначеЕсли НомерВариантаПоиска = 2 тогда
		СтрокаИменСвойствПоиска = "КодПоДРФО, ЭтоГруппа";
	ИначеЕсли НомерВариантаПоиска = 3 тогда
		СтрокаИменСвойствПоиска = "Наименование, ПометкаУдаления, ЭтоГруппа";
	Иначе
		СтрокаИменСвойствПоиска = "Наименование, ЭтоГруппа";
 	КонецЕсли;
КонецЕсли;

Теперь, когда нужное физ. лицо найдено, поиск сотрудника не представляет сложности. В событие "Поля поиска" ПКО "СотрудникиОрганизаций":

Если СвойстваПоиска["ЭтоГруппа"] = Истина Тогда
	СтрокаИменСвойствПоиска = "Наименование, ЭтоГруппа";		
Иначе

	Если НомерВариантаПоиска = 1 тогда
	 
	 СтрокаИменСвойствПоиска = "Физлицо, Организация, ЭтоГруппа, ПометкаУдаления";
	 
	Иначе 
	 
	 СтрокаИменСвойствПоиска = "Физлицо, Организация, ЭтоГруппа";
	  
 	КонецЕсли;
КонецЕсли;

 


Похожие материалы

Комментарии