Sprache auf ungültig setzen im Admin-Bereich
[kivitendo-erp.git] / SL / Controller / TimeRecording.pm
index 45c58cd..930f346 100644 (file)
@@ -5,10 +5,12 @@ use parent qw(SL::Controller::Base);
 
 use DateTime;
 use English qw(-no_match_vars);
+use List::Util qw(sum0);
 use POSIX qw(strftime);
 
 use SL::Controller::Helper::GetModels;
 use SL::Controller::Helper::ReportGenerator;
+use SL::Controller::Helper::ReportGenerator::ControlRow qw(make_control_row);
 use SL::DB::Customer;
 use SL::DB::Employee;
 use SL::DB::Order;
@@ -17,9 +19,10 @@ use SL::DB::Project;
 use SL::DB::TimeRecording;
 use SL::DB::TimeRecordingArticle;
 use SL::Helper::Flash qw(flash);
-use SL::Helper::Number qw(_round_number _parse_number);
+use SL::Helper::Number qw(_round_number _parse_number _round_total);
 use SL::Helper::UserPreferences::TimeRecording;
 use SL::Locale::String qw(t8);
+use SL::Presenter::Tag qw(checkbox_tag);
 use SL::ReportGenerator;
 
 use Rose::Object::MakeMethods::Generic
@@ -31,7 +34,9 @@ use Rose::Object::MakeMethods::Generic
 
 # safety
 __PACKAGE__->run_before('check_auth');
-__PACKAGE__->run_before('check_auth_edit', only => [ qw(edit save delete) ]);
+__PACKAGE__->run_before('check_auth_edit',     only => [ qw(edit save delete) ]);
+__PACKAGE__->run_before('check_auth_edit_all', only => [ qw(mark_as_booked) ]);
+
 
 my %sort_columns = (
   date         => t8('Date'),
@@ -63,7 +68,35 @@ sub action_list {
   $self->make_filter_summary;
   $self->prepare_report;
 
-  $self->report_generator_list_objects(report => $self->{report}, objects => $self->models->get);
+  my $objects = $self->models->get;
+
+  my $total   = sum0 map { _round_total($_->duration_in_hours) } @$objects;
+  my $total_h = int($total);
+  my $total_m = int($total * 60.0 + 0.5) % 60;
+  my $total_s = sprintf('%d:%02d', $total_h, $total_m);
+
+  push @$objects, make_control_row("separator");
+  push @$objects, make_control_row("data",
+                                   row => {
+                                     map( { $_ => {class => 'listtotal'} } keys %{$self->{report}->{columns}} ),
+                                     description => {data => t8('Total'), class => 'listtotal'},
+                                     duration    => {data => $total_s,    class => 'listtotal'}
+                                   });
+
+  $self->report_generator_list_objects(report => $self->{report}, objects => $objects);
+}
+
+sub action_mark_as_booked {
+  my ($self) = @_;
+
+  if (scalar @{ $::form->{ids} }) {
+    SL::DB::Manager::TimeRecording->update_all(
+      set   => { booked => 1              },
+      where => [ id     => $::form->{ids} ]
+    );
+  }
+
+  $self->redirect_to(safe_callback());
 }
 
 sub action_edit {
@@ -86,10 +119,13 @@ sub action_edit {
     $self->{end_time}   = $self->time_recording->end_time->to_kivitendo_time;
   }
 
+  my $inputs_to_disable = $self->get_inputs_to_disable;
+
   $self->setup_edit_action_bar;
 
   $self->render('time_recording/form',
-                title  => t8('Time Recording'),
+                title             => t8('Time Recording'),
+                inputs_to_disable => $inputs_to_disable,
   );
 }
 
@@ -237,7 +273,8 @@ sub init_all_time_recording_articles {
 }
 
 sub init_all_orders {
-  my $orders = SL::DB::Manager::Order->get_all(query => [or             => [ closed => 0, closed => undef ],
+  my $orders = SL::DB::Manager::Order->get_all(query => [or             => [ closed    => 0, closed    => undef, id => $_[0]->time_recording->order_id ],
+                                                         or             => [ quotation => 0, quotation => undef ],
                                                          '!customer_id' => undef]);
   return [ map { [$_->id, sprintf("%s %s", $_->number, $_->customervendor->name) ] } sort { $a->number <=> $b->number } @{$orders||[]} ];
 }
@@ -258,15 +295,24 @@ sub check_auth_edit {
   }
 }
 
+sub check_auth_edit_all {
+  my ($self) = @_;
+
+  $::auth->assert('time_recording_edit_all');
+}
+
 sub prepare_report {
   my ($self) = @_;
 
   my $report      = SL::ReportGenerator->new(\%::myconfig, $::form);
   $self->{report} = $report;
 
-  my @columns  = qw(date start_time end_time order customer project part description staff_member duration booked);
+  my @columns  = qw(ids date start_time end_time order customer project part description staff_member duration booked);
 
   my %column_defs = (
+    ids          => { raw_header_data => checkbox_tag("", id => "check_all", checkall  => "[data-checkall=1]"),
+                      align           => 'center',
+                      raw_data        => sub { $_[0]->booked ? '' : checkbox_tag("ids[]", value => $_[0]->id, "data-checkall" => 1) }   },
     date         => { text => t8('Date'),         sub => sub { $_[0]->date_as_date },
                       obj_link => sub { $self->url_for(action => 'edit', 'id' => $_[0]->id, callback => $self->models->get_callback) }  },
     start_time   => { text => t8('Start'),        sub => sub { $_[0]->start_time_as_timestamp },
@@ -276,7 +322,7 @@ sub prepare_report {
     order        => { text => t8('Sales Order'),  sub => sub { $_[0]->order && $_[0]->order->number } },
     customer     => { text => t8('Customer'),     sub => sub { $_[0]->customer->displayable_name } },
     part         => { text => t8('Article'),      sub => sub { $_[0]->part && $_[0]->part->displayable_name } },
-    project      => { text => t8('Project'),      sub => sub { $_[0]->project && $_[0]->project->displayable_name } },
+    project      => { text => t8('Project'),      sub => sub { $_[0]->project && $_[0]->project->full_description(sytle => 'both') } },
     description  => { text => t8('Description'),  sub => sub { $_[0]->description_as_stripped_html },
                       raw_data => sub { $_[0]->description_as_restricted_html }, # raw_data only used for html(?)
                       obj_link => sub { $self->url_for(action => 'edit', 'id' => $_[0]->id, callback => $self->models->get_callback) }  },
@@ -286,6 +332,11 @@ sub prepare_report {
     booked       => { text => t8('Booked'),       sub => sub { $_[0]->booked ? t8('Yes') : t8('No') } },
   );
 
+  if (!$self->can_edit_all) {
+    @columns = grep {'ids' ne $_} @columns;
+    delete $column_defs{ids};
+  }
+
   my $title        = t8('Time Recordings');
   $report->{title} = $title;    # for browser titlebar (title-tag)
 
@@ -321,8 +372,8 @@ sub make_filter_summary {
   my $filter = $::form->{filter} || {};
   my @filter_strings;
 
-  my $staff_member = $filter->{staff_member_id} ? SL::DB::Employee->new(id => $filter->{staff_member_id})->load->safe_name        : '';
-  my $project      = $filter->{project_id}      ? SL::DB::Project->new (id => $filter->{project_id})     ->load->displayable_name : '';
+  my $staff_member = $filter->{staff_member_id} ? SL::DB::Employee->new(id => $filter->{staff_member_id})->load->safe_name                         : '';
+  my $project      = $filter->{project_id}      ? SL::DB::Project->new (id => $filter->{project_id})     ->load->full_description(sytle => 'both') : '';
 
   my @filters = (
     [ $filter->{"date:date::ge"},                              t8('From Date')       ],
@@ -352,6 +403,19 @@ sub setup_list_action_bar {
         submit    => [ '#filter_form', { action => 'TimeRecording/list' } ],
         accesskey => 'enter',
       ],
+      combobox => [
+        action => [
+          t8('Actions'),
+          only_if => $self->can_edit_all,
+        ],
+        action => [
+          t8('Mark as booked'),
+          submit  => [ '#form', { action => 'TimeRecording/mark_as_booked', callback => $self->models->get_callback } ],
+          checks  => [ [ 'kivi.check_if_entries_selected', '[name="ids[]"]' ] ],
+          confirm => $::locale->text('Do you really want to mark the selected entries as booked?'),
+          only_if => $self->can_edit_all,
+        ],
+      ],
       action => [
         t8('Add'),
         link => $self->url_for(action => 'edit', callback => $self->models->get_callback),
@@ -387,4 +451,12 @@ sub safe_callback {
   $::form->{callback} || (action => 'list')
 }
 
+sub get_inputs_to_disable {
+  my ($self) = @_;
+
+  return [qw(customer project)]  if $self->time_recording->order_id;
+  return [qw(customer)]          if $self->time_recording->project_id && $self->time_recording->project->customer_id;
+}
+
+
 1;