Создание ведомостей на выплату зарплаты / Модуль менеджера

файл
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

#Область СлужебныеПроцедурыИФункции

#Область Создание_ведомостей 

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

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

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

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

	РезультатыЗапроса = Запрос.ВыполнитьПакет();
	Если РезультатыЗапроса[0].Пустой() Тогда
		Возврат Неопределено
	КонецЕсли;	
		
	ВыборкаОрганизации = РезультатыЗапроса[0].Выбрать();
	ВыборкаОрганизации.Следующий();
	ВыборкаПериода = РезультатыЗапроса[1].Выбрать();
	ВыборкаПериода.Следующий();

	ОписаниеОперации = ВедомостьНаВыплатуЗарплаты.ОписаниеОперацииВыплаты();
	ОписаниеОперации.Организация        = ВыборкаОрганизации.Организация;
	ОписаниеОперации.ПериодРегистрации  = ВыборкаПериода.ПериодРегистрации;
	ОписаниеОперации.Дата               = ДатаВыплаты;
	ОписаниеОперации.ПорядокВыплаты     = СпособВыплаты.ХарактерВыплаты;
	ОписаниеОперации.СпособПолучения    = СпособВыплаты.СпособПолучения;
	
	ОписаниеОперации.ДокументыОснования = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(РасчетныйДокумент);
	
	Возврат ОписаниеОперации
	
КонецФункции

Функция ПараметрыРасчетаЗарплаты(СпособВыплаты)
	ПараметрыРасчетаЗарплаты = ВедомостьНаВыплатуЗарплаты.ПараметрыРасчетаЗарплаты();
	ПараметрыРасчетаЗарплаты.Округление = СпособВыплаты.Округление;
	Возврат ПараметрыРасчетаЗарплаты
КонецФункции

Функция ПараметрыРасчетаНДФЛ(СпособВыплаты, ДатаВыплаты)
	ПараметрыРасчетаНДФЛ = ВедомостьНаВыплатуЗарплаты.ПараметрыРасчетаНДФЛ();	
	ПараметрыРасчетаНДФЛ.ПланируемаяДатаВыплаты = ДатаВыплаты;
	ПараметрыРасчетаНДФЛ.ОкончательныйРасчет    = СпособВыплаты.ОкончательныйРасчетНДФЛ;
	Возврат ПараметрыРасчетаНДФЛ
КонецФункции

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

	Запрос.Текст = 
	"ВЫБРАТЬ
	|	ЗарплатаКВыплате.Подразделение КАК ПодразделениеВыплаты,
	|	ДетализацияМестВыплат.ВидМестаВыплаты КАК ВидМестаВыплаты,
	|	ДетализацияМестВыплат.МестоВыплаты КАК МестоВыплаты,
	|	ЗарплатаКВыплате.Сотрудник КАК Сотрудник,
	|	ЗарплатаКВыплате.ФизическоеЛицо КАК ФизическоеЛицо,
	|	ЗарплатаКВыплате.Подразделение КАК Подразделение,
	|	ЗарплатаКВыплате.Организация КАК Организация,
	|	ЗарплатаКВыплате.ПериодВзаиморасчетов КАК ПериодВзаиморасчетов,
	|	ЗарплатаКВыплате.СтатьяФинансирования КАК СтатьяФинансирования,
	|	ЗарплатаКВыплате.СтатьяРасходов КАК СтатьяРасходов,
	|	ЗарплатаКВыплате.ВидДоходаИсполнительногоПроизводства КАК ВидДоходаИсполнительногоПроизводства,
	|	ЗарплатаКВыплате.ДокументОснование КАК ДокументОснование,
	|	ЛОЖЬ КАК Распределенное,
	|	СУММА(ЗарплатаКВыплате.КВыплате) КАК КВыплате
	|ИЗ
	|	ВТЗарплатаКВыплате КАК ЗарплатаКВыплате
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТДетализацияМестВыплат КАК ДетализацияМестВыплат
	|		ПО ЗарплатаКВыплате.Сотрудник = ДетализацияМестВыплат.Сотрудник
	|		ЛЕВОЕ СОЕДИНЕНИЕ ВТСотрудникиНесколькоМестВыплат КАК СотрудникиНесколькоМестВыплат
	|		ПО ЗарплатаКВыплате.Сотрудник = СотрудникиНесколькоМестВыплат.Сотрудник
	|ГДЕ
	|	СотрудникиНесколькоМестВыплат.Сотрудник ЕСТЬ NULL
	|
	|СГРУППИРОВАТЬ ПО
	|	ДетализацияМестВыплат.ВидМестаВыплаты,
	|	ДетализацияМестВыплат.МестоВыплаты,
	|	ЗарплатаКВыплате.Сотрудник,
	|	ЗарплатаКВыплате.ФизическоеЛицо,
	|	ЗарплатаКВыплате.ПериодВзаиморасчетов,
	|	ЗарплатаКВыплате.СтатьяФинансирования,
	|	ЗарплатаКВыплате.СтатьяРасходов,
	|	ЗарплатаКВыплате.ВидДоходаИсполнительногоПроизводства,
	|	ЗарплатаКВыплате.ДокументОснование,
	|	ЗарплатаКВыплате.Подразделение,
	|	ЗарплатаКВыплате.Организация
	|
	|УПОРЯДОЧИТЬ ПО
	|	ФизическоеЛицо,
	|	Сотрудник,
	|	ПериодВзаиморасчетов,
	|	СтатьяФинансирования,
	|	СтатьяРасходов,
	|	ВидДоходаИсполнительногоПроизводства,
	|	Подразделение,
	|	ДокументОснование";
	Зарплата = Запрос.Выполнить().Выгрузить();
	
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	ДетализацияМестВыплат.Сотрудник КАК Сотрудник,
	|	ЗарплатаСотрудников.ПериодВзаиморасчетов КАК ПериодВзаиморасчетов,
	|	ДетализацияМестВыплат.ВидМестаВыплаты КАК ВидМестаВыплаты,
	|	ДетализацияМестВыплат.МестоВыплаты КАК МестоВыплаты,
	|	ДетализацияМестВыплат.СпособОграниченияВыплаты КАК СпособОграниченияВыплаты,
	|	ДетализацияМестВыплат.Размер КАК Размер,
	|	ДетализацияМестВыплат.ПоУмолчанию КАК ПоУмолчанию,
	|	ЗарплатаСотрудников.КВыплате КАК КВыплате,
	|	ВЫБОР
	|		КОГДА ДетализацияМестВыплат.СпособОграниченияВыплаты = ЗНАЧЕНИЕ(Перечисление.СпособОграниченияВыплаты.Процентом)
	|			ТОГДА ВЫРАЗИТЬ(ЗарплатаСотрудников.КВыплате * ДетализацияМестВыплат.Размер / 100 КАК ЧИСЛО(15, 2))
	|		КОГДА ДетализацияМестВыплат.СпособОграниченияВыплаты = ЗНАЧЕНИЕ(Перечисление.СпособОграниченияВыплаты.ФиксированнойСуммой)
	|			ТОГДА ДетализацияМестВыплат.Размер
	|	КОНЕЦ КАК ОстатокРаспределения
	|ИЗ
	|	(ВЫБРАТЬ
	|		СотрудникиНесколькоМестВыплат.Сотрудник КАК Сотрудник,
	|		ЗарплатаКВыплате.ПериодВзаиморасчетов КАК ПериодВзаиморасчетов,
	|		СУММА(ЗарплатаКВыплате.КВыплате) КАК КВыплате
	|	ИЗ
	|		ВТСотрудникиНесколькоМестВыплат КАК СотрудникиНесколькоМестВыплат
	|			ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТЗарплатаКВыплате КАК ЗарплатаКВыплате
	|			ПО СотрудникиНесколькоМестВыплат.Сотрудник = ЗарплатаКВыплате.Сотрудник
	|	
	|	СГРУППИРОВАТЬ ПО
	|		СотрудникиНесколькоМестВыплат.Сотрудник,
	|		ЗарплатаКВыплате.ПериодВзаиморасчетов) КАК ЗарплатаСотрудников
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТДетализацияМестВыплат КАК ДетализацияМестВыплат
	|		ПО ЗарплатаСотрудников.Сотрудник = ДетализацияМестВыплат.Сотрудник
	|УПОРЯДОЧИТЬ ПО
	|	ДетализацияМестВыплат.Сотрудник,
	|	ЗарплатаСотрудников.ПериодВзаиморасчетов,
	|	ДетализацияМестВыплат.ПоУмолчанию Убыв
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ЗарплатаКВыплате.Подразделение КАК ПодразделениеВыплаты,
	|	ЗарплатаКВыплате.Сотрудник КАК Сотрудник,
	|	ЗарплатаКВыплате.ФизическоеЛицо КАК ФизическоеЛицо,
	|	ЗарплатаКВыплате.Подразделение КАК Подразделение,
	|	ЗарплатаКВыплате.Организация КАК Организация,
	|	ЗарплатаКВыплате.ПериодВзаиморасчетов КАК ПериодВзаиморасчетов,
	|	ЗарплатаКВыплате.СтатьяФинансирования КАК СтатьяФинансирования,
	|	ЗарплатаКВыплате.СтатьяРасходов КАК СтатьяРасходов,
	|	ЗарплатаКВыплате.ВидДоходаИсполнительногоПроизводства КАК ВидДоходаИсполнительногоПроизводства,
	|	ЗарплатаКВыплате.ДокументОснование КАК ДокументОснование,
	|	СУММА(ЗарплатаКВыплате.КВыплате) КАК КВыплате
	|ИЗ
	|	ВТЗарплатаКВыплате КАК ЗарплатаКВыплате
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТСотрудникиНесколькоМестВыплат КАК СотрудникиНесколькоМестВыплат
	|		ПО ЗарплатаКВыплате.Сотрудник = СотрудникиНесколькоМестВыплат.Сотрудник
	|
	|СГРУППИРОВАТЬ ПО
	|	ЗарплатаКВыплате.Сотрудник,
	|	ЗарплатаКВыплате.ФизическоеЛицо,
	|	ЗарплатаКВыплате.ПериодВзаиморасчетов,
	|	ЗарплатаКВыплате.СтатьяФинансирования,
	|	ЗарплатаКВыплате.СтатьяРасходов,
	|	ЗарплатаКВыплате.ВидДоходаИсполнительногоПроизводства,
	|	ЗарплатаКВыплате.ДокументОснование,
	|	ЗарплатаКВыплате.Подразделение,
	|	ЗарплатаКВыплате.Организация
	|
	|УПОРЯДОЧИТЬ ПО
	|	ФизическоеЛицо,
	|	Сотрудник,
	|	ПериодВзаиморасчетов,
	|	СтатьяФинансирования,
	|	СтатьяРасходов,
	|	ВидДоходаИсполнительногоПроизводства,
	|	Подразделение,
	|	ДокументОснование";
	
	Результат = Запрос.ВыполнитьПакет();
	РазмерыОграничений = Результат[0].Выгрузить();
	ЗарплатаКРаспределению = Результат[1].Выгрузить();
	СтруктураОтбора = Новый Структура("Сотрудник,ПериодВзаиморасчетов");
	УдаляемыеСтроки = Новый Массив();
	Для Каждого РазмерОграниченийСотрудника из РазмерыОграничений Цикл
		ЗаполнитьЗначенияСвойств(СтруктураОтбора,РазмерОграниченийСотрудника);
		ЗарплатаПоСотруднику = ЗарплатаКРаспределению.НайтиСтроки(СтруктураОтбора);
		Для Каждого СтрокаЗарплатаПоСотруднику Из ЗарплатаПоСотруднику Цикл
			СтрокаЗарплатыСотрудника = Зарплата.Добавить();
			ЗаполнитьЗначенияСвойств(СтрокаЗарплатыСотрудника,СтрокаЗарплатаПоСотруднику);
			ЗаполнитьЗначенияСвойств(СтрокаЗарплатыСотрудника,РазмерОграниченийСотрудника,"ВидМестаВыплаты,МестоВыплаты");
			СтрокаЗарплатыСотрудника.Распределенное = Истина;
			
			СтрокаЗарплатыСотрудника.КВыплате = МИН(СтрокаЗарплатаПоСотруднику.КВыплате, РазмерОграниченийСотрудника.ОстатокРаспределения);
			РазмерОграниченийСотрудника.ОстатокРаспределения = РазмерОграниченийСотрудника.ОстатокРаспределения - СтрокаЗарплатыСотрудника.КВыплате;
			СтрокаЗарплатаПоСотруднику.КВыплате = СтрокаЗарплатаПоСотруднику.КВыплате - СтрокаЗарплатыСотрудника.КВыплате;
			Если РазмерОграниченийСотрудника.ОстатокРаспределения <=0 Тогда
				Прервать;
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
	
	ВедомостьНаВыплатуЗарплатыРасширенный.РаспределитьОстатокУмолчанию(Зарплата,ЗарплатаКРаспределению, РазмерыОграничений);
	
	ДобавляемыеТипы = Новый Массив;
	ДобавляемыеТипы.Добавить(Тип("СправочникСсылка.КлассификаторБанков"));
	ОписаниеТиповМестВыплат = Новый ОписаниеТипов(Зарплата.Колонки.МестоВыплаты.ТипЗначения, ДобавляемыеТипы);
	Зарплата.Колонки.Добавить("МестоВыплатыБанк", ОписаниеТиповМестВыплат);
	Зарплата.ЗагрузитьКолонку(Зарплата.ВыгрузитьКолонку("МестоВыплаты"),"МестоВыплатыБанк");
	Зарплата.Колонки.Удалить("МестоВыплаты");
	Зарплата.Колонки.МестоВыплатыБанк.Имя = "МестоВыплаты";
	
	
	МестаВыплатСотрудников = Зарплата.Скопировать(,"Сотрудник,ВидМестаВыплаты,МестоВыплаты");
	МестаВыплатСотрудников.Свернуть("Сотрудник,ВидМестаВыплаты,МестоВыплаты");
	МестаВыплатСотрудников.Колонки.Добавить("МестВыплат", ОбщегоНазначения.ОписаниеТипаЧисло(3));
	МестаВыплатСотрудников.ЗаполнитьЗначения("1","МестВыплат");
	МестаВыплатСотрудников.Свернуть("Сотрудник,ВидМестаВыплаты","МестВыплат");
	СтруктураОтбора = Новый Структура("Сотрудник,ВидМестаВыплаты");
	Для Каждого МестоВыплаты из МестаВыплатСотрудников Цикл
		Если МестоВыплаты.ВидМестаВыплаты = Перечисления.ВидыМестВыплатыЗарплаты.БанковскийСчет Тогда
			Если МестоВыплаты.МестВыплат = 1 Тогда
				ЗаполнитьЗначенияСвойств(СтруктураОтбора, МестоВыплаты);
				СтрокиМестВыплаты = Зарплата.НайтиСтроки(СтруктураОтбора);
				Для Каждого СтрокаМестВыплаты из СтрокиМестВыплаты Цикл
					Если ТипЗнч(СтрокаМестВыплаты.МестоВыплаты) = Тип("СправочникСсылка.БанковскиеСчетаКонтрагентов") Тогда
						СтрокаМестВыплаты.МестоВыплаты = СтрокаМестВыплаты.МестоВыплаты.Банк;
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	
	Возврат Зарплата
КонецФункции

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

КонецПроцедуры

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

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

	Возврат КлючиВедомостей
	
КонецФункции

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

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

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

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

#КонецОбласти

#Область Сохранение_ведомостей 

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

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

#КонецОбласти

#КонецОбласти

#КонецЕсли

Связанные материалы