Вы здесь

Расчёт стажа у сотрудника. Как лучше сделать?

0

Есть простая и достаточно распространённая задача автоматически считать стаж работы сотрудника. При создании ноды сотрудника мы указываем промежутки, когда он работал, например:

01.1990-12.1995
05-1998-04.2000
04.2000-н.в.

Из этого мы должны автоматически получить расчёт, конечный пользователь должен видеть, что стаж составляет 25 лет 3 месяца... Сейчас пытаюсь решить эту задачу стандартным полем даты. Логика в том, что я указываю промежутки дат в формате, который мне нужен, ну а если сотрудник работает по настоящее время - я просто не указываю конечную дату.

Вопрос:
1) Как решить расчёт технически без сильной нагрузки на ресурсы? Подсчёт должен осуществляться раз в месяц или неделю?
2) Какие ещё есть способы? Каков опыт в решении аналогичных задач?
3) Какие минусы у моего способа?

Версия Drupal: 
7.x
Вопрос задан 21.01.2018 - 10:11

Вычитаете из даты окончания дату начала, складываете получившиеся стажи, выводите с помощью format_interval(). В чём у вас сложность?

Комментарий оставлен 21.01.2018 - 10:35

Сложность, как часто бывает, в деталях. Получается мне нужно сделать шаблон для поля даты и в нём прописать логику?

Комментарий оставлен 22.03.2018 - 15:48

Ответы

0

Сделали следующее:
1) Установили модуль Field collection
2) Сделали коллекцию полей с названием field-c-worker-experience, в которую вошло два поля: Запись о периоде трудовой деятельности (field_worker_work_interval) и Работа по специальности (field_worker_work_spec_flag). Первое поле - это дата с возможность указать начальную и конечную дату, второе - галочка (чтобы потом понять какой стаж у нас по специальности ,а какой общий)
3) Вывели это на php в шаблоне ноды. Следующий код все хитро считает и выводит:

$items = field_get_items('node', $node,'field_c_worker_experience'); //получаем колекцию полей
            if(!empty($items)){ //проверяем есть ли добавленные элементы колекции
                function calculate_age($date1, $date2 = NULL){ //функция по подсчету интервала между двух дат
                    if(!$date2){ //если вторая дата не задана принимаем ее как текущую
                        $cd = getdate();
                        $date2 = $cd['year'].'-'.$cd['mon'].'-'.$cd['mday'].' '.$cd['hours'].':'.$cd['minutes'].':'.$cd['seconds'];
                    }
                    $datetime1 = new DateTime($date1); //создаем переменные дат
                    $datetime2 = new DateTime($date2);
                    $age = $datetime1->diff($datetime2); //считаем интервал
                    return $age;
                }
                $start_date = new DateTime('2000-01-01'); //начальная дата отсчета
                $work_sum = new DateTime('2000-01-01'); //начальная дата отсчетата стажа
                $work_sum_spec = new DateTime('2000-01-01'); //начальная дата отсчетата стажа по специальности

                foreach ($items as $item){ //перебираем элементы колекции
                    $fc = field_collection_field_get_entity($item); //получаем элемент колекции
                    $date1 = $fc->field_worker_work_interval['und'][0]['value']; //дата 1
                    $date2 = $fc->field_worker_work_interval['und'][0]['value2']; // дата 2
                    $spec_flag = $fc->field_worker_work_spec_flag['und'][0]['value']; //флаг специальности
                    if($date1==$date2)$date2 = NULL; //если вторая дата совпадает, то присваеваем ей пустое значение для подсчета по текущий день
                    $result = calculate_age($date1, $date2); //получаем интервал между датами
                    $work_sum->add($result); //суммируем интервал к начальной дате отсчета
                    if($spec_flag) $work_sum_spec->add($result); //суммируем интервал к начальной дате отсчета по специальности
                    //получаем конечные интервалы
                    $age_work = $start_date->diff($work_sum);
                    $age_spec = $start_date->diff($work_sum_spec);
                }
                function number($n, $titles){ //функция по выводу правильной приставки к числу
                    $cases = array(2, 0, 1, 1, 1, 2);
                    return $titles[($n % 100 > 4 && $n % 100 < 20) ? 2 : $cases[min($n % 10, 5)]];
                }
                function date_output($y, $m){ //функция подготавливает стаж с правильной приставкой для вывода
                    if($y==0&&$m==0){return "уточняется";//если количество лет и месяцев = 0
                    } else {
                        if($y>=1){//если количество лет больше или равно 1
                            $ym = $y.number($y, array(' год ', ' года ', ' лет '));
                            if($m!=0)$ym = $ym.$m.number($m, array(' месяц', ' месяца', ' месяцев'));
                            return $ym;
                        } else {return "меньше года";}
                    }
                }
                //выводим искомое
                echo '<div class="clearfix"></div>';
                echo '<span class="h5">';
                    echo '<strong>Cтаж работы общий:</strong></br> '.date_output($age_work->format('%y'), $age_work->format('%m')).' (на '.date('d.m.Y').')';
                    echo '<div class="clearfix margin-top-10 margin-bottom-10"></div>';
                    echo '<strong>Cтаж работы по специальности:</strong></br> '.date_output($age_spec->format('%y'), $age_spec->format('%m')).' (на '.date('d.m.Y').')';
                echo '</span>';
            }
Ответ дан 19.07.2019 - 14:16