Есть простая и достаточно распространённая задача автоматически считать стаж работы сотрудника. При создании ноды сотрудника мы указываем промежутки, когда он работал, например:
01.1990-12.1995
05-1998-04.2000
04.2000-н.в.
Из этого мы должны автоматически получить расчёт, конечный пользователь должен видеть, что стаж составляет 25 лет 3 месяца... Сейчас пытаюсь решить эту задачу стандартным полем даты. Логика в том, что я указываю промежутки дат в формате, который мне нужен, ну а если сотрудник работает по настоящее время - я просто не указываю конечную дату.
Вопрос:
1) Как решить расчёт технически без сильной нагрузки на ресурсы? Подсчёт должен осуществляться раз в месяц или неделю?
2) Какие ещё есть способы? Каков опыт в решении аналогичных задач?
3) Какие минусы у моего способа?
Ответы
Сделали следующее:
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>';
}
Вычитаете из даты окончания дату начала, складываете получившиеся стажи, выводите с помощью format_interval(). В чём у вас сложность?
Сложность, как часто бывает, в деталях. Получается мне нужно сделать шаблон для поля даты и в нём прописать логику?