$data['designation'] = $_REQUEST['designation']; $data['comment'] = isset($_REQUEST['comment']) && !empty($_REQUEST['comment']) ? $_REQUEST['comment'] : ''; $data['commentType'] = $_REQUEST['commentType']; $data['refundable'] = getRequestBool('refundable'); $data['multiplier'] = getRequestDecimal($_REQUEST['multiplier']); $data['value'] = getRequestDecimal($_REQUEST['edit_value']); $data['userID'] = $kga['user']['userID']; if (!is_numeric($data['multiplier']) || $data['multiplier'] <= 0) { $errors['multiplier'] = $kga['lang']['errorMessages']['multiplierNegative']; } // parse new day and time $edit_day = Kimai_Format::expand_date_shortcut($_REQUEST['edit_day']); $edit_time = Kimai_Format::expand_time_shortcut($_REQUEST['edit_time']); // validate day and time $new = "{$edit_day}-{$edit_time}"; if (!Kimai_Format::check_time_format($new)) { $errors[''] = $kga['lang']['TimeDateInputError']; } // convert to internal time format $new_time = convert_time_strings($new, $new); $data['timestamp'] = $new_time['in']; expenseAccessAllowed($data, $action, $errors); if (count($errors) > 0) { echo json_encode(array('errors' => $errors)); break; } $result = false; if ($id) { if (expense_edit($id, $data) === false) { $errors[''] = $kga['lang']['error']; }
/** * Format a number as a money value. * * @param int $number amount of money * @return string formatted string */ public function money($number) { return Kimai_Format::formatCurrency($number, false); }
// Load data and return it // Load data and return it case 'reload': $view->assign('exportData', export_get_data($in, $out, $filterUsers, $filterCustomers, $filterProjects, $filterActivities, false, $reverse_order, $default_location, $filter_cleared, $filter_type, false, $filter_refundable)); $view->assign('total', Kimai_Format::formatDuration($database->get_duration($in, $out, $filterUsers, $filterCustomers, $filterProjects, $filterActivities, $filter_cleared))); $ann = export_get_user_annotations($in, $out, $filterUsers, $filterCustomers, $filterProjects, $filterActivities); Kimai_Format::formatAnnotations($ann); $view->assign('user_annotations', $ann); $ann = export_get_customer_annotations($in, $out, $filterUsers, $filterCustomers, $filterProjects, $filterActivities); Kimai_Format::formatAnnotations($ann); $view->assign('customer_annotations', $ann); $ann = export_get_project_annotations($in, $out, $filterUsers, $filterCustomers, $filterProjects, $filterActivities); Kimai_Format::formatAnnotations($ann); $view->assign('project_annotations', $ann); $ann = export_get_activity_annotations($in, $out, $filterUsers, $filterCustomers, $filterProjects, $filterActivities); Kimai_Format::formatAnnotations($ann); $view->assign('activity_annotations', $ann); $view->assign('timeformat', $timeformat); $view->assign('dateformat', $dateformat); if (isset($kga['user'])) { $view->assign('disabled_columns', export_get_disabled_headers($kga['user']['userID'])); } echo $view->render("table.php"); break; // Export as html file // Export as html file case 'export_html': $database->user_set_preferences(array('print_summary' => isset($_REQUEST['print_summary']) ? 1 : 0, 'reverse_order' => isset($_REQUEST['reverse_order']) ? 1 : 0), 'ki_export.print.'); $exportData = export_get_data($in, $out, $filterUsers, $filterCustomers, $filterProjects, $filterActivities, false, $reverse_order, $default_location, $filter_cleared, $filter_type, false, $filter_refundable); $timeSum = 0; $wageSum = 0;
/** * Get a combined array with time recordings and expenses to export. * * @param int $start Time from which to take entries into account. * @param int $end Time until which to take entries into account. * @param array $users Array of user IDs to filter by. * @param array $customers Array of customer IDs to filter by. * @param array $projects Array of project IDs to filter by. * @param array $activities Array of activity IDs to filter by. * @param bool $limit sbould the amount of entries be limited * @param bool $reverse_order should the entries be put out in reverse order * @param string $default_location use this string if no location is set for the entry * @param int $filter_cleared (-1: show all, 0:only cleared 1: only not cleared) entries * @param int $filter_type (-1 show time and expenses, 0: only show time entries, 1: only show expenses) * @param int $limitCommentSize should comments be cut off, when they are too long * @return array with time recordings and expenses chronologically sorted */ function export_get_data($start, $end, $users = null, $customers = null, $projects = null, $activities = null, $limit = false, $reverse_order = false, $default_location = '', $filter_cleared = -1, $filter_type = -1, $limitCommentSize = true, $filter_refundable = -1) { global $expense_ext_available, $database; $timeSheetEntries = array(); $expenses = array(); if ($filter_type != 1) { $timeSheetEntries = $database->get_timeSheet($start, $end, $users, $customers, $projects, $activities, $limit, $reverse_order, $filter_cleared); } if ($filter_type != 0 && $expense_ext_available) { $expenses = get_expenses($start, $end, $users, $customers, $projects, $limit, $reverse_order, $filter_refundable, $filter_cleared); } $result_arr = array(); $timeSheetEntries_index = 0; $expenses_index = 0; $keys = array('type', 'id', 'time_in', 'time_out', 'duration', 'formattedDuration', 'decimalDuration', 'rate', 'wage', 'wage_decimal', 'budget', 'approved', 'statusID', 'status', 'billable', 'customerID', 'customerName', 'projectID', 'projectName', 'description', 'projectComment', 'activityID', 'activityName', 'comment', 'commentType', 'location', 'trackingNumber', 'username', 'cleared'); while ($timeSheetEntries_index < count($timeSheetEntries) && $expenses_index < count($expenses)) { $arr = array(); foreach ($keys as $key) { $arr[$key] = null; } $arr['location'] = $default_location; if (!$reverse_order && $timeSheetEntries[$timeSheetEntries_index]['start'] > $expenses[$expenses_index]['timestamp'] || $reverse_order && $timeSheetEntries[$timeSheetEntries_index]['start'] < $expenses[$expenses_index]['timestamp']) { if ($timeSheetEntries[$timeSheetEntries_index]['end'] != 0) { // active recordings will be omitted $arr['type'] = 'timeSheet'; $arr['id'] = $timeSheetEntries[$timeSheetEntries_index]['timeEntryID']; $arr['time_in'] = $timeSheetEntries[$timeSheetEntries_index]['start']; $arr['time_out'] = $timeSheetEntries[$timeSheetEntries_index]['end']; $arr['duration'] = $timeSheetEntries[$timeSheetEntries_index]['duration']; $arr['formattedDuration'] = $timeSheetEntries[$timeSheetEntries_index]['formattedDuration']; $arr['decimalDuration'] = sprintf("%01.2f", $timeSheetEntries[$timeSheetEntries_index]['duration'] / 3600); $arr['rate'] = $timeSheetEntries[$timeSheetEntries_index]['rate']; $arr['wage'] = $timeSheetEntries[$timeSheetEntries_index]['wage']; $arr['wage_decimal'] = $timeSheetEntries[$timeSheetEntries_index]['wage_decimal']; $arr['budget'] = $timeSheetEntries[$timeSheetEntries_index]['budget']; $arr['approved'] = $timeSheetEntries[$timeSheetEntries_index]['approved']; $arr['statusID'] = $timeSheetEntries[$timeSheetEntries_index]['statusID']; $arr['status'] = $timeSheetEntries[$timeSheetEntries_index]['status']; $arr['billable'] = $timeSheetEntries[$timeSheetEntries_index]['billable']; $arr['customerID'] = $timeSheetEntries[$timeSheetEntries_index]['customerID']; $arr['customerName'] = $timeSheetEntries[$timeSheetEntries_index]['customerName']; $arr['projectID'] = $timeSheetEntries[$timeSheetEntries_index]['projectID']; $arr['projectName'] = $timeSheetEntries[$timeSheetEntries_index]['projectName']; $arr['description'] = $timeSheetEntries[$timeSheetEntries_index]['description']; $arr['projectComment'] = $timeSheetEntries[$timeSheetEntries_index]['projectComment']; $arr['activityID'] = $timeSheetEntries[$timeSheetEntries_index]['activityID']; $arr['activityName'] = $timeSheetEntries[$timeSheetEntries_index]['activityName']; if ($limitCommentSize) { $arr['comment'] = Kimai_Format::addEllipsis($timeSheetEntries[$timeSheetEntries_index]['comment'], 150); } else { $arr['comment'] = $timeSheetEntries[$timeSheetEntries_index]['comment']; } $arr['commentType'] = $timeSheetEntries[$timeSheetEntries_index]['commentType']; $arr['location'] = $timeSheetEntries[$timeSheetEntries_index]['location']; $arr['trackingNumber'] = $timeSheetEntries[$timeSheetEntries_index]['trackingNumber']; $arr['username'] = $timeSheetEntries[$timeSheetEntries_index]['userName']; $arr['cleared'] = $timeSheetEntries[$timeSheetEntries_index]['cleared']; $result_arr[] = $arr; } $timeSheetEntries_index++; } else { $arr['type'] = 'expense'; $arr['id'] = $expenses[$expenses_index]['expenseID']; $arr['time_in'] = $expenses[$expenses_index]['timestamp']; $arr['time_out'] = $expenses[$expenses_index]['timestamp']; $arr['wage'] = sprintf("%01.2f", $expenses[$expenses_index]['value'] * $expenses[$expenses_index]['multiplier']); $arr['customerID'] = $expenses[$expenses_index]['customerID']; $arr['customerName'] = $expenses[$expenses_index]['customerName']; $arr['projectID'] = $expenses[$expenses_index]['projectID']; $arr['projectName'] = $expenses[$expenses_index]['projectName']; $arr['description'] = $expenses[$expenses_index]['designation']; $arr['projectComment'] = $expenses[$expenses_index]['projectComment']; if ($limitCommentSize) { $arr['comment'] = Kimai_Format::addEllipsis($expenses[$expenses_index]['comment'], 150); } else { $arr['comment'] = $expenses[$expenses_index]['comment']; } $arr['activityName'] = $expenses[$expenses_index]['designation']; $arr['comment'] = $expenses[$expenses_index]['comment']; $arr['commentType'] = $expenses[$expenses_index]['commentType']; $arr['username'] = $expenses[$expenses_index]['userName']; $arr['cleared'] = $expenses[$expenses_index]['cleared']; $result_arr[] = $arr; $expenses_index++; } } while ($timeSheetEntries_index < count($timeSheetEntries)) { if ($timeSheetEntries[$timeSheetEntries_index]['end'] != 0) { // active recordings will be omitted $arr = array(); foreach ($keys as $key) { $arr[$key] = null; } $arr['location'] = $default_location; $arr['type'] = 'timeSheet'; $arr['id'] = $timeSheetEntries[$timeSheetEntries_index]['timeEntryID']; $arr['time_in'] = $timeSheetEntries[$timeSheetEntries_index]['start']; $arr['time_out'] = $timeSheetEntries[$timeSheetEntries_index]['end']; $arr['duration'] = $timeSheetEntries[$timeSheetEntries_index]['duration']; $arr['formattedDuration'] = $timeSheetEntries[$timeSheetEntries_index]['formattedDuration']; $arr['decimalDuration'] = sprintf("%01.2f", $timeSheetEntries[$timeSheetEntries_index]['duration'] / 3600); $arr['rate'] = $timeSheetEntries[$timeSheetEntries_index]['rate']; $arr['wage'] = $timeSheetEntries[$timeSheetEntries_index]['wage']; $arr['wage_decimal'] = $timeSheetEntries[$timeSheetEntries_index]['wage_decimal']; $arr['budget'] = $timeSheetEntries[$timeSheetEntries_index]['budget']; $arr['approved'] = $timeSheetEntries[$timeSheetEntries_index]['approved']; $arr['statusID'] = $timeSheetEntries[$timeSheetEntries_index]['statusID']; $arr['status'] = $timeSheetEntries[$timeSheetEntries_index]['status']; $arr['billable'] = $timeSheetEntries[$timeSheetEntries_index]['billable']; $arr['customerID'] = $timeSheetEntries[$timeSheetEntries_index]['customerID']; $arr['customerName'] = $timeSheetEntries[$timeSheetEntries_index]['customerName']; $arr['projectID'] = $timeSheetEntries[$timeSheetEntries_index]['projectID']; $arr['projectName'] = $timeSheetEntries[$timeSheetEntries_index]['projectName']; $arr['projectComment'] = $timeSheetEntries[$timeSheetEntries_index]['projectComment']; $arr['activityID'] = $timeSheetEntries[$timeSheetEntries_index]['activityID']; $arr['activityName'] = $timeSheetEntries[$timeSheetEntries_index]['activityName']; $arr['description'] = $timeSheetEntries[$timeSheetEntries_index]['description']; if ($limitCommentSize) { $arr['comment'] = Kimai_Format::addEllipsis($timeSheetEntries[$timeSheetEntries_index]['comment'], 150); } else { $arr['comment'] = $timeSheetEntries[$timeSheetEntries_index]['comment']; } $arr['commentType'] = $timeSheetEntries[$timeSheetEntries_index]['commentType']; $arr['location'] = $timeSheetEntries[$timeSheetEntries_index]['location']; $arr['trackingNumber'] = $timeSheetEntries[$timeSheetEntries_index]['trackingNumber']; $arr['username'] = $timeSheetEntries[$timeSheetEntries_index]['userName']; $arr['cleared'] = $timeSheetEntries[$timeSheetEntries_index]['cleared']; $result_arr[] = $arr; } $timeSheetEntries_index++; } while ($expenses_index < count($expenses)) { $arr = array(); foreach ($keys as $key) { $arr[$key] = null; } $arr['location'] = $default_location; $arr['type'] = 'expense'; $arr['id'] = $expenses[$expenses_index]['expenseID']; $arr['time_in'] = $expenses[$expenses_index]['timestamp']; $arr['time_out'] = $expenses[$expenses_index]['timestamp']; $arr['wage'] = sprintf("%01.2f", $expenses[$expenses_index]['value'] * $expenses[$expenses_index]['multiplier']); $arr['customerID'] = $expenses[$expenses_index]['customerID']; $arr['customerName'] = $expenses[$expenses_index]['customerName']; $arr['projectID'] = $expenses[$expenses_index]['projectID']; $arr['projectName'] = $expenses[$expenses_index]['projectName']; $arr['description'] = $expenses[$expenses_index]['designation']; $arr['projectComment'] = $expenses[$expenses_index]['projectComment']; if ($limitCommentSize) { $arr['comment'] = Kimai_Format::addEllipsis($expenses[$expenses_index]['comment'], 150); } else { $arr['comment'] = $expenses[$expenses_index]['comment']; } $arr['commentType'] = $expenses[$expenses_index]['commentType']; $arr['username'] = $expenses[$expenses_index]['userName']; $arr['cleared'] = $expenses[$expenses_index]['cleared']; $expenses_index++; $result_arr[] = $arr; } return $result_arr; }
function invoice_add_to_array(&$array, $row, $short_form) { global $activityIndexMap; if ($short_form && $row['type'] == 'timeSheet') { if (isset($activityIndexMap[$row['desc']])) { $index = $activityIndexMap[$row['desc']]; $totalTime = $array[$index]['hour']; $totalAmount = $array[$index]['amount']; $start = $array[$index]['start']; $end = $array[$index]['end']; $duration = $array[$index]['duration']; $array[$index] = array('type' => 'timeSheet', 'desc' => $row['desc'], 'start' => $start < $row['start'] ? $start : $row['start'], 'end' => $end > $row['end'] ? $end : $row['end'], 'hour' => $totalTime + $row['hour'], 'fDuration' => Kimai_Format::formatDuration($duration + $row['duration']), 'duration' => $duration + $row['duration'], 'timestamp' => $start < $row['start'] ? $start : $row['start'], 'amount' => $totalAmount + $row['amount'], 'description' => $row['description'], 'rate' => ($totalAmount + $row['amount']) / ($totalTime + $row['hour']), 'comment' => $row['comment'], 'username' => $row['username'], 'useralias' => $row['useralias'], 'location' => $row['location'], 'trackingNr' => $row['trackingNr'], 'projectID' => $row['projectID'], 'projectName' => $row['projectName'], 'projectComment' => $row['projectComment'], 'date' => date("m/d/Y", $row['timestamp'])); return; } else { $activityIndexMap[$row['desc']] = count($array); } } $array[] = $row; }
if (isset($kga['customer'])) { $customers = array($kga['customer']['customerID']); } else { $users = array($kga['user']['userID']); } // Get the total amount of time shown in the table. $total = Kimai_Format::formatDuration($database->get_duration($in, $out, $users, $customers, null)); $view->assign('total', $total); $view->assign('exportData', export_get_data($in, $out, $users, $customers)); // Get the annotations for the user sub list. $userAnnotations = export_get_user_annotations($in, $out, $users, $customers); Kimai_Format::formatAnnotations($userAnnotations); $view->assign('user_annotations', $userAnnotations); // Get the annotations for the customer sub list. $customerAnnotations = export_get_customer_annotations($in, $out, $users, $customers); Kimai_Format::formatAnnotations($customerAnnotations); $view->assign('customer_annotations', $customerAnnotations); // Get the annotations for the project sub list. $projectAnnotations = export_get_project_annotations($in, $out, $users, $customers); Kimai_Format::formatAnnotations($projectAnnotations); $view->assign('project_annotations', $projectAnnotations); // Get the annotations for the activity sub list. $activityAnnotations = export_get_activity_annotations($in, $out, $users, $customers); Kimai_Format::formatAnnotations($activityAnnotations); $view->assign('activity_annotations', $activityAnnotations); // Get the columns the user had disabled last time. if (isset($kga['user'])) { $view->assign('disabled_columns', export_get_disabled_headers($kga['user']['userID'])); } $view->assign('table_display', $view->render("table.php")); echo $view->render('main.php');
/** * returns time of currently running activity recording as array * * result is meant as params for the stopwatch if the window is reloaded * * <pre> * returns: * [all] start time of entry in unix seconds (forgot why I named it this way, sorry ...) * [hour] * [min] * [sec] * </pre> * * @return array * @author th */ public function get_current_timer() { $user = MySQL::SQLValue($this->kga['user']['userID'], MySQL::SQLVALUE_NUMBER); $p = $this->kga['server_prefix']; $this->conn->Query("SELECT timeEntryID, start FROM {$p}timeSheet WHERE userID = {$user} AND end = 0;"); if ($this->conn->RowCount() == 0) { $current_timer['all'] = 0; $current_timer['hour'] = 0; $current_timer['min'] = 0; $current_timer['sec'] = 0; } else { $row = $this->conn->RowArray(0, MYSQLI_ASSOC); $start = (int) $row['start']; $aktuelleMessung = Kimai_Format::hourminsec(time() - $start); $current_timer['all'] = $start; $current_timer['hour'] = $aktuelleMessung['h']; $current_timer['min'] = $aktuelleMessung['i']; $current_timer['sec'] = $aktuelleMessung['s']; } return $current_timer; }
} $invoiceArray[$time_index]['hour'] = $rounded; $invoiceArray[$time_index]['amount'] = $invoiceArray[$time_index]['hour'] * $rate; } $time_index++; } } // calculate invoice sums $ttltime = 0; $rawTotalTime = 0; $total = 0; while (list($id, $fd) = each($invoiceArray)) { $total += $invoiceArray[$id]['amount']; $ttltime += $invoiceArray[$id]['hour']; } $fttltime = Kimai_Format::formatDuration($ttltime * 3600); // sort invoice entries if (isset($_REQUEST['sort_invoice'])) { switch ($_REQUEST['sort_invoice']) { case 'date_asc': uasort($invoiceArray, 'ext_invoice_sort_by_date_asc'); break; case 'date_desc': uasort($invoiceArray, 'ext_invoice_sort_by_date_desc'); break; case 'name': uasort($invoiceArray, 'ext_invoice_sort_by_name'); break; } } $vat_rate = $customer['vat'];
$wd = $kga['lang']['weekdays_short'][date("w", time())]; $dp_start = 0; if ($kga['calender_start'] != "") { $dp_start = $kga['calender_start']; } else { if (isset($kga['user'])) { $dp_start = date("d/m/Y", $database->getjointime($kga['user']['userID'])); } } $dp_today = date("d/m/Y", time()); $view->assign('dp_start', $dp_start); $view->assign('dp_today', $dp_today); if (isset($kga['customer'])) { $view->assign('total', Kimai_Format::formatDuration($database->get_duration($in, $out, null, array($kga['customer']['customerID'])))); } else { $view->assign('total', Kimai_Format::formatDuration($database->get_duration($in, $out, $kga['user']['userID']))); } // =========================== // = DatePicker localization = // =========================== $localized_DatePicker = ""; $view->assign('weekdays_array', sprintf("['%s','%s','%s','%s','%s','%s','%s']\n", $kga['lang']['weekdays'][0], $kga['lang']['weekdays'][1], $kga['lang']['weekdays'][2], $kga['lang']['weekdays'][3], $kga['lang']['weekdays'][4], $kga['lang']['weekdays'][5], $kga['lang']['weekdays'][6])); $view->assign('weekdays_short_array', sprintf("['%s','%s','%s','%s','%s','%s','%s']\n", $kga['lang']['weekdays_short'][0], $kga['lang']['weekdays_short'][1], $kga['lang']['weekdays_short'][2], $kga['lang']['weekdays_short'][3], $kga['lang']['weekdays_short'][4], $kga['lang']['weekdays_short'][5], $kga['lang']['weekdays_short'][6])); $view->assign('months_array', sprintf("['%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s']\n", $kga['lang']['months'][0], $kga['lang']['months'][1], $kga['lang']['months'][2], $kga['lang']['months'][3], $kga['lang']['months'][4], $kga['lang']['months'][5], $kga['lang']['months'][6], $kga['lang']['months'][7], $kga['lang']['months'][8], $kga['lang']['months'][9], $kga['lang']['months'][10], $kga['lang']['months'][11])); $view->assign('months_short_array', sprintf("['%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s']", $kga['lang']['months_short'][0], $kga['lang']['months_short'][1], $kga['lang']['months_short'][2], $kga['lang']['months_short'][3], $kga['lang']['months_short'][4], $kga['lang']['months_short'][5], $kga['lang']['months_short'][6], $kga['lang']['months_short'][7], $kga['lang']['months_short'][8], $kga['lang']['months_short'][9], $kga['lang']['months_short'][10], $kga['lang']['months_short'][11])); // assign view placeholders $view->assign('current_timer_hour', $current_timer['hour']); $view->assign('current_timer_min', $current_timer['min']); $view->assign('current_timer_sec', $current_timer['sec']); $view->assign('current_timer_start', $current_timer['all'] ? $current_timer['all'] : time()); $view->assign('current_time', time());
// customer logged in $ann = expenses_by_user($in, $out, null, array($kga['customer']['customerID'])); } $ann = Kimai_Format::formatCurrency($ann); $view->assign('user_annotations', $ann); // TODO: function for loops or convert it in template with new function if (isset($kga['user'])) { // user logged in $ann = expenses_by_customer($in, $out, array($kga['user']['userID'])); } else { // customer logged in $ann = expenses_by_customer($in, $out, null, array($kga['customer']['customerID'])); } $ann = Kimai_Format::formatCurrency($ann); $view->assign('customer_annotations', $ann); if (isset($kga['user'])) { // user logged in $ann = expenses_by_project($in, $out, array($kga['user']['userID'])); } else { // customer logged in $ann = expenses_by_project($in, $out, null, array($kga['customer']['customerID'])); } $ann = Kimai_Format::formatCurrency($ann); $view->assign('project_annotations', $ann); if (isset($kga['user'])) { $view->assign('hideComments', !$kga->getSettings()->isShowComments()); } else { $view->assign('hideComments', true); } $view->assign('expenses_display', $view->render("expenses.php")); echo $view->render('main.php');