вторник, 24 марта 2015 г.

1c специалист задача 3.30

Решение:
Основные моменты задачи:

  • Пользователи создают ВР сами
  • Отпуск в месяце не должен превышать 10 дней
  • Оплата по окладу и по "вахте".
  • Вахта оплачивается по тарифу, который 1 раз может поменяться



Диаграмма Ганта.

1) Раз пользователи должны сами создавать ВР, то добавляем перечисление "Способы расчета".  Значения перечисления:

  • По тарифу
  • по окладу
  • отпуск
  • невыход неуважительный
  • невыход невыясненный

Добавляем реквизит этого типа в ПВР "Основные начисления". Исходя из условия задачи достаточно одного ПВР.

Настраиваем вытесняющие и базовые ВР.

2) Доработаем обработку "Заполнение графиков" и заполним графики. (подробнее)


4) Создаем регистр расчета.

5) Дорабатываем документ "Начисление ЗП", 
В форме документа "вешаем " обработчик события


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

&НаСервереБезКонтекста
Функция ЭтоВахта(ВР)
Возврат ?(ВР.СпособРасчета = Перечисления.СпособРасчета.ПоТарифу, Истина,Ложь); 

КонецФункции // ЭтоВахта()

в обработке проведения формируем первичные записи.

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
ПериодРегистрации = НачалоМесяца(ПериодРегистрации);
КонецПроцедуры


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

Запрос.УстановитьПараметр("Ссылка", Ссылка);
Запрос.УстановитьПараметр("ДатаНачала",ПериодРегистрации);
Запрос.УстановитьПараметр("ДатаОкончания", КонецМесяца(ПериодРегистрации));



РезультатЗапроса = Запрос.ВыполнитьПакет();

Если Не РезультатЗапроса[2].Пустой() Тогда
Выборка = РезультатЗапроса[2].Выбрать();
Пока Выборка.Следующий() Цикл
Если Выборка.СпособРасчета = Перечисления.СпособРасчета.ПоТарифу И Выборка.ТарифНач <> Выборка.ТарифКон И  
КонецДня(Выборка.ДатаСменыТарифа)<Выборка.ПериодДействияКонец Тогда
Движение = Движения.ОсновныеНачисления.Добавить();
ЗаполнитьЗначенияСвойств(Движение, Выборка);
Движение.ПериодДействияКонец = Выборка.ДатаСменыТарифа-1;
Движение.ИсходныеДанные = Выборка.ТарифНач;
Движение.График = Справочники.ВидыГрафиков.ШестиДневка;

Движение = Движения.ОсновныеНачисления.Добавить();
ЗаполнитьЗначенияСвойств(Движение, Выборка);
Движение.ПериодДействияНачало = Выборка.ДатаСменыТарифа;
Движение.ИсходныеДанные = Выборка.ТарифКон;
Движение.График = Справочники.ВидыГрафиков.ШестиДневка;

Иначе
Движение = Движения.ОсновныеНачисления.Добавить();
ЗаполнитьЗначенияСвойств(Движение, Выборка);
Если Выборка.СпособРасчета = Перечисления.СпособРасчета.НевыходНевыясненный Тогда
Движение.Результат =0;
ИначеЕсли Выборка.СпособРасчета = Перечисления.СпособРасчета.ПоТарифу Тогда
Движение.ИсходныеДанные = Выборка.ТарифНач;
Движение.График = Справочники.ВидыГрафиков.ШестиДневка;
ИначеЕсли Выборка.СпособРасчета = Перечисления.СпособРасчета.Отпуск Тогда
Движение.График = Справочники.ВидыГрафиков.ШестиДневка;
Движение.БазовыйПериодНачало = НачалоМесяца(ДобавитьМесяц(Выборка.ПериодДействияКонец,-3));
Движение.БазовыйПериодКонец = НачалоМесяца(Выборка.ПериодДействияКонец)-1;
КонецЕсли;

КонецЕсли;


КонецЦикла;
КонецЕсли;


Сотрудники =    РезультатЗапроса[3].Выгрузить().ВыгрузитьКолонку("Сотрудник");
Подразделения = РезультатЗапроса[4].Выгрузить().ВыгрузитьКолонку("Подразделение");
СпособыРасчета = РезультатЗапроса[5].Выгрузить().ВыгрузитьКолонку("СпособРасчета");

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

Если СпособыРасчета.Найти(Перечисления.СпособРасчета.Отпуск)<> Неопределено Тогда
Расчеты.РассчитатьНачисления(Движения.ОсновныеНачисления, Перечисления.СпособРасчета.Отпуск, Сотрудники,Подразделения,ПериодРегистрации);
Движения.ОсновныеНачисления.Записать(,Истина);
КонецЕсли;

Если СпособыРасчета.Найти(Перечисления.СпособРасчета.ПоТарифу)<> Неопределено Тогда
Расчеты.РассчитатьНачисления(Движения.ОсновныеНачисления, Перечисления.СпособРасчета.ПоТарифу, Сотрудники,Подразделения,ПериодРегистрации);
Движения.ОсновныеНачисления.Записать(,Истина);
КонецЕсли;

Если СпособыРасчета.Найти(Перечисления.СпособРасчета.ПоОкладу)<> Неопределено Тогда
Расчеты.РассчитатьНачисления(Движения.ОсновныеНачисления, Перечисления.СпособРасчета.ПоОкладу, Сотрудники,Подразделения,ПериодРегистрации);
Движения.ОсновныеНачисления.Записать(,Истина);
КонецЕсли;




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



Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)   ;

ПериодРегистрации = НачалоМесяца(ПериодРегистрации);
КонецПроцедуры

 Непосредственный расчет в общем модуле:

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

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

Выборка = Запрос.Выполнить().Выбрать();
Для Каждого Запись Из НаборЗаписей Цикл
Если Запись.ВидРасчета.СпособРасчета <> СпособРасчета Тогда
Продолжить;
КонецЕсли;

Выборка.Сбросить();
Отбор = Новый Структура;
Отбор.Вставить("НомерСтроки", Запись.НомерСтроки);
Если Выборка.НайтиСледующий(Отбор) Тогда 
Если СпособРасчета = Перечисления.СпособРасчета.НевыходНеуважительный Тогда 
Запись.Результат = Выборка.ДниФакт *(-200);
Запись.ИсходныеДанные =Выборка.ДниФакт; 
ИначеЕсли СпособРасчета = Перечисления.СпособРасчета.ПоТарифу Тогда 
Запись.Результат = Выборка.ЧасыФакт *Запись.ИсходныеДанные;
ИначеЕсли СпособРасчета = Перечисления.СпособРасчета.ПоОкладу Тогда 
Запись.Результат = Выборка.ДниФакт * Выборка.Оклад;
Запись.ИсходныеДанные =Выборка.Оклад; 
ИначеЕсли СпособРасчета = Перечисления.СпособРасчета.Отпуск и Выборка.ДниБаза <> 0 Тогда 
Если Выборка.ДниФакт + Выборка.УжеОтгулял <= 10 Тогда
Запись.Результат = Выборка.ДниФакт *(Выборка.БазаОтпуска/Выборка.ДниБаза );
Запись.ИсходныеДанные =Выборка.БазаОтпуска; 
Запись.ДнейОтпуска =Выборка.ДниФакт 
Иначе
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Отпуск не рассчитан, обнаружено превышение дней отпуска у сотрудника "+Выборка.Сотрудник + (Выборка.ДниФакт + Выборка.УжеОтгулял )+  " дней";
Сообщение.Сообщить();
Запись.Результат = 0;
Запись.ИсходныеДанные =0; 
Запись.ДнейОтпуска =0; 
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;

КонецПроцедуры
6) Отчеты
Диаграмма Ганта - тут

Скачать решение задачи 3.30 (1с специалист по платформе)

Комментариев нет:

Отправить комментарий