Separated users section on reports in 2 for active and inactive users.
[timetracker.git] / WEB-INF / lib / ttReportHelper.class.php
index ac3582e..9c6dfb0 100644 (file)
@@ -30,6 +30,7 @@ import('ttClientHelper');
 import('DateAndTime');
 import('Period');
 import('ttTimeHelper');
+import('ttConfigHelper');
 
 require_once(dirname(__FILE__).'/../../plugins/CustomFields.class.php');
 
@@ -72,6 +73,8 @@ class ttReportHelper {
     if ($options['invoice']=='2') $dropdown_parts .= ' and l.invoice_id is null';
     if ($options['timesheet']==TIMESHEET_NOT_ASSIGNED) $dropdown_parts .= ' and l.timesheet_id is null';
     if ($options['timesheet']==TIMESHEET_ASSIGNED) $dropdown_parts .= ' and l.timesheet_id is not null';
+    if ($options['approved']=='1') $dropdown_parts .= ' and l.approved = 1';
+    if ($options['approved']=='2') $dropdown_parts .= ' and l.approved = 0';
     if ($options['paid_status']=='1') $dropdown_parts .= ' and l.paid = 1';
     if ($options['paid_status']=='2') $dropdown_parts .= ' and l.paid = 0';
 
@@ -105,12 +108,6 @@ class ttReportHelper {
     $group_id = $user->getGroup();
     $org_id = $user->org_id;
 
-    // A shortcut for timesheets.
-    if ($options['timesheet_id']) {
-      $where = " where ei.timesheet_id = ".$options['timesheet_id']." and ei.group_id = $group_id and ei.org_id = $org_id";
-      return $where;
-    }
-
     // Prepare dropdown parts.
     $dropdown_parts = '';
     if ($options['client_id'])
@@ -120,8 +117,11 @@ class ttReportHelper {
     if ($options['project_id']) $dropdown_parts .= ' and ei.project_id = '.$options['project_id'];
     if ($options['invoice']=='1') $dropdown_parts .= ' and ei.invoice_id is not null';
     if ($options['invoice']=='2') $dropdown_parts .= ' and ei.invoice_id is null';
-    if ($options['timesheet']==TIMESHEET_NOT_ASSIGNED) $dropdown_parts .= ' and ei.timesheet_id is null';
-    if ($options['timesheet']==TIMESHEET_ASSIGNED) $dropdown_parts .= ' and ei.timesheet_id is not null';
+    if (isset($options['timesheet']) && ($options['timesheet']!=TIMESHEET_ALL && $options['timesheet']!=TIMESHEET_NOT_ASSIGNED)) {
+        $dropdown_parts .= ' and 0 = 1'; // Expense items do not have a timesheet_id.
+    }
+    if ($options['approved']=='1') $dropdown_parts .= ' and ei.approved = 1';
+    if ($options['approved']=='2') $dropdown_parts .= ' and ei.approved = 0';
     if ($options['paid_status']=='1') $dropdown_parts .= ' and ei.paid = 1';
     if ($options['paid_status']=='2') $dropdown_parts .= ' and ei.paid = 0';
 
@@ -155,6 +155,9 @@ class ttReportHelper {
     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();
@@ -233,6 +236,9 @@ class ttReportHelper {
         array_push($fields, "cast(l.billable * coalesce(upb.rate, 0) * time_to_sec(l.duration)/3600 as decimal(10,2)) as cost"); // Use project rate for user.
       array_push($fields, "null as expense"); 
     }
+    // Add approved.
+    if ($options['show_approved'])
+      array_push($fields, 'l.approved');
     // Add paid status.
     if ($canViewReports && $options['show_paid'])
       array_push($fields, 'l.paid');
@@ -249,6 +255,9 @@ class ttReportHelper {
     // 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;
@@ -272,17 +281,22 @@ class ttReportHelper {
     }
     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;
     if ($user->isPluginEnabled('ts')) {
       $timesheet_option = $options['timesheet'];
       if ($timesheet_option == TIMESHEET_PENDING)
-        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.submit_status = 1 and ts.approval_status is null)";
+        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.submit_status = 1 and ts.approve_status is null)";
       else if ($timesheet_option == TIMESHEET_APPROVED)
-        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.approval_status = 1)";
+        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.approve_status = 1)";
       else if ($timesheet_option == TIMESHEET_NOT_APPROVED)
-        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.approval_status = 0)";
+        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.approve_status = 0)";
       else if ($options['show_timesheet'])
         $inner_joins .= " left join tt_timesheets ts on (l.timesheet_id = ts.id)"; // Left join for timesheet nme.
     }
@@ -329,6 +343,9 @@ class ttReportHelper {
         array_push($fields, 'ei.name as note');
       array_push($fields, 'ei.cost as cost');
       array_push($fields, 'ei.cost as expense');
+      // Add approved.
+      if ($options['show_approved'])
+        array_push($fields, 'ei.approved');
       // Add paid status.
       if ($canViewReports && $options['show_paid'])
         array_push($fields, 'ei.paid');
@@ -343,7 +360,10 @@ class ttReportHelper {
       if (($canViewReports || $isClient) && $options['show_invoice'])
         array_push($fields, 'i.name as invoice');
       if ($options['show_timesheet'])
-        array_push($fields, 'ts.name as timesheet_name');
+        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;
@@ -355,25 +375,16 @@ class ttReportHelper {
         $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)";
-
-      // Prepare sql query part for inner joins.
-      $inner_joins = null;
-      if ($user->isPluginEnabled('ts')) {
-        $timesheet_option = $options['timesheet'];
-        if ($timesheet_option == TIMESHEET_PENDING)
-          $inner_joins .= " inner join tt_timesheets ts on (ei.timesheet_id = ts.id and ts.submit_status = 1 and ts.approval_status is null)";
-        else if ($timesheet_option == TIMESHEET_APPROVED)
-          $inner_joins .= " inner join tt_timesheets ts on (ei.timesheet_id = ts.id and ts.approval_status = 1)";
-        else if ($timesheet_option == TIMESHEET_NOT_APPROVED)
-          $inner_joins .= " inner join tt_timesheets ts on (ei.timesheet_id = ts.id and ts.approval_status = 0)";
-        else if ($options['show_timesheet'])
-          $inner_joins .= " left join tt_timesheets ts on (ei.timesheet_id = ts.id)"; // Left join for timesheet name.
+      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);
 
       // Construct sql query for expense items.
-      $sql_for_expense_items = "select ".join(', ', $fields)." from tt_expense_items ei $left_joins $inner_joins $where";
+      $sql_for_expense_items = "select ".join(', ', $fields)." from tt_expense_items ei $left_joins $where";
 
       // Construct a union.
       $sql = "($sql) union all ($sql_for_expense_items)";
@@ -556,32 +567,21 @@ class ttReportHelper {
     if ($user->isPluginEnabled('ts') && $options['timesheet']) {
       $timesheet_option = $options['timesheet'];
       if ($timesheet_option == TIMESHEET_PENDING)
-        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.submit_status = 1 and ts.approval_status is null)";
+        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.submit_status = 1 and ts.approve_status is null)";
       else if ($timesheet_option == TIMESHEET_APPROVED)
-        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.approval_status = 1)";
+        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.approve_status = 1)";
       else if ($timesheet_option == TIMESHEET_NOT_APPROVED)
-        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.approval_status = 0)";
+        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.approve_status = 0)";
     }
     // Prepare a query for time items.
     $sql = "select $time_part $units_part $cost_part from tt_log l $left_joins $inner_joins $where";
 
     // If we have expenses, query becomes a bit more complex.
     if ($options['show_cost'] && $user->isPluginEnabled('ex')) {
-      // Prepare sql query part for inner joins.
-      $inner_joins = null;
-      if ($user->isPluginEnabled('ts') && $options['timesheet']) {
-        $timesheet_option = $options['timesheet'];
-        if ($timesheet_option == TIMESHEET_PENDING)
-          $inner_joins .= " inner join tt_timesheets ts on (ei.timesheet_id = ts.id and ts.submit_status = 1 and ts.approval_status is null)";
-        else if ($timesheet_option == TIMESHEET_APPROVED)
-          $inner_joins .= " inner join tt_timesheets ts on (ei.timesheet_id = ts.id and ts.approval_status = 1)";
-        else if ($timesheet_option == TIMESHEET_NOT_APPROVED)
-          $inner_joins .= " inner join tt_timesheets ts on (ei.timesheet_id = ts.id and ts.approval_status = 0)";
-      }
       $where = ttReportHelper::getExpenseWhere($options);
       $sql_for_expenses = "select null as time";
       if ($options['show_work_units']) $sql_for_expenses .= ", null as units";
-      $sql_for_expenses .= ", sum(cost) as cost, sum(cost) as expenses from tt_expense_items ei $inner_joins $where";
+      $sql_for_expenses .= ", sum(cost) as cost, sum(cost) as expenses from tt_expense_items ei $where";
 
       // Create a combined query.
       $combined = "select sum(time) as time";
@@ -649,6 +649,60 @@ class ttReportHelper {
     }
   }
 
+  // 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;
+    $mdb2 = getConnection();
+
+    $group_id = $user->getGroup();
+    $org_id = $user->org_id;
+
+    $approved_val = (int) $approved;
+    if ($time_log_ids) {
+      $sql = "update tt_log set approved = $approved_val".
+        " where id in(".join(', ', $time_log_ids).") and group_id = $group_id and org_id = $org_id";
+      $affected = $mdb2->exec($sql);
+      if (is_a($affected, 'PEAR_Error')) die($affected->getMessage());
+    }
+    if ($expense_item_ids) {
+      $sql = "update tt_expense_items set approved = $approved_val".
+        " where id in(".join(', ', $expense_item_ids).") and group_id = $group_id and org_id = $org_id";
+      $affected = $mdb2->exec($sql);
+      if (is_a($affected, 'PEAR_Error')) die($affected->getMessage());
+    }
+  }
+
   // The markPaid marks a set of records as either paid or unpaid.
   static function markPaid($time_log_ids, $expense_item_ids, $paid = true) {
     global $user;
@@ -682,6 +736,10 @@ class ttReportHelper {
     $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)
@@ -704,6 +762,24 @@ class ttReportHelper {
     $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>';
@@ -797,16 +873,20 @@ class ttReportHelper {
         $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_approved'])
+        $body .= '<td style="'.$tableHeaderCentered.'" width="5%">'.$i18n->get('label.approved').'</td>';
       if ($options['show_paid'])
         $body .= '<td style="'.$tableHeaderCentered.'" width="5%">'.$i18n->get('label.paid').'</td>';
       if ($options['show_ip'])
         $body .= '<td style="'.$tableHeaderCentered.'" width="5%">'.$i18n->get('label.ip').'</td>';
       if ($options['show_invoice'])
         $body .= '<td style="'.$tableHeader.'">'.$i18n->get('label.invoice').'</td>';
+      if ($options['show_timesheet'])
+        $body .= '<td style="'.$tableHeader.'">'.$i18n->get('label.timesheet').'</td>';
       $body .= '</tr>';
 
       // Initialize variables to print subtotals.
@@ -841,15 +921,17 @@ class ttReportHelper {
               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>';
               }
+              if ($options['show_approved']) $body .= '<td></td>';
               if ($options['show_paid']) $body .= '<td></td>';
               if ($options['show_ip']) $body .= '<td></td>';
               if ($options['show_invoice']) $body .= '<td></td>';
+              if ($options['show_timesheet']) $body .= '<td></td>';
               $body .= '</tr>';
               $body .= '<tr><td>&nbsp;</td></tr>';
             }
@@ -879,10 +961,15 @@ class ttReportHelper {
             $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_approved']) {
+            $body .= '<td style="'.$cellRightAligned.'">';
+            $body .= $record['approved'] == 1 ? $i18n->get('label.yes') : $i18n->get('label.no');
+            $body .= '</td>';
+          }
           if ($options['show_paid']) {
             $body .= '<td style="'.$cellRightAligned.'">';
             $body .= $record['paid'] == 1 ? $i18n->get('label.yes') : $i18n->get('label.no');
@@ -895,8 +982,15 @@ class ttReportHelper {
           }
           if ($options['show_invoice'])
             $body .= '<td style="'.$cellRightAligned.'">'.htmlspecialchars($record['invoice']).'</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'];
@@ -917,15 +1011,17 @@ class ttReportHelper {
         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'];
           $body .= '</td>';
         }
+        if ($options['show_approved']) $body .= '<td></td>';
         if ($options['show_paid']) $body .= '<td></td>';
         if ($options['show_ip']) $body .= '<td></td>';
         if ($options['show_invoice']) $body .= '<td></td>';
+        if ($options['show_timesheet']) $body .= '<td></td>';
         $body .= '</tr>';
       }
 
@@ -942,15 +1038,17 @@ class ttReportHelper {
       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'];
         $body .= '</td>';
       }
+      if ($options['show_approved']) $body .= '<td></td>';
       if ($options['show_paid']) $body .= '<td></td>';
       if ($options['show_ip']) $body .= '<td></td>';
       if ($options['show_invoice']) $body .= '<td></td>';
+      if ($options['show_timesheet']) $body .= '<td></td>';
       $body .= '</tr>';
 
       $body .= '</table>';
@@ -1053,15 +1151,28 @@ class ttReportHelper {
     $options['billable'] = $bean->getAttribute('include_records');
     $options['invoice'] = $bean->getAttribute('invoice');
     $options['paid_status'] = $bean->getAttribute('paid_status');
+    $options['approved'] = $bean->getAttribute('approved');
+    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 ($user->isPluginEnabled('ts') && $user->isClient() && !$user->can('view_client_unapproved'))
-      $options['timesheet'] = TIMESHEET_APPROVED; // Restrict clients to approved timesheet records only.
-    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_client'] = $bean->getAttribute('chclient');
     $options['show_invoice'] = $bean->getAttribute('chinvoice');
+    $options['show_approved'] = $bean->getAttribute('chapproved');
     $options['show_paid'] = $bean->getAttribute('chpaid');
     $options['show_ip'] = $bean->getAttribute('chip');
     $options['show_project'] = $bean->getAttribute('chproject');
@@ -1074,6 +1185,7 @@ class ttReportHelper {
     $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');
@@ -1086,13 +1198,19 @@ class ttReportHelper {
     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;
         }
@@ -1553,11 +1671,11 @@ class ttReportHelper {
     if ($user->isPluginEnabled('ts') && $options['timesheet']) {
       $timesheet_option = $options['timesheet'];
       if ($timesheet_option == TIMESHEET_PENDING)
-        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.submit_status = 1 and ts.approval_status is null)";
+        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.submit_status = 1 and ts.approve_status is null)";
       else if ($timesheet_option == TIMESHEET_APPROVED)
-        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.approval_status = 1)";
+        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.approve_status = 1)";
       else if ($timesheet_option == TIMESHEET_NOT_APPROVED)
-        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.approval_status = 0)";
+        $inner_joins .= " inner join tt_timesheets ts on (l.timesheet_id = ts.id and ts.approve_status = 0)";
     }
     $join .= $inner_joins;
     return $join;
@@ -1606,18 +1724,6 @@ class ttReportHelper {
     if (ttReportHelper::groupingBy('project', $options)) {
       $join .= ' left join tt_projects p on (ei.project_id = p.id)';
     }
-    // Prepare inner joins.
-    $inner_joins = null;
-    if ($user->isPluginEnabled('ts') && $options['timesheet']) {
-      $timesheet_option = $options['timesheet'];
-      if ($timesheet_option == TIMESHEET_PENDING)
-        $inner_joins .= " inner join tt_timesheets ts on (ei.timesheet_id = ts.id and ts.submit_status = 1 and ts.approval_status is null)";
-      else if ($timesheet_option == TIMESHEET_APPROVED)
-        $inner_joins .= " inner join tt_timesheets ts on (ei.timesheet_id = ts.id and ts.approval_status = 1)";
-      else if ($timesheet_option == TIMESHEET_NOT_APPROVED)
-        $inner_joins .= " inner join tt_timesheets ts on (ei.timesheet_id = ts.id and ts.approval_status = 0)";
-    }
-    $join .= $inner_joins;
     return $join;
   }