Добрый день!
Была у меня задача загрузить сотрудников (внештатников) из Excel файла и создать их в ЗУП 3.0 (в части загрузки мне, кстати, очень помогла вот эта статья)
Я эту задачу решил, и хочу поделиться с вами своим опытом.
Лирическое отступление
Я потратил на попытки понять, в какие регистры надо записать Сотрудника, практически целый день. Смотрел код нескольких форм справочника Сотрудники, нажимал F12, погружаясь в дебри общих модулей, некоторые из которых не делали ничего, кроме вызова функции из другого общего модуля. Зачем так было сделано, почему функции модуля содержат только возврат функций другого модуля? Достаточно сложно было разобраться в хитросплетениях этого кода.
Программное создание Сотрудника
Итак, что же нужно сделать, чтобы создать Сотрудника?
- Создать элемент справочника ФизическиеЛица. При этом желательно заполнить ИНН и СНИЛС.
- Создать элемент справочника Сотрудники. Установить ему реквизиты ФизическоеЛицо и ГоловнаяОрганизация.
- Сделать запись в регистр ДокументыФизическихЛиц
- Сделать запись в регистр МестаВыплатыЗарплатыСотрудников и создать для этого элемент справочника БанковскиеСчетаКонтрагентов
- Самое неочевидное - запись в регистр РолиСотрудников с ролью Договорник либо Работник. Я потратил на это больше всего времени и долго недоумевал, почему у меня не открывается в режиме Предприятия созданный Сотрудник.
- Сделать запись в регистр ДанныеДляПодбораСотрудников.
Также у меня в комментариях упоминается регистр ТекущиеКадровыеДанныеСотрудников, но он, судя по всему, необязателен - у меня заработало и без него.
После всех этих магических записей, наконец, можно создать договор ГПХ с Сотрудником.
Программное создание Договора ГПХ или Авторского договора
С созданием договоров было проще. В ЗУП есть два вида договоров для внештатных сотрудников: ДоговорРаботыУслуги для ГПХ и ДоговорАвторскогоЗаказа для авторов или, например, журналистов. Также я устанавливал признак УдалитьОплатаПоАктамВыполненныхРабот. Остальное можно посмотреть в коде
Код
В коде предполагается, что есть ТаблицаЗначений, загруженная из файла Excel. Пара нюансов: в колонке ВидРаботАвторский предполагается, что находится либо строка "АвторскийДоговор", либо "ДоговорГПХ", руководителя брал из регистра СведенияОбОтветственныхЛицах, организацию заполнял на форме обработки. Для получения сведений о руководителе есть функция в общем модуле СведенияОбОтветственныхЛицах, но я использовал свою - на случай, если данные не заполнены, нужно было подставить значения по умолчанию.
Создание сотрудников:
структура = ПолучитьСтруктуруПараметровОрганизации(орг);
Руководитель = структура.рукссылка;
ДолжностьРук = структура.Должность;
для каждого строкаТЧ из ТаблицаИзФайла цикл
//ФизЛицо
ФизЛицо = справочники.ФизическиеЛица.СоздатьЭлемент();
ФизЛицо.Наименование = сокрлп(СтрокаТч.ФИО);
ФизЛицо.ДатаРождения = строкаТЧ.датаРождения;
ФизЛицо.ГруппаДоступа = ГруппаДоступа;
ФизЛицо.ИНН = СтрокаТЧ.ИНН;
ФизЛицо.СтраховойНомерПФР = СтрокаТЧ.Снилс;
ФизЛицо.ФИО = сокрлп(СтрокаТч.ФИО);
//признак записи
физЛицоЗаписано=ложь;
попытка
физлицо.Записать();
физЛицоЗаписано=истина;
исключение
ош = ОписаниеОшибки();
мСтрОшибок = мСтрОшибок + ош;
сооб = новый СообщениеПользователю;
сооб.Текст = ош;
сооб.Сообщить();
конецпопытки;
//сотрудник
если физЛицоЗаписано тогда
Сотрудник = Справочники.Сотрудники.СоздатьЭлемент();
Сотрудник.Наименование = сокрлп(СтрокаТч.ФИО);
Сотрудник.ФизическоеЛицо = ФизЛицо.Ссылка;
Сотрудник.ГоловнаяОрганизация = Организация;
//Сотрудник.УдалитьВидЗанятости = Перечисления.ВидыЗанятости.Подработка;
сотрудникЗаписан=ложь;
попытка
Сотрудник.Записать();
сотрудникЗаписан = истина;
исключение
ош = ОписаниеОшибки();
мСтрОшибок = мСтрОшибок + ош;
сооб = новый СообщениеПользователю;
сооб.Текст = ош;
сооб.Сообщить();
конецпопытки;
конецесли;
//регистры:
//ДокументыФизическихЛиц СрезПоследних
если физЛицоЗаписано тогда
ДокументФизЛицзапись = РегистрыСведений.ДокументыФизическихЛиц.СоздатьМенеджерЗаписи();
//измерения
ДокументФизЛицзапись.ВидДокумента = Справочники.ВидыДокументовФизическихЛиц.ПаспортРФ;
ДокументФизЛицзапись.Физлицо = ФизЛицо.Ссылка;
//ресурсы
ДокументФизЛицзапись.ДатаВыдачи = СтрокаТЧ.ДатаВыдачи;
ДокументФизЛицзапись.КемВыдан = СтрокаТч.КемВыдан;
ДокументФизЛицзапись.Серия = строкатч.серияПаспорта;
ДокументФизЛицзапись.Номер = строкатч.НомерПаспорта;
ДокументФизЛицзапись.ЯвляетсяДокументомУдостоверяющимЛичность = истина;
////действует с - текущая дата
ДокументФизЛицзапись.Период = текущаяДата();
попытка
ДокументФизЛицзапись.Записать(истина);
исключение
ош = ОписаниеОшибки();
мСтрОшибок = мСтрОшибок + ош;
сооб = новый СообщениеПользователю;
сооб.Текст = ош;
сооб.Сообщить();
конецпопытки;
конецесли;
//регистры
если сотрудникЗаписан и физЛицоЗаписано тогда
//МестаВыплатыЗарплатыСотрудников - личный счет, по физлицу!
СчетВыплаты = РегистрыСведений.МестаВыплатыЗарплатыСотрудников.СоздатьМенеджерЗаписи();
//измерения
СчетВыплаты.Сотрудник = Сотрудник.Ссылка;
//действует с - ПРЕДЫДУЩИЙ МЕСЯЦ
СчетВыплаты.Период = ДобавитьМесяц(НачалоМесяца(ТекущаяДата()),-1);
СчетВыплаты.ФизическоеЛицо = Физлицо.Ссылка;
//ресурсы
СчетВыплаты.Вид = Перечисления.ВидыМестВыплатыЗарплаты.БанковскийСчет;
//место выплаты - БанковскиеСчетаКонтрагентов
место = справочники.БанковскиеСчетаКонтрагентов.СоздатьЭлемент();
место.Владелец = физлицо.Ссылка;
место.НомерСчета = Строкатч.РасчетныйСчет;
Бик = сокрлп(строкаТЧ.Бик);//КлассификаторБанковРФ
банкНайти= справочники.КлассификаторБанковРФ.НайтиПоКоду(Бик);
место.Банк = банкНайти;
место.Наименование = строка(физлицо.Ссылка)+" ; "+Строка(банкНайти)+" ; "+Строка(Строкатч.РасчетныйСчет);
попытка
место.Записать();
исключение
ош = ОписаниеОшибки();
мСтрОшибок = мСтрОшибок + ош;
сооб = новый СообщениеПользователю;
сооб.Текст = ош;
сооб.Сообщить();
конецпопытки;
СчетВыплаты.МестоВыплаты=место.Ссылка;
попытка
СчетВыплаты.Записать(истина);
исключение
ош = ОписаниеОшибки();
мСтрОшибок = мСтрОшибок + ош;
сооб = новый СообщениеПользователю;
сооб.Текст = ош;
сооб.Сообщить();
конецпопытки;
//регистры - ТекущиеКадровыеДанныеСотрудников
если ГруппаДоступа = Справочники.ГруппыДоступаФизическихЛиц.НайтиПоНаименованию("Штатные сотрудники") тогда
//штатник
мРоль = Перечисления.РолиСотрудников.Работник;
ВидЗанятости = Перечисления.ВидыЗанятости.ОсновноеМестоРаботы;
иначе
//договорник
мРоль = Перечисления.РолиСотрудников.Договорник;
ВидЗанятости = Перечисления.ВидыЗанятости.Подработка;
конецесли;
//регистр РолиСотрудников
//роли - обязательно!
РегистрРолей = РегистрыСведений.РолиСотрудников.СоздатьМенеджерЗаписи();
РегистрРолей.Период = НачалоДня(ТекущаяДата());
РегистрРолей.Сотрудник = Сотрудник.Ссылка;
РегистрРолей.РольСотрудника = мРоль;
РегистрРолей.Записать(истина);
//вид занятости!!! обязательно (чтоб были оформлены трудовые отношения.
//смотри запрос в списке формы выбора справочника сотрудников
регистрЗанятости = РегистрыСведений.ДанныеДляПодбораСотрудников.СоздатьМенеджерЗаписи();
регистрЗанятости.Период = НачалоДня(ТекущаяДата());
регистрЗанятости.Сотрудник = Сотрудник.Ссылка;
регистрЗанятости.ФизическоеЛицо = ФизЛицо.Ссылка;
регистрЗанятости.Организация = орг.Ссылка;
регистрЗанятости.Филиал = орг.Ссылка;
регистрЗанятости.Подразделение = справочники.ПодразделенияОрганизаций.ПустаяСсылка();
регистрЗанятости.Должность = справочники.Должности.ПустаяСсылка();
регистрЗанятости.ДолжностьПоШтатномуРасписанию = справочники.ШтатноеРасписание.ПустаяСсылка();
видДог = СтрокаТЧ.ВидДоговора;
если не видДог = "АвторскийДоговор" тогда
//договоры гпх
регистрЗанятости.УдалитьПоДоговоруГПХ=Истина;
конецесли;
//ресурсы регистра
//регистрЗанятости.ВидСобытия = Перечисления.ВидыКадровыхСобытий.Прием;
//реги
регистрЗанятости.ВидЗанятости = ВидЗанятости;
регистрЗанятости.Окончание = Дата(2099,1,1);
регистрЗанятости.Записать(истина);
конецесли;
//Создание Договора
если сотрудникЗаписан и физЛицоЗаписано тогда
//создаем договор
попытка
видДог = СтрокаТЧ.ВидДоговора;
суммаДог = строкаТЧ.СуммаДоговора;
ВидРаботАвтДог = СтрокаТЧ.ВидРаботАвторский;
ДатаНачалаДоговора = СтрокаТЧ.ДатаНачала;
ДатаКонцаДоговора = Строкатч.ДатаОкончания;
ДатаДоговора = СтрокаТЧ.ДатаДоговора;
текЮзер = ПараметрыСеанса.ТекущийПользователь;
если видДог = "АвторскийДоговор" тогда
Договор = Документы.ДоговорАвторскогоЗаказа.СоздатьДокумент();
//должно быть заполнено для авторских.
договор.ВидАвторскогоДоговора = ВидРаботАвтДог;
//ндфд для авторских 2207 или 2201
//
//Сумма в пределах нормативов затрат, связанных с получением авторских вознаграждений
//договор.КодВычета = Справочники.ВидыВычетовНДФЛ.Код405;
иначе
Договор = Документы.ДоговорРаботыУслуги.СоздатьДокумент();
конецесли;
Договор.Организация = Организация;
Договор.Подразделение = СтрокаТЧ.Подразделение.Ссылка;
Договор.Сотрудник = сотрудник.Ссылка;
договор.ФизическоеЛицо = физлицо.Ссылка;
договор.ДатаНачала = ДатаНачалаДоговора;
договор.дата = ДатаДоговора;
договор.Руководитель = Руководитель.ссылка;
договор.ДолжностьРуководителя=ДолжностьРук.ссылка;
договор.ДатаОкончания = ДатаКонцаДоговора;
//новое при обновлении зуп
Договор.УдалитьОплатаПоАктамВыполненныхРабот = истина;
договор.Сумма = СуммаДог;
договор.Ответственный = текЮзер;
//проведем договор
договор.Записать(РежимЗаписиДокумента.Проведение);
ссылкаДог = Договор.Ссылка;
массивДоговоров.Добавить(ссылкаДог);
счетчикУспешно = счетчикУспешно+1;
//добавим в ТЧ Успешных
строкаУспех = Объект.УспешноЗагруженные.Добавить();
строкаУспех.Сотрудник = сотрудник.Ссылка;
строкаУспех.Договор = Договор.Ссылка;
исключение
договор.Записать(РежимЗаписиДокумента.Запись);
ош = ОписаниеОшибки();
мСтрОшибок = мСтрОшибок + "при проведении договора "+ош;
сооб = новый СообщениеПользователю;
сооб.Текст = ош;
сооб.Сообщить();
конецпопытки;
ИНАЧЕ
счетчикОшибка= счетчикОшибка+1;
строшибок = стрОшибок+" При создании сотрудника "+строкатч.ФИО+" Ошибки:"+мСтрОшибок+Символы.ПС;
конецесли;
Конеццикла;
Сведения о руководителе:
&НаСервере
функция ПолучитьСтруктуруПараметровОрганизации(Организация)
СтруктураВозврата = новый структура;
орг = Организация;
если орг = справочники.Организации.ПустаяСсылка() тогда
орг = РегламентированнаяОтчетность.ПолучитьОрганизациюПоУмолчанию();
если орг = справочники.Организации.ПустаяСсылка() тогда
//получим первую из справочника
выб = справочники.Организации.Выбрать();
выб.Следующий();
орг = выб.Ссылка;
конецесли;
конецесли;
запросПоОрганизации= новый запрос;
запросПоОрганизации.Текст="ВЫБРАТЬ
| СведенияОбОтветственныхЛицахСрезПоследних.Период,
| СведенияОбОтветственныхЛицахСрезПоследних.Организация,
| СведенияОбОтветственныхЛицахСрезПоследних.Руководитель,
| СведенияОбОтветственныхЛицахСрезПоследних.ДолжностьРуководителя,
| СведенияОбОтветственныхЛицахСрезПоследних.ГлавныйБухгалтер,
| СведенияОбОтветственныхЛицахСрезПоследних.Кассир,
| СведенияОбОтветственныхЛицахСрезПоследних.ДолжностьКассира,
| СведенияОбОтветственныхЛицахСрезПоследних.РуководительКадровойСлужбы,
| СведенияОбОтветственныхЛицахСрезПоследних.ДолжностьРуководителяКадровойСлужбы,
| СведенияОбОтветственныхЛицахСрезПоследних.ОтветственныйЗаВУР,
| СведенияОбОтветственныхЛицахСрезПоследних.ДолжностьОтветственногоЗаВУР,
| СведенияОбОтветственныхЛицахСрезПоследних.ОтветственныйЗаОхрануТруда,
| СведенияОбОтветственныхЛицахСрезПоследних.ДолжностьОтветственногоЗаОхрануТруда
|ИЗ
| РегистрСведений.СведенияОбОтветственныхЛицах.СрезПоследних(&Дата, ) КАК СведенияОбОтветственныхЛицахСрезПоследних
|ГДЕ
| СведенияОбОтветственныхЛицахСрезПоследних.Организация = &Организация";
запросПоОрганизации.УстановитьПараметр("Дата",текущаядата());
запросПоОрганизации.УстановитьПараметр("Организация",орг);
выборка = запросПоОрганизации.Выполнить().Выбрать();
если выборка.Количество()=0 тогда
//в регистре ничего нет - ПО УМОЛЧАНИЮ
РукСтрока = "Иванов Иван Иванович";
РукСтрокаРП = "Иванова Ивана Ивановича";
РукИнициалы = "Иванов И.И.";
РукДолжность = справочники.Должности.НайтиПоНаименованию("Генеральный директор");
РукСсылка = Справочники.ФизическиеЛица.НайтиПоНаименованию(рукстрока);
иначе
выборка.Следующий();
РукСтрока = Строка(Выборка.Руководитель);
РукСсылка = Выборка.Руководитель;
попытка
пол = ?(Выборка.Руководитель.пол=Перечисления.ПолФизическогоЛица.Мужской,1,2);
исключение
пол=1;
конецпопытки;
РукСтрокаРП = "Иванова Ивана Ивановича";
РукИнициалы = ФизическиеЛицаКлиентСервер.ФамилияИнициалыФизЛица(РукСтрока);
РукДолжность = выборка.ДолжностьРуководителя;
конецесли;
ДанныеРегистрацииВНалоговомОргане = ЗарплатаКадрыВызовСервера.ДанныеРегистрацииВНалоговомОргане(орг.Ссылка, орг.РегистрацияВНалоговомОргане);
Кпп = строка(ДанныеРегистрацииВНалоговомОргане.КПП);
если пустаяСтрока(Кпп) тогда
кпп = "770123456";
конецесли;
ИннКппОрг = "ИНН "+строка(орг.инн)+"/КПП "+кпп;
ОгрнОрг = "ОГРН "+строка(орг.ОГРН);
НазваниеОрг = " "+сокрлп(орг.НаименованиеСокращенное)+" ";
запросАдрес= новый запрос;
запросАдрес.Текст="ВЫБРАТЬ
| ОрганизацииКонтактнаяИнформация.Тип,
| ОрганизацииКонтактнаяИнформация.Вид,
| ОрганизацииКонтактнаяИнформация.Представление
|ИЗ
| Справочник.Организации.КонтактнаяИнформация КАК ОрганизацииКонтактнаяИнформация
|ГДЕ
| ОрганизацииКонтактнаяИнформация.Ссылка = &Ссылка
| И ОрганизацииКонтактнаяИнформация.Тип = &Тип
| И ОрганизацииКонтактнаяИнформация.Вид = &Вид";
запросАдрес.УстановитьПараметр("Ссылка",орг.Ссылка);
запросАдрес.УстановитьПараметр("Тип",Перечисления.ТипыКонтактнойИнформации.Адрес);
запросАдрес.УстановитьПараметр("Вид",Справочники.ВидыКонтактнойИнформации.ЮрАдресОрганизации);
выбАдрес=запросАдрес.Выполнить().Выбрать();
если выбАдрес.Количество()=0 тогда
АдресОрг = "127000, МОСКВА, улица Одинэсная, д. 83";
иначе
выбАдрес.Следующий();
АдресОрг = строка(выбАдрес.Представление);
конецесли;
СтруктураВозврата.Вставить("Руководитель",РукСтрока);
СтруктураВозврата.Вставить("РуководительРодПадеж",РукСтрокаРП);
СтруктураВозврата.Вставить("РуководительИнициалы",РукИнициалы);
СтруктураВозврата.Вставить("ИннКппОрг",ИннКппОрг);
СтруктураВозврата.Вставить("ОгрнОрг",ОгрнОрг);
СтруктураВозврата.Вставить("НазваниеОрг",НазваниеОрг);
СтруктураВозврата.Вставить("АдресОрг",АдресОрг);
СтруктураВозврата.Вставить("Должность",РукДолжность);
СтруктураВозврата.Вставить("РукСсылка",РукСсылка);
возврат СтруктураВозврата;
конецфункции