1с перебрать даты за период
Собираюсь решить задачу, но ни разу с таким не сталкивался - может кто имеет опыт и поделиться?
Задача - необходимо проанализировать гарфик работника(по периодам в часах)(это план) и проходы его через электронную проходную(факт)
на основании анализа ввести документы отклонений(типа прогул)
итого сотрудник отсутствовал всего 1:30 и нужно ввести документ отклонения от графика как прогул на 1:30.
Пересечение 2 конкретных периодов можно отловить и проаналзировать а вот как проанализировать пересечения групп периодов ?
Если кто сталкивался с такой задачей, буду рад любому совету.
В чем проблема.Добавь к периодам плана поле "ЧасовПоПлану" и вычитай из него часы тех периодов факта, которые в них попали.
(0) А если он не хочет никуда выходить на обед?
Не проще считать время проведенное на территории и если оно меньше того, что он должен отработать, тогда уже прогул
(2) Ты еще предложи не считать прогулы, если работник справляется со своими обязанностями. Не для того такие системы внедряются.
(2)
проще - но у кадров свой однозначный запрос - зачем? - не могу знать!
есть трафарет(план) и факт должен с ним совпадать.
Насчет обедов - допускается присутствие сотрудников во время обеда на территории, но это время согласно плану не считается рабочим.
(0) Не понял, почему в обед нужно сразу писать прогул, а после обеда "нужно посмотреть другие периоды"?
Нужно уточнить постановку. Если общее время за день закрывает план, этого достаточно? А за месяц?
(4) Чем отличается:
> 12-12:30 и 12-13 - факт обеда больше на 30 минут - нужно ввести прогул на 30 минут
от
> 12:30-17 и 13-15 - факт не закрывает план - но ничего не вводим - нужно посмотреть другие периоды, вдруг он дальше все закрыл
Почему там нужно, а тут не нужно?
(5) Недостаточно - рабочим временем в итоге учитывается время которое строго вошло в рамки плана.
Кстати - факт и план я собрал, в том же виде как они приведены в примере(т.е. периодами)
но как их сравнить? не могу понять.
Время по плану и так известно и их сравниваешь.
(6) скорректирую пример
Факт
16-17
вот так лучше - 12-13 человек не был на территории.(вышел в 12 и вернулся только в 13) т.к. это время ближе всего к периоду плана "обед" то и сравниваем с ним.
И немного не понятно тут "факт не закрывает план - но ничего не вводим - нужно посмотреть другие периоды, вдруг он дальше все закрыл".
Как он в принципе может "закрыть" дальше, если вы не даете ему работать свыше плана
(12) у меня не сводится к часам в день. У меня сводится к времени в "разрешенных" интервалах
(13) например факт может быть таким
15:10-17
Тогда человек всего 10 минут не был на рабочем месте - предположим что он встречал курьера. в любом случаем до 15 минут отклонений за раз - мы ему простим итого план он выполнил.
1) Взять пересечения интервалов факта и плана (только рабочее время), Просуммировать.
2) Просуммировать план (только рабочее время).
3) Сравнить, разницу пишем в прогул.
(4) Нет. Не свожу. Из остатка часов планового присутствия вычитаются только то количество часов, которое определяется пересечением фактического периода с плановыми. Мне казалось, это очевидно.
Удобнее всего, как я и говорил, просто добавить в табличку периодов планового присутствия колонку, где на старте рассчитать количество плановых часов присутствия для каждого периода.
Потом при обходе фактических периодов пробегаешься по табличке плановых периодов и "примеряешь" каждый фактический период к каждому плановому. Если есть пересечение, то вычитаешь количество часов НА ПЕРЕСЕЧЕНИИ из количества часов планового присутствия для периода. Итог по колонке в конце даст общее количество часов прогула.
Можно и без колонки, тупо из общего количества часов планового присутствия вычитать. Но так не останется инфы, в какие конкретно периоды сотр не вписался, а это может быть полезным.
Это как раз фигня задача. Я как увидел тему, подумал что речь про более интересную задачу - как получить эти самые периоды фактического присутствия из данных СКУД, где вход и выход отдельными событиями пишется. С учетом всевозможных отклонений. Двойных срабатываний, проходом без отметки и так далее.
мыслите множествами. тогда пересечение интервалов не важно. а важно только общая сумма отработанных часов.
(21) Перед тем как начинать мыслить, полезно прочитать ТЗ.
(19) Сравнивать каждый с каждым хм. я такое предлагал кадрам но они почему то забраковали. сегодня добьюсь от них письменного ответа. спасибо.
(20) да случаи прохода бывают разные, "волшебные" - 2 входа подряд с разницей в 2 часа. пока принято решение что это был выход по "чужой карте" и наказывается не зачётом того периода где нет выхода.
(23) Причем тут вообще "кадры"? Это детали внутренней реализации.
У тебя же небольшое количество периодов планового присутствия. В сабже - два. Дообеденный и послеобеденный. В чем проблема сравнивать их на пересечение с каждым фактическим?
(23) Вот интересно - а у программистов, разрабатывающих эту чудо-систему, есть план пристуствия на рабочем месте, который надо закрывать? Или это другое?
(24) в чем проблема - если у нас 1 вид документа отклонения(прогул) на любое отклонение от плана и мы можем все отклонения просто просуммировать между собой, если больше одного то получается что на каждое отклонение от плана необходимо вводить свой документ(со своим видом)(например прогул И отпуск без сохранения зп(уж не знаю чем это от прогула отличается, но вот такое бывает))
(25) план есть у любого сотрудника предприятия(даже у директора) - часть программистов не являются сотрудниками текущего предприятия и имеют право свободного входа\выхода. любопытный вы наш.
ну и как мы узнаем отклонение в часах при
План
12:30-17
Если последовательно сравнивать периоды - то 12:30-17 и 13-15 даст отклонение в 2,5 часа от плана
и 12:30-17 и 16-17 - 3,5 часа. после того как просуммируем будет отклонение 6 часов. что неверно - ведь реальное отклонение только 1,5 часа с 12:30-13 и с 15-16 - этого мы не сможем узнать просто последовательно сравнивая периоды. так что пока план нерабочий.
чем жестче закручивают гайки контролируя каждый шаг сотрудников и карая за любое отклонение тем меньше сотрудник заинтересован в результатах своего труда, а лишь в соблюдении всего этого бреда за который могут наказать.
через некоторое время адекватные люди задаются вопросом а нахрена я вообще тут нахожусь если вместо работы голова забита только прогулами объяснительными как не опоздать как не выйти позже чем положено и т.д. и уходят туда где нет подобного бреда.
(28) это управленческие вопросы - не вижу смысла поднимать их в данной теме.
(29) а без этого тривиальная задача.
перебираем фактические периоды, вырезаем их из плановых. все что осталось - отсутствия. все что сверху вырезалось - переработки.
дальше поступаем с этими периодами согласно имеющемуся ТЗ. вводим документы например.
(29) Мне чет не совсем понятно, что это за отметки факта, у вас сотрудники по несколько раз на дню через проходную проходят? Если так, то если человек вышел через проходную не в обед, то все, прогул?
(32) у нас на предприятии проще, считаются только крайние отметки, чтобы зафиксировать когда пришел на работу и когда ушел домой. Обед вообще не привязан ко времени, есть час в течении дня, когда захотел, тогда и покушал. И нет никаких проблем
(27) Не понял, как ты считаешь.
Факт 13:00 - 15.00 (2 часа, они же результат пересечения с планом, вычитаем из плана остается остаток 2.5 плановых часа)
Факт 16:00 - 17:00 (1 час, он же результат пересечения с планом, вычитаем из остатка плановых часов, остается 1.5 плановых часа)
(32) все верно
проход через проходную может быть сколько угодно раз в день. отсутствие на предприятии больше 15 минут в рабочее(плановое) время - сразу прогул.
(37) Т.е. если видишь что опаздываешь, то проще на работу вообще не ехать. Удобно.
(39) пишешь заявление о предоставлении отпуска на период опоздания в счет будущей переработки))
Ну смотри сравниваем последовательно периоды
план
12:30-17
1. 12:30-17 и 13-15 даст отклонение в 2,5 часа от плана - 12:30-13 - 30 минут и 15-17 2 часа. итого отклонения по текущему факту 2,5 часа
2. 12:30-17 и 16-17 - 3,5 часа. с 12:30 - 16 - 3,5 часа отклонения.
Итого 6 часов отклонения.
а ты как предлагаешь?
(41) Я тебе уже на пальцах расписал. Не тупи. Пересечение множеств/промежутков - это их общая часть. А ты чего насчитал?
(43) можешь показать на пальцах алгоритм? что такое "общая часть", как ее определить?
(45) Нарисуй на бумажке два отрезочка. Один под другим. Заштрихуй ту часть, где одновременно две линии придется. Это и будет общая часть. Пересечение.
(46) отлично - а алгоритм как выглядит? не могу сообразить.
(47) Писал навскидку, поэтому лучше перепроверить:
(48) Уважаемый у нас же не двух а 3 - как вы утверждаете
так вот мой вопрос - как т определяешь что эти 2 периода это некая общая часть?
Там где про "общую" часть писалось - это про сравнение ДВУХ периодов. А не трех. Потому что ты не понимал что такое пересечение двух множеств и вместо этого считал их разность.
(50) можно алгоритм этого "попарного сравнения"?
я знаю только алгоритм сравнения 2 периодов между собой (именного его вы и привели).
еще раз в (48) вы указали сравнение 2 периодов между собой. а что за алгоритм "Речь о попарном сравнении всех плановых периодов с каждым фактическим". как вы выразились - можно его увидеть?
(55) имея вот такие простые входные данные
План
12:30-17
итого 16200-9000 -12600 = -5400 сек. что неверно.
верный ответ 5400 сек отклонения от плана.
то ваш алгоритм и того ошибочней посчитает.
(37) вообще-то прогул по ТК это совсем другое.
и ваши истории с прогулом за 15 минутное опоздание продолжаются ровно до того момента пока не найдется принципиальный и грамотный сотрудник который натравит на вас трудинспекцию, которая вас там уже всех за такие прогулы поставит в коленно-локтевую позицию.
(60) А по теме до сих пор вопросы остались?
(61) остались. я привел пример расчета по вашему циклу в (56) - вы нет.откуда вы взяли ваш результат мне решительно непонятно. прошу раскрыть вопрос.
(62) я не просто так прошу - я утверждаю - ваш алгоритм выдает совершенно неверный результат.
(62) Подставил эти исходные данные в (55)
А вот проверка для (57):
(65) Приношу свои искренние извинения за свой тупизм.
На тестовом примере алгоритм выдал верный результат.
ухожу в отладку и применение алгоритма к реальным данным.
Ближе к вечеру отпишу все ли нормально.
Спасибо за помощь.
еще раз. прошу меня простить, что я неверно прочитал алгоритм, а он работает так как задумано.
Так что тоже извиняюсь, если был местами резок. Но мне казалось, что это довольно тривиальная задача и тема себя быстро исчерпает.
(67) ты еще погоди.
я же только на тестовом примере проверил.
надо
проверить на реальных данных, возможно там будет не так все радужно.
но в любом случае , спасибо за помощь.
(33) а если сотрудник вышел в обед и вернулся через 2 часа, то есть 1 час прогулял?
выдает корректный результат
Отсутствовал 15 минут (которые прощаются, но главное что мы их видим).
Еще раз спасибо. продолжаю тестирование.
(0) о, я с этой темой сталкивался очень подробно.
Реализовывал одну такую систему. Пиши в лычку, скину описалово.
для затравки:
Учет отметок о приходе
Время сотрудника первоначально делится на моменты его нахождения на работе и за ее пределами, например, так:
При этом первая и последняя запись всегда «на работе». На работе обозначает что сотрудник находился на рабочем месте, на территории предприятия
Расписания вводятся в базе «1С: Биометрия».
Расписания заносятся в справочник «Расписания».
Учет отклонений рабочего времени
Когда задано расписание, то появляется возможность учитывать отклонения рабочего времени.
Виды рабочего времени бывают такими:
1. Рабочее время (РВ) – сотрудник находится на рабочем месте.
2. Опоздание (ОП) – сотрудник пришел на работу позже назначенного времени
5. Перерыв (ПР) – сотрудник ушел с работы внутри интервала не рабочего времени.
6. Прогул (НВ) – если сотрудник должен быть на рабочем месте, но отсутствовал, задается рамками начала и окончания рабочего дня.
7. Отсутствие(ОТ) – сотрудник ушел с работы внутри интервала рабочего времени.
8. Прогул (ПГ) – прогул.
Каждый интервал времени расписания помечается следующими полями:
1. Рабочее время – флажок того, что время считается рабочим. Если не установлен, то время не рабочее, например, перерыв – не рабочее время.
2. Опоздание – фиксировать опоздание, если первая отметка рабочего времени позже интервала.
3. Преждевременный уход – фиксировать преждевременный уход, если последняя отметка рабочего времени раньше интервала.
4. Переработка – присутствие сотрудника в этом интервале времени считается переработкой.
5. Перерыв – время относится к перерыву.
Для расписания в целом задаются следующие параметры:
1. Норма перерывов – какое количество перерывов допустимо в течении рабочего дня. Время, превышающее норму перерывов относится в «Отсутствие».
2. Максимальное опоздание – какое максимальное опоздание начисляется, в минутах. После этого время относится в «Отсутствие». Если не задано, то опоздание считается по факту.
3. Допустимое опоздание – какое опоздание разрешается, в минутах.
4. Вычитать допустимое опоздание – если флаг установлен, то из зафиксированного опоздания вычитается допустимое опоздание, иначе опоздание считается без вычетов.
5. Максимальная переработка – какое максимальное время переработки учитывается. Если не задано, то переработка учитывается по факту.
6. Максимальный преждевременный уход – какое максимальное время преждевременного ухода учитывать.
7. Допустимый преждевременный уход – какой преждевременный уход разрешается, в минутах.
8. Вычитать допустимый преждевременный уход – если флаг установлен, то из зафиксированного преждевременного ухода вычитается преждевременный уход, иначе преждевременный уход считается без вычетов.
9. Минимальное рабочее время – если задано, то в случае, если рабочее время получилось меньше, рабочее время обнуляется и фиксируется прогул.
Итогом расчета рабочего времени является список интервалов, каждый из которых относится к определенному виду времени.
В итоге получается сумма по каждому из видов времени в минутах. Она сохраняется по каждому расчету в регистре «Начисленное время».
Пример: Рабочее время 420, Опоздание 10, Перерыв 60, Переработка 30.
Чтобы скорректировать рабочее время используется регистр «Корректировки времени», где для каждого сотрудника на определенную дату можно указать другое значение по виду времени. Значения из этого регистра имеют приоритет над расчетными. Каждую запись можно сопроводить комментарием.
Пример: Сотрудник ездил по делам в течении трех часов, в итоге у него Отсутствие 180. Нужно создать корректировочную запись Отсутствие 0, с комментарием «Отсутствие по делам, согласовано с руководством».
Пример: Сотрудник опоздал на час из-за сбоя в работе транспорта, в итоге у него Опоздание 60. Нужно создать корректировочную запись Опоздание 0, с комментарием «Опоздал из-за сбоя транспорта, объяснительная приложена и проверена Ивановым И.И.».
Назначение расписаний сотрудникам
В регистре «Назначения» назначается расписание сотрудникам. Одному сотруднику можно назначить на дату несколько расписаний, тогда по каждому из них ему будут посчитаны показатели рабочего времени.
Алгоритм расчета часов по расписаниям
Алгоритм позволяет определить прогулы сотрудников. Поэтому анализируются данные за выбранный в обработке период времени. Если период не выбран, то используется дата от начальной до минимальной.
Изначально таблица проходов рассчитывается в разрезе Person ID + Дата + Точка.
Затем за каждый анализируемый день по таблице назначения расписаний определяется, какие расписания действуют для сотрудников на этот день.
Формируется таблица расчета часов в разрезе: Физлицо + Дата + Точка + Расписание + Подразделение.
Аналог типовой функции РазложитьНаПериоды(ДатаНачала = '00010101', ДатаОкончания = '00010101') , только релизовано на языке запросов. Не удалось найти готового решения, поэтому выкладываю запрос по разбиению периода на помесячные интервалы тут.
архив с текстом запроса и сохраненная версия для "Универсальной консоли отчетов"Специальные предложения
(16) давайте я поясню свою мысль.
Предложенное вами решение без должного основания использует зависимости:
1) от наличия в составе конфигурации такого объекта как регистр сведений "РегламентированныйПроизводственныйКалендарь";
2) от его правильной заполненности на нужный период.
Если первая зависимость легко проверяется (при попытке использовать этот метод в конфигурации без календаря, вы просто получите ошибку), то вторая зависимость неприятнее. При частичной заполненности календаря вы получите ошибку в отчете, которую еще потребуется поискать.
Кроме того, используемый принцип совершенно зря перебирает все даты периода, когда из месяца требуется только одна запись. То есть работает в 30 раз медленнее возможного.
Вопрос, наверное не такой уж важный, но тут много начинающих, которые используют готовый код, никак его не осмысливая. В результате чего недостаточно проработанные, сделанные на скорую руку решения множатся. Авторы публикаций могли бы этому препятствовать, а вы, кажется, способствуете.
Кстати, если уж настаиваете на использовании календаря, могу предложить вот такой вариант из одного запроса:
Он короче и более универсальный - легко вид периода (день, месяц, год, квартал) поменять.
А вообще в свете вопроса (15) можно было бы и конкурс объявить на решение этой задачи без календаря.
Существует несколько способов получить нужные данные.
Непосредственно в запросе
Способ подходит практически для любой ситуации и поэтому наиболее универсален. Единственный,
пожалуй, минус этого способа - если в отчете пользователю не требуется курс, то запрос будет
выбирать избыточные данные.
Вызов СрезПоследних() можно использовать только с передачей в него заранее готового значения даты,
на которую требуется получить значения. Поэтому сабж делается через стыковку нескольких запросов -
основной, к нему стыкуется запрос по регистру сведений с условием по дате и поиском записи с
маскимальной датой (периодом).
В 8.1. вместо обращения к курсам валют удобнее и надежнее использовать временную таблицу с нужными
датами, потому что не во всех организациях ведут курсы валют ежедневно. ;-)
Для общего развития:
Что есть срез последних в платформе?
В зависимости от периодичности регистра (по времени, по позиции регистратора) ВТ разворачивается в
следующий запрос:
1. По времени (год, месяц, . секунда)
2. По позиции регистратора
В данном случае нужно еще раз обернуть выборку
Все это можно увидеть посмотрев технологический журнал с включенным режимом протоколирования
запросов
Система компоновки данных
Данный способ подходит для отчетов. Из очевидных плюсов - если курс (или другие данные) не нужны для
построения отчета, то СКД не будет их получать. Однако быстродействие такого отчета может оказаться
и несколько ниже, чем в первом способе.
Для примера сделаем отчет - список заказов покупателей.
Для этого создадим набор данных "Документы" - запрос:
Для того, чтобы получить информацию о курсах валют, добавим второй набор данных - запрос "Курсы
валют":
Главное здесь - параметры связи. При соединении наборов данных, если указан параметр, СКД передает в подчиненный набор (в нашем случае - запрос "Курсы валют") параметры, указанные в соединении.
Значениями параметров будут значения соответствующих полей набора-источника.
1С 8.3 Разбить период по подпериодам (месяц, неделя, день, квартал)
&НаСервере
Функция ЗапросомРазбитьПериодНаПодпериоды ( Знач НачДата , Знач КонДата )
// например НачДата 05.05.2021, КонДата 27.09.2021
Запрос = Новый Запрос ( "ВЫБРАТЬ
| НАЧАЛОПЕРИОДА(&НачДата, МЕСЯЦ) КАК Период
|ИТОГИ ПО
| Период ПЕРИОДАМИ(МЕСЯЦ, &НачДата, &КонДата)" );
Запрос . УстановитьПараметр ( "НачДата" , НачДата );
Запрос . УстановитьПараметр ( "КонДата" , КонДата );
РезультатЗапроса = Запрос . Выполнить ();
Если Не РезультатЗапроса . Пустой () Тогда // Такая проверка рекомендуется фирмой 1С
Записи = РезультатЗапроса . Выбрать ( ОбходРезультатаЗапроса . ПоГруппировкам , "Период" , "ВСЕ" );
// Обход результата запроса по каждой записи в полученной выборке
Пока Записи . Следующий () Цикл
Сообщить ( Записи . Период );
// 01.05.2021 0:00:00
// 01.06.2021 0:00:00
// 01.07.2021 0:00:00
// 01.08.2021 0:00:00
// 01.09.2021 0:00:00
//Год_Даты = СокрЛП(Год(Записи.Период)); // 2 021
//Месяц_Даты = СокрЛП(Месяц(Записи.Период)); // 9
//Сообщить(Год_Даты+" "+Месяц_Даты);
КонецЦикла;
Иначе // Например: Сообщить("Данные отсутствуют!");
КонецЕсли;
&НаСервере
Функция РазбитьПериодНаПодпериоды ( Знач НачДата , Знач КонДата , УровеньДетализации )
ТаблицаДат = Новый ТаблицаЗначений ;
ТаблицаДат . Колонки . Добавить ( "НачДата" );
ТаблицаДат . Колонки . Добавить ( "КонДата" );
ПервыйОбходЦикла = Истина;
Если УровеньДетализации = "День" Тогда
Пока НачДата <= КонДата Цикл
Если ПервыйОбходЦикла Тогда
Если КонецДня ( НачДата ) >= КонДата Тогда
НоваяСтрока = ТаблицаДат . Добавить ();
НоваяСтрока . НачДата = НачДата ;
НоваяСтрока . КонДата = КонДата ;
Прервать;
Иначе
НоваяСтрока = ТаблицаДат . Добавить ();
НоваяСтрока . НачДата = НачДата ;
НоваяСтрока . КонДата = КонецДня ( НачДата );
КонецЕсли;
Иначе
Если КонецДня ( НачДата ) >= КонДата Тогда
НоваяСтрока = ТаблицаДат . Добавить ();
НоваяСтрока . НачДата = НачалоДня ( НачДата );
НоваяСтрока . КонДата = КонДата ;
Прервать;
Иначе
НоваяСтрока = ТаблицаДат . Добавить ();
НоваяСтрока . НачДата = НачалоДня ( НачДата );
НоваяСтрока . КонДата = КонецДня ( НачДата );
КонецЕсли;
КонецЕсли;
НачДата = КонецДня ( НачДата )+ 1 ;
ПервыйОбходЦикла = Ложь;
КонецЦикла;
Пока НачДата <= КонДата Цикл
Если ПервыйОбходЦикла Тогда
Если КонецНедели ( НачДата ) >= КонДата Тогда
НоваяСтрока = ТаблицаДат . Добавить ();
НоваяСтрока . НачДата = НачДата ;
НоваяСтрока . КонДата = КонДата ;
Прервать;
Иначе
НоваяСтрока = ТаблицаДат . Добавить ();
НоваяСтрока . НачДата = НачДата ;
НоваяСтрока . КонДата = КонецНедели ( НачДата );
КонецЕсли;
Иначе
Если КонецНедели ( НачДата ) >= КонДата Тогда
НоваяСтрока = ТаблицаДат . Добавить ();
НоваяСтрока . НачДата = НачалоНедели ( НачДата );
НоваяСтрока . КонДата = КонДата ;
Прервать;
Иначе
НоваяСтрока = ТаблицаДат . Добавить ();
НоваяСтрока . НачДата = НачалоНедели ( НачДата );
НоваяСтрока . КонДата = КонецНедели ( НачДата );
КонецЕсли;
КонецЕсли;
НачДата = КонецНедели ( НачДата )+ 1 ;
ПервыйОбходЦикла = Ложь;
КонецЦикла;
Читайте также: