]> wagnertech.de Git - mfinanz.git/commitdiff
Merge branch 'master' of vc.linet-services.de:public/lx-office-erp
authorThomas Heck <theck@linet-services.de>
Wed, 5 Sep 2012 12:36:34 +0000 (14:36 +0200)
committerThomas Heck <theck@linet-services.de>
Wed, 5 Sep 2012 12:36:34 +0000 (14:36 +0200)
21 files changed:
SL/Controller/BackgroundJob.pm
SL/Controller/BackgroundJobHistory.pm
SL/Controller/Base.pm
SL/Controller/Helper/GetModels.pm
SL/Controller/Helper/Paginated.pm [new file with mode: 0644]
SL/Controller/Helper/Sorted.pm
SL/DB/Helper/Paginated.pm
SL/DB/Manager/BackgroundJob.pm
SL/DB/Manager/BackgroundJobHistory.pm
SL/DB/Manager/OrderItem.pm [new file with mode: 0644]
SL/DB/OrderItem.pm
SL/Template/Plugin/L.pm
bin/mozilla/io.pl
bin/mozilla/vk.pl
templates/webpages/background_job/form.html
templates/webpages/background_job/list.html
templates/webpages/background_job_history/list.html
templates/webpages/background_job_history/show.html
templates/webpages/common/paginate.html
templates/webpages/delivery_plan/_list.html
templates/webpages/delivery_plan/report_bottom.html

index 57ec5c377bac1876bdcbbddacd12665037ca430b..f80f57a1c0b200e6b6b917f9bccef4d6a168aa5b 100644 (file)
@@ -4,6 +4,9 @@ use strict;
 
 use parent qw(SL::Controller::Base);
 
+use SL::Controller::Helper::GetModels;
+use SL::Controller::Helper::Paginated;
+use SL::Controller::Helper::Sorted;
 use SL::DB::BackgroundJob;
 use SL::Helper::Flash;
 use SL::System::TaskServer;
@@ -11,13 +14,26 @@ use SL::System::TaskServer;
 use Rose::Object::MakeMethods::Generic
 (
   scalar                  => [ qw(background_job) ],
-  'scalar --get_set_init' => [ qw(task_server) ],
+  'scalar --get_set_init' => [ qw(task_server back_to) ],
 );
 
 __PACKAGE__->run_before('check_auth');
 __PACKAGE__->run_before('check_task_server');
 __PACKAGE__->run_before('load_background_job', only => [ qw(edit update destroy execute) ]);
 
+__PACKAGE__->make_paginated(ONLY => [ qw(list) ]);
+
+__PACKAGE__->make_sorted(
+  ONLY         => [ qw(list) ],
+
+  package_name => $::locale->text('Package name'),
+  type         => $::locale->text('Execution type'),
+  active       => $::locale->text('Active'),
+  cron_spec    => $::locale->text('Execution schedule'),
+  last_run_at  => $::locale->text('Last run at'),
+  next_run_at  => $::locale->text('Next run at'),
+);
+
 #
 # actions
 #
@@ -27,7 +43,7 @@ sub action_list {
 
   $self->render('background_job/list',
                 title           => $::locale->text('Background jobs'),
-                BACKGROUND_JOBS => SL::DB::Manager::BackgroundJob->get_all_sorted);
+                BACKGROUND_JOBS => $self->get_models);
 }
 
 sub action_new {
@@ -63,7 +79,7 @@ sub action_destroy {
     flash_later('error', $::locale->text('The background job could not be destroyed.'));
   }
 
-  $self->redirect_to(action => 'list');
+  $self->redirect_to($self->back_to);
 }
 
 sub action_save_and_execute {
@@ -123,7 +139,7 @@ sub create_or_update {
   flash_later('info', $is_new ? $::locale->text('The background job has been created.') : $::locale->text('The background job has been saved.'));
   return if $return;
 
-  $self->redirect_to(action => 'list');
+  $self->redirect_to($self->back_to);
 }
 
 sub load_background_job {
@@ -140,4 +156,9 @@ sub check_task_server {
   flash('warning', $::locale->text('The task server does not appear to be running.')) if !$self->task_server->is_running;
 }
 
+sub init_back_to {
+  my ($self) = @_;
+  return $::form->{back_to} || $self->url_for(action => 'list');
+}
+
 1;
index ec9ebfe5a959b646ed183bdd009113769cdeb47d..5992dc00aa2020f7809ed8fd9aacf2bd570f9f6d 100644 (file)
@@ -5,6 +5,7 @@ use strict;
 use parent qw(SL::Controller::Base);
 
 use SL::Controller::Helper::GetModels;
+use SL::Controller::Helper::Paginated;
 use SL::Controller::Helper::Sorted;
 use SL::DB::BackgroundJobHistory;
 use SL::Helper::Flash;
@@ -20,6 +21,8 @@ __PACKAGE__->run_before('check_auth');
 __PACKAGE__->run_before('add_stylesheet');
 __PACKAGE__->run_before('check_task_server');
 
+__PACKAGE__->make_paginated(ONLY => [ qw(list) ]);
+
 __PACKAGE__->make_sorted(
   ONLY         => [ qw(list) ],
 
index 4dace86ed91844d63e7efd05142c499df2dc1fd1..1188ffe8bb38d3753b62efc176689031e3bf4ed7 100644 (file)
@@ -204,7 +204,9 @@ sub _run_action {
 }
 
 sub _controller_name {
-  return (split(/::/, ref($_[0]) || $_[0]))[-1];
+  my $class = ref($_[0]) || $_[0];
+  $class    =~ s/^SL::Controller:://;
+  return $class;
 }
 
 sub _dispatch {
index 4658717f6bf4e4946c07adc2810ba3d75d294fde..00ef31017d8db686066db7b9689f0bdc2b89d2da 100644 (file)
@@ -5,7 +5,8 @@ use strict;
 use Exporter qw(import);
 our @EXPORT = qw(get_callback get_models);
 
-my $current_action;
+use constant PRIV => '__getmodelshelperpriv';
+
 my %registered_handlers = ( callback => [], get_models => [] );
 
 sub register_get_models_handlers {
@@ -15,7 +16,7 @@ sub register_get_models_handlers {
   $only           = [ $only ] if !ref $only;
   my %hook_params = @{ $only } ? ( only => $only ) : ();
 
-  $class->run_before(sub { $current_action = $_[1]; }, %hook_params);
+  $class->run_before(sub { $_[0]->{PRIV()} = { current_action => $_[1] }; }, %hook_params);
 
   map { push @{ $registered_handlers{$_} }, $additional_handlers{$_} if $additional_handlers{$_} } keys %registered_handlers;
 }
@@ -23,7 +24,7 @@ sub register_get_models_handlers {
 sub get_callback {
   my ($self, %override_params) = @_;
 
-  my %default_params = _run_handlers($self, 'callback', action => $current_action);
+  my %default_params = _run_handlers($self, 'callback', action => ($self->{PRIV()} || {})->{current_action});
 
   return $self->url_for(%default_params, %override_params);
 }
diff --git a/SL/Controller/Helper/Paginated.pm b/SL/Controller/Helper/Paginated.pm
new file mode 100644 (file)
index 0000000..f4a319d
--- /dev/null
@@ -0,0 +1,291 @@
+package SL::Controller::Helper::Paginated;
+
+use strict;
+
+use Exporter qw(import);
+our @EXPORT = qw(make_paginated get_paginate_spec get_current_paginate_params _save_current_paginate_params _get_models_handler_for_paginated _callback_handler_for_paginated);
+
+use constant PRIV => '__paginatedhelper_priv';
+
+my $controller_paginate_spec;
+
+sub make_paginated {
+  my ($class, %specs)       = @_;
+
+  $specs{MODEL}           ||=  $class->_controller_name;
+  $specs{MODEL}             =~ s{ ^ SL::DB:: (?: .* :: )? }{}x;
+  $specs{PER_PAGE}        ||= "SL::DB::Manager::$specs{MODEL}"->default_objects_per_page;
+  $specs{FORM_PARAMS}     ||= [ qw(page per_page) ];
+  $specs{ONLY}            ||= [];
+  $specs{ONLY}              = [ $specs{ONLY} ] if !ref $specs{ONLY};
+
+  $controller_paginate_spec = \%specs;
+
+  my %hook_params           = @{ $specs{ONLY} } ? ( only => $specs{ONLY} ) : ();
+  $class->run_before('_save_current_paginate_params', %hook_params);
+
+  SL::Controller::Helper::GetModels::register_get_models_handlers(
+    $class,
+    callback   => '_callback_handler_for_paginated',
+    get_models => '_get_models_handler_for_paginated',
+    ONLY       => $specs{ONLY},
+  );
+
+  # $::lxdebug->dump(0, "CONSPEC", \%specs);
+}
+
+sub get_paginate_spec {
+  my ($class_or_self) = @_;
+
+  return $controller_paginate_spec;
+}
+
+sub get_current_paginate_params {
+  my ($self, %params)   = @_;
+
+  my $spec              = $self->get_paginate_spec;
+
+  my $priv              = $self->{PRIV()} || {};
+  $params{page}         = $priv->{page}     unless defined $params{page};
+  $params{per_page}     = $priv->{per_page} unless defined $params{per_page};
+
+  my %paginate_params   =  (
+    page                => ($params{page}     * 1) || 1,
+    per_page            => ($params{per_page} * 1) || $spec->{PER_PAGE},
+  );
+
+  my $calculated_params = "SL::DB::Manager::$spec->{MODEL}"->paginate(%paginate_params, args => {});
+  %paginate_params      = (
+    %paginate_params,
+    num_pages    => $calculated_params->{max},
+    common_pages => $calculated_params->{common},
+  );
+
+  # $::lxdebug->dump(0, "get_current_paginate_params: ", \%paginate_params);
+
+  return %paginate_params;
+}
+
+#
+# private functions
+#
+
+sub _save_current_paginate_params {
+  my ($self)        = @_;
+
+  my $paginate_spec = $self->get_paginate_spec;
+  $self->{PRIV()}   = {
+    page            => $::form->{ $paginate_spec->{FORM_PARAMS}->[0] } || 1,
+    per_page        => $::form->{ $paginate_spec->{FORM_PARAMS}->[1] } * 1,
+  };
+
+  # $::lxdebug->message(0, "saving current paginate params to " . $self->{PRIV()}->{page} . ' / ' . $self->{PRIV()}->{per_page});
+}
+
+sub _callback_handler_for_paginated {
+  my ($self, %params) = @_;
+  my $priv            = $self->{PRIV()} || {};
+
+  if ($priv->{page}) {
+    my $paginate_spec                             = $self->get_paginate_spec;
+    $params{ $paginate_spec->{FORM_PARAMS}->[0] } = $priv->{page};
+    $params{ $paginate_spec->{FORM_PARAMS}->[1] } = $priv->{per_page} if $priv->{per_page};
+  }
+
+  # $::lxdebug->dump(0, "CB handler for paginated; params nach modif:", \%params);
+
+  return %params;
+}
+
+sub _get_models_handler_for_paginated {
+  my ($self, %params)    = @_;
+  $params{model}       ||= $self->get_paginate_spec->{MODEL};
+
+  "SL::DB::Manager::$params{model}"->paginate($self->get_current_paginate_params, args => \%params);
+
+  # $::lxdebug->dump(0, "GM handler for paginated; params nach modif:", \%params);
+
+  return %params;
+}
+
+1;
+__END__
+
+=pod
+
+=encoding utf8
+
+=head1 NAME
+
+SL::Controller::Helper::Paginated - A helper for semi-automatic handling
+of paginating lists of database models in a controller
+
+=head1 SYNOPSIS
+
+In a controller:
+
+  use SL::Controller::Helper::GetModels;
+  use SL::Controller::Helper::Paginated;
+
+  __PACKAGE__->make_paginated(
+    MODEL       => 'BackgroundJobHistory',
+    ONLY        => [ qw(list) ],
+    FORM_PARAMS => [ qw(page per_page) ],
+  );
+
+  sub action_list {
+    my ($self) = @_;
+
+    my $paginated_models = $self->get_models;
+    $self->render('controller/list', ENTRIES => $paginated_models);
+  }
+
+In said template:
+
+  [% USE L %]
+
+  <table>
+   <thead>
+    <tr>
+     ...
+    </tr>
+   </thead>
+
+   <tbody>
+    [% FOREACH entry = ENTRIES %]
+     <tr>
+      ...
+     </tr>
+    [% END %]
+   </tbody>
+  </table>
+
+  [% L.paginate_controls %]
+
+=head1 OVERVIEW
+
+This specialized helper module enables controllers to display a
+paginatable list of database models with as few lines as possible. It
+can also be combined trivially with the L<SL::Controller::Sorted>
+helper for sortable lists.
+
+For this to work the controller has to provide the information which
+indexes are eligible for paginateing etc. by a call to
+L<make_paginated> at compile time.
+
+The underlying functionality that enables the use of more than just
+the paginate helper is provided by the controller helper
+C<GetModels>. See the documentation for L<SL::Controller::Sorted> for
+more information on it.
+
+A template can use the method C<paginate_controls> from the layout
+helper module C<L> which renders the links for navigation between the
+pages.
+
+This module requires that the Rose model managers use their C<Paginated>
+helper.
+
+The C<Paginated> helper hooks into the controller call to the action via
+a C<run_before> hook. This is done so that it can remember the paginate
+parameters that were used in the current view.
+
+=head1 PACKAGE FUNCTIONS
+
+=over 4
+
+=item C<make_paginated %paginate_spec>
+
+This function must be called by a controller at compile time. It is
+uesd to set the various parameters required for this helper to do its
+magic.
+
+The hash C<%paginate_spec> can include the following parameters:
+
+=over 4
+
+=item * C<MODEL>
+
+Optional. A string: the name of the Rose database model that is used
+as a default in certain cases. If this parameter is missing then it is
+derived from the controller's package (e.g. for the controller
+C<SL::Controller::BackgroundJobHistory> the C<MODEL> would default to
+C<BackgroundJobHistory>).
+
+=item * C<PER_PAGE>
+
+Optional. An integer: the number of models to return per page.
+
+Defaults to the underlying database model's default number of models
+per page.
+
+=item * C<FORM_PARAMS>
+
+Optional. An array reference with exactly two strings that name the
+indexes in C<$::form> in which the current page's number (the first
+element in the array) and the number of models per page (the second
+element in the array) are stored.
+
+Defaults to the values C<page> and C<per_page> if missing.
+
+=item * C<ONLY>
+
+Optional. An array reference containing a list of action names for
+which the paginate parameters should be saved. If missing or empty then
+all actions invoked on the controller are monitored.
+
+=back
+
+=back
+
+=head1 INSTANCE FUNCTIONS
+
+These functions are called on a controller instance.
+
+=over 4
+
+=item C<get_paginate_spec>
+
+Returns a hash containing the currently active paginate
+parameters. The following keys are returned:
+
+=over 4
+
+=item * C<page>
+
+The currently active page number (numbering starts at 1).
+
+=item * C<per_page>
+
+Number of models per page (at least 1).
+
+=item * C<num_pages>
+
+Number of pages to display (at least 1).
+
+=item * C<common_pages>
+
+An array reference with one hash reference for each possible
+page. Each hash ref contains the keys C<active> (C<1> if that page is
+the currently active page), C<page> (the page number this hash
+reference describes) and C<visible> (whether or not it should be
+displayed).
+
+=back
+
+=item C<get_current_paginate_params>
+
+Returns a hash reference to the paginate spec structure given in the call
+to L<make_paginated> after normalization (hash reference construction,
+applying default parameters etc).
+
+=back
+
+=head1 BUGS
+
+Nothing here yet.
+
+=head1 AUTHOR
+
+Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
+
+=cut
index 817f80319fb6015156868b8fad333e175589d5a7..4afae9d79f34ab2ff15a96392df339a230c3b240 100644 (file)
@@ -5,7 +5,9 @@ use strict;
 use Exporter qw(import);
 our @EXPORT = qw(make_sorted get_sort_spec get_current_sort_params _save_current_sort_params _get_models_handler_for_sorted _callback_handler_for_sorted);
 
-my ($controller_sort_spec, $current_sort_by, $current_sort_dir);
+use constant PRIV => '__sortedhelperpriv';
+
+my $controller_sort_spec;
 
 sub make_sorted {
   my ($class, %specs) = @_;
@@ -22,8 +24,9 @@ sub make_sorted {
     $spec->{model_column} ||= $column;
   }
 
-  $specs{DEFAULT_DIR}   = $specs{DEFAULT_DIR} || !defined($specs{DEFAULT_DIR}) ? 1 : 0;
-  $specs{DEFAULT_BY}  ||= { "SL::DB::Manager::$specs{MODEL}"->_sort_spec }->{default}->[0];
+  my %model_sort_spec   = "SL::DB::Manager::$specs{MODEL}"->_sort_spec;
+  $specs{DEFAULT_DIR}   = $specs{DEFAULT_DIR} ? 1 : defined($specs{DEFAULT_DIR}) ? $specs{DEFAULT_DIR} * 1 : $model_sort_spec{default}->[1];
+  $specs{DEFAULT_BY}  ||= $model_sort_spec{default}->[0];
   $specs{FORM_PARAMS} ||= [ qw(sort_by sort_dir) ];
   $specs{ONLY}        ||= [];
   $specs{ONLY}          = [ $specs{ONLY} ] if !ref $specs{ONLY};
@@ -55,8 +58,9 @@ sub get_current_sort_params {
   my $sort_spec = $self->get_sort_spec;
 
   if (!$params{sort_by}) {
-    $params{sort_by}  = $current_sort_by;
-    $params{sort_dir} = $current_sort_dir;
+    my $priv          = $self->{PRIV()} || {};
+    $params{sort_by}  = $priv->{by};
+    $params{sort_dir} = $priv->{dir};
   }
 
   my $by          = $params{sort_by} || $sort_spec->{DEFAULT_BY};
@@ -73,22 +77,25 @@ sub get_current_sort_params {
 #
 
 sub _save_current_sort_params {
-  my ($self) = @_;
+  my ($self)      = @_;
 
-  my $sort_spec     = $self->get_sort_spec;
-  $current_sort_by  =   $::form->{ $sort_spec->{FORM_PARAMS}->[0] };
-  $current_sort_dir = !!$::form->{ $sort_spec->{FORM_PARAMS}->[1] } * 1;
+  my $sort_spec   = $self->get_sort_spec;
+  $self->{PRIV()} = {
+    by            =>   $::form->{ $sort_spec->{FORM_PARAMS}->[0] },
+    dir           => !!$::form->{ $sort_spec->{FORM_PARAMS}->[1] } * 1,
+  };
 
-  # $::lxdebug->message(0, "saving current sort params to $current_sort_by / $current_sort_dir");
+  # $::lxdebug->message(0, "saving current sort params to " . $self->{PRIV()}->{by} . ' / ' . $self->{PRIV()}->{dir});
 }
 
 sub _callback_handler_for_sorted {
   my ($self, %params) = @_;
 
-  if ($current_sort_by) {
+  my $priv = $self->{PRIV()} || {};
+  if ($priv->{by}) {
     my $sort_spec                             = $self->get_sort_spec;
-    $params{ $sort_spec->{FORM_PARAMS}->[0] } = $current_sort_by;
-    $params{ $sort_spec->{FORM_PARAMS}->[1] } = $current_sort_dir;
+    $params{ $sort_spec->{FORM_PARAMS}->[0] } = $priv->{by};
+    $params{ $sort_spec->{FORM_PARAMS}->[1] } = $priv->{dir};
   }
 
   # $::lxdebug->dump(0, "CB handler for sorted; params nach modif:", \%params);
@@ -143,7 +150,7 @@ In a controller:
   sub action_list {
     my ($self) = @_;
 
-    my $sorted_models = $self->get_sorted;
+    my $sorted_models = $self->get_models;
     $self->render('controller/list', ENTRIES => $sorted_models);
   }
 
@@ -186,6 +193,9 @@ calls to e.g. C<SL::DB::Manager::SomeModel::get_all>.
 A template on the other hand can use the method
 C<sortable_table_header> from the layout helper module C<L>.
 
+This module requires that the Rose model managers use their C<Sorted>
+helper.
+
 The C<Sorted> helper hooks into the controller call to the action via
 a C<run_before> hook. This is done so that it can remember the sort
 parameters that were used in the current view.
@@ -207,31 +217,32 @@ that can be used for sorting (similar to database column names). The
 second kind are also the indexes you use in a template when calling
 C<[% L.sorted_table_header(...) %]>.
 
-Control parameters include the following (all required parameters
-occur first):
+Control parameters include the following:
 
 =over 4
 
+=item * C<MODEL>
+
+Optional. A string: the name of the Rose database model that is used
+as a default in certain cases. If this parameter is missing then it is
+derived from the controller's package (e.g. for the controller
+C<SL::Controller::BackgroundJobHistory> the C<MODEL> would default to
+C<BackgroundJobHistory>).
+
 =item * C<DEFAULT_BY>
 
-Required. A string: the index to sort by if the user hasn't clicked on
+Optional. A string: the index to sort by if the user hasn't clicked on
 any column yet (meaning: if the C<$::form> parameters for sorting do
 not contain a valid index).
 
+Defaults to the underlying database model's default sort column name.
+
 =item * C<DEFAULT_DIR>
 
 Optional. Default sort direction (ascending for trueish values,
 descrending for falsish values).
 
-Defaults to C<1> if missing.
-
-=item * C<MODEL>
-
-Optional. A string: the name of the Rose database model that is used
-as a default in certain cases. If this parameter is missing then it is
-derived from the controller's package (e.g. for the controller
-C<SL::Controller::BackgroundJobHistory> the C<MODEL> would default to
-C<BackgroundJobHistory>).
+Defaults to the underlying database model's default sort direction.
 
 =item * C<FORM_PARAMS>
 
index a24d4d7e065d14f7babcc30f1b0d9b0dfc8f611c..a0ad02cb8b0098be092e7f165ef3afdba7c999fa 100644 (file)
@@ -9,18 +9,18 @@ our @EXPORT = qw(paginate disable_paginating);
 use List::MoreUtils qw(any);
 
 sub paginate {
-  my ($self, %params) = @_;
-  my $page = $params{page} || 1;
-  my %args = %{ $params{args} || {} };
-
-  my $ret = { };
-
-  $ret->{per_page} = per_page($self, %params);
-  $ret->{max}    = ceil($self->get_all_count(%args), $ret->{per_page}) || 1;
-  $ret->{cur}    = $page < 1 ? 1
-                 : $page > $ret->{max} ? $ret->{max}
-                 : $page;
-  $ret->{common} = make_common_pages($ret->{cur}, $ret->{max});
+  my ($self, %params)     = @_;
+  my $page                = $params{page} || 1;
+  my %args                = %{ $params{args} || {} };
+
+  my $ret                 = { };
+
+  $ret->{per_page}        = per_page($self, %params);
+  $ret->{max}             = ceil($self->get_all_count(%args), $ret->{per_page}) || 1;
+  $ret->{cur}             = $page < 1 ? 1
+                          : $page > $ret->{max} ? $ret->{max}
+                          : $page;
+  $ret->{common}          = make_common_pages($ret->{cur}, $ret->{max});
 
   $params{args}{page}     = $ret->{cur};
   $params{args}{per_page} = $ret->{per_page};
index 1bb89ee7d73836ab7fc5ae2e703b572908963f26..6212f94161be9e98b8f2aaf5465ed88c131eda55 100644 (file)
@@ -5,6 +5,7 @@ use strict;
 use SL::DB::Helper::Manager;
 use base qw(SL::DB::Helper::Manager);
 
+use SL::DB::Helper::Paginated;
 use SL::DB::Helper::Sorted;
 
 sub object_class { 'SL::DB::BackgroundJob' }
index 132188f3c7519154eba75df39aa11086fbca535d..4f1ddd3059478965faf63dbf045df7ab6eca9c3a 100644 (file)
@@ -5,6 +5,7 @@ use strict;
 use SL::DB::Helper::Manager;
 use base qw(SL::DB::Helper::Manager);
 
+use SL::DB::Helper::Paginated;
 use SL::DB::Helper::Sorted;
 
 sub object_class { 'SL::DB::BackgroundJobHistory' }
diff --git a/SL/DB/Manager/OrderItem.pm b/SL/DB/Manager/OrderItem.pm
new file mode 100644 (file)
index 0000000..000369e
--- /dev/null
@@ -0,0 +1,36 @@
+package SL::DB::Manager::OrderItem;
+
+use strict;
+
+use SL::DB::Helper::Manager;
+use base qw(SL::DB::Helper::Manager);
+
+use SL::DB::Helper::Paginated;
+use SL::DB::Helper::Sorted;
+
+sub object_class { 'SL::DB::OrderItem' }
+
+__PACKAGE__->make_manager_methods;
+
+sub _sort_spec {
+  return ( columns => { delivery_date => [ 'deliverydate',        ],
+                        description   => [ 'lower(orderitems.description)',  ],
+                        partnumber    => [ 'part.partnumber',     ],
+                        qty           => [ 'qty'                  ],
+                        ordnumber     => [ 'order.ordnumber'      ],
+                        customer      => [ 'lower(customer.name)', ],
+                        position      => [ 'trans_id', 'runningnumber' ],
+                        reqdate       => [ 'COALESCE(orderitems.reqdate, order.reqdate)' ],
+                        orddate       => [ 'order.orddate' ],
+                        sellprice     => [ 'sellprice' ],
+                        discount      => [ 'discount' ],
+                        transdate     => [ 'transdate::date', 'order.reqdate' ],
+                      },
+           default => [ 'position', 1 ],
+           nulls   => { }
+         );
+}
+
+sub default_objects_per_page { 40 }
+
+1;
index f24abcaf12f4a6ee19b3dc9576155da1f79b7ecd..3b868d350991bee5fb9c79b55fb6e8236ec675c6 100644 (file)
@@ -6,6 +6,7 @@ use List::Util qw(sum);
 use SL::AM;
 
 use SL::DB::MetaSetup::OrderItem;
+use SL::DB::Manager::OrderItem;
 use SL::DB::Helper::CustomVariables (
   sub_module  => 'orderitems',
   cvars_alias => 1,
@@ -37,9 +38,6 @@ __PACKAGE__->meta->add_relationship(
   },
 );
 
-# Creates get_all, get_all_count, get_all_iterator, delete_all and update_all.
-__PACKAGE__->meta->make_manager_class;
-
 __PACKAGE__->meta->initialize;
 
 sub is_price_update_available {
@@ -56,30 +54,4 @@ sub shipped_qty {
   return sum(map { AM->convert_unit($_->unit => $self->unit) * $_->qty } @doi);
 }
 
-package SL::DB::Manager::OrderItem;
-
-use SL::DB::Helper::Paginated;
-use SL::DB::Helper::Sorted;
-
-sub _sort_spec {
-  return ( columns => { delivery_date => [ 'deliverydate',        ],
-                        description   => [ 'lower(orderitems.description)',  ],
-                        partnumber    => [ 'part.partnumber',     ],
-                        qty           => [ 'qty'                  ],
-                        ordnumber     => [ 'order.ordnumber'      ],
-                        customer      => [ 'lower(customer.name)', ],
-                        position      => [ 'trans_id', 'runningnumber' ],
-                        reqdate       => [ 'COALESCE(orderitems.reqdate, order.reqdate)' ],
-                        orddate       => [ 'order.orddate' ],
-                        sellprice     => [ 'sellprice' ],
-                        discount      => [ 'discount' ],
-                        transdate     => [ 'transdate::date', 'order.reqdate' ],
-                      },
-           default => [ 'position', 1 ],
-           nulls   => { }
-         );
-}
-
-sub default_objects_per_page { 40 }
-
 1;
index 6d6b59f2d77729ffa58dbe5c1131499acb2d4818..39b520e842b336967092c18b6c12b611729a3c48 100644 (file)
@@ -83,6 +83,15 @@ sub html_tag {
   return "<${tag}${attributes}>${content}</${tag}>";
 }
 
+sub img_tag {
+  my ($self, @slurp) = @_;
+  my %options = _hashify(@slurp);
+
+  $options{alt} ||= '';
+
+  return $self->html_tag('img', undef, %options);
+}
+
 sub select_tag {
   my $self            = shift;
   my $name            = shift;
@@ -670,6 +679,33 @@ sub sortable_table_header {
   return '<a href="' . $controller->get_callback(%params) . '">' . _H($title) . $image . '</a>';
 }
 
+sub paginate_controls {
+  my ($self)          = @_;
+
+  my $controller      = $self->{CONTEXT}->stash->get('SELF');
+  my $paginate_spec   = $controller->get_paginate_spec;
+  my %paginate_params = $controller->get_current_paginate_params;
+
+  my %template_params = (
+    pages             => {
+      cur             => $paginate_params{page},
+      max             => $paginate_params{num_pages},
+      common          => $paginate_params{common_pages},
+    },
+    url_maker         => sub {
+      my %url_params                                    = _hashify(@_);
+      $url_params{ $paginate_spec->{FORM_PARAMS}->[0] } = delete $url_params{page};
+      $url_params{ $paginate_spec->{FORM_PARAMS}->[1] } = delete $url_params{per_page} if exists $url_params{per_page};
+
+      return $controller->get_callback(%url_params);
+    },
+  );
+
+  my $output;
+  $controller->_template_obj->process('templates/webpages/common/paginate.html', \%template_params, \$output);
+  return $output;
+}
+
 1;
 
 __END__
@@ -1011,6 +1047,13 @@ underlying call to L<SL::Controller::Base::url_for>.
 See the documentation of L<SL::Controller::Helper::Sorted> for an
 overview and further usage instructions.
 
+=item C<paginate_controls>
+
+Create a set of links used to paginate a list view.
+
+See the documentation of L<SL::Controller::Helper::Paginated> for an
+overview and further usage instructions.
+
 =back
 
 =head2 CONVERSION FUNCTIONS
index e25f963a86ce170996a64755e978aa7e9bf86700..1aa0248d0be8e17371acea54b77d2b158fa7b35d 100644 (file)
@@ -226,6 +226,7 @@ sub display_row {
     # adjust prices by unit, ignore if pricegroup changed
     if ((!$form->{"prices_$i"}) || ($form->{"new_pricegroup_$i"} == $form->{"old_pricegroup_$i"})) {
         $form->{"sellprice_$i"} *= AM->convert_unit($form->{"selected_unit_$i"}, $form->{"unit_old_$i"}, $all_units) || 1;
+        $form->{"lastcost_$i"} *= AM->convert_unit($form->{"selected_unit_$i"}, $form->{"unit_old_$i"}, $all_units) || 1;
         $form->{"unit_old_$i"}   = $form->{"selected_unit_$i"};
     }
     my $this_unit = $form->{"unit_$i"};
@@ -248,7 +249,10 @@ sub display_row {
     $column_data{"unit"} = AM->unit_select_html($all_units, "unit_$i", $this_unit, $form->{"id_$i"} ? $form->{"unit_$i"} : undef);
 # / unit ending
 
+#count the max of decimalplaces of sellprice and lastcost, so the same number of decimalplaces
+#is shown for lastcost and sellprice.
     my $decimalplaces = ($form->{"sellprice_$i"} =~ /\.(\d+)/) ? max 2, length $1 : 2;
+    $decimalplaces = ($form->{"lastcost_$i"} =~ /\.(\d+)/) ? max $decimalplaces, length $1 : $decimalplaces;
 
     my $price_factor   = $price_factors{$form->{"price_factor_id_$i"}} || 1;
     my $discount       = $form->round_amount($form->{"qty_$i"} * $form->{"sellprice_$i"} *        $form->{"discount_$i"}  / 100 / $price_factor, 2);
@@ -355,7 +359,7 @@ sub display_row {
     } else {
       $real_sellprice            = $linetotal;
     };
-    my $real_lastcost            = $form->{"lastcost_$i"} * $form->{"qty_$i"} / ( $form->{"marge_price_factor_$i"} || 1 );
+    my $real_lastcost            = $form->round_amount($form->{"lastcost_$i"} * $form->{"qty_$i"} / $price_factor, 2);
     my $marge_percent_warn       = $myconfig{marge_percent_warn} * 1 || 15;
     my $marge_adjust_credit_note = $form->{type} eq 'credit_note' ? -1 : 1;
 
@@ -377,7 +381,7 @@ sub display_row {
         &nbsp;<b>%s</b> <input size="5" name="lastcost_$i" value="%s">|,
                    $marge_color, $locale->text('Ertrag'),$form->{"marge_absolut_$i"}, $form->{"marge_percent_$i"},
                    $locale->text('LP'), $form->format_amount(\%myconfig, $form->{"listprice_$i"}, 2),
-                   $locale->text('EK'), $form->format_amount(\%myconfig, $form->{"lastcost_$i"}, 2) }
+                   $locale->text('EK'), $form->format_amount(\%myconfig, $form->{"lastcost_$i"}, $decimalplaces) }
       if $form->{"id_$i"} && ($form->{type} =~ /^sales_/ ||  $form->{type} =~ /invoice/ || $form->{type} =~ /^credit_note$/ ) && !$is_delivery_order;
 
     $form->{"listprice_$i"} = $form->format_amount(\%myconfig, $form->{"listprice_$i"}, 2)
index a89fa0242459b2c49b8c92eff329641cea383116..fe28838f873a5bbdcb3fa338babc882fc4c173e8 100644 (file)
@@ -334,8 +334,8 @@ sub invoice_transactions {
     $ar->{price_factor} = 1 unless $ar->{price_factor};
     # calculate individual sellprice
     # discount was already accounted for in db sellprice
-    $ar->{sellprice} = $ar->{sellprice} / $ar->{price_factor} / $basefactor;
-    $ar->{lastcost} = $ar->{lastcost} / $ar->{price_factor};
+    $ar->{sellprice}       = $ar->{sellprice}  / $ar->{price_factor} / $basefactor;
+    $ar->{lastcost}        = $ar->{lastcost}   / $ar->{price_factor} / $basefactor;
     $ar->{sellprice_total} = $ar->{qty} * ( $ar->{fxsellprice} * ( 1 - $ar->{discount} ) ) / $ar->{price_factor};
     $ar->{lastcost_total}  = $ar->{qty} * $ar->{lastcost} * $basefactor;
     # marge_percent wird neu berechnet, da Wert in invoice leer ist (Bug)
index b5869f38e72380eb13ee3e13b5e2097286eef149..737a49edf2995dfad1aaa301a93b6234a4ae5a01 100644 (file)
@@ -1,11 +1,11 @@
 [% USE HTML %][% USE L %][% USE LxERP %]
 <body>
 
- <form method="post" action="controller.pl">
-  <div class="listtop">[% FORM.title %]</div>
+ <h1>[% FORM.title %]</h1>
 
 [%- INCLUDE 'common/flash.html' %]
 
+ <form method="post" action="controller.pl">
   <table>
    <tr>
     <th align="right">[%- LxERP.t8('Active') %]</th>
@@ -42,6 +42,7 @@
 
   <p>
    [% L.hidden_tag("id", SELF.background_job.id) %]
+   [% L.hidden_tag("back_to", SELF.back_to) %]
    [% L.hidden_tag("action", "BackgroundJob/dispatch") %]
    [% L.submit_tag("action_" _  (SELF.background_job.id ? "update" : "create"), LxERP.t8('Save')) %]
    [%- IF SELF.background_job.id %]
index 6ccef1c2041ccb146055c0233dde25fbc1b5130b..b8ea3f64dcc39051ba4f7d89c61674eff27e3a7a 100644 (file)
@@ -1,7 +1,7 @@
 [% USE HTML %][% USE L %][% USE LxERP %]
 
 <body>
- <div class="listtop">[% FORM.title %]</div>
+ <h1>[% FORM.title %]</h1>
 
 [%- INCLUDE 'common/flash.html' %]
 
    <table id="background_job_list" width="100%">
     <thead>
      <tr class="listheading">
-      <th>[%- LxERP.t8('Package name') %]</th>
-      <th>[%- LxERP.t8('Execution type') %]</th>
-      <th>[%- LxERP.t8('Active') %]</th>
-      <th>[%- LxERP.t8('Execution schedule') %]</th>
-      <th>[%- LxERP.t8('Last run at') %]</th>
-      <th>[%- LxERP.t8('Next run at') %]</th>
+      <th>[% L.sortable_table_header('package_name') %]</th>
+      <th>[% L.sortable_table_header('type') %]</th>
+      <th>[% L.sortable_table_header('active') %]</th>
+      <th>[% L.sortable_table_header('cron_spec') %]</th>
+      <th>[% L.sortable_table_header('last_run_at') %]</th>
+      <th>[% L.sortable_table_header('next_run_at') %]</th>
      </tr>
     </thead>
 
@@ -28,7 +28,7 @@
     [%- FOREACH background_job = BACKGROUND_JOBS %]
     <tr class="listrow[% loop.count % 2 %]" id="background_job_id_[% background_job.id %]">
      <td>
-      <a href="[% SELF.url_for(action => 'edit', id => background_job.id) %]">
+      <a href="[% SELF.url_for(action => 'edit', id => background_job.id, back_to => SELF.get_callback) %]">
        [%- HTML.escape(background_job.package_name) %]
       </a>
      </td>
    </table>
   [%- END %]
 
+  [% L.paginate_controls %]
+
   <hr size="3" noshade>
 
   <p>
-   <a href="[% SELF.url_for(action => 'new') %]">[%- LxERP.t8('Create new background job') %]</a>
+   <a href="[% SELF.url_for(action => 'new', back_to => SELF.get_callback) %]">[%- LxERP.t8('Create new background job') %]</a>
    |
    <a href="[% SELF.url_for(controller => 'BackgroundJobHistory', action => 'list') %]">[%- LxERP.t8('View background job history') %]</a>
    |
index 6086776d141aa701b4a3aea4704c775a5673a379..bf732d44eed0f4bd1fb7fbf6f72474a6fe826839 100644 (file)
@@ -1,7 +1,7 @@
 [% USE HTML %][% USE L %][% USE LxERP %]
 
 <body>
- <div class="listtop">[% FORM.title %]</div>
+ <h1>[% FORM.title %]</h1>
 
 [%- INCLUDE 'common/flash.html' %]
 
@@ -49,6 +49,8 @@
    </table>
   [%- END %]
 
+  [% L.paginate_controls %]
+
   <hr size="3" noshade>
 
   <p>
index 0a0584fbc4032d3915c734bcb862bd05f90661a6..e9df400604a9afd61db9505a87b8c26d98b8691c 100644 (file)
@@ -1,7 +1,7 @@
 [% USE HTML %][% USE L %][% USE LxERP %]
 <body>
 
- <div class="listtop">[% FORM.title %]</div>
+ <h1>[% FORM.title %]</h1>
 
 [%- INCLUDE 'common/flash.html' %]
 
index 8878193f253428bcecbe5e443f6cd2bef1acb6b5..089972947473e08ff5c998bcabfb5652c6964d35 100644 (file)
@@ -1,10 +1,18 @@
 [%- USE T8 %]
-<span class='paginate'>
+[%- MACRO build_url BLOCK %]
+ [%- IF base_url %]
+  [%- base_url %]&page=[% page %]
+ [%- ELSE %]
+  [% url_maker('page' => page) %]
+ [%- END %]
+[%- END %]
 [%- IF pages.max > 1 %]
-[%- IF pages.cur > 1 %]<a class='paginate-prev' href='[% base_url _ "&page=" _ (pages.cur - 1) %]'>&laquo; [% 'prev' | $T8 %]</a> [% ELSE %]<b>&laquo;</b> [% END %]
+<div class='paginate'>
+[%- IF pages.cur > 1 %]<a class='paginate-prev' href='[% build_url(page=pages.cur - 1) %]'>&laquo; [% 'prev' | $T8 %]</a> [% ELSE %]<b>&laquo;</b> [% END %]
 [%- FOR p = pages.common %]
   [%- NEXT UNLESS p.visible %]
-  [%- IF p.active %]<a class='paginate-page' href="[% base_url _ "&page=" _ p.page %]">[% p.page %]</a> [% ELSE %]<b>[% p.page %]</b> [%- END %]
+  [%- IF p.active %]<a class='paginate-page' href="[% build_url(page=p.page) %]">[% p.page %]</a> [% ELSE %]<b>[% p.page %]</b> [%- END %]
 [%- END %]
-[%- IF pages.cur < pages.max %]<a class='paginate-next' href='[% base_url _ "&page=" _ (pages.cur + 1) %]'>[% 'next' | $T8 %] &raquo;</a>[% ELSE %]<b>&raquo;</b>[%- END %]
+[%- IF pages.cur < pages.max %]<a class='paginate-next' href='[% build_url(page=pages.cur + 1) %]'>[% 'next' | $T8 %] &raquo;</a>[% ELSE %]<b>&raquo;</b>[%- END %]
+</div>
 [%- END %]
index f0bb2772bfca9c0b9efd903646eb8e438e155be8..d0d2159d1eaab27839690582155136ed9a119cdf 100644 (file)
@@ -38,7 +38,7 @@
   </tr>
   [%- END %]
  </table>
- <p align=right>[% PROCESS 'common/paginate.html' pages=SELF.pages, base_url=SELF.url_for(action='list', sort_dir=SELF.sort_dir, sort_by=SELF.sort_by) %]</p>
+ [% PROCESS 'common/paginate.html' pages=SELF.pages, base_url=SELF.url_for(action='list', sort_dir=SELF.sort_dir, sort_by=SELF.sort_by) %]
 
 [%- END %]
 </div>
index 3193961d970a51368a4294f02a9d9a58ac623e93..1843c054c1ce99d187a8b2c3d9d9380fa857056b 100644 (file)
@@ -1,4 +1,4 @@
 [% SET report_bottom_url_args = {} %]
 [%     report_bottom_url_args.import(SELF.flat_filter) %]
 [%     report_bottom_url_args.import({action='list', sort_dir=SELF.sort_dir, sort_by=SELF.sort_by}) %]
-<p align=right>[% PROCESS 'common/paginate.html' pages=SELF.pages, base_url=SELF.url_for(report_bottom_url_args) %]</p>
+[% PROCESS 'common/paginate.html' pages=SELF.pages, base_url=SELF.url_for(report_bottom_url_args) %]