From: Sven Schöling Date: Wed, 14 Dec 2011 15:30:29 +0000 (+0100) Subject: Merge branch 'master' of vc.linet-services.de:public/lx-office-erp X-Git-Tag: release-2.7.0beta1~127 X-Git-Url: http://wagnertech.de/gitweb/gitweb.cgi/mfinanz.git/commitdiff_plain/df5d9efd810efd8bd01349d22e3fd4f356cc99ac?hp=2828d1565b297bf51e3e06ae8b6baec1817c294d Merge branch 'master' of vc.linet-services.de:public/lx-office-erp --- diff --git a/SL/Controller/Helper/ParseFilter.pm b/SL/Controller/Helper/ParseFilter.pm index 3753d1618..ac086f594 100644 --- a/SL/Controller/Helper/ParseFilter.pm +++ b/SL/Controller/Helper/ParseFilter.pm @@ -36,7 +36,7 @@ sub parse_filter { my $query = _parse_filter($flattened, %params); - _launder_keys($filter) unless $params{no_launder}; + _launder_keys($filter, $params{launder_to}) unless $params{no_launder}; return ($query && @$query ? (query => $query) : ()), @@ -44,23 +44,27 @@ sub parse_filter { } sub _launder_keys { - my ($filter) = @_; + my ($filter, $launder_to) = @_; + $launder_to ||= $filter; return unless ref $filter eq 'HASH'; - my @keys = keys %$filter; - for my $key (@keys) { + for my $key (keys %$filter) { my $orig = $key; $key =~ s/:/_/g; - $filter->{$key} = $filter->{$orig}; - _launder_keys($filter->{$key}); + if ('' eq ref $filter->{$orig}) { + $launder_to->{$key} = $filter->{$orig}; + } elsif ('ARRAY' eq ref $filter->{$orig}) { + $launder_to->{$key} = [ @{ $filter->{$orig} } ]; + } else { + $launder_to->{$key} ||= { }; + _launder_keys($filter->{$key}, $launder_to->{$key}); + } }; - - return $filter; } sub _pre_parse { my ($filter, $with_objects, $prefix, %params) = @_; - return () unless 'HASH' eq ref $filter; + return (undef, $with_objects) unless 'HASH' eq ref $filter; $with_objects ||= []; my @result; @@ -207,18 +211,38 @@ and later The special empty method will be used to set the method for the previous method-less input. -=item Laundering filter +=back + +=head1 LAUNDERING Unfortunately Template cannot parse the postfixes if you want to rerender the filter. For this reason all colons filter keys are by -default laundered into underscores. If you don't want this to happen -pass C<< no_launder => 1 >> as a parameter. A full select_tag then -loks like this: +default laundered into underscores, so you can use them like this: [% L.input_tag('filter.price:number::lt', filter.price_number__lt) %] +All of your original entries will stay intactg. If you don't want this to +happen pass C<< no_launder => 1 >> as a parameter. Additionally you can pass a +different target for the laundered values with the C parameter. It +takes an hashref and will deep copy all values in your filter to the target. So +if you have a filter that looks liek this: -=back + $filter = { + 'price:number::lt' => '2,30', + 'closed => '1', + } + +and parse it with + + parse_filter($filter, launder_to => $laundered_filter = { }) + +the original filter will be unchanged, and C<$laundered_filter> will end up +like this: + + $filter = { + 'price_number__lt' => '2,30', + 'closed => '1', + } =head1 FILTERS (leading with :) diff --git a/SL/Controller/Helper/ReportGenerator.pm b/SL/Controller/Helper/ReportGenerator.pm new file mode 100644 index 000000000..345537529 --- /dev/null +++ b/SL/Controller/Helper/ReportGenerator.pm @@ -0,0 +1,101 @@ +#===================================================================== +# LX-Office ERP +# Copyright (C) 2004 +# Based on SQL-Ledger Version 2.1.9 +# Web http://www.lx-office.org +###################################################################### +# +# Mixin for controllers to use ReportGenerator things +# +###################################################################### + +use strict; + +use List::Util qw(max); + +use SL::Form; +use SL::Common; +use SL::MoreCommon; +use SL::ReportGenerator; + +use Exporter 'import'; +our @EXPORT = qw( + action_report_generator_export_as_pdf action_report_generator_export_as_csv + action_report_generator_back report_generator_do +); + +sub action_report_generator_export_as_pdf { + my ($self) = @_; + if ($::form->{report_generator_pdf_options_set}) { + my $saved_form = save_form(); + + $self->report_generator_do('PDF'); + + if ($::form->{report_generator_printed}) { + restore_form($saved_form); + $::form->{MESSAGE} = $::locale->text('The list has been printed.'); + $self->report_generator_do('HTML'); + } + + return; + } + + my @form_values = $::form->flatten_variables(grep { ($_ ne 'login') && ($_ ne 'password') } keys %{ $::form }); + + $::form->get_lists('printers' => 'ALL_PRINTERS'); + map { $_->{selected} = $::myconfig{default_printer_id} == $_->{id} } @{ $::form->{ALL_PRINTERS} }; + + $::form->{copies} = max $::myconfig{copies} * 1, 1; + $::form->{title} = $::locale->text('PDF export -- options'); + $::form->header; + print $::form->parse_html_template('report_generator/pdf_export_options', { + 'HIDDEN' => \@form_values, + 'ALLOW_FONT_SELECTION' => SL::ReportGenerator->check_for_pdf_api, }); +} + +sub action_report_generator_export_as_csv { + my ($self) = @_; + if ($::form->{report_generator_csv_options_set}) { + $self->report_generator_do('CSV'); + return; + } + + my @form_values = $::form->flatten_variables(grep { ($_ ne 'login') && ($_ ne 'password') } keys %{ $::form }); + + $::form->{title} = $::locale->text('CSV export -- options'); + $::form->header; + print $::form->parse_html_template('report_generator/csv_export_options', { 'HIDDEN' => \@form_values }); +} + +sub action_report_generator_back { + $_[0]->report_generator_do('HTML'); +} + +sub report_generator_set_default_sort { + my ($default_sortorder, $default_sortdir) = @_; + + $::form->{sort} ||= $default_sortorder; + $::form->{sortdir} = $default_sortdir unless (defined $::form->{sortdir}); + $::form->{sortdir} = $::form->{sortdir} ? 1 : 0; +} + +sub report_generator_do { + my ($self, $format) = @_; + + my $nextsub = $::form->{report_generator_nextsub}; + if (!$nextsub) { + $::form->error($::locale->text('report_generator_nextsub is not defined.')); + } + + foreach my $key (split m/ +/, $::form->{report_generator_variable_list}) { + $::form->{$key} = $::form->{"report_generator_hidden_${key}"}; + } + + $::form->{report_generator_output_format} = $format; + + delete @{$::form}{map { "report_generator_$_" } qw(nextsub variable_list)}; + + $self->_run_action($nextsub); +} + +1; diff --git a/SL/DB/Helper/Paginated.pm b/SL/DB/Helper/Paginated.pm new file mode 100644 index 000000000..a24d4d7e0 --- /dev/null +++ b/SL/DB/Helper/Paginated.pm @@ -0,0 +1,151 @@ +package SL::DB::Helper::Paginated; + +use strict; + +require Exporter; +our @ISA = qw(Exporter); +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}); + + $params{args}{page} = $ret->{cur}; + $params{args}{per_page} = $ret->{per_page}; + delete $params{args}{limit}; + delete $params{args}{offset}; + + return $ret; +} + +sub per_page { + my ($self, %params) = @_; + + return $params{per_page} if exists $params{per_page}; + return $self->default_objects_per_page; +} + +sub ceil { + my ($a, $b) = @_; + use integer; + + return 1 unless $b; + return $a / $b + ($a % $b ? 1 : 0); +} + +sub make_common_pages { + my ($cur, $max) = @_; + return [ + map { + active => $_ != $cur, + page => $_, + visible => calc_visibility($cur, $max, $_), + }, 1 .. $max + ]; +} + +sub calc_visibility { + my ($cur, $max, $this) = @_; + any { $_ } abs($cur - $this) < 5, + $this <= 3, + $this == $max, + any { abs ($cur - $this) == $_ } 10, 50, 100, 500, 1000, 5000; +} + +sub disable_paginating { + my ($self, %params) = @_; + + delete $params{args}{page}; + delete $params{args}{per_page}; +} + +1; + +__END__ + +=encoding utf-8 + +=head1 NAME + +SL::Helper::Paginated - Manager mixin for paginating results. + +=head1 SYNOPSIS + +In the manager: + + use SL::Helper::Paginated; + + __PACKAGE__->default_objects_per_page(10); # optional, defaults to 20 + +In the controller: + + my %args = ( + query => [ id => $params{list_of_selected_ids}, + other_attr => $::form->{other_attr}, ], + ); + + $self->{pages} = SL::DB::Manager::MyObject->paginate(args => \%args, page => $::form->{page}); + $self->{objects} = SL::DB::Manager::MyObject->get_all(%args); + +In the template: + + [% PROCESS 'common/paginate.html' + pages=SELF.pages + base_url=L.url_for(action='list', ...) + %] + +=head1 FUNCTIONS + +=over 4 + +=item C args => HREF, page => $page, [ per_page => $per_page ] + +Paginate will prepare information to be used for paginating, change the given +args to use them, and return a data structure containing information for later +display. + +C needs to contain a reference to a hash, which will be used as an +argument for C. After C the keys C and C +will be set. The keys C and C will be unset, should they exist, +since they don't make sense with paginating. + +C should contain a value between 1 and the maximum pages. Will be +sanitized. + +The parameter C is optional. If not given the default value of the +Manager will be used. + +=back + +=head1 TEMPLATE HELPERS + +=over 4 + +=item C pages=SELF.pages, base_url=URL + +The template will render a simple list of links to the +various other pages. A C must be given for the links to work. + +=back + +=head1 BUGS + +None yet. + +=head1 AUTHOR + +Sven Schöling Es.schoeling@linet-services.deE + +=cut diff --git a/SL/DB/OrderItem.pm b/SL/DB/OrderItem.pm index 9e045f74d..6efee0049 100644 --- a/SL/DB/OrderItem.pm +++ b/SL/DB/OrderItem.pm @@ -27,6 +27,11 @@ __PACKAGE__->meta->add_relationship( class => 'SL::DB::Unit', column_map => { unit => 'name' }, }, + order => { + type => 'one to one', + class => 'SL::DB::Order', + column_map => { trans_id => 'id' }, + }, ); # Creates get_all, get_all_count, get_all_iterator, delete_all and update_all. @@ -39,4 +44,26 @@ sub is_price_update_available { return $self->origprice > $self->part->sellprice; } +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' ], + transdate => [ 'transdate', 'lower(order.reqdate::text)' ], + }, + default => [ 'position', 1 ], + nulls => { } + ); +} + +sub default_objects_per_page { 40 } + 1; diff --git a/SL/ReportGenerator.pm b/SL/ReportGenerator.pm index 6b9990180..f81435e71 100644 --- a/SL/ReportGenerator.pm +++ b/SL/ReportGenerator.pm @@ -23,6 +23,7 @@ sub new { $self->{options} = { 'std_column_visibility' => 0, 'output_format' => 'HTML', + 'controller_class ' => '', 'allow_pdf_export' => 1, 'allow_csv_export' => 1, 'html_template' => 'report_generator/html_report', @@ -389,6 +390,7 @@ sub prepare_html_content { 'EXPORT_VARIABLE_LIST' => join(' ', @{ $self->{export}->{variable_list} }), 'EXPORT_NEXTSUB' => $self->{export}->{nextsub}, 'DATA_PRESENT' => $self->{data_present}, + 'CONTROLLER_DISPATCH' => $opts->{controller_class}, }; return $variables; @@ -768,6 +770,10 @@ sub _generate_csv_content { } } +sub check_for_pdf_api { + return eval { require PDF::API2; 1; } ? 1 : 0; +} + 1; __END__ @@ -921,6 +927,12 @@ Used to determine if a button for CSV export should be displayed. Default is yes The template to be used for HTML reports. Default is 'report_generator/html_report'. +=item controller_class + +If this is used from a C based controller class, pass the +class name here and make sure C is +used in the controller. That way the exports stay functional. + =back =head2 PDF Options diff --git a/bin/mozilla/gl.pl b/bin/mozilla/gl.pl index 625490dc8..6ed1e4c44 100644 --- a/bin/mozilla/gl.pl +++ b/bin/mozilla/gl.pl @@ -211,232 +211,27 @@ sub edit { sub search { - $main::lxdebug->enter_sub(); - - $main::auth->assert('general_ledger'); - - my $form = $main::form; - my %myconfig = %main::myconfig; - my $locale = $main::locale; - my $cgi = $::request->{cgi}; - - $form->{title} = $locale->text('Journal'); - - $form->all_departments(\%myconfig); - - # departments - if (@{ $form->{all_departments} || [] }) { - $form->{selectdepartment} = "