From: Thomas Heck Date: Wed, 5 Sep 2012 12:36:34 +0000 (+0200) Subject: Merge branch 'master' of vc.linet-services.de:public/lx-office-erp X-Git-Tag: release-3.0.0beta1~251 X-Git-Url: http://wagnertech.de/gitweb/gitweb.cgi/mfinanz.git/commitdiff_plain/dc7791df0d3e919e691fb3fd3d7ee20e3c5e7ca1?hp=f2b76d67f773954dcfa59ff7c3ebb6f6607e2e43 Merge branch 'master' of vc.linet-services.de:public/lx-office-erp --- diff --git a/SL/Controller/BackgroundJob.pm b/SL/Controller/BackgroundJob.pm index 57ec5c377..f80f57a1c 100644 --- a/SL/Controller/BackgroundJob.pm +++ b/SL/Controller/BackgroundJob.pm @@ -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; diff --git a/SL/Controller/BackgroundJobHistory.pm b/SL/Controller/BackgroundJobHistory.pm index ec9ebfe5a..5992dc00a 100644 --- a/SL/Controller/BackgroundJobHistory.pm +++ b/SL/Controller/BackgroundJobHistory.pm @@ -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) ], diff --git a/SL/Controller/Base.pm b/SL/Controller/Base.pm index 4dace86ed..1188ffe8b 100644 --- a/SL/Controller/Base.pm +++ b/SL/Controller/Base.pm @@ -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 { diff --git a/SL/Controller/Helper/GetModels.pm b/SL/Controller/Helper/GetModels.pm index 4658717f6..00ef31017 100644 --- a/SL/Controller/Helper/GetModels.pm +++ b/SL/Controller/Helper/GetModels.pm @@ -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 index 000000000..f4a319d2c --- /dev/null +++ b/SL/Controller/Helper/Paginated.pm @@ -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 %] + + + + + ... + + + + + [% FOREACH entry = ENTRIES %] + + ... + + [% END %] + +
+ + [% 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 +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 at compile time. + +The underlying functionality that enables the use of more than just +the paginate helper is provided by the controller helper +C. See the documentation for L for +more information on it. + +A template can use the method C from the layout +helper module C which renders the links for navigation between the +pages. + +This module requires that the Rose model managers use their C +helper. + +The C helper hooks into the controller call to the action via +a C 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 + +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 + +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 the C would default to +C). + +=item * C + +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 + +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 and C if missing. + +=item * C + +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 + +Returns a hash containing the currently active paginate +parameters. The following keys are returned: + +=over 4 + +=item * C + +The currently active page number (numbering starts at 1). + +=item * C + +Number of models per page (at least 1). + +=item * C + +Number of pages to display (at least 1). + +=item * C + +An array reference with one hash reference for each possible +page. Each hash ref contains the keys C (C<1> if that page is +the currently active page), C (the page number this hash +reference describes) and C (whether or not it should be +displayed). + +=back + +=item C + +Returns a hash reference to the paginate spec structure given in the call +to L after normalization (hash reference construction, +applying default parameters etc). + +=back + +=head1 BUGS + +Nothing here yet. + +=head1 AUTHOR + +Moritz Bunkus Em.bunkus@linet-services.deE + +=cut diff --git a/SL/Controller/Helper/Sorted.pm b/SL/Controller/Helper/Sorted.pm index 817f80319..4afae9d79 100644 --- a/SL/Controller/Helper/Sorted.pm +++ b/SL/Controller/Helper/Sorted.pm @@ -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. A template on the other hand can use the method C from the layout helper module C. +This module requires that the Rose model managers use their C +helper. + The C helper hooks into the controller call to the action via a C 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 + +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 the C would default to +C). + =item * C -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 Optional. Default sort direction (ascending for trueish values, descrending for falsish values). -Defaults to C<1> if missing. - -=item * C - -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 the C would default to -C). +Defaults to the underlying database model's default sort direction. =item * C diff --git a/SL/DB/Helper/Paginated.pm b/SL/DB/Helper/Paginated.pm index a24d4d7e0..a0ad02cb8 100644 --- a/SL/DB/Helper/Paginated.pm +++ b/SL/DB/Helper/Paginated.pm @@ -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}; diff --git a/SL/DB/Manager/BackgroundJob.pm b/SL/DB/Manager/BackgroundJob.pm index 1bb89ee7d..6212f9416 100644 --- a/SL/DB/Manager/BackgroundJob.pm +++ b/SL/DB/Manager/BackgroundJob.pm @@ -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' } diff --git a/SL/DB/Manager/BackgroundJobHistory.pm b/SL/DB/Manager/BackgroundJobHistory.pm index 132188f3c..4f1ddd305 100644 --- a/SL/DB/Manager/BackgroundJobHistory.pm +++ b/SL/DB/Manager/BackgroundJobHistory.pm @@ -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 index 000000000..000369e76 --- /dev/null +++ b/SL/DB/Manager/OrderItem.pm @@ -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; diff --git a/SL/DB/OrderItem.pm b/SL/DB/OrderItem.pm index f24abcaf1..3b868d350 100644 --- a/SL/DB/OrderItem.pm +++ b/SL/DB/OrderItem.pm @@ -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; diff --git a/SL/Template/Plugin/L.pm b/SL/Template/Plugin/L.pm index 6d6b59f2d..39b520e84 100644 --- a/SL/Template/Plugin/L.pm +++ b/SL/Template/Plugin/L.pm @@ -83,6 +83,15 @@ sub html_tag { return "<${tag}${attributes}>${content}"; } +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 '' . _H($title) . $image . ''; } +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. See the documentation of L for an overview and further usage instructions. +=item C + +Create a set of links used to paginate a list view. + +See the documentation of L for an +overview and further usage instructions. + =back =head2 CONVERSION FUNCTIONS diff --git a/bin/mozilla/io.pl b/bin/mozilla/io.pl index e25f963a8..1aa0248d0 100644 --- a/bin/mozilla/io.pl +++ b/bin/mozilla/io.pl @@ -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 {  %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) diff --git a/bin/mozilla/vk.pl b/bin/mozilla/vk.pl index a89fa0242..fe28838f8 100644 --- a/bin/mozilla/vk.pl +++ b/bin/mozilla/vk.pl @@ -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) diff --git a/templates/webpages/background_job/form.html b/templates/webpages/background_job/form.html index b5869f38e..737a49edf 100644 --- a/templates/webpages/background_job/form.html +++ b/templates/webpages/background_job/form.html @@ -1,11 +1,11 @@ [% USE HTML %][% USE L %][% USE LxERP %] -
-
[% FORM.title %]
+

[% FORM.title %]

[%- INCLUDE 'common/flash.html' %] + @@ -42,6 +42,7 @@

[% 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 %] diff --git a/templates/webpages/background_job/list.html b/templates/webpages/background_job/list.html index 6ccef1c20..b8ea3f64d 100644 --- a/templates/webpages/background_job/list.html +++ b/templates/webpages/background_job/list.html @@ -1,7 +1,7 @@ [% USE HTML %][% USE L %][% USE LxERP %] -

[% FORM.title %]
+

[% FORM.title %]

[%- INCLUDE 'common/flash.html' %] @@ -15,12 +15,12 @@
[%- LxERP.t8('Active') %]
- - - - - - + + + + + + @@ -28,7 +28,7 @@ [%- FOREACH background_job = BACKGROUND_JOBS %] @@ -64,10 +64,12 @@
[%- LxERP.t8('Package name') %][%- LxERP.t8('Execution type') %][%- LxERP.t8('Active') %][%- LxERP.t8('Execution schedule') %][%- LxERP.t8('Last run at') %][%- LxERP.t8('Next run at') %][% L.sortable_table_header('package_name') %][% L.sortable_table_header('type') %][% L.sortable_table_header('active') %][% L.sortable_table_header('cron_spec') %][% L.sortable_table_header('last_run_at') %][% L.sortable_table_header('next_run_at') %]
- + [%- HTML.escape(background_job.package_name) %]
[%- END %] + [% L.paginate_controls %] +

- [%- LxERP.t8('Create new background job') %] + [%- LxERP.t8('Create new background job') %] | [%- LxERP.t8('View background job history') %] | diff --git a/templates/webpages/background_job_history/list.html b/templates/webpages/background_job_history/list.html index 6086776d1..bf732d44e 100644 --- a/templates/webpages/background_job_history/list.html +++ b/templates/webpages/background_job_history/list.html @@ -1,7 +1,7 @@ [% USE HTML %][% USE L %][% USE LxERP %] -

[% FORM.title %]
+

[% FORM.title %]

[%- INCLUDE 'common/flash.html' %] @@ -49,6 +49,8 @@ [%- END %] + [% L.paginate_controls %] +

diff --git a/templates/webpages/background_job_history/show.html b/templates/webpages/background_job_history/show.html index 0a0584fbc..e9df40060 100644 --- a/templates/webpages/background_job_history/show.html +++ b/templates/webpages/background_job_history/show.html @@ -1,7 +1,7 @@ [% USE HTML %][% USE L %][% USE LxERP %] -

[% FORM.title %]
+

[% FORM.title %]

[%- INCLUDE 'common/flash.html' %] diff --git a/templates/webpages/common/paginate.html b/templates/webpages/common/paginate.html index 8878193f2..089972947 100644 --- a/templates/webpages/common/paginate.html +++ b/templates/webpages/common/paginate.html @@ -1,10 +1,18 @@ [%- USE T8 %] - +[%- 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 %]« [% 'prev' | $T8 %] [% ELSE %]« [% END %] +
+[%- IF pages.cur > 1 %]« [% 'prev' | $T8 %] [% ELSE %]« [% END %] [%- FOR p = pages.common %] [%- NEXT UNLESS p.visible %] - [%- IF p.active %][% p.page %] [% ELSE %][% p.page %] [%- END %] + [%- IF p.active %][% p.page %] [% ELSE %][% p.page %] [%- END %] [%- END %] -[%- IF pages.cur < pages.max %][% 'next' | $T8 %] »[% ELSE %]»[%- END %] +[%- IF pages.cur < pages.max %][% 'next' | $T8 %] »[% ELSE %]»[%- END %] +
[%- END %] diff --git a/templates/webpages/delivery_plan/_list.html b/templates/webpages/delivery_plan/_list.html index f0bb2772b..d0d2159d1 100644 --- a/templates/webpages/delivery_plan/_list.html +++ b/templates/webpages/delivery_plan/_list.html @@ -38,7 +38,7 @@ [%- END %] -

[% PROCESS 'common/paginate.html' pages=SELF.pages, base_url=SELF.url_for(action='list', sort_dir=SELF.sort_dir, sort_by=SELF.sort_by) %]

+ [% 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 %] diff --git a/templates/webpages/delivery_plan/report_bottom.html b/templates/webpages/delivery_plan/report_bottom.html index 3193961d9..1843c054c 100644 --- a/templates/webpages/delivery_plan/report_bottom.html +++ b/templates/webpages/delivery_plan/report_bottom.html @@ -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}) %] -

[% PROCESS 'common/paginate.html' pages=SELF.pages, base_url=SELF.url_for(report_bottom_url_args) %]

+[% PROCESS 'common/paginate.html' pages=SELF.pages, base_url=SELF.url_for(report_bottom_url_args) %]