]> wagnertech.de Git - mfinanz.git/commitdiff
Merge branch 'master' of vc.linet-services.de:public/lx-office-erp
authorSven Schöling <s.schoeling@linet-services.de>
Thu, 27 Oct 2011 12:39:33 +0000 (14:39 +0200)
committerSven Schöling <s.schoeling@linet-services.de>
Thu, 27 Oct 2011 12:39:33 +0000 (14:39 +0200)
39 files changed:
SL/AM.pm
SL/Auth.pm
SL/CA.pm
SL/Common.pm
SL/Controller/Helper/ParseFilter.pm [new file with mode: 0644]
SL/DATEV.pm
SL/DB/Helper/Sorted.pm
SL/DO.pm
SL/Form.pm
SL/IC.pm
SL/IS.pm
SL/OE.pm
SL/Projects.pm
SL/RecordLinks.pm
SL/ReportGenerator.pm
SL/SEPA.pm
SL/USTVA.pm
SL/WH.pm
bin/mozilla/am.pl
bin/mozilla/ap.pl
bin/mozilla/gl.pl
bin/mozilla/ic.pl
bin/mozilla/io.pl
bin/mozilla/is.pl
bin/mozilla/oe.pl
bin/mozilla/pe.pl
bin/mozilla/rp.pl
bin/mozilla/todo.pl
bin/mozilla/ustva.pl
config/lx_office.conf.default
t/Support/TestSetup.pm [new file with mode: 0644]
t/controllers/helpers/parse_filter.t [new file with mode: 0644]
t/structure/no_lexicals_in_postif.t [new file with mode: 0644]
t/wh/transfer.t [new file with mode: 0644]
templates/webpages/pe/partsgroup_form.html [new file with mode: 0644]
templates/webpages/pe/partsgroup_report.html [new file with mode: 0644]
templates/webpages/pe/pricegroup_form.html [new file with mode: 0644]
templates/webpages/pe/pricegroup_report.html [new file with mode: 0644]
templates/webpages/pe/search.html [new file with mode: 0644]

index ab712c85231331c88e12277e633ab5c3dc619ae7..70f56f92557650dd3704c42360c204625f139dab 100644 (file)
--- a/SL/AM.pm
+++ b/SL/AM.pm
@@ -1333,6 +1333,7 @@ sub retrieve_units {
   $main::lxdebug->enter_sub();
 
   my ($self, $myconfig, $form, $prefix) = @_;
+  $prefix ||= '';
 
   my $dbh = $form->get_standard_dbh;
 
index 7ca8d0bfdd9e002a73f2a000a3f03caf28d4a980..37586b8fffd1ffc3cf0f42b9676becf9533bd0ef 100644 (file)
@@ -512,7 +512,7 @@ sub restore_session {
   my $self = shift;
 
   $session_id        =  $::request->{cgi}->cookie($self->get_session_cookie_name());
-  $session_id        =~ s|[^0-9a-f]||g;
+  $session_id        =~ s|[^0-9a-f]||g if $session_id;
 
   $self->{SESSION}   = { };
 
index c200b664eafa3223d88e46077fc4dec498080bcd..52d2b0bafb7102322e9a12d0083f7144d73bb3fd 100644 (file)
--- a/SL/CA.pm
+++ b/SL/CA.pm
@@ -84,7 +84,7 @@ sub all_accounts {
     $amount{ $ref->{accno} } = $ref->{amount};
   }
 
-  my $where = "AND c.id = $chart_id" if ($chart_id ne '');
+  my $where = $chart_id ne '' ? "AND c.id = $chart_id" : '';
 
   $query = qq{
     SELECT
index c0bca019566e71c3e8757c8bc235631cdd7e45bb..371bb8a7dea1bc5d92ca7e4a2e3a777a56a4f712 100644 (file)
@@ -496,8 +496,8 @@ sub save_email_status {
 
   $intnotes .= "\n\n" if ($intnotes);
 
-  my $cc  = $main::locale->text('Cc') . ": $form->{cc}\n"   if $form->{cc};
-  my $bcc = $main::locale->text('Bcc') . ": $form->{bcc}\n" if $form->{bcc};
+  my $cc  = $form->{cc}  ? $main::locale->text('Cc') . ": $form->{cc}\n"   : '';
+  my $bcc = $form->{bcc} ? $main::locale->text('Bcc') . ": $form->{bcc}\n" : '';
   my $now = scalar localtime;
 
   $intnotes .= $main::locale->text('[email]') . "\n"
diff --git a/SL/Controller/Helper/ParseFilter.pm b/SL/Controller/Helper/ParseFilter.pm
new file mode 100644 (file)
index 0000000..3753d16
--- /dev/null
@@ -0,0 +1,302 @@
+package SL::Controller::Helper::ParseFilter;
+
+use strict;
+
+use Exporter qw(import);
+our @EXPORT = qw(parse_filter);
+
+use DateTime;
+use SL::Helper::DateTime;
+use List::MoreUtils qw(uniq);
+use Data::Dumper;
+
+my %filters = (
+  date    => sub { DateTime->from_lxoffice($_[0]) },
+  number  => sub { $::form->parse_amount(\%::myconfig, $_[0]) },
+  percent => sub { $::form->parse_amount(\%::myconfig, $_[0]) / 100 },
+  head    => sub { $_[0] . '%' },
+  tail    => sub { '%' . $_[0] },
+  substr  => sub { '%' . $_[0] . '%' },
+);
+
+my %methods = (
+  lt     => sub { +{ lt    => $_[0] } },
+  gt     => sub { +{ gt    => $_[0] } },
+  ilike  => sub { +{ ilike => $_[0] } },
+  like   => sub { +{ like  => $_[0] } },
+  enable => sub { ;;;; },
+);
+
+sub parse_filter {
+  my ($filter, %params) = @_;
+
+  my $hint_objects = $params{with_objects} || [];
+
+  my ($flattened, $objects) = _pre_parse($filter, $hint_objects, '', %params);
+
+  my $query = _parse_filter($flattened, %params);
+
+  _launder_keys($filter) unless $params{no_launder};
+
+  return
+    ($query   && @$query   ? (query => $query) : ()),
+    ($objects && @$objects ? ( with_objects => [ uniq @$objects ]) : ());
+}
+
+sub _launder_keys {
+  my ($filter) = @_;
+  return unless ref $filter eq 'HASH';
+  my @keys = keys %$filter;
+  for my $key (@keys) {
+    my $orig = $key;
+    $key =~ s/:/_/g;
+    $filter->{$key} = $filter->{$orig};
+    _launder_keys($filter->{$key});
+  };
+
+  return $filter;
+}
+
+sub _pre_parse {
+  my ($filter, $with_objects, $prefix, %params) = @_;
+
+  return () unless 'HASH'  eq ref $filter;
+  $with_objects ||= [];
+
+  my @result;
+
+  while (my ($key, $value) = each %$filter) {
+    next if !defined $value || $value eq ''; # 0 is fine
+    if ('HASH' eq ref $value) {
+      my ($query, $more_objects) = _pre_parse($value, $with_objects, _prefix($prefix, $key));
+      push @result,        @$query if $query;
+      push @$with_objects, $key, ($more_objects ? @$more_objects : ());
+    } else {
+      push @result, _prefix($prefix, $key) => $value;
+    }
+  }
+
+  return \@result, $with_objects;
+}
+
+sub _parse_filter {
+  my ($flattened, %params) = @_;
+
+  return () unless 'ARRAY' eq ref $flattened;
+
+  my %sorted = ( @$flattened );
+
+  my @keys = sort { length($b) <=> length($a) } keys %sorted;
+  for my $key (@keys) {
+    next unless $key =~ /^(.*\b)::$/;
+    $sorted{$1 . '::' . delete $sorted{$key} } = delete $sorted{$1} if $sorted{$1} && $sorted{$key};
+  }
+
+  my %result;
+  while (my ($key, $value) = each %sorted) {
+    ($key, $value) = _apply_all($key, $value, qr/\b:(\w+)/,  { %filters, %{ $params{filters} || {} } });
+    ($key, $value) = _apply_all($key, $value, qr/\b::(\w+)/, { %methods, %{ $params{methods} || {} } });
+    $result{$key} = $value;
+  }
+  return [ %result ];
+}
+
+sub _prefix {
+  join '.', grep $_, @_;
+}
+
+sub _apply {
+  my ($value, $name, $filters) = @_;
+  return $value unless $name && $filters->{$name};
+  return [ map { _apply($_, $name, $filters) } @$value ] if 'ARRAY' eq ref $value;
+  return $filters->{$name}->($value);
+}
+
+sub _apply_all {
+  my ($key, $value, $re, $subs) = @_;
+
+  while ($key =~ s/$re//) {
+    $value = _apply($value, $1, $subs);
+  }
+
+  return $key, $value;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+SL::Controller::Helper::ParseFilter - Convert a form filter spec into a RDBO get_all filter
+
+=head1 SYNOPSIS
+
+  use SL::Controller::Helper::ParseFilter;
+  SL::DB::Object->get_all(parse_filter($::form->{filter}));
+
+  # or more complex
+  SL::DB::Object->get_all(parse_filter($::form->{filter},
+    with_objects => [ qw(part customer) ]));
+
+=head1 DESCRIPTION
+
+A search filter will usually search for things in relations of the actual
+search target. A search for sales orders may be filtered by the name of the
+customer. L<Rose::DB::Object> alloes you to search for these by filtering them prefixed with their table:
+
+  query => [
+    'customer.name'          => 'John Doe',
+    'department.description' => [ ilike => '%Sales%' ],
+    'orddate'                => [ lt    => DateTime->today ],
+  ]
+
+Unfortunately, if you specify them in you form as these strings, the form
+parser will convert them into nested structures like this:
+
+  $::form = bless {
+    filter => {
+      customer => {
+        name => 'John Doe',
+      },
+    },
+  }, Form;
+
+And the substring match requires you to recognize the ilike, and modify the value.
+
+C<parse_filter> tries to ease this by recognizing these structures and
+providing suffixes for common search patterns.
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item C<parse_filter \%FILTER, [ %PARAMS ]>
+
+First argument is the filter from form. It is highly recommended that you put
+all filter attributes into a named container as to not confuse them with the
+rest of your form.
+
+Nested structures will be parsed and interpreted as foreign references. For
+example if you search for L<Order>s, this input will search for those with a
+specific L<Salesman>:
+
+  [% L.select_tag('filter.salesman.id', ...) %]
+
+Additionally you can add modifier to the name to set a certain method:
+
+  [% L.input_tag('filter.department.description:substr::ilike', ...) %]
+
+This will add the "% .. %" wildcards for substr matching in SQL, and add an
+C<< ilike => $value >> block around it to match case insensitively.
+
+As a rule all value filters require a single colon and must be placed before
+match method suffixes, which are appended with 2 colons. See below for a full
+list of modifiers.
+
+The reason for the method being last is that it is possible to specify the
+method in another input. Suppose you want a date input and a separate
+before/after/equal select, you can use the following:
+
+  [% L.date_tag('filter.appointed_date:date', ... ) %]
+
+and later
+
+  [% L.select_tag('filter.appointed_date::', ... ) %]
+
+The special empty method will be used to set the method for the previous
+method-less input.
+
+=item Laundering filter
+
+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:
+
+  [% L.input_tag('filter.price:number::lt', filter.price_number__lt) %]
+
+
+=back
+
+=head1 FILTERS (leading with :)
+
+The following filters are built in, and can be used.
+
+=over 4
+
+=item date
+
+Parses the input string with C<< DateTime->from_lxoffice >>
+
+=item number
+
+Pasres the input string with C<< Form->parse_amount >>
+
+=item percent
+
+Parses the input string with C<< Form->parse_amount / 100 >>
+
+=item head
+
+Adds "%" at the end of the string.
+
+=item tail
+
+Adds "%" at the end of the string.
+
+=item substr
+
+Adds "% .. %" around the search string.
+
+=back
+
+=head2 METHODS (leading with ::)
+
+=over 4
+
+=item lt
+
+=item gt
+
+=item ilike
+
+=item like
+
+All these are recognized like the L<Rose::DB::Object> methods.
+
+=back
+
+=head1 BUGS AND CAVEATS
+
+This will not properly handle multiple versions of the same object in different
+context.
+
+Suppose you want all L<SL::DB::Order>s which have either themselves a certain
+customer, or are linked to a L<SL::DB::Invoice> with this customer, the
+following will not work as you expect:
+
+  # does not work!
+  L.input_tag('customer.name:substr::ilike', ...)
+  L.input_tag('invoice.customer.name:substr::ilike', ...)
+
+This will sarch for orders whoe invoice has the _same_ customer, which matches
+both inputs. This is because tables are aliased by their name and not by their
+position in with_objects.
+
+=head1 TODO
+
+=over 4
+
+=item *
+
+Additional filters shoud be pluggable.
+
+=back
+
+=head1 AUTHOR
+
+Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
+
+=cut
index 6c6f1c744916d09350e0aed587b114428d07d78b..7f38c88c11fbb3a8e4a8f4fec8182318ec186ccd 100644 (file)
@@ -942,7 +942,7 @@ sub kne_stammdatenexport {
     push @values, $form->{accnoto};
   }
 
-  my $where_str = ' WHERE ' . join(' AND ', map { "($_)" } @where) if (scalar @where);
+  my $where_str = @where ? ' WHERE ' . join(' AND ', map { "($_)" } @where) : '';
 
   my $query     = qq|SELECT c.accno, c.description
                      FROM chart c
index 9442c842e9d820e94e7b45d5c1257b306187ea2b..1b6c42a3cc8c7a7b6013ef10ac88896729cad339 100644 (file)
@@ -47,7 +47,7 @@ sub _get_sort_spec {
 sub _make_sort_spec {
   my ($class) = @_;
 
-  my %sort_spec = $class->_sort_spec if defined &{ "${class}::_sort_spec" };
+  my %sort_spec = defined &{ "${class}::_sort_spec" } ? $class->_sort_spec : ();
 
   my $meta = $class->object_class->meta;
 
index 5b5cf1d1338a89f0638c0d745fa0f1aaf60f9a5c..0d2a5ec21efd109041730f63e45623888a5406e3 100644 (file)
--- a/SL/DO.pm
+++ b/SL/DO.pm
@@ -408,7 +408,7 @@ sub mark_orders_if_delivered {
                                         'to_table'   => 'delivery_orders',
                                         'to_id'      => $params{do_id});
 
-  my ($oe_id)  = $links[0]->{from_id} if (scalar @links);
+  my $oe_id  = @links ? $links[0]->{from_id} : undef;
 
   return $main::lxdebug->leave_sub() if (!$oe_id);
 
index da832f8712aa0266f02055b98d7224bcf2327643..15d66cec9b785564916aa7304ecc661f51a55f88 100644 (file)
@@ -2341,7 +2341,7 @@ sub _get_taxcharts {
     $key = $params;
   }
 
-  my $where = ' WHERE ' . join(' AND ', map { "($_)" } @where) if (@where);
+  my $where = @where ? ' WHERE ' . join(' AND ', map { "($_)" } @where) : '';
 
   my $query = qq|SELECT * FROM tax $where ORDER BY taxkey|;
 
@@ -2456,7 +2456,7 @@ sub _get_customers {
 
   my $options        = ref $key eq 'HASH' ? $key : { key => $key };
   $options->{key}  ||= "all_customers";
-  my $limit_clause   = "LIMIT $options->{limit}" if $options->{limit};
+  my $limit_clause   = $options->{limit} ? "LIMIT $options->{limit}" : '';
 
   my @where;
   push @where, qq|business_id IN (SELECT id FROM business WHERE salesman)| if  $options->{business_is_salesman};
@@ -3665,8 +3665,8 @@ sub prepare_for_printing {
     $extension            = 'xls';
   }
 
-  my $printer_code    = '_' . $self->{printer_code} if $self->{printer_code};
-  my $email_extension = '_email' if -f "$self->{templates}/$self->{formname}_email${language}${printer_code}.${extension}";
+  my $printer_code    = $self->{printer_code} ? '_' . $self->{printer_code} : '';
+  my $email_extension = -f "$::myconfig{templates}/$self->{formname}_email${language}.${extension}" ? '_email' : '';
   $self->{IN}         = "$self->{formname}${email_extension}${language}${printer_code}.${extension}";
 
   # Format dates.
index 82b43cd4c1c6d703f456b8d3dcce4f22873677cb..8fd9281679651cbaf9667b55b1c9ad40041ed659 100644 (file)
--- a/SL/IC.pm
+++ b/SL/IC.pm
@@ -1048,7 +1048,7 @@ sub all_parts {
   my $select_clause = join ', ',    map { $token_builder->($_, 1) } @select_tokens;
   my $join_clause   = join ' ',     @joins{ grep $joins_needed{$_}, @join_order };
   my $where_clause  = join ' AND ', map { "($_)" } @where_tokens;
-  my $group_clause  = ' GROUP BY ' . join ', ',    map { $token_builder->($_) } @group_tokens if scalar @group_tokens;
+  my $group_clause  = @group_tokens ? ' GROUP BY ' . join ', ',    map { $token_builder->($_) } @group_tokens : '';
 
   my %oe_flag_to_cvar = (
     bought   => 'invoice',
index c9a44281d84f0aa95e511e6e108b7078017f9297..3aa0d3ca988b3ff084094eac68067c67346cfc34 100644 (file)
--- a/SL/IS.pm
+++ b/SL/IS.pm
@@ -1440,7 +1440,7 @@ sub retrieve_invoice {
 
   my ($sth, $ref, $query);
 
-  my $query_transdate = ", current_date AS invdate" if !$form->{id};
+  my $query_transdate = !$form->{id} ? ", current_date AS invdate" : '';
 
   $query =
     qq|SELECT
index bfa43f23536a7d522eb2baede844a2c23c65d4f4..969402692a43173f70fd527335a75a4dbdadb6d2 100644 (file)
--- a/SL/OE.pm
+++ b/SL/OE.pm
@@ -190,7 +190,7 @@ SQL
   }
 
   if ($form->{periodic_invoices_active} ne $form->{periodic_invoices_inactive}) {
-    my $not  = 'NOT' if ($form->{periodic_invoices_inactive});
+    my $not  = $form->{periodic_invoices_inactive} ? 'NOT' : '';
     $query  .= qq| AND ${not} COALESCE(pcfg.active, 'f')|;
   }
 
index c25e75ae3264e9babffe251a7c716be8a0727190..d3df51fdd9e1b009519d7c3c46d1cc25fe033e95 100644 (file)
@@ -104,7 +104,7 @@ sub search_projects {
   }
 
 
-  my $where = 'WHERE ' . join(' AND ', map { "($_)" } @filters) if (scalar @filters);
+  my $where = @filters ? 'WHERE ' . join(' AND ', map { "($_)" } @filters) : '';
 
   my $sortorder =  $params{sort} ? $params{sort} : "projectnumber";
   $sortorder    =~ s/[^a-z_]//g;
index cef2c4df0e7aee8e5186a1d8d9601793919e2cb9..da63872d4c62e8847568ebec9e4f4d15dd72e83b 100644 (file)
@@ -193,7 +193,7 @@ sub delete {
     add_token(\@where_tokens, \@where_values, col => $col, val => $params{$col}) if $params{$col};
   }
 
-  my $where = "WHERE ". join ' AND ', map { "($_)" } @where_tokens if scalar @where_tokens;
+  my $where = @where_tokens ? "WHERE ". join ' AND ', map { "($_)" } @where_tokens : '';
   my $query = "DELETE FROM record_links $where";
 
   do_query($form, $dbh, $query, @where_values);
index 441eb159d1b28ba64917e221a6a8c265a9b68e09..6b9990180196438103c5ec677d6f6d0ddf7917ec 100644 (file)
@@ -564,8 +564,8 @@ sub generate_pdf_content {
   my $font_height       = $font_size + 2 * $padding;
   my $title_font_height = $font_size + 2 * $padding;
 
-  my $header_height     = 2 * $title_font_height if ($opts->{title});
-  my $footer_height     = 2 * $font_height       if ($pdfopts->{number});
+  my $header_height     = $opts->{title}     ? 2 * $title_font_height : undef;
+  my $footer_height     = $pdfopts->{number} ? 2 * $font_height       : undef;
 
   my $top_text_height   = 0;
 
index 32e763cdba0edfc64fb226aebb674447e5862bc7..ced75be7e1274e11727231e11e8ae6000b08d25f 100644 (file)
@@ -305,7 +305,7 @@ sub list_exports {
   push @where,  'se.vc = ?';
   push @values, $vc;
 
-  my $where = ' WHERE ' . join(' AND ', map { "(${_})" } @where) if (@where);
+  my $where = @where ? ' WHERE ' . join(' AND ', map { "(${_})" } @where) : '';
 
   my $query =
     qq|SELECT se.id, se.employee_id, se.executed, se.closed, itime::date AS export_date,
index 1cec7447c8c47dea9ea3134273042158f05078d8..abbf4a32c527fe3b54f707ef5ed0f4704d5a65cd 100644 (file)
@@ -113,8 +113,8 @@ sub report_variables {
   my $attribute  = $arg_ref->{attribute}; #
   my $dec_places = (defined $arg_ref->{dec_places}) ? $arg_ref->{dec_places}:undef;
 
-  my $where_type = "AND tax.report_headings.type = '$type'" if ( $type );
-  my $where_dcp  = "AND tax.report_variables.dec_places = '$dec_places'" if ( defined $dec_places );
+  my $where_type = $type ? "AND tax.report_headings.type = '$type'" : '';
+  my $where_dcp  = defined $dec_places ? "AND tax.report_variables.dec_places = '$dec_places'" : '';
 
   my $query = qq|
     SELECT $attribute
index 04b1914e003a29456e96e0f67483552a3d98dfd7..2a5039d298a9eb5ae8306d77cec7da4e15e70791 100644 (file)
--- a/SL/WH.pm
+++ b/SL/WH.pm
@@ -351,7 +351,7 @@ sub get_warehouse_journal {
   $sort_order    = $filter{order}        unless $sort_order;
   my $sort_spec  = "${sort_col} " . ($sort_order ? " DESC" : " ASC");
 
-  my $where_clause = join(" AND ", @filter_ary) . " AND " if (@filter_ary);
+  my $where_clause = @filter_ary ? join(" AND ", @filter_ary) . " AND " : '';
 
   $select_tokens{'trans'} = {
      "parts_id"             => "i1.parts_id",
index 111e14e949cef19524f552c26c0d316ebf21429f..b6996d169b1e34edda36daa47affa331d5e93f0c 100644 (file)
@@ -2051,7 +2051,8 @@ sub show_am_history {
 
   my $dbh = $form->dbconnect(\%myconfig);
 
-  my $restriction  = qq| AND (| . join(' OR ', map { " addition = " . $dbh->quote($_) } split(m/\,/, $form->{einschraenkungen})) . qq|)| if $form->{einschraenkungen};
+  my $restriction;
+  $restriction     = qq| AND (| . join(' OR ', map { " addition = " . $dbh->quote($_) } split(m/\,/, $form->{einschraenkungen})) . qq|)| if $form->{einschraenkungen};
   $restriction    .= qq| AND h.itime::date >= | . conv_dateq($form->{fromdate})                                                          if $form->{fromdate};
   $restriction    .= qq| AND h.itime::date <= | . conv_dateq($form->{todate})                                                            if $form->{todate};
   if ($form->{mitarbeiter} =~ m/^\d+$/) {
index 6d24657f32076985fff167b8ea4370904494cddb..f62294eaa7d2372d25c99464dc30f8cac9b1ab5d 100644 (file)
@@ -285,7 +285,8 @@ sub form_header {
   my $notes =
     qq|<textarea name=notes rows=$rows cols=50 wrap=soft $readonly>$form->{notes}</textarea>|;
 
-  my $department = qq|
+  my $department;
+  $department = qq|
               <tr>
                 <th align="right" nowrap>| . $locale->text('Department') . qq|</th>
                 <td colspan=3><select name=department>$form->{selectdepartment}</select>
index 6ef1ca3e38cac853087a6248fa326e257b1513d9..625490dc86958b6eb7b0eb393ef20dda90d6a692 100644 (file)
@@ -234,7 +234,8 @@ sub search {
     } (@{ $form->{all_departments} || [] });
   }
 
-  my $department = qq|
+  my $department;
+  $department = qq|
         <tr>
           <th align=right nowrap>| . $locale->text('Department') . qq|</th>
           <td colspan=3><select name=department>$form->{selectdepartment}</select></td>
@@ -1017,7 +1018,7 @@ sub display_rows {
     my $projectnumber_hidden = qq|
     <input type="hidden" name="project_id_$i" value="$form->{"project_id_$i"}">|;
 
-    my $copy2credit = 'onkeyup="copy_debit_to_credit()"' if $i == 1;
+    my $copy2credit = $i == 1 ? 'onkeyup="copy_debit_to_credit()"' : '';
 
     print qq|<tr valign=top>
     $accno
@@ -1079,10 +1080,9 @@ sub form_header {
   $form->{title} = $locale->text("$title General Ledger Transaction");
   my $readonly   = ($form->{id}) ? "readonly" : "";
 
-  my $show_details_checked = "checked" if $form->{show_details};
-
-  my $ob_transaction_checked = "checked" if $form->{ob_transaction};
-  my $cb_transaction_checked = "checked" if $form->{cb_transaction};
+  my $show_details_checked   = $form->{show_details}   ? "checked" : '';
+  my $ob_transaction_checked = $form->{ob_transaction} ? "checked" : '';
+  my $cb_transaction_checked = $form->{cb_transaction} ? "checked" : '';
 
   # $locale->text('Add General Ledger Transaction')
   # $locale->text('Edit General Ledger Transaction')
@@ -1410,7 +1410,7 @@ $follow_ups_block
 
   } else {
     if ($form->{draft_id}) {
-      my $remove_draft_checked = 'checked' if ($form->{remove_draft});
+      my $remove_draft_checked = $form->{remove_draft} ? 'checked' : '';
       print qq|<p>\n|
         . qq|  <input name="remove_draft" id="remove_draft" type="checkbox" class="checkbox" ${remove_draft_checked}>|
         . qq|  <label for="remove_draft">| . $locale->text('Remove Draft') . qq|</label>\n|
index 215ec16ab1fdfdfbe33a5ca1b791a3e6209c3a52..a30378123a01bf5370e87ad96aa4e526b420d582 100644 (file)
@@ -1273,7 +1273,7 @@ sub generate_report {
   my %subtotals = map { $_ => 0 } ('onhand', @subtotal_columns);
   my %totals    = map { $_ => 0 } @subtotal_columns;
   my $idx       = 0;
-  my $same_item = $form->{parts}[0]{ $form->{sort} } if (scalar @{ $form->{parts} });
+  my $same_item = @{ $form->{parts} } ? $form->{parts}[0]{ $form->{sort} } : undef;
 
   my $defaults  = AM->get_defaults();
 
index a4e027d6caa5cbe8ceda64aee203699dc28a1af9..2d23c76ae81ac00d2bea184b8746bcb276284777 100644 (file)
@@ -359,7 +359,7 @@ sub display_row {
 # calculate onhand
     if ($form->{"id_$i"}) {
       my $part         = IC->get_basic_part_info(id => $form->{"id_$i"});
-      my $onhand_color = 'color="#ff0000"' if  $part->{onhand} < $part->{rop};
+      my $onhand_color = $part->{onhand} < $part->{rop} ? 'color="#ff0000"' : '';
       push @ROW2, { value => sprintf "<b>%s</b> <font %s>%s %s</font>",
                       $locale->text('On Hand'),
                       $onhand_color,
@@ -1457,7 +1457,7 @@ sub print_form {
     $extension            = 'xls';
   }
 
-  my $email_extension = '_email' if (($form->{media} eq 'email') && (-f "$myconfig{templates}/$form->{formname}_email$form->{language}${printer_code}.${extension}"));
+  my $email_extension = (($form->{media} eq 'email') && (-f "$myconfig{templates}/$form->{formname}_email$form->{language}${printer_code}.${extension}")) ? '_email' : '';
 
   $form->{IN}         = "$form->{formname}${email_extension}$form->{language}${printer_code}.${extension}";
 
index 19f546db3e903ad048b44891af9a6c6b30d3b16f..686de618b3eb748b03a3f40b2ad59871b17a70cc 100644 (file)
@@ -489,7 +489,7 @@ sub update {
   $form->{exchangerate} = $form->parse_amount(\%myconfig, $form->{exchangerate}) unless $recursive_call;
 
   $form->{print_and_post} = 0         if $form->{second_run};
-  my $taxincluded            = "checked" if $form->{taxincluded};
+  my $taxincluded         = $form->{taxincluded} ? "checked" : '';
   $form->{update} = 1;
 
   &check_name("customer");
index 24540eed8d9448212184e8da0960ffaea21efeaf..c9ddfa5be82d09cc502d07654277b1927eba9218 100644 (file)
@@ -1301,7 +1301,10 @@ sub invoice {
     $form->{quodate}      = $form->{transdate};
   }
 
-  my $payment_id = $form->{payment_id} if $form->{payment_id};
+  my $payment_id;
+  if ($form->{payment_id}) {
+    $payment_id = $form->{payment_id};
+  }
 
   # if the name changed get new values
   if (&check_name($form->{vc})) {
index 532dcfac5baf69ceae50091a3e9862ce86f45b71..a9cee792dd558232bd8c741f9a12bb93606a0b6c 100644 (file)
@@ -42,604 +42,183 @@ use strict;
 # end of main
 
 sub add {
-  $main::lxdebug->enter_sub();
+  $::lxdebug->enter_sub;
+  $::auth->assert('config');
 
-  $main::auth->assert('config');
+  $::form->{title} = "Add";
+  $::form->{callback} ||= "$::form->{script}?action=add&type=$::form->{type}";
 
-  my $form     = $main::form;
+  call_sub("form_$::form->{type}");
 
-  $form->{title} = "Add";
-
-  # construct callback
-  $form->{callback} =
-    "$form->{script}?action=add&type=$form->{type}"
-    unless $form->{callback};
-
-  call_sub("form_$form->{type}_header");
-  call_sub("form_$form->{type}_footer");
-
-  $main::lxdebug->leave_sub();
+  $::lxdebug->leave_sub;
 }
 
 sub edit {
-  $main::lxdebug->enter_sub();
+  $::lxdebug->enter_sub;
+  $::auth->assert('config');
 
-  $main::auth->assert('config');
+  $::form->{title} = "Edit";
 
-  my $form     = $main::form;
-  my %myconfig = %main::myconfig;
-
-  # show history button
-  $form->{javascript} = qq|<script type="text/javascript" src="js/show_history.js"></script>|;
-  #/show hhistory button
-  $form->{title} = "Edit";
-
-  if ($form->{type} eq 'partsgroup') {
-    PE->get_partsgroup(\%myconfig, \%$form);
+  if ($::form->{type} eq 'partsgroup') {
+    PE->get_partsgroup(\%::myconfig, $::form);
   }
-  if ($form->{type} eq 'pricegroup') {
-    PE->get_pricegroup(\%myconfig, \%$form);
+  if ($::form->{type} eq 'pricegroup') {
+    PE->get_pricegroup(\%::myconfig, $::form);
   }
-  call_sub("form_$form->{type}_header");
-  call_sub("form_$form->{type}_footer");
+  call_sub("form_$::form->{type}");
 
-  $main::lxdebug->leave_sub();
+  $::lxdebug->leave_sub;
 }
 
 sub search {
-  $main::lxdebug->enter_sub();
-
-  $main::auth->assert('config');
-
-  my $form     = $main::form;
-  my $locale   = $main::locale;
-
-  my ($report, $sort, $number);
-  if ($form->{type} eq 'partsgroup') {
-    $report        = "partsgroup_report";
-    $sort          = 'partsgroup';
-    $form->{title} = $locale->text('Groups');
-
-    $number = qq|
-  <tr>
-    <th align=right width=1%>| . $locale->text('Group') . qq|</th>
-    <td><input name=partsgroup size=20></td>
-  </tr>
-|;
-
-  }
-
-  # for pricesgroups
-  if ($form->{type} eq 'pricegroup') {
-    $report        = "pricegroup_report";
-    $sort          = 'pricegroup';
-    $form->{title} = $locale->text('Pricegroup');
+  $::lxdebug->enter_sub;
+  $::auth->assert('config');
 
-    $number = qq|
-  <tr>
-    <th align=right width=1%>| . $locale->text('Pricegroup') . qq|</th>
-    <td><input name=pricegroup size=20></td>
-  </tr>
-|;
+  $::form->header;
+  print $::form->parse_html_template('pe/search', {
+    is_pricegroup => $::form->{type} eq 'pricegroup',
+  });
 
-  }
-
-  $form->header;
-
-  print qq|
-<body>
-
-<form method=post action=$form->{script}>
-
-<input type=hidden name=sort value=$sort>
-<input type=hidden name=type value=$form->{type}>
-
-<table width=100%>
-  <tr>
-    <th class=listtop>$form->{title}</th>
-  </tr>
-  <tr height="5"></tr>
-  <tr>
-    <td>
-      <table width=100%>
-        $number
-        <tr>
-          <td></td>
-          <td><input name=status class=radio type=radio value=all checked>&nbsp;| . $locale->text('All') . qq|
-          <input name=status class=radio type=radio value=orphaned>&nbsp;| . $locale->text('Orphaned') . qq|</td>
-        </tr>
-      </table>
-    </td>
-  </tr>
-  <tr>
-    <td><hr size=3 noshade></td>
-  </tr>
-</table>
-
-<input type=hidden name=nextsub value=$report>
-
-<br>
-<input class=submit type=submit name=action value="|
-    . $locale->text('Continue') . qq|">
-</form>
-
-</body>
-</html>
-|;
-
-  $main::lxdebug->leave_sub();
+  $::lxdebug->leave_sub;
 }
 
 sub save {
-  $main::lxdebug->enter_sub();
-
-  $main::auth->assert('config');
+  $::lxdebug->enter_sub;
+  $::auth->assert('config');
 
-  my $form     = $main::form;
-  my %myconfig = %main::myconfig;
-  my $locale   = $main::locale;
-
-  if ($form->{type} eq 'partsgroup') {
-    $form->isblank("partsgroup", $locale->text('Group missing!'));
-    PE->save_partsgroup(\%myconfig, \%$form);
-    $form->redirect($locale->text('Group saved!'));
+  if ($::form->{type} eq 'partsgroup') {
+    $::form->isblank("partsgroup", $::locale->text('Group missing!'));
+    PE->save_partsgroup(\%::myconfig, $::form);
+    $::form->redirect($::locale->text('Group saved!'));
   }
 
   # choice pricegroup and save
-  if ($form->{type} eq 'pricegroup') {
-    $form->isblank("pricegroup", $locale->text('Pricegroup missing!'));
-    PE->save_pricegroup(\%myconfig, \%$form);
-    $form->redirect($locale->text('Pricegroup saved!'));
+  if ($::form->{type} eq 'pricegroup') {
+    $::form->isblank("pricegroup", $::locale->text('Pricegroup missing!'));
+    PE->save_pricegroup(\%::myconfig, $::form);
+    $::form->redirect($::locale->text('Pricegroup saved!'));
   }
   # saving the history
-  if(!exists $form->{addition} && $form->{id} ne "") {
-    $form->{snumbers} = qq|projectnumber_| . $form->{projectnumber};
-    $form->{addition} = "SAVED";
-    $form->save_history;
+  if(!exists $::form->{addition} && $::form->{id} ne "") {
+    $::form->{snumbers} = qq|projectnumber_| . $::form->{projectnumber};
+    $::form->{addition} = "SAVED";
+    $::form->save_history;
   }
   # /saving the history
 
-  $main::lxdebug->leave_sub();
+  $::lxdebug->leave_sub;
 }
 
 sub delete {
-  $main::lxdebug->enter_sub();
-
-  $main::auth->assert('config');
-
-  my $form     = $main::form;
-  my %myconfig = %main::myconfig;
-  my $locale   = $main::locale;
+  $::lxdebug->enter_sub;
+  $::auth->assert('config');
 
-  PE->delete_tuple(\%myconfig, \%$form);
+  PE->delete_tuple(\%::myconfig, $::form);
 
-  if ($form->{type} eq 'partsgroup') {
-    $form->redirect($locale->text('Group deleted!'));
+  if ($::form->{type} eq 'partsgroup') {
+    $::form->redirect($::locale->text('Group deleted!'));
   }
-  if ($form->{type} eq 'pricegroup') {
-    $form->redirect($locale->text('Pricegroup deleted!'));
+  if ($::form->{type} eq 'pricegroup') {
+    $::form->redirect($::locale->text('Pricegroup deleted!'));
   }
   # saving the history
-  if(!exists $form->{addition}) {
-    $form->{snumbers} = qq|projectnumber_| . $form->{projectnumber};
-    $form->{addition} = "DELETED";
-    $form->save_history;
+  if(!exists $::form->{addition}) {
+    $::form->{snumbers} = qq|projectnumber_| . $::form->{projectnumber};
+    $::form->{addition} = "DELETED";
+    $::form->save_history;
   }
   # /saving the history
-  $main::lxdebug->leave_sub();
+  $::lxdebug->leave_sub;
 }
 
-sub continue { call_sub($main::form->{"nextsub"}); }
+sub continue { call_sub($::form->{nextsub}); }
 
 sub partsgroup_report {
-  $main::lxdebug->enter_sub();
+  $::lxdebug->enter_sub;
+  $::auth->assert('config');
 
-  $main::auth->assert('config');
+  $::form->{$_} = $::form->unescape($::form->{$_}) for qw(partsgroup);
+  PE->partsgroups(\%::myconfig, $::form);
 
-  my $form     = $main::form;
-  my %myconfig = %main::myconfig;
-  my $locale   = $main::locale;
+  my $callback = build_std_url("action=partsgroup_report", qw(type status));
 
-  map { $form->{$_} = $form->unescape($form->{$_}) } qw(partsgroup);
-  PE->partsgroups(\%myconfig, \%$form);
+  my $option = '';
+  $option .= $::locale->text('All')      if $::form->{status} eq 'all';
+  $option .= $::locale->text('Orphaned') if $::form->{status} eq 'orphaned';
 
-  my $callback =
-    "$form->{script}?action=partsgroup_report&type=$form->{type}&status=$form->{status}";
-
-  my ($option);
-  if ($form->{status} eq 'all') {
-    $option = $locale->text('All');
-  }
-  if ($form->{status} eq 'orphaned') {
-    $option .= $locale->text('Orphaned');
-  }
-  if ($form->{partsgroup}) {
-    $callback .= "&partsgroup=$form->{partsgroup}";
-    $option   .= "\n<br>" . $locale->text('Group') . " : $form->{partsgroup}";
+  if ($::form->{partsgroup}) {
+    $callback .= "&partsgroup=$::form->{partsgroup}";
+    $option   .= ", " . $::locale->text('Group') . " : $::form->{partsgroup}";
   }
 
-  my @column_index = $form->sort_columns(qw(partsgroup));
-  my %column_header;
-  $column_header{partsgroup} =
-    qq|<th class=listheading width=90%>| . $locale->text('Group') . qq|</th>|;
-
-  $form->{title} = $locale->text('Groups');
-
-  $form->header;
-
-  print qq|
-<body>
-
-<table width=100%>
-  <tr>
-    <th class=listtop>$form->{title}</th>
-  </tr>
-  <tr height="5"></tr>
-  <tr>
-    <td>$option</td>
-  </tr>
-  <tr>
-    <td>
-      <table width=100%>
-        <tr class=listheading>
-|;
-
-  map { print "$column_header{$_}\n" } @column_index;
-
-  print qq|
-        </tr>
-|;
-
   # escape callback
-  $form->{callback} = $callback;
-
-  # escape callback for href
-  $callback = $form->escape($callback);
-
-  my ($i, %column_data);
-  foreach my $ref (@{ $form->{item_list} }) {
-
-    $i++;
-    $i %= 2;
-
-    print qq|
-        <tr valign=top class=listrow$i>
-|;
-
-    $column_data{partsgroup} =
-      qq|<td><a href=$form->{script}?action=edit&type=$form->{type}&status=$form->{status}&id=$ref->{id}&callback=$callback>$ref->{partsgroup}</td>|;
-    map { print "$column_data{$_}\n" } @column_index;
-
-    print "
-        </tr>
-";
-  }
-
-  print qq|
-      </table>
-    </td>
-  </tr>
-  <tr>
-    <td><hr size=3 noshade></td>
-  </tr>
-</table>
-
-<br>
-<form method=post action=$form->{script}>
-
-<input name=callback type=hidden value="$form->{callback}">
-
-<input type=hidden name=type value=$form->{type}>
-
-<input class=submit type=submit name=action value="|
-    . $locale->text('Add') . qq|">
+  $::form->{callback} = $callback;
 
-  </form>
+  $::form->header;
+  print $::form->parse_html_template('pe/partsgroup_report', {
+    option   => $option,
+    callback => $callback,
+    editlink => build_std_url('action=edit', qw(type status callback)),
+  });
 
-</body>
-</html>
-|;
-
-  $main::lxdebug->leave_sub();
+  $::lxdebug->leave_sub;
 }
 
-sub form_partsgroup_header {
-  $main::lxdebug->enter_sub();
-
-  $main::auth->assert('config');
-
-  my $form     = $main::form;
-  my $locale   = $main::locale;
-
-  $form->{title} = $locale->text("$form->{title} Group");
+sub form_partsgroup {
+  $::lxdebug->enter_sub;
+  $::auth->assert('config');
 
   # $locale->text('Add Group')
   # $locale->text('Edit Group')
+  $::form->{title} = $::locale->text("$::form->{title} Group");
 
-  $form->{partsgroup} =~ s/\"/&quot;/g;
-
-  $form->header;
-
-  print qq|
-<body>
-
-<form method=post action=$form->{script}>
-
-<input type=hidden name=id value=$form->{id}>
-<input type=hidden name=type value=$form->{type}>
-
-<table width=100%>
-  <tr>
-    <th class=listtop>$form->{title}</th>
-  </tr>
-  <tr height="5"></tr>
-  <tr>
-    <td>
-      <table width=100%>
-        <tr>
-          <th align=right>| . $locale->text('Group') . qq|</th>
-          <td><input name=partsgroup size=30 value="$form->{partsgroup}"></td>
-        </tr>
-      </table>
-    </td>
-  </tr>
-  <tr>
-    <td colspan=2><hr size=3 noshade></td>
-  </tr>
-</table>
-|;
-
-  $main::lxdebug->leave_sub();
-}
+  $::form->header;
+  print $::form->parse_html_template('pe/partsgroup_form');
 
-sub form_partsgroup_footer {
-  $main::lxdebug->enter_sub();
-
-  $main::auth->assert('config');
-
-  my $form     = $main::form;
-  my $locale   = $main::locale;
-
-  print qq|
-
-<input name=callback type=hidden value="$form->{callback}">
-
-<br><input type=submit class=submit name=action value="|
-    . $locale->text('Save') . qq|">
-|;
-
-  if ($form->{id} && $form->{orphaned}) {
-    print qq|
-<input type=submit class=submit name=action value="|
-      . $locale->text('Delete') . qq|">|;
-  }
-
-# button for saving history
-print qq|
-    <input type=button onclick=set_history_window(|
-    . $form->{id}
-    . qq|); name=history id=history value=|
-    . $locale->text('history')
-    . qq|>|;
-# /button for saving history
-  print qq|
-</form>
-
-</body>
-</html>
-|;
-
-  $main::lxdebug->leave_sub();
+  $::lxdebug->leave_sub;
 }
 
-#################################
-# get pricesgroups and build up html-code
-#
 sub pricegroup_report {
-  $main::lxdebug->enter_sub();
+  $::lxdebug->enter_sub;
+  $::auth->assert('config');
 
-  $main::auth->assert('config');
+  $::form->{$_} = $::form->unescape($::form->{$_}) for qw(pricegroup);
+  PE->pricegroups(\%::myconfig, $::form);
 
-  my $form     = $main::form;
-  my %myconfig = %main::myconfig;
-  my $locale   = $main::locale;
+  my $callback = build_std_url('action=pricegroup_report', qw(type status));
 
-  map { $form->{$_} = $form->unescape($form->{$_}) } qw(pricegroup);
-  PE->pricegroups(\%myconfig, \%$form);
+  my $option = '';
+  $option .= $::locale->text('All')      if $::form->{status} eq 'all';
+  $option .= $::locale->text('Orphaned') if $::form->{status} eq 'orphaned';
 
-  my $callback =
-    "$form->{script}?action=pricegroup_report&type=$form->{type}&status=$form->{status}";
-
-  my $option;
-  if ($form->{status} eq 'all') {
-    $option = $locale->text('All');
-  }
-  if ($form->{status} eq 'orphaned') {
-    $option .= $locale->text('Orphaned');
+  if ($::form->{pricegroup}) {
+    $callback .= "&pricegroup=$::form->{pricegroup}";
+    $option   .= ", " . $::locale->text('Pricegroup') . " : $::form->{pricegroup}";
   }
-  if ($form->{pricegroup}) {
-    $callback .= "&pricegroup=$form->{pricegroup}";
-    $option   .=
-      "\n<br>" . $locale->text('Pricegroup') . " : $form->{pricegroup}";
-  }
-
-  my @column_index = $form->sort_columns(qw(pricegroup));
-  my %column_header;
-  $column_header{pricegroup} =
-      qq|<th class=listheading width=90%>|
-    . $locale->text('Pricegroup')
-    . qq|</th>|;
-
-  $form->{title} = $locale->text('Pricegroup');
-
-  $form->header;
-
-  print qq|
-<body>
-
-<table width=100%>
-  <tr>
-    <th class=listtop>$form->{title}</th>
-  </tr>
-  <tr height="5"></tr>
-  <tr>
-    <td>$option</td>
-  </tr>
-  <tr>
-    <td>
-      <table width=100%>
-        <tr class=listheading>
-|;
-
-  map { print "$column_header{$_}\n" } @column_index;
-
-  print qq|
-        </tr>
-|;
 
   # escape callback
-  $form->{callback} = $callback;
-
-  # escape callback for href
-  $callback = $form->escape($callback);
-
-  my ($i, %column_data);
-  foreach my $ref (@{ $form->{item_list} }) {
-
-    $i++;
-    $i %= 2;
+  $::form->{callback} = $callback;
 
-    print qq|
-        <tr valign=top class=listrow$i>
-|;
-    $column_data{pricegroup} =
-      qq|<td><a href=$form->{script}?action=edit&type=$form->{type}&status=$form->{status}&id=$ref->{id}&callback=$callback>$ref->{pricegroup}</td>|;
+  $::form->header;
+  print $::form->parse_html_template('pe/pricegroup_report', {
+    option   => $option,
+    callback => $callback,
+    editlink => build_std_url('action=edit', qw(type status callback)),
+  });
 
-    map { print "$column_data{$_}\n" } @column_index;
-
-    print "
-        </tr>
-";
-  }
-
-  print qq|
-      </table>
-    </td>
-  </tr>
-  <tr>
-    <td><hr size=3 noshade></td>
-  </tr>
-</table>
-
-<br>
-<form method=post action=$form->{script}>
-
-<input name=callback type=hidden value="$form->{callback}">
-
-<input type=hidden name=type value=$form->{type}>
-
-<input class=submit type=submit name=action value="|
-    . $locale->text('Add') . qq|">
-
-  </form>
-
-</body>
-</html>
-|;
-
-  $main::lxdebug->leave_sub();
+  $::lxdebug->leave_sub;
 }
 
-#######################
-#build up pricegroup_header
-#
-sub form_pricegroup_header {
-  $main::lxdebug->enter_sub();
-
-  $main::auth->assert('config');
-
-  my $form     = $main::form;
-  my $locale   = $main::locale;
+sub form_pricegroup {
+  $::lxdebug->enter_sub;
+  $::auth->assert('config');
 
   # $locale->text('Add Pricegroup')
   # $locale->text('Edit Pricegroup')
+  $::form->{title} = $::locale->text("$::form->{title} Pricegroup");
 
-  $form->{title} = $locale->text("$form->{title} Pricegroup");
-
-  $form->{pricegroup} =~ s/\"/&quot;/g;
-
-  $form->header;
-
-  print qq|
-<body>
-
-<form method=post action=$form->{script}>
-
-<input type=hidden name=id value=$form->{id}>
-<input type=hidden name=type value=$form->{type}>
-
-<table width=100%>
-  <tr>
-    <th class=listtop>$form->{title}</th>
-  </tr>
-  <tr height="5"></tr>
-  <tr>
-    <td>
-      <table width=100%>
-        <tr>
-          <th align=right>| . $locale->text('Preisgruppe') . qq|</th>
-          <td><input name=pricegroup size=30 value="$form->{pricegroup}"></td>
-        </tr>
-      </table>
-    </td>
-  </tr>
-  <tr>
-    <td colspan=2><hr size=3 noshade></td>
-  </tr>
-</table>
-|;
-
-  $main::lxdebug->leave_sub();
-}
-######################
-#build up pricegroup_footer
-#
-sub form_pricegroup_footer {
-  $main::lxdebug->enter_sub();
-
-  $main::auth->assert('config');
-
-  my $form     = $main::form;
-  my $locale   = $main::locale;
-
-  print qq|
-
-<input name=callback type=hidden value="$form->{callback}">
-
-<br><input type=submit class=submit name=action value="|
-    . $locale->text('Save') . qq|">
-|;
-
-  if ($form->{id} && $form->{orphaned}) {
-    print qq|
-<input type=submit class=submit name=action value="|
-      . $locale->text('Delete') . qq|">|;
-  }
+  $::form->header;
+  print $::form->parse_html_template('pe/pricegroup_form');
 
-# button for saving history
-print qq|
-    <input type=button onclick=set_history_window(|
-    . $form->{id}
-    . qq|); name=history id=history value=|
-    . $locale->text('history')
-    . qq|>|;
-# /button for saving history
-  print qq|
-</form>
-
-</body>
-</html>
-|;
-
-  $main::lxdebug->leave_sub();
+  $::lxdebug->leave_sub;
 }
index 062c44f4e03cad5123033940e0a26a56d37331bd..dc1b153843e80c9f075b12bf72c28afb9ea6f36e 100644 (file)
@@ -158,7 +158,8 @@ sub report {
     map { $form->{selectdepartment} .= "<option>$_->{description}--$_->{id}\n" } @{ $form->{all_departments} || [] };
   }
 
-  my $department = qq|
+  my $department;
+  $department = qq|
         <tr>
           <th align=right nowrap>| . $locale->text('Department') . qq|</th>
           <td colspan=3><select name=department>$form->{selectdepartment}</select></td>
index db482fa21d61170111e3d105fe8a11248f83d157..c50d44d5ecc84f678933ecafffba00058225be0a 100644 (file)
@@ -37,7 +37,7 @@ sub create_todo_list {
   my $form     = $main::form;
 
   my %params   = @_;
-  my $postfix  = '_login' if ($params{login_screen});
+  my $postfix  = $params{login_screen} ? '_login' : '';
 
   my %todo_cfg = TODO->get_user_config('login' => $form->{login});
 
index 7aa371fbfc91adf9a987a0e79a427c4316b742b9..c455740be8e37d21ed6d8fb90365898f70595c73 100644 (file)
@@ -1107,13 +1107,13 @@ $::form->{title} = $::locale->text('Tax Office Preferences');
   $::form->{title} = $::locale->text('Tax Office Preferences');
 
 
-  my $select_tax_office = $ustva->fa_auswahl($land, $amt, $ustva->query_finanzamt(\%::myconfig, $::form));
-  my $checked_accrual = q|checked="checked"| if ($::form->{method} eq 'accrual');
-  my $checked_cash = q|checked="checked"| if ($::form->{method} eq 'cash');
-  my $checked_monthly = "checked" if ($::form->{FA_voranmeld} eq 'month');
-  my $checked_quarterly = "checked" if ($::form->{FA_voranmeld} eq 'quarter');
-  my $checked_dauerfristverlaengerung = "checked" if ($::form->{FA_dauerfrist} eq '1');
-  my $checked_kz_71 = "checked" if ($::form->{FA_71} eq 'X');
+  my $select_tax_office               = $ustva->fa_auswahl($land, $amt, $ustva->query_finanzamt(\%::myconfig, $::form));
+  my $checked_accrual                 = $::form->{method}        eq 'accrual' ? q|checked="checked"| : '';
+  my $checked_cash                    = $::form->{method}        eq 'cash'    ? q|checked="checked"| : '';
+  my $checked_monthly                 = $::form->{FA_voranmeld}  eq 'month'   ? "checked"            : '';
+  my $checked_quarterly               = $::form->{FA_voranmeld}  eq 'quarter' ? "checked"            : '';
+  my $checked_dauerfristverlaengerung = $::form->{FA_dauerfrist} eq '1'       ? "checked"            : '';
+  my $checked_kz_71                   = $::form->{FA_71}         eq 'X'       ? "checked"            : '';
 
   my $_hidden_variables_ref;
 
@@ -1255,7 +1255,7 @@ sub config_step2 {
   my $patterncount   = $form->{patterncount};
   my $elster_pattern = $form->{elster_pattern};
   my $delimiter      = $form->{delimiter};
-  my $steuernummer = $form->{steuernummer} if ($stnr eq '');
+  my $steuernummer   = $stnr eq '' ? $form->{steuernummer} : '';
 
   $form->{FA_Oeffnungszeiten} =~ s/\\\\n/\n/g;
 
index b0c3e66e5bf6199be4d8c162fe144e309d27782f..d84b1c951e83c549c94cc79c3b69f3cdea0e1a26 100644 (file)
@@ -178,6 +178,11 @@ history_file = users/console_history
 # to the lx-office log will be put here if triggered from the console
 log_file = /tmp/lxoffice_console_debug.log
 
+[testing]
+
+# autologin to use if none is given
+login = demo
+
 [debug]
 # Use DBIx::Log4perl for logging DBI calls. The string LXDEBUGFILE
 # will be replaced by the file name configured for $::lxdebug.
diff --git a/t/Support/TestSetup.pm b/t/Support/TestSetup.pm
new file mode 100644 (file)
index 0000000..c23b4fd
--- /dev/null
@@ -0,0 +1,52 @@
+package Support::TestSetup;
+
+use strict;
+
+use Data::Dumper;
+use CGI qw( -no_xhtml);
+use SL::Auth;
+use SL::Form;
+use SL::Locale;
+use SL::LXDebug;
+use Data::Dumper;
+use SL::LxOfficeConf;
+use SL::InstanceConfiguration;
+SL::LxOfficeConf->read;
+
+sub _login {
+  my $login = shift;
+
+  die 'need login' unless $login;
+
+  package main;
+
+  $::lxdebug       = LXDebug->new(file => \*STDERR);
+  $::locale        = Locale->new($::lx_office_conf{system}->{language});
+  $::form          = Form->new;
+  $::auth          = SL::Auth->new;
+  $::instance_conf = SL::InstanceConfiguration->new;
+  $::request       = { cgi => CGI->new({}) };
+
+  die 'cannot reach auth db'               unless $::auth->session_tables_present;
+
+  $::auth->restore_session;
+
+  require "bin/mozilla/common.pl";
+
+  die "cannot find user $login"            unless %::myconfig = $::auth->read_user($login);
+
+  $::form->{login} = $login; # normaly implicit at login
+
+  die "cannot find locale for user $login" unless $::locale   = Locale->new($::myconfig{countrycode});
+
+  $::instance_conf->init;
+
+  return 1;
+}
+
+sub login {
+  my $login        = shift || $::lx_office_conf{testing}{login}        || 'demo';
+  _login($login);
+}
+
+1;
diff --git a/t/controllers/helpers/parse_filter.t b/t/controllers/helpers/parse_filter.t
new file mode 100644 (file)
index 0000000..84547e0
--- /dev/null
@@ -0,0 +1,128 @@
+use lib 't';
+
+use Test::More tests => 13;
+use Test::Deep;
+use Data::Dumper;
+
+use_ok 'Support::TestSetup';
+use_ok 'SL::Controller::Helper::ParseFilter';
+
+undef *::any; # Test::Deep exports any (for junctions) and MoreCommon exports any (like in List::Moreutils)
+
+Support::TestSetup::login();
+my ($filter, $expected);
+
+sub test ($$$) {
+  my $got = { parse_filter($_[0]) };
+  cmp_deeply(
+    $got,
+    $_[1],
+    $_[2]
+  ) or do {
+    print STDERR "expected => ", Dumper($_[1]), "\ngot: => ", Dumper($got), $/;
+  }
+}
+
+test { }, {
+}, 'minimal test';
+
+test {
+  name => 'Test',
+  whut => 'moof',
+}, {
+  query => [ %{{
+    name => 'Test',
+    whut => 'moof'
+  }} ],
+}, 'basic test';
+
+test {
+  customer => {
+    name => 'rainer',
+  }
+}, {
+  query => [ 'customer.name' => 'rainer' ],
+  with_objects => [ 'customer' ],
+}, 'joining customers';
+
+test {
+  customer => {
+    chart => {
+      accno => 'test',
+    }
+  }
+}, {
+  query => [ 'customer.chart.accno' => 'test' ],
+  with_objects => bag( 'customer', 'chart' ),
+}, 'nested joins';
+
+test {
+  'customer:substr' => 'Meyer'
+}, {
+  query => [ customer => '%Meyer%' ]
+}, 'simple filter substr';
+
+test {
+  'customer::ilike' => 'Meyer'
+}, {
+  query => [ customer => { ilike => 'Meyer' } ]
+}, 'simple method ilike';
+
+test {
+  customer => {
+    chart => {
+      'accno:tail::like' => '1200'
+    }
+  },
+},
+{
+  query => [ 'customer.chart.accno' => { like => '%1200' } ],
+  with_objects => bag('customer', 'chart' ),
+}, 'all together';
+
+
+test {
+  customer => {
+    name => 'test',
+  },
+  invoice => {
+    customer => {
+      name => 'test',
+    },
+  },
+}, {
+  'query' => [ %{{
+               'invoice.customer.name'  => 'test',
+               'customer.name'          => 'test',
+             }} ],
+  'with_objects' => bag( 'invoice', 'customer' )
+}, 'object in more than one relationship';
+
+test {
+  'orddate:date::' => 'lt',
+  'orddate:date' => '20.3.2010',
+}, {
+    'query' => [
+                 'orddate' => { 'lt' => isa('DateTime') }
+               ]
+
+}, 'method dispatch and date constructor';
+
+test {
+  id => [
+    123, 125, 157
+  ]
+}, {
+  query => [ id => [ 123,125,157 ] ],
+}, 'arrays as value';
+
+test {
+  'sellprice:number' => [
+    '123,4', '2,34', '0,4',
+  ]
+}, {
+  query => [
+    sellprice => [ 123.4, 2.34, 0.4 ],
+  ],
+}, 'arrays with filter';
+
diff --git a/t/structure/no_lexicals_in_postif.t b/t/structure/no_lexicals_in_postif.t
new file mode 100644 (file)
index 0000000..3f90693
--- /dev/null
@@ -0,0 +1,65 @@
+use strict;
+use lib 't';
+use Support::Files;
+use Test::More;
+
+if (eval { require PPI; 1 }) {
+  plan tests => scalar(@Support::Files::testitems);
+} else {
+  plan skip_all => "PPI not installed";
+}
+
+my $fh;
+{
+    local $^W = 0;  # Don't complain about non-existent filehandles
+    if (-e \*Test::More::TESTOUT) {
+        $fh = \*Test::More::TESTOUT;
+    } elsif (-e \*Test::Builder::TESTOUT) {
+        $fh = \*Test::Builder::TESTOUT;
+    } else {
+        $fh = \*STDOUT;
+    }
+}
+
+my @testitems = @Support::Files::testitems;
+
+foreach my $file (@testitems) {
+  my $clean = 1;
+  my $source;
+  {
+    # due to a bug in PPI it cannot determine the encoding of a source file by
+    # use utf8; normaly this would be no problem but some people instist on
+    # putting strange stuff into the source. as a workaround read in the source
+    # with :utf8 layer and pass it to PPI by reference
+    # there are still some latin chars, but it's not the purpose of this test
+    # to find them, so warnings about it will be ignored
+    local $^W = 0; # don't care about invalid chars in comments
+    local $/ = undef;
+    open my $fh, '<:utf8', $file or die $!;
+    $source = <$fh>;
+  }
+
+  my $doc = PPI::Document->new(\$source) or do {
+    print $fh "?: PPI error for file $file: " . PPI::Document::errstr() . "\n";
+    ok 0, $file;
+    next;
+  };
+  my $stmts = $doc->find('Statement::Variable');
+
+  for my $var (@{ $stmts || [] }) {
+    # local can have valid uses like this, and our is extremely uncommon
+    next unless $var->type eq 'my';
+
+    # no if? alright
+    next unless $var->find(sub { $_[1]->content eq 'if' });
+
+    # token "if" is not in the top level struvture - no problem
+    # most likely an anonymous sub or a complicated map/grep/reduce
+    next unless grep { $_->content eq 'if'  } $var->schildren;
+
+    $clean = 0;
+    print $fh "?: $var \n";
+  }
+
+  ok $clean, $file;
+}
diff --git a/t/wh/transfer.t b/t/wh/transfer.t
new file mode 100644 (file)
index 0000000..36ec0fe
--- /dev/null
@@ -0,0 +1,77 @@
+use strict;
+use Test::More;
+
+use lib 't';
+
+use_ok 'Support::TestSetup';
+use_ok 'SL::DB::Part';
+use_ok 'SL::DB::Warehouse';
+use_ok 'SL::WH';
+
+Support::TestSetup::login();
+
+my $part = SL::DB::Manager::Part->get_first;
+is(ref $part, 'SL::DB::Part', 'loading a part to test with id ' . $part->id);
+
+my $wh = SL::DB::Manager::Warehouse->get_first;
+is(ref $wh, 'SL::DB::Warehouse', 'loading a warehouse to test with id ' . $wh->id);
+
+my $bin1 = $wh->bins->[0];
+is(ref $bin1, 'SL::DB::Bin', 'getting first bin to test with id ' . $bin1->id);
+
+my $bin2 = $wh->bins->[1];
+is(ref $bin2, 'SL::DB::Bin', 'getting another bin to test with id ' . $bin2->id);
+
+my $report = sub {
+  $::form->{l_warehouseid} = 'Y';
+  $::form->{l_binid} = 'Y';
+  my ($result) = WH->get_warehouse_report(
+    warehouse_id => $wh->id,
+    bin_id       => $bin1->id,
+    partsid      => $part->id,
+    chargenumber => '',
+  );
+  $result->{qty} ||= 0;
+  return $result;
+};
+
+my $r1 = $report->();
+
+WH->transfer({
+   transfer_type    => 'transfer',
+   parts_id         => $part->id,
+   src_warehouse_id => $wh->id,
+   dst_warehouse_id => $wh->id,
+   src_bin_id       => $bin1->id,
+   dst_bin_id       => $bin2->id,
+   qty              => 4,
+   chargenumber     => '',
+});
+
+my $r2 = $report->();
+
+is $r1->{qty}, $r2->{qty} + 4, 'transfer one way';
+
+WH->transfer({
+   transfer_type    => 'transfer',
+   parts_id         => $part->id,
+   src_warehouse_id => $wh->id,
+   dst_warehouse_id => $wh->id,
+   src_bin_id       => $bin2->id,
+   dst_bin_id       => $bin1->id,
+   qty              => 4,
+   chargenumber     => '',
+});
+
+
+my $r3 = $report->();
+
+is $r2->{qty}, $r3->{qty} - 4, 'and back';
+
+done_testing;
+
+
+
+
+
+1;
diff --git a/templates/webpages/pe/partsgroup_form.html b/templates/webpages/pe/partsgroup_form.html
new file mode 100644 (file)
index 0000000..99ea233
--- /dev/null
@@ -0,0 +1,44 @@
+[%- USE L %]
+[%- USE T8 %]
+[%- USE HTML %]
+[% L.javascript_tag('show_history.js') %]
+<body>
+
+<form method=post action="[% script %]">
+
+<input type=hidden name=id value="[% id %]">
+<input type=hidden name=type value="[% type %]">
+
+<table width=100%>
+  <tr>
+    <th class=listtop>[% title %]</th>
+  </tr>
+  <tr height="5"></tr>
+  <tr>
+    <td>
+      <table width=100%>
+        <tr>
+          <th align=right>[% 'Group' | $T8 %]</th>
+          <td><input name=partsgroup size=30 value="[% partsgroup | html %]"></td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr>
+    <td colspan=2><hr size=3 noshade></td>
+  </tr>
+</table>
+
+<br>
+
+<input name=callback type=hidden value="[% callback | html %]">
+<input type=submit class=submit name=action value="[% 'Save' | $T8 %]">
+[%- IF id && orphaned %]
+<input type=submit class=submit name=action value="[% 'Delete' | $T8 %]">
+[%- END %]
+
+<input type=button onclick="set_history_window([% id %]);" name=history id=history value="[% 'history' | $T8 %]">
+</form>
+
+</body>
+</html>
diff --git a/templates/webpages/pe/partsgroup_report.html b/templates/webpages/pe/partsgroup_report.html
new file mode 100644 (file)
index 0000000..c66bb49
--- /dev/null
@@ -0,0 +1,41 @@
+[%- USE HTML %]
+[%- USE T8 %]
+<body>
+
+<table width=100%>
+  <tr>
+    <th class=listtop>[% 'Groups' | $T8 %]</th>
+  </tr>
+  <tr height="5"></tr>
+  <tr>
+    <td>[% option %]</td>
+  </tr>
+  <tr>
+    <td>
+      <table width=100%>
+        <tr class=listheading>
+          <th class=listheading width=90%>[% 'Group' | $T8 %]</th>
+        </tr>
+[%- FOREACH row = item_list %]
+        <tr valign=top class="listrow[% loop.count % 2 %]">
+          <td><a href="[% editlink %]&id=[% row.id %]">[% row.partsgroup %]</a></td>
+        </tr>
+[%- END %]
+      </table>
+    </td>
+  </tr>
+  <tr>
+    <td><hr size=3 noshade></td>
+  </tr>
+</table>
+
+<br>
+<form method=post action="[% script %]">
+  <input name=callback type=hidden value="[% callback | html %]">
+  <input type=hidden name=type value="[% type %]">
+  <input class=submit type=submit name=action value="[% 'Add' | $T8 %]">
+</form>
+
+</body>
+</html>
+
diff --git a/templates/webpages/pe/pricegroup_form.html b/templates/webpages/pe/pricegroup_form.html
new file mode 100644 (file)
index 0000000..d1b022d
--- /dev/null
@@ -0,0 +1,44 @@
+[%- USE L %]
+[%- USE T8 %]
+[%- USE HTML %]
+[% L.javascript_tag('show_history.js') %]
+<body>
+
+<form method=post action="[% script %]">
+
+<input type=hidden name=id value="[% id %]"
+<input type=hidden name=type value="[% type %]">
+
+<table width=100%>
+  <tr>
+    <th class=listtop>[% title %]</th>
+  </tr>
+  <tr height="5"></tr>
+  <tr>
+    <td>
+      <table width=100%>
+        <tr>
+          <th align=right>[% 'Pricegroup' | $T8 %]</th>
+          <td><input name=pricegroup size=30 value="[% pricegroup | html %]"></td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr>
+    <td colspan=2><hr size=3 noshade></td>
+  </tr>
+</table>
+
+<br>
+
+<input name=callback type=hidden value="[% callback | html %]">
+<input type=submit class=submit name=action value="[% 'Save' | $T8 %]">
+[%- IF id && orphaned %]
+<input type=submit class=submit name=action value="[% 'Delete' | $T8 %]">
+[%- END %]
+
+<input type=button onclick="set_history_window([% id %]);" name=history id=history value="[% 'history' | $T8 %]">
+</form>
+
+</body>
+</html>
diff --git a/templates/webpages/pe/pricegroup_report.html b/templates/webpages/pe/pricegroup_report.html
new file mode 100644 (file)
index 0000000..c205a1b
--- /dev/null
@@ -0,0 +1,41 @@
+[%- USE HTML %]
+[%- USE T8 %]
+<body>
+
+<table width=100%>
+  <tr>
+    <th class=listtop>[% 'Pricegroup' | $T8 %]</th>
+  </tr>
+  <tr height="5"></tr>
+  <tr>
+    <td>[% option %]</td>
+  </tr>
+  <tr>
+    <td>
+      <table width=100%>
+        <tr class=listheading>
+          <th class=listheading width=90%>[% 'Pricegroup' | $T8 %]</th>
+        </tr>
+[%- FOREACH row = item_list %]
+        <tr valign=top class="listrow[% loop.count % 2 %]">
+          <td><a href="[% editlink %]&id=[% row.id %]">[% row.pricegroup %]</a></td>
+        </tr>
+[%- END %]
+      </table>
+    </td>
+  </tr>
+  <tr>
+    <td><hr size=3 noshade></td>
+  </tr>
+</table>
+
+<br>
+<form method=post action="[% script %]">
+  <input name=callback type=hidden value="[% callback | html %]">
+  <input type=hidden name=type value="[% type %]">
+  <input class=submit type=submit name=action value="[% 'Add' | $T8 %]">
+</form>
+
+</body>
+</html>
+
diff --git a/templates/webpages/pe/search.html b/templates/webpages/pe/search.html
new file mode 100644 (file)
index 0000000..6ea5be4
--- /dev/null
@@ -0,0 +1,48 @@
+[%- USE T8 %]
+[%- USE LxERP %]
+<body>
+
+<form method=post action="[% script %]">
+
+<input type=hidden name=sort value="[% is_pricegroup ? 'pricegroup' : 'partsgroup' %]">
+<input type=hidden name=type value="[% type %]">
+
+<table width=100%>
+  <tr>
+    <th class=listtop>[% is_pricegroup ? LxERP.t8('Pricegroup') : LxERP.t8('Groups') %]</th>
+  </tr>
+  <tr height="5"></tr>
+  <tr>
+    <td>
+      <table width=100%>
+        <tr>
+[%- IF is_pricegroup %]
+          <th align=right width=1%>[% 'Pricegroup' | $T8 %]</th>
+          <td><input name=pricegroup size=20></td>
+[%- ELSE %]
+          <th align=right width=1%>[% 'Group' | $T8 %]</th>
+          <td><input name=partsgroup size=20></td>
+[%- END %]
+        </tr>
+        <tr>
+          <td></td>
+          <td><input name=status class=radio type=radio value=all checked> [% 'All' | $T8 %]
+              <input name=status class=radio type=radio value=orphaned> [% 'Orphaned' | $T8 %]</td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr>
+    <td><hr size=3 noshade></td>
+  </tr>
+</table>
+
+<input type=hidden name=nextsub value="[% is_pricegroup ? 'pricegroup_report' : 'partsgroup_report' %]">
+
+<br>
+<input class=submit type=submit name=action value="[% 'Continue' | $T8 %]">
+</form>
+
+</body>
+</html>
+