diff --git a/lib/dolisirh_function.lib.php b/lib/dolisirh_function.lib.php index 2349f1b..331de43 100644 --- a/lib/dolisirh_function.lib.php +++ b/lib/dolisirh_function.lib.php @@ -22,6 +22,8 @@ */ require_once DOL_DOCUMENT_ROOT . '/projet/class/task.class.php'; +require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php'; +require_once __DIR__ . '/../class/workinghours.class.php'; /** * Add or delete task from favorite by the user @@ -208,7 +210,7 @@ function setCategoriesObject($categories = array(), $type_categ = '', $remove_ex } /** - * Load time spent into this->weekWorkLoad and this->weekWorkLoadPerTask for all day of a week of project. + * Load time spent within a time range for a project. * Note: array weekWorkLoad and weekWorkLoadPerTask are reset and filled at each call. * * @param int $datestart First day @@ -274,27 +276,29 @@ function loadTimeSpentWithinRangeByProject($datestart, $dateend, $project_id, $t } /** - * Load time spent into this->weekWorkLoad and this->weekWorkLoadPerTask for all day of a week of project. - * Note: array weekWorkLoad and weekWorkLoadPerTask are reset and filled at each call. + * Load time spent within a time range. * * @param int $datestart First day * @param int $dateend Last day * @param int $taskid Filter on a task id * @param int $userid Time spent by a particular user - * @return int 0 < if OK, >0 if KO + * @return array Array with minutes, hours and total time spent * @throws Exception */ function loadTimeSpentWithinRange($datestart, $dateend, $taskid = 0, $userid = 0) { global $db; - $error = 0; - - $task = new Task($db); if (empty($datestart)) { dol_print_error('', 'Error datestart parameter is empty'); } + $workinghours = new Workinghours($db); + $holiday = new Holiday($db); + + $daysInRange = num_between_day($datestart, $dateend, 1); + $workinghoursArray = $workinghours->fetchCurrentWorkingHours($userid, 'user'); + $sql = "SELECT ptt.rowid as taskid, ptt.task_duration, ptt.task_date, ptt.task_datehour, ptt.fk_task"; $sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time AS ptt, ".MAIN_DB_PREFIX."projet_task as pt"; $sql .= " WHERE ptt.fk_task = pt.rowid"; @@ -307,9 +311,28 @@ function loadTimeSpentWithinRange($datestart, $dateend, $taskid = 0, $userid = 0 $sql .= " AND ptt.fk_user=".((int) $userid); } - $timeSpent = array(); + $timeSpent = array( + 'days' => 0, + 'hours' => 0, + 'minutes' => 0, + 'total' => 0 + ); - $objects = array(); + for ($idw = 0; $idw < $daysInRange; $idw++) { + $day_start_date = dol_time_plus_duree($datestart, $idw, 'd'); // $firstdaytoshow is a date with hours = 0 + $day_end_date = dol_time_plus_duree($datestart, $idw + 1, 'd'); // $firstdaytoshow is a date with hours = 0 + + $statusofholidaytocheck = Holiday::STATUS_APPROVED; + + $isavailablefordayanduser = $holiday->verifDateHolidayForTimestamp($userid, $day_start_date, $statusofholidaytocheck); + $isavailable[dol_print_date($day_start_date,'dayrfc')] = $isavailablefordayanduser; // in projectLinesPerWeek later, we are using $firstdaytoshow and dol_time_plus_duree to loop on each day + + $day_is_available = !num_public_holiday($day_start_date, $day_end_date); + + if (!$day_is_available) { + $isavailable[dol_print_date($day_start_date,'dayrfc')] = 0; + } + } //print $sql; $resql = $db->query($sql); @@ -321,18 +344,178 @@ function loadTimeSpentWithinRange($datestart, $dateend, $taskid = 0, $userid = 0 $obj = $db->fetch_object($resql); $hours = floor($obj->task_duration / 3600); - $minutes = ($obj->task_duration % 3600); + $minutes = floor($obj->task_duration / 60); $timeSpent['hours'] += $hours; $timeSpent['minutes'] += $minutes; $timeSpent['total'] += $obj->task_duration; + + if ($isavailable[$obj->task_date]) { + $days_worked[$obj->task_date] = 1; + } + $i++; } $db->free($resql); - return $timeSpent; - } else { - return -1; } + $timeSpent['days'] = is_array($days_worked) && !empty($days_worked) ? count($days_worked) : 0; + + return $timeSpent; +} + +/** + * Load time to spend within a time range. + * + * @param int $datestart First day + * @param int $dateend Last day + * @param int $taskid Filter on a task id + * @param int $userid Time spent by a particular user + * @return int 0 < if OK, >0 if KO + * @throws Exception + */ +function loadTimeToSpendWithinRange($datestart, $dateend, $taskid = 0, $userid = 0) +{ + global $db; + + if (empty($datestart)) { + dol_print_error('', 'Error datestart parameter is empty'); + } + + $workinghours = new Workinghours($db); + $holiday = new Holiday($db); + + $daysInRange = num_between_day($datestart, $dateend, 1); + $workinghoursArray = $workinghours->fetchCurrentWorkingHours($userid, 'user'); + + $time_to_spend = array( + 'days' => 0, + 'minutes' => 0 + ); + + for ($idw = 0; $idw < $daysInRange; $idw++) { + $day_start_date = dol_time_plus_duree($datestart, $idw, 'd'); // $firstdaytoshow is a date with hours = 0 + $day_end_date = dol_time_plus_duree($datestart, $idw + 1, 'd'); // $firstdaytoshow is a date with hours = 0 + + $statusofholidaytocheck = Holiday::STATUS_APPROVED; + + $isavailablefordayanduser = $holiday->verifDateHolidayForTimestamp($userid, $day_start_date, $statusofholidaytocheck); + $isavailable[$day_start_date] = $isavailablefordayanduser; // in projectLinesPerWeek later, we are using $firstdaytoshow and dol_time_plus_duree to loop on each day + + $day_is_available = !num_public_holiday($day_start_date, $day_end_date); + + if ($day_is_available) { + $currentDay = date('l', $day_start_date); + $currentDay = 'workinghours_' . strtolower($currentDay); + $time_to_spend['minutes'] += $workinghoursArray->{$currentDay}; + if ($workinghoursArray->{$currentDay} / 60 > 0) { + $time_to_spend['days']++; + } + } + } + return $time_to_spend; +} + +/** + * Load time to spend within a time range. + * + * @param int $datestart First day + * @param int $dateend Last day + * @param int $taskid Filter on a task id + * @param int $userid Time spent by a particular user + * @return int 0 < if OK, >0 if KO + * @throws Exception + */ +function loadPassedTimeWithinRange($datestart, $dateend, $taskid = 0, $userid = 0) +{ + global $db; + + if (empty($datestart)) { + dol_print_error('', 'Error datestart parameter is empty'); + } + + $workinghours = new Workinghours($db); + $holiday = new Holiday($db); + + $daysInRange = num_between_day($datestart, $dateend, 1); + $workinghoursArray = $workinghours->fetchCurrentWorkingHours($userid, 'user'); + + $passed_working_time = array( + 'minutes' => 0 + ); + + for ($idw = 0; $idw < $daysInRange; $idw++) { + $day_start_date = dol_time_plus_duree($datestart, $idw, 'd'); // $firstdaytoshow is a date with hours = 0 + $day_end_date = dol_time_plus_duree($datestart, $idw + 1, 'd'); // $firstdaytoshow is a date with hours = 0 + + $statusofholidaytocheck = Holiday::STATUS_APPROVED; + + $isavailablefordayanduser = $holiday->verifDateHolidayForTimestamp($userid, $day_start_date, $statusofholidaytocheck); + $isavailable[$day_start_date] = $isavailablefordayanduser; // in projectLinesPerWeek later, we are using $firstdaytoshow and dol_time_plus_duree to loop on each day + + $day_is_available = !num_public_holiday($day_start_date, $day_end_date); + + if ($day_is_available) { + $currentDay = date('l', $day_start_date); + $currentDay = 'workinghours_' . strtolower($currentDay); + $passed_working_time['minutes'] += $workinghoursArray->{$currentDay}; + } + } + return $passed_working_time; +} + +/** + * Load difference between passed time and spent time within a time range. + * + * @param int $datestart First day + * @param int $dateend Last day + * @param int $taskid Filter on a task id + * @param int $userid Time spent by a particular user + * @return int 0 < if OK, >0 if KO + * @throws Exception + */ +function loadDifferenceBetweenPassedAndSpentTimeWithinRange($datestart, $dateend, $taskid = 0, $userid = 0) +{ + global $db; + + if (empty($datestart)) { + dol_print_error('', 'Error datestart parameter is empty'); + } + $passed_working_time = loadPassedTimeWithinRange($datestart, $dateend, $taskid, $userid); + $spent_working_time = loadTimeSpentWithinRange($datestart, $dateend, $taskid, $userid); + + return $passed_working_time['minutes'] - $spent_working_time['minutes']; +} + +/** + * Load all time spending infos within a time range. + * + * @param int $datestart First day + * @param int $dateend Last day + * @param int $taskid Filter on a task id + * @param int $userid Time spent by a particular user + * @return int 0 < if OK, >0 if KO + * @throws Exception + */ +function loadTimeSpendingInfosWithinRange($datestart, $dateend, $taskid = 0, $userid = 0) +{ + global $db; + + if (empty($datestart)) { + dol_print_error('', 'Error datestart parameter is empty'); + } + $planned_working_time = loadTimeToSpendWithinRange($datestart, $dateend, $taskid, $userid); + $passed_working_time = loadPassedTimeWithinRange($datestart, $dateend, $taskid, $userid); + $spent_working_time = loadTimeSpentWithinRange($datestart, $dateend, $taskid, $userid); + $working_time_difference = loadDifferenceBetweenPassedAndSpentTimeWithinRange($datestart, $dateend, $taskid, $userid); + + $time_spending_infos = array( + 'planned' => $planned_working_time, + 'passed' => $passed_working_time, + 'spent' => $spent_working_time, + 'difference' => $working_time_difference + ); + + return $time_spending_infos; } /** diff --git a/view/timesheet/timesheet_card.php b/view/timesheet/timesheet_card.php index 65167d5..dd66eee 100644 --- a/view/timesheet/timesheet_card.php +++ b/view/timesheet/timesheet_card.php @@ -663,8 +663,6 @@ print '' . "\n"; // Common attributes - //$keyforbreak='fieldkeytoswitchonsecondcolumn'; // We change column just before this field - unset($object->fields['fk_project']); // Hide field already shown in banner unset($object->fields['fk_soc']); // Hide field already shown in banner @@ -679,119 +677,41 @@ $now = dol_now(); $datestart = dol_getdate($object->date_start, false, 'Europe/Paris'); - //$firstdaytoshow = dol_get_first_day($datestart['year'], $datestart['mon']); - //$firstdaytoshowgmt = dol_get_first_day($datestart['year'], $datestart['mon'], true); // Due to Dolibarr issue in common field add we do substract 12 hours in timestamp $firstdaytoshow = $object->date_start - 12 * 3600; - $firstdaytoshowgmt = $object->date_start - 12 * 3600; - //$dayInMonth = cal_days_in_month(CAL_GREGORIAN, $datestart['mon'], $datestart['year']); - $dayInMonth = num_between_day($object->date_start, $object->date_end, 1); - //$lastdaytoshow = dol_get_last_day($datestart['year'], $datestart['mon']); $lastdaytoshow = $object->date_end - 12 * 3600; - $currentDayCurrent = date('d', $now); - $currentMonth = date('m', $now); - $isavailable = array(); - $workinghoursArray = $workinghours->fetchCurrentWorkingHours($object->fk_user_assign, 'user'); - $workinghoursMonth = 0; - $nbworkinghoursMonth = 0; - if ($currentMonth == $datestart['mon']) { - $dayInMonthCurrent = $dayInMonth; - } else { - $dayInMonthCurrent = $dayInMonth; - } - - for ($idw = 0; $idw < $dayInMonth; $idw++) { - $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); // $firstdaytoshow is a date with hours = 0 - $dayinloopfromfirstdaytoshowgmt = dol_time_plus_duree($firstdaytoshowgmt, $idw, 'd'); // $firstdaytoshow is a date with hours = 0 - - $statusofholidaytocheck = Holiday::STATUS_APPROVED; - - $isavailablefordayanduser = $holiday->verifDateHolidayForTimestamp($object->fk_user_assign, $dayinloopfromfirstdaytoshow, $statusofholidaytocheck); - $isavailable[$dayinloopfromfirstdaytoshow] = $isavailablefordayanduser; // in projectLinesPerWeek later, we are using $firstdaytoshow and dol_time_plus_duree to loop on each day - - $test = num_public_holiday($dayinloopfromfirstdaytoshowgmt, $dayinloopfromfirstdaytoshowgmt + 86400, $mysoc->country_code); - if ($test) { - $isavailable[$dayinloopfromfirstdaytoshow] = array('morning' => false, 'afternoon' => false, 'morning_reason' => 'public_holiday', 'afternoon_reason' => 'public_holiday'); - } - } - - $tasksarray = $task->getTasksArray(0, 0, 0, 0, 0, '', '', '', $object->fk_user_assign, 0, array()); - - if (count($tasksarray) > 0) { - $usertmp->fetch($object->fk_user_assign); - $j = 0; - $level = 0; - $projectsrole = $task->getUserRolesForProjectsOrTasks($usertmp, 0, 0, 0, 1); - $tasksrole = $task->getUserRolesForProjectsOrTasks(0, $usertmp, 0, 0, 1); - $restrictviewformytask = ((!isset($conf->global->PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED)) ? 2 : $conf->global->PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED); - $conf->global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS = 0; - $totalforvisibletasks = loadTimeSpentWithinRange($object->date_start, $object->date_end, 0, $object->fk_user_assign); - } $start_date = dol_print_date($firstdaytoshow, "dayreduceformat"); $end_date = dol_print_date($lastdaytoshow, "dayreduceformat"); - // Planned working hours + $timeSpendingInfos = loadTimeSpendingInfosWithinRange($firstdaytoshow, $lastdaytoshow, 0, $object->fk_user_assign); + + // Planned working time + $planned_working_time = $timeSpendingInfos['planned']; + print ''; // Hours passed + $passed_working_time = $timeSpendingInfos['passed']; + print ''; - //Worked hours - print ''; @@ -821,7 +745,7 @@ print ' - '; print $langs->trans("DiffSpentAndConsumedWorkedHoursMonth", $start_date, $end_date); print ' : '; - print (($difftotaltime != 0) ? convertSecondToTime(abs($difftotaltime), 'allhourmin') : '00:00').''; + print (($difftotaltime != 0) ? convertSecondToTime(abs($difftotaltime * 60), 'allhourmin') : '00:00').''; print ''; print ''; @@ -836,7 +760,7 @@ print '
'; ?> - +
trans('ErrorConfigWorkingHours') ?>
'; print $langs->trans("Total"); - for ($idw = 0; $idw < $dayInMonth; $idw++) { - $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); - if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { - $currentDay = date('l', $dayinloopfromfirstdaytoshow); - $currentDay = 'workinghours_' . strtolower($currentDay); - $plannedWorkingHours += $workinghoursArray->{$currentDay} * 60; - if ($workinghoursArray->{$currentDay} / 60 > 0) { - $nbworkinghoursMonth++; - } - if ($totalforvisibletasks['total'] > 0) { - $nbconsumedworkinghoursMonth++; - } - } - } - print ' - '; print $langs->trans("ExpectedWorkedHoursMonthTimeSheet", $start_date, $end_date); print ' : '; - print (($plannedWorkingHours != 0) ? convertSecondToTime($plannedWorkingHours, 'allhourmin') : '00:00') . ''; - print '' . ' - ' . $langs->trans("ExpectedWorkedDayMonth") . ' ' . $nbworkinghoursMonth . ''; + print (($planned_working_time['minutes'] != 0) ? convertSecondToTime($planned_working_time['minutes'] * 60, 'allhourmin') : '00:00') . ''; + print '' . ' - ' . $langs->trans("ExpectedWorkedDayMonth") . ' ' . $planned_working_time['days'] . ''; print ''; print '
'; print $langs->trans("Total"); - $passedWorkingHours = 0; - for ($idw = 0; $idw < $dayInMonthCurrent; $idw++) { - $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); - if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { - $currentDay = date('l', $dayinloopfromfirstdaytoshow); - $currentDay = 'workinghours_' . strtolower($currentDay); - $passedWorkingHours += $workinghoursArray->{$currentDay} * 60; - - } - } print ' - '; print $langs->trans("SpentWorkedHoursMonth", $start_date, $end_date); - print ' : ' . (($passedWorkingHours != 0) ? convertSecondToTime($passedWorkingHours, 'allhourmin') : '00:00') . ''; + print ' : ' . (($passed_working_time['minutes'] != 0) ? convertSecondToTime($passed_working_time['minutes'] * 60, 'allhourmin') : '00:00') . ''; print '
'; - print $langs->trans("Total"); - for ($idw = 0; $idw < $dayInMonthCurrent; $idw++) { - $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); - if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { - $workedHoursOnDay = loadTimeSpentWithinRange($dayinloopfromfirstdaytoshow, dol_time_plus_duree($dayinloopfromfirstdaytoshow, 1, 'd'), 0, $object->fk_user_assign); - if (!empty($workedHoursOnDay)) { - $workedHoursArray[$dayinloopfromfirstdaytoshow] = $workedHoursOnDay; - $workedHours += $workedHoursOnDay['total']; - } - } - } - $workedDays = is_array($workedHoursArray) ? count($workedHoursArray) : 0; - - $difftotaltime = $passedWorkingHours - $workedHours; + //Difference between passed and worked hours + $difftotaltime = $timeSpendingInfos['difference']; if ($difftotaltime < 0) { $morecss = colorStringToArray($conf->global->DOLISIRH_EXCEEDED_TIME_SPENT_COLOR); @@ -807,11 +727,15 @@ $noticetitle = $langs->trans('TimeSpentPerfect'); } + //Worked hours + $worked_time = $timeSpendingInfos['spent']; + print '
'; + print $langs->trans("Total"); print ' - '; print $langs->trans("ConsumedWorkedHoursMonth", $start_date, $end_date); - print ' : '.convertSecondToTime($workedHours, 'allhourmin').''; + print ' : '.convertSecondToTime($worked_time['total'], 'allhourmin').''; print '' . ' - ' . $langs->trans("ConsumedWorkedDayMonth") . ' '; - print $workedDays . ''; + print $worked_time['days'] . ''; print ''; print '