import('DateAndTime');
import('Period');
import('ttTimeHelper');
+import('ttConfigHelper');
require_once(dirname(__FILE__).'/../../plugins/CustomFields.class.php');
global $user;
$mdb2 = getConnection();
+ $group_id = $user->getGroup();
+ $org_id = $user->org_id;
+
// Determine these once as they are used in multiple places in this function.
$canViewReports = $user->can('view_reports') || $user->can('view_all_reports');
$isClient = $user->isClient();
// Add timesheet name if it is selected.
if ($options['show_timesheet'])
array_push($fields, 'ts.name as timesheet_name');
+ // Add has_files.
+ if ($options['show_files'])
+ array_push($fields, 'if(Sub1.entity_id is null, 0, 1) as has_files');
// Prepare sql query part for left joins.
$left_joins = null;
}
if ($includeCost && MODE_TIME != $trackingMode)
$left_joins .= " left join tt_user_project_binds upb on (l.user_id = upb.user_id and l.project_id = upb.project_id)";
+ if ($options['show_files']) {
+ $left_joins .= " left join (select distinct entity_id from tt_files".
+ " where entity_type = 'time' and group_id = $group_id and org_id = $org_id and status = 1) Sub1".
+ " on (l.id = Sub1.entity_id)";
+ }
// Prepare sql query part for inner joins.
$inner_joins = null;
array_push($fields, 'i.name as invoice');
if ($options['show_timesheet'])
array_push($fields, 'null as timesheet_name');
+ // Add has_files.
+ if ($options['show_files'])
+ array_push($fields, 'if(Sub1.entity_id is null, 0, 1) as has_files');
// Prepare sql query part for left joins.
$left_joins = null;
$left_joins .= " left join tt_projects p on (p.id = ei.project_id)";
if (($canViewReports || $isClient) && $options['show_invoice'])
$left_joins .= " left join tt_invoices i on (i.id = ei.invoice_id and i.status = 1)";
+ if ($options['show_files']) {
+ $left_joins .= " left join (select distinct entity_id from tt_files".
+ " where entity_type = 'expense' and group_id = $group_id and org_id = $org_id and status = 1) Sub1".
+ " on (ei.id = Sub1.entity_id)";
+ }
$where = ttReportHelper::getExpenseWhere($options);
$res = $mdb2->query($sql);
if (is_a($res, 'PEAR_Error')) die($res->getMessage());
while ($val = $res->fetchRow()) {
- $time = $val['time'] ? sec_to_time_fmt_hm($val['time']) : null;
+ $time = ttTimeHelper::minutesToDuration($val['time'] / 60);
$rowLabel = ttReportHelper::makeGroupByLabel($val['group_field'], $options);
if ($options['show_cost']) {
$decimalMark = $user->getDecimalMark();
if (is_a($res, 'PEAR_Error')) die($res->getMessage());
$val = $res->fetchRow();
- $total_time = $val['time'] ? sec_to_time_fmt_hm($val['time']) : null;
+ $total_time = ttTimeHelper::minutesToDuration($val['time'] / 60);
if ($options['show_cost']) {
$total_cost = $val['cost'];
if (!$total_cost) $total_cost = '0.00';
}
}
+ // The assignToTimesheet assigns a set of tt_log records to a specific timesheet.
+ static function assignToTimesheet($timesheet_id, $time_log_ids) {
+ global $user;
+ $mdb2 = getConnection();
+
+ $user_id = $user->getUser();
+ $group_id = $user->getGroup();
+ $org_id = $user->org_id;
+
+ if ($time_log_ids) {
+ // Use inner join as a protection mechanism not to do anything with "acted upon" timesheets.
+ // Allow oprations only with pending timesheets.
+ if ($timesheet_id) {
+ // Assigning a timesheet to records.
+ $inner_join = " inner join tt_timesheets ts on (ts.id = $timesheet_id".
+ " and ts.user_id = $user_id and ts.approve_status is null". // Timesheet to assign to is pending.
+ // Part below: existing timesheet either not exists or is also pending.
+ " and (l.timesheet_id is null or (l.timesheet_id = ts.id and ts.approve_status is null)))";
+ } else {
+ $inner_join = " inner join tt_timesheets ts on (ts.id = l.timesheet_id".
+ " and ts.user_id = $user_id and ts.approve_status is null)"; // Do not deassign from acted-upon timesheets.
+ }
+
+ $sql = "update tt_log l $inner_join".
+ " set l.timesheet_id = ".$mdb2->quote($timesheet_id).
+ " where l.id in(".join(', ', $time_log_ids).") and l.user_id = $user_id and l.group_id = $group_id and l.org_id = $org_id";
+ $affected = $mdb2->exec($sql);
+ if (is_a($affected, 'PEAR_Error')) die($affected->getMessage());
+ }
+ }
+
// The markApproved marks a set of records as either approved or unapproved.
static function markApproved($time_log_ids, $expense_item_ids, $approved = true) {
global $user;
$canViewReports = $user->can('view_reports') || $user->can('view_all_reports');
$isClient = $user->isClient();
+ $config = new ttConfigHelper($user->getConfig());
+ $show_note_column = $options['show_note'] && !$config->getDefinedValue('report_note_on_separate_row');
+ $show_note_row = $options['show_note'] && $config->getDefinedValue('report_note_on_separate_row');
+
$items = ttReportHelper::getItems($options);
$grouping = ttReportHelper::grouping($options);
if ($grouping)
$cellLeftAlignedSubtotal = 'font-weight: bold; text-align: left; vertical-align: top;';
$cellRightAlignedSubtotal = 'font-weight: bold; text-align: right; vertical-align: top;';
+ // Determine column span for note field.
+ $colspan = 1;
+ if ($user->can('view_reports') || $user->can('view_all_reports') || $user->isClient()) $colspan++;
+ if ($options['show_client']) $colspan++;
+ if ($options['show_project']) $colspan++;
+ if ($options['show_task']) $colspan++;
+ if ($options['show_custom_field_1']) $colspan++;
+ if ($options['show_start']) $colspan++;
+ if ($options['show_end']) $colspan++;
+ if ($options['show_duration']) $colspan++;
+ if ($options['show_work_units']) $colspan++;
+ if ($options['show_cost']) $colspan++;
+ if ($options['show_approved']) $colspan++;
+ if ($options['show_paid']) $colspan++;
+ if ($options['show_ip']) $colspan++;
+ if ($options['show_invoice']) $colspan++;
+ if ($options['show_timesheet']) $colspan++;
+
// Start creating email body.
$body = '<html>';
$body .= '<head><meta http-equiv="content-type" content="text/html; charset='.CHARSET.'"></head>';
$body .= '<td style="'.$tableHeaderCentered.'" width="5%">'.$i18n->get('label.duration').'</td>';
if ($options['show_work_units'])
$body .= '<td style="'.$tableHeaderCentered.'" width="5%">'.$i18n->get('label.work_units_short').'</td>';
- if ($options['show_note'])
+ if ($show_note_column)
$body .= '<td style="'.$tableHeader.'">'.$i18n->get('label.note').'</td>';
if ($options['show_cost'])
$body .= '<td style="'.$tableHeaderCentered.'" width="5%">'.$i18n->get('label.cost').'</td>';
if ($options['show_end']) $body .= '<td></td>';
if ($options['show_duration']) $body .= '<td style="'.$cellRightAlignedSubtotal.'">'.$subtotals[$prev_grouped_by]['time'].'</td>';
if ($options['show_work_units']) $body .= '<td style="'.$cellRightAlignedSubtotal.'">'.$subtotals[$prev_grouped_by]['units'].'</td>';
- if ($options['show_note']) $body .= '<td></td>';
+ if ($show_note_column) $body .= '<td></td>';
if ($options['show_cost']) {
$body .= '<td style="'.$cellRightAlignedSubtotal.'">';
$body .= ($canViewReports || $isClient) ? $subtotals[$prev_grouped_by]['cost'] : $subtotals[$prev_grouped_by]['expenses'];
$body .= '<td style="'.$cellRightAligned.'">'.$record['duration'].'</td>';
if ($options['show_work_units'])
$body .= '<td style="'.$cellRightAligned.'">'.$record['units'].'</td>';
- if ($options['show_note'])
+ if ($show_note_column)
$body .= '<td style="'.$cellLeftAligned.'">'.htmlspecialchars($record['note']).'</td>';
if ($options['show_cost'])
$body .= '<td style="'.$cellRightAligned.'">'.$record['cost'].'</td>';
if ($options['show_timesheet'])
$body .= '<td style="'.$cellRightAligned.'">'.htmlspecialchars($record['timesheet']).'</td>';
$body .= '</tr>';
-
+ if ($show_note_row && $record['note']) {
+ $body .= '<tr style="'.$row_style.'">';
+ $body .= '<td style="'.$cellRightAligned.'">'.$i18n->get('label.note').':</td>';
+ $body .= '<td colspan="'.$colspan.'">'.$record['note'].'</td>';
+ $body .= '</tr>';
+ }
$prev_date = $record['date'];
if ($print_subtotals)
$prev_grouped_by = $record['grouped_by'];
if ($options['show_end']) $body .= '<td></td>';
if ($options['show_duration']) $body .= '<td style="'.$cellRightAlignedSubtotal.'">'.$subtotals[$cur_grouped_by]['time'].'</td>';
if ($options['show_work_units']) $body .= '<td style="'.$cellRightAlignedSubtotal.'">'.$subtotals[$cur_grouped_by]['units'].'</td>';
- if ($options['show_note']) $body .= '<td></td>';
+ if ($show_note_column) $body .= '<td></td>';
if ($options['show_cost']) {
$body .= '<td style="'.$cellRightAlignedSubtotal.'">';
$body .= ($canViewReports || $isClient) ? $subtotals[$cur_grouped_by]['cost'] : $subtotals[$cur_grouped_by]['expenses'];
if ($options['show_end']) $body .= '<td></td>';
if ($options['show_duration']) $body .= '<td style="'.$cellRightAlignedSubtotal.'">'.$totals['time'].'</td>';
if ($options['show_work_units']) $body .= '<td style="'.$cellRightAlignedSubtotal.'">'.$totals['units'].'</td>';
- if ($options['show_note']) $body .= '<td></td>';
+ if ($show_note_column) $body .= '<td></td>';
if ($options['show_cost']) {
$body .= '<td nowrap style="'.$cellRightAlignedSubtotal.'">'.htmlspecialchars($user->currency).' ';
$body .= ($canViewReports || $isClient) ? $totals['cost'] : $totals['expenses'];
if ($user->isPluginEnabled('ap') && $user->isClient() && !$user->can('view_client_unapproved'))
$options['approved'] = 1; // Restrict clients to approved records only.
$options['timesheet'] = $bean->getAttribute('timesheet');
- if (is_array($bean->getAttribute('users'))) $options['users'] = join(',', $bean->getAttribute('users'));
+
+ $active_users_in_bean = $bean->getAttribute('users_active');
+ if ($active_users_in_bean && is_array($active_users_in_bean)) {
+ $users = join(',', $active_users_in_bean);
+ }
+ $inactive_users_in_bean = $bean->getAttribute('users_inactive');
+ if ($inactive_users_in_bean && is_array($inactive_users_in_bean)) {
+ if ($users) $users .= ',';
+ $users .= join(',', $inactive_users_in_bean);
+ }
+ if ($users) $options['users'] = $users;
+
$options['period'] = $bean->getAttribute('period');
$options['period_start'] = $bean->getAttribute('start_date');
$options['period_end'] = $bean->getAttribute('end_date');
$options['show_custom_field_1'] = $bean->getAttribute('chcf_1');
$options['show_work_units'] = $bean->getAttribute('chunits');
$options['show_timesheet'] = $bean->getAttribute('chtimesheet');
+ $options['show_files'] = $bean->getAttribute('chfiles');
$options['show_totals_only'] = $bean->getAttribute('chtotalsonly');
$options['group_by1'] = $bean->getAttribute('group_by1');
$options['group_by2'] = $bean->getAttribute('group_by2');
global $user;
// Check users.
- $users_in_bean = $bean->getAttribute('users');
- if (is_array($users_in_bean)) {
+ $active_users_in_bean = $bean->getAttribute('users_active');
+ $inactive_users_in_bean = $bean->getAttribute('users_inactive');
+ if (is_array($active_users_in_bean) || is_array($inactive_users_in_bean)) {
$users_in_group = ttGroupHelper::getUsers();
foreach ($users_in_group as $user_in_group) {
$valid_ids[] = $user_in_group['id'];
}
- foreach ($users_in_bean as $user_in_bean) {
+ foreach ($active_users_in_bean as $user_in_bean) {
+ if (!in_array($user_in_bean, $valid_ids)) {
+ return false;
+ }
+ }
+ foreach ($inactive_users_in_bean as $user_in_bean) {
if (!in_array($user_in_bean, $valid_ids)) {
return false;
}