Часто при внедрении 1С:ЗУП на больших проектах внутри холдинга возникает задача реализовать групповой перерасчет документов «Начисление зарплаты». Заказчики хотят иметь возможность выделять сразу несколько документов в списке и их пересчитывать нажатием на одну кнопку. Типовой ЗУП не дает возможности перерасчитывать документы прямо в списке.
![](//infostart.ru/upload/iblock/0b8/0b8b57b96aabe0db04fd5529a7308889.png)
1. Групповой перерасчет выбранных в списке документов "Начисление зарплаты и Взносов" в ЗУП 3.1.2
Заказчик хочет следующий функционал:
![](//infostart.ru/upload/iblock/088/0882748873212390797207a60392e71e.gif)
Решение.
В конфигураторе создаем новую форму списка документа копированием типовой. Задаем префикс в имени формы. Создаем команду формы списка, подменю «ГруппаПересчетДокументов». Устанавливаем флаг «Множественный выбор» в свойствах элемента формы «Список» - чтобы пользователи могли выделять несколько документов при нажатии «Ctrl+Клик мыши».
![](//infostart.ru/upload/iblock/540/540f472bf122b8dcf435e4ab6e73991d.jpg)
![](//infostart.ru/upload/iblock/7de/7dec15e54d5bbacb28a2c382829fc57e.jpg)
Спустя некоторое время добавил еще одну кнопку:
![](//infostart.ru/upload/iblock/4d6/4d6cdb2816213265730d5e66dbf3ec8e.jpg)
Кнопка "Пересчитать (аналог: над таблицей Начисления)" - работает так же, как если бы мы открыли документ и нажали в нем кнопку Пересчитать над табличной частью Начисления (справа от кнопки Очистить), пересчет может потребоваться когда мы вручную меняем Результат начисления по сотруднику и надо по цепочке далее пересчитать зависимые начисления, налоги и взносы.
Кнопка "Пересчитать (аналог: таблица Начисления Сtrl+A --> прав. кнопка мыши Пересчитать сотрудника)" - работает так же, как если бы мы открыли документ, выделили все строки в таблице Начисления (Сtrl+A) и нажали правой кнопкой мыши Пересчитать сотрудника. В этом случае происходит не только пересчет сотрудника, но перезаполнение всех начислений сотрудника (как при первичном нажатии на кнопку Подбор). Это может понадобиться, когда сотрудник в документ есть, но в документе не хватает каких-либо начислений по нему (их ввели немного позже, после первого заполнения документа). Можно не заходя внутрь документа сделать дозаполнение недостающих начислений и сразу перерасчет.
В модуле созданной формы списка пропишем текст процедуры «ПересчитатьСотрудниковВДокументах»
Листинг нетипового функционала модуля формы списка ЗУП 3.1.2
#Область Нетиповая
&НаКлиенте
//Кнопка 1
Процедура ПересчитатьСотрудниковВДокументах(Команда)
//Предупредить пользователя о том, чтобы по выбранным документам не было открытых форм. Формы открыты: Да/Нет.
МассивВыделенныхДокументов = Элементы.Список.ВыделенныеСтроки;
Для Каждого ЭлМасДок из МассивВыделенныхДокументов Цикл
ФормаДокумента = ПолучитьФорму("Документ.НачислениеЗарплаты.Форма.ФормаДокумента", Новый Структура("Ключ",ЭлМасДок), ЭтаФорма);
ИмяТаблицы = "Начисления";
ВедущееПоле = "Сотрудник";
ТипВедущегоПоля = Тип("СправочникСсылка.Сотрудники");
//------------------------------------------------------------------------------------------------------------------------------------------
//1.
ФормаДокумента.СотрудникиКРасчету = СоответствиеСотрудникиКРасчету(ФормаДокумента, ИмяТаблицы);
ФормаДокумента.ПересчитатьДокументНаКлиенте();
//------------------------------------------------------------------------------------------------------------------------------------------
//2.
ФормаДокумента.Записать();
//------------------------------------------------------------------------------------------------------------------------------------------
//3. Закроем окно длительной операции
ОкнаПриложения = ПолучитьОкна();
Для Каждого ОкноПриложения Из ОкнаПриложения Цикл
Если ОкноПриложения.Содержимое.Количество()=0 Тогда Продолжить; КонецЕсли;
Если ОкноПриложения.Содержимое[0].ИмяФормы="ОбщаяФорма.ДлительнаяОперация" и НЕ ОкноПриложения.НачальнаяСтраница и НЕ ОкноПриложения.Основное Тогда
ФормаДлОп = ОкноПриложения.ПолучитьСодержимое();
Если ФормаДлОп.Открыта() Тогда
ФормаДлОп.Закрыть();
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Элементы.Список.Обновить();
ЭтаФорма.ОбновитьОтображениеДанных();
КонецПроцедуры
&НаКлиенте
Функция СоответствиеСотрудникиКРасчету(ФормаДокумента, ИмяТаблицы)
ОписаниеТаблицы = РасчетЗарплатыРасширенныйКлиентСервер.ОписаниеТаблицыРасчета();
ОписаниеТаблицы.ИмяПоляДляВставкиПоказателей = "ДатыНачисления";
ОписаниеТаблицы.СодержитПолеСотрудник = Истина;
ОписаниеТаблицы.ИмяРеквизитаСотрудник = "Сотрудник";
ОписаниеТаблицы.ИмяПоляДляВставкиРаспределенияРезультатов = "НачисленияРезультат";
ОписаниеТаблицы.ОтображатьПоляОписанияВремени = Истина;
ОписаниеТаблицы.ОтображатьПоляНормыВремени = Ложь; //Истина
ОписаниеТаблицы.УправлятьОтображениемПолейОписанияВремени = Ложь; //Истина
ОписаниеТаблицы.ОтменятьВсеИсправления = Ложь;
ОписаниеТаблицы.ПутьКДаннымАдресРаспределенияРезультатовВХранилище = "АдресТаблицыРаспределенияНачислений";
ОписаниеТаблицы.ВставлятьПослеПоля = Истина;
ОписаниеТаблицы.РаспределениеРезультатовЗависимыеТаблицы = "Начисления,Пособия,НДФЛ,Удержания,ПогашениеЗаймов";
ОписаниеТаблицы.СодержитПолеКодВычета = Истина;
ОписаниеТаблицы.ИмяРеквизитаДокументОснование = "ДокументОснование";
ОписаниеТаблицы.ПутьКДаннымАдресРаспределенияПоТерриториямУсловиямТруда = "АдресТаблицыРаспределенияПоТерриториямУсловиямТруда";
ОписаниеТаблицы.Вставить("НачисленияРезультат","");
СписокСотрудников = Новый Соответствие;
Для Каждого ТекСтр Из ФормаДокумента.Объект[ИмяТаблицы] Цикл
ФЛ = ТекСтр.ФизическоеЛицо;
Если СписокСотрудников.Получить(ФЛ) = Неопределено Тогда
СписокСотрудников.Вставить(ФЛ,Истина);
КонецЕсли;
КонецЦикла;
СтруктураНачисления = Новый Структура("ОписаниеТаблицы,СписокСотрудников");
СтруктураНачисления.ОписаниеТаблицы = ОписаниеТаблицы;
СтруктураНачисления.СписокСотрудников = СписокСотрудников;
СотрудникиКРасчету = Новый Соответствие();
СотрудникиКРасчету.Вставить("Начисления", СтруктураНачисления);
Возврат СотрудникиКРасчету;
КонецФункции
&НаКлиенте
//Кнопка 2
Процедура ПерезаполнитьИПересчитатьСотрудника(Команда)
//Предупредить пользователя о том, чтобы по выбранным документам не было открытых форм. Формы открыты: Да/Нет.
МассивВыделенныхДокументов = Элементы.Список.ВыделенныеСтроки;
Для Каждого ЭлМасДок из МассивВыделенныхДокументов Цикл
ФормаДокумента = ПолучитьФорму("Документ.НачислениеЗарплаты.Форма.ФормаДокумента", Новый Структура("Ключ",ЭлМасДок), ЭтаФорма);
ИмяТаблицы = "Начисления";
ВедущееПоле = "Сотрудник";
ТипВедущегоПоля = Тип("СправочникСсылка.Сотрудники");
//------------------------------------------------------------------------------------------------------------------------------------------
//1.
Для каждого Стр Из ФормаДокумента.Объект.Начисления Цикл
ФормаДокумента.Элементы.Начисления.ВыделенныеСтроки.Добавить(Стр.НомерСтроки-1);
КонецЦикла;
ИдентификаторыСтрок = ФормаДокумента.Элементы[ИмяТаблицы].ВыделенныеСтроки;
//РасчетЗарплатыРасширенныйКлиент.ПересчитатьСотрудника(ФормаДокумента, "Начисления", "Сотрудник", Тип("СправочникСсылка.Сотрудники"));
ФормаДокумента.ПересчитатьСотрудника(ИмяТаблицы, ИдентификаторыСтрок, ВедущееПоле, ТипВедущегоПоля);
//------------------------------------------------------------------------------------------------------------------------------------------
//2.
ФормаДокумента.Записать();
//------------------------------------------------------------------------------------------------------------------------------------------
//3. Закроем окно длительной операции
ОкнаПриложения = ПолучитьОкна();
Для Каждого ОкноПриложения Из ОкнаПриложения Цикл
Если ОкноПриложения.Содержимое.Количество()=0 Тогда Продолжить; КонецЕсли;
Если ОкноПриложения.Содержимое[0].ИмяФормы="ОбщаяФорма.ДлительнаяОперация" и НЕ ОкноПриложения.НачальнаяСтраница и НЕ ОкноПриложения.Основное Тогда
ФормаДлОп = ОкноПриложения.ПолучитьСодержимое();
Если ФормаДлОп.Открыта() Тогда
ФормаДлОп.Закрыть();
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Элементы.Список.Обновить();
ЭтаФорма.ОбновитьОтображениеДанных();
КонецПроцедуры
#КонецОбласти
Пример работы реализованного функционала в пользовательском режиме 1С:Предприятие:
![](//infostart.ru/upload/iblock/ebc/ebc3471061651ab5083920705c5b2fbe.jpg)
Перерасчет выбранных документов работает так же, как и кнопки внутри документа «Пересчитать» или «Пересчитать сотрудника» (если все сотрудники выбраны):
![](//infostart.ru/upload/iblock/45c/45c522a96d756a5fe6adfdef513fc784.jpg)
Подводные камни:
1) перед началом перерасчета выделенных документов желательно организовать проверку не открыта ли какая либо из форм одного из выбранных документов сейчас, если открыта - выдавать предупреждение о том, что надо ее закрыть (этого в коде выше нет)
2) в процессе перерасчета начинают отображаться формы длительной операции - нужно позаботиться о закрытии этих форм после перерасчета (в коде выше это есть)
3) после перерасчета выбранных документов иногда приходится обновить список документов вручную, поскольку некоторые документы начинают отображаться как не проведенные, хотя в коде и присутствует строчка
Элементы.Список.Обновить();
4) массовый перерасчет документов может вызывать конфликт блокировок при выполнении транзакции по причине превышении времени ожидания запроса на блокировку.
![](//infostart.ru/upload/iblock/095/0955b2acb07bb61d74094b8cbd541f93.jpg)
5) рекомендую изучить механизм утверждения (и расчета) межрасчетных документов в журнале "Начисление зарплаты": когда кадровики вводят документы, затем расчетчики должны эти документы выделить, утвердить и рассчитать. Механизм работы кнопки "Утвердить" содержит типовые алгоритмы перебора выделенных документов и их расчета - очень рекомендую их изучить.
![](//infostart.ru/upload/iblock/0b8/0b8b57b96aabe0db04fd5529a7308889.png)
2. Групповой перерасчет выбранных в списке документов "Начисление зарплаты сотрудникам организаций" в ЗУП 2.5.123
Заказчик хочет следующий функционал:
![](//infostart.ru/upload/iblock/e67/e670905c8a221bc9b0228f32ce381923.gif)
Решение.
В конфигураторе создаем новую форму списка документа копированием типовой. В элемент формы «ДокументСписок» добавляем колонку «Пометка» (без привязки к данным базы данных). Для элемента формы «ДокументСписок» добавляем командную панель с тремя подменю, см. рисунок.
![](//infostart.ru/upload/iblock/37f/37f34cfd3e84109f5f6792a25b065180.jpg)
Реализация выделения документов в списке.
Создаем реквизит формы «ТаблицаПометок».
![](//infostart.ru/upload/iblock/d4d/d4d9e65cb1d0dc806e6910ee583faaa2.jpg)
Создаем 3 процедуры для выделения документов в списке:
ДокументСписокПриПолученииДанных(…),ДокументСписокВыбор(…),КоманднаяПанель1СнятьФлажки(…)
Листинг процедур для выделения документов в списке (ЗУП 2.5.123):
Процедура ДокументСписокПриПолученииДанных(Элемент, ОформленияСтрок)
Если ТаблицаПометок.Количество()=0 Тогда Возврат; КонецЕсли;
Для Каждого СтрокаТЧ Из ОформленияСтрок Цикл
ДанныеСтроки = СтрокаТЧ.ДанныеСтроки;
Ячейки = СтрокаТЧ.Ячейки;
ЭлТаб = ТаблицаПометок.Найти(ДанныеСтроки.Ссылка,"Ссылка");
Если ЭлТаб=Неопределено Тогда Продолжить; КонецЕсли;
Ячейки.Пометка.УстановитьКартинку( ?(ЭлТаб.Пометка, БиблиотекаКартинок.Утвердить, Новый Картинка) );
СтрокаТЧ.Шрифт = Новый Шрифт (,,ЭлТаб.Пометка);
КонецЦикла;
КонецПроцедуры
Процедура КоманднаяПанель1СнятьФлажки(Кнопка)
Для Каждого ТекСтр Из ТаблицаПометок Цикл
ТекСтр.Пометка = Ложь;
КонецЦикла;
ЭлементыФормы.ДокументСписок.ОбновитьСтроки();
КонецПроцедуры
Процедура ДокументСписокВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
Если Колонка.Имя="Пометка" Тогда
СтандартнаяОбработка=Ложь;
ЭлТаб = ТаблицаПометок.Найти(Элемент.ТекущиеДанные.Ссылка,"Ссылка");
Если ЭлТаб=Неопределено Тогда
НовСтр = ТаблицаПометок.Добавить();
НовСтр.Ссылка = Элемент.ТекущиеДанные.Ссылка;
НовСтр.Пометка = Истина;
Иначе
ЭлТаб.Пометка = НЕ ЭлТаб.Пометка;
КонецЕсли;
КонецЕсли;
ЭлементыФормы.ДокументСписок.ОбновитьСтроки();
КонецПроцедуры
Реализация перерасчетов выделенных документов в списке.
Для каждой кнопки подменю добавленной командной панели элемента формы «ДокументСписок» создаем свой обработчик и одну общую процедуру ОбработатьДокументы(ВариантДействий) для всех вариантов перерасчета выбранных документов.
В ЗУП 2.5 в обычных формах мы можем очень просто реализовать расчет в форме списка:
Объект.РассчитатьВсе(); или Объект.РассчитатьНачисления(); или Объект.РассчитатьНДФЛ();
Листинг процедур перерасчета выделенных документов (ЗУП 2.5.123)
////////////////////////////////////////////////////////////////////////////////
//Обработчики кнопок
Процедура КоманднаяПанель1РассчитатьВсе(Кнопка)
ОбработатьДокументы("РассчитатьВсе");
КонецПроцедуры
Процедура КоманднаяПанель1РассчитатьНачисления(Кнопка)
ОбработатьДокументы("РассчитатьНачисления");
КонецПроцедуры
Процедура КоманднаяПанель1РассчитатьНДФЛ(Кнопка)
ОбработатьДокументы("РассчитатьНДФЛ");
КонецПроцедуры
Процедура КоманднаяПанель1РассчитатьУдержания(Кнопка)
ОбработатьДокументы("РассчитатьУдержания");
КонецПроцедуры
//{20140604.Заказчик.Пантелеев Иван(/)}
Процедура ОбработатьДокументы(ВариантДействий)
// Индикация
ФормаИндикации = ПолучитьОбщуюФорму("ХодВыполненияОбработкиДанных");
Если ФормаИндикации.Открыта() Тогда
ФормаИндикации.Закрыть();
КонецЕсли;
ФормаИндикации.НаименованиеОбработкиДанных = "Отображение состояния процесса";
ФормаИндикации.КомментарийОбработкиДанных = "Выполняется обработка отмеченных документов";
ФормаИндикации.Значение = 0;
ФормаИндикации.МаксимальноеЗначение = ТаблицаПометок.Количество();
ФормаИндикации.Открыть();
Попытка
НачатьТранзакцию();
НомПП=0;
Для Каждого ТекСтр Из ТаблицаПометок Цикл
НомПП=НомПП+1;
Если Не ТекСтр.Пометка Тогда Продолжить; КонецЕсли;
Объект = ТекСтр.Ссылка.ПолучитьОбъект();
Если Найти("РассчитатьВсеРассчитатьНачисленияРассчитатьНДФЛРассчитатьУдержания", ВариантДействий)>0 Тогда
Если ВариантДействий="РассчитатьВсе" Тогда
Объект.РассчитатьВсе();
ИначеЕсли ВариантДействий="РассчитатьНачисления" Тогда
Объект.РассчитатьНачисления();
ИначеЕсли ВариантДействий="РассчитатьНДФЛ" Тогда
Объект.РассчитатьНДФЛ();
ИначеЕсли ВариантДействий="РассчитатьУдержания" Тогда
Объект.РассчитатьУдержания();
КонецЕсли;
Если Объект.Проведен Тогда
Объект.Записать(РежимЗаписиДокумента.Проведение);
Иначе
Объект.Записать();
КонецЕсли;
ИначеЕсли Найти("ПровестиОтменаПроведения", ВариантДействий)>0 Тогда
Если ВариантДействий="Провести" Тогда
Объект.Записать(РежимЗаписиДокумента.Проведение);
ИначеЕсли ВариантДействий="ОтменаПроведения" Тогда
Объект.Записать(РежимЗаписиДокумента.ОтменаПроведения);
КонецЕсли;
ИначеЕсли Найти("ПометитьНаУдалениеСнятьПометкуНаУдаление", ВариантДействий)>0 Тогда
Если ВариантДействий="ПометитьНаУдаление" Тогда
Если НЕ Объект.ПометкаНаУдаление Тогда
Объект.ПометкаНаУдаление = Истина;
Объект.Записать();
КонецЕсли;
ИначеЕсли ВариантДействий="СнятьПометкуНаУдаление" Тогда
Если Объект.ПометкаНаУдаление Тогда
Объект.ПометкаНаУдаление = Ложь;
Объект.Записать();
КонецЕсли;
КонецЕсли;
КонецЕсли;
ОбработкаПрерыванияПользователя();
ЭлементыФормы.ДокументСписок.ОбновитьСтроки();
ФормаИндикации.Значение = НомПП;
ФормаИндикации.КомментарийЗначения = "Обработка документа : "+Строка(ТекСтр.Ссылка);
КонецЦикла;
ЗафиксироватьТранзакцию();
Исключение
Сообщение = Новый СообщениеПользователю();
ОтменитьТранзакцию();
Сообщение.Текст = ОписаниеОшибки();
Сообщение.УстановитьДанные(Объект);
Сообщение.Сообщить();
КонецПопытки;
// Убираем индикацию
Если ФормаИндикации.Открыта() Тогда
ФормаИндикации.Закрыть();
КонецЕсли;
КонецПроцедуры
Пример работы реализованного функционала в ЗУП 2.5.123:
![](//infostart.ru/upload/iblock/b58/b58d73695ab7ccc755eb88a8eae51612.jpg)
![](//infostart.ru/upload/iblock/0b8/0b8b57b96aabe0db04fd5529a7308889.png)
Ссылки на публикации по теме перерасчетов документов в списке для ЗУП:
Групповой перерасчет отпусков. ЗУП 3.0, ЗУП 3.1 Корп
Групповой перерасчет документов начисления зарплаты. ЗУП 3.0
Рекомендую публикации, посвященные теме внедрений ЗУП на больших проектах:
Отчет "Штатное расписание и расстановка на выбранные даты"
Учет и расчет выплат работникам за время прохождения медосмотров в программе «1С:ЗУП» редакции 2.5
Отчет по состояниям (отклонениям) сотрудников за период.
Отчет «Среднесписочная численность» для ЗУП
Пример создания в КД 2.1 правил обмена данными ЗУП 2.5 -> БП 3.0.
Пример создания в КД 2.1 правил выгрузки данных регистра «Лицевые счета работников» из ЗУП 2.5 в справочник «Банковские счета» БП 3.0
![](//infostart.ru/upload/iblock/fbe/fbe3cbc8bf3a5a0ae30bfdc23b3bd774.png)
Вопросы, предложения и замечания по статье пишите в комментариях.
Если статья принесла Вам пользу, то поддержите развитие публикации и автора - поставьте звездочку и/или напишите комментарий.
С пожеланием творческих успехов всем посетителям сайта ИС, Пантелеев Иван.