Projektverwaltung auf Rose- und Controller-Code umgestellt
authorMoritz Bunkus <m.bunkus@linet-services.de>
Thu, 24 Jan 2013 11:35:38 +0000 (12:35 +0100)
committerMoritz Bunkus <m.bunkus@linet-services.de>
Thu, 24 Jan 2013 12:03:54 +0000 (13:03 +0100)
16 files changed:
SL/Controller/Project.pm [new file with mode: 0644]
SL/DB/Manager/Project.pm [new file with mode: 0644]
SL/DB/Project.pm
SL/Projects.pm [deleted file]
bin/mozilla/arap.pl
bin/mozilla/projects.pl [deleted file]
bin/mozilla/rp.pl
locale/de/all
menu.ini
projects.pl [deleted symlink]
templates/webpages/project/form.html [new file with mode: 0644]
templates/webpages/project/report_bottom.html [new file with mode: 0644]
templates/webpages/project/search.html [new file with mode: 0644]
templates/webpages/projects/project_form.html [deleted file]
templates/webpages/projects/search.html [deleted file]
templates/webpages/rp/report.html

diff --git a/SL/Controller/Project.pm b/SL/Controller/Project.pm
new file mode 100644 (file)
index 0000000..fa42007
--- /dev/null
@@ -0,0 +1,290 @@
+package SL::Controller::Project;
+
+use strict;
+
+use parent qw(SL::Controller::Base);
+
+use Clone qw(clone);
+
+use SL::Controller::Helper::GetModels;
+use SL::Controller::Helper::Paginated;
+use SL::Controller::Helper::Sorted;
+use SL::Controller::Helper::ParseFilter;
+use SL::Controller::Helper::ReportGenerator;
+use SL::CVar;
+use SL::DB::Customer;
+use SL::DB::Project;
+use SL::Helper::Flash;
+use SL::Locale::String;
+
+use Rose::Object::MakeMethods::Generic
+(
+ scalar => [ qw(project db_args flat_filter) ],
+);
+
+__PACKAGE__->run_before('check_auth');
+__PACKAGE__->run_before('load_project', only => [ qw(edit update destroy) ]);
+
+__PACKAGE__->get_models_url_params('flat_filter');
+__PACKAGE__->make_paginated(
+  MODEL         => 'Project',
+  PAGINATE_ARGS => 'db_args',
+  ONLY          => [ qw(list) ],
+);
+
+__PACKAGE__->make_sorted(
+  MODEL         => 'Project',
+  ONLY          => [ qw(list) ],
+
+  DEFAULT_BY    => 'projectnumber',
+  DEFAULT_DIR   => 1,
+
+  customer      => t8('Customer'),
+  description   => t8('Description'),
+  projectnumber => t8('Project Number'),
+  type          => t8('Type'),
+);
+
+
+#
+# actions
+#
+
+sub action_search {
+  my ($self) = @_;
+
+  my %params;
+
+  $params{CUSTOM_VARIABLES} = CVar->get_configs(module => 'Projects');
+  ($params{CUSTOM_VARIABLES_FILTER_CODE}, $params{CUSTOM_VARIABLES_INCLUSION_CODE})
+    = CVar->render_search_options(variables      => $params{CUSTOM_VARIABLES},
+                                  include_prefix => 'l_',
+                                  include_value  => 'Y');
+
+  $self->render('project/search', %params);
+}
+
+sub action_list {
+  my ($self) = @_;
+
+  $self->setup_db_args_from_filter;
+  $self->flat_filter({ map { $_->{key} => $_->{value} } $::form->flatten_variables('filter') });
+  # $self->make_filter_summary;
+
+  $self->prepare_report;
+
+  $self->{projects} = $self->get_models(%{ $self->db_args });
+
+  $self->list_objects;
+}
+
+sub action_new {
+  my ($self) = @_;
+
+  $self->project(SL::DB::Project->new);
+  $self->display_form(title    => $::locale->text('Create a new project'),
+                      callback => $::form->{callback} || $self->url_for(action => 'new'));
+}
+
+sub action_edit {
+  my ($self) = @_;
+  $self->display_form(title    => $::locale->text('Edit project #1', $self->project->projectnumber),
+                      callback => $::form->{callback} || $self->url_for(action => 'edit', id => $self->project->id));
+}
+
+sub action_create {
+  my ($self) = @_;
+
+  $self->project(SL::DB::Project->new);
+  $self->create_or_update;
+}
+
+sub action_update {
+  my ($self) = @_;
+  $self->create_or_update;
+}
+
+sub action_destroy {
+  my ($self) = @_;
+
+  if (eval { $self->project->delete; 1; }) {
+    flash_later('info',  $::locale->text('The project has been deleted.'));
+  } else {
+    flash_later('error', $::locale->text('The project is in use and cannot be deleted.'));
+  }
+
+  $self->redirect_to(action => 'search');
+}
+
+#
+# filters
+#
+
+sub check_auth {
+  $::auth->assert('project_edit');
+}
+
+#
+# helpers
+#
+
+sub display_form {
+  my ($self, %params) = @_;
+
+  $params{ALL_CUSTOMERS}    = SL::DB::Manager::Customer->get_all_sorted(where => [ or => [ obsolete => 0, obsolete => undef, id => $self->project->customer_id ]]);
+  $params{CUSTOM_VARIABLES} = CVar->get_custom_variables(module => 'Projects', trans_id => $self->project->id);
+  CVar->render_inputs(variables => $params{CUSTOM_VARIABLES}) if @{ $params{CUSTOM_VARIABLES} };
+
+  $::request->{layout}->focus('#projectnumber');
+
+  $self->render('project/form', %params);
+}
+
+sub create_or_update {
+  my $self   = shift;
+  my $is_new = !$self->project->id;
+  my $params = delete($::form->{project}) || { };
+
+  delete $params->{id};
+  $self->project->assign_attributes(%{ $params });
+
+  my @errors = $self->project->validate;
+
+  if (@errors) {
+    flash('error', @errors);
+    $self->display_form(title    => $is_new ? $::locale->text('Create a new project') : $::locale->text('Edit project'),
+                        callback => $::form->{callback});
+    return;
+  }
+
+  $self->project->save;
+
+  CVar->save_custom_variables(
+    dbh          => $self->project->db->dbh,
+    module       => 'Projects',
+    trans_id     => $self->project->id,
+    variables    => $::form,
+    always_valid => 1,
+  );
+
+  flash_later('info', $is_new ? $::locale->text('The project has been created.') : $::locale->text('The project has been saved.'));
+
+  $self->redirect_to($::form->{callback} || (action => 'search'));
+}
+
+sub load_project {
+  my ($self) = @_;
+  $self->project(SL::DB::Project->new(id => $::form->{id})->load);
+}
+
+sub setup_db_args_from_filter {
+  my ($self) = @_;
+
+  $self->{filter} = {};
+  my %args = parse_filter(
+    $self->_pre_parse_filter($::form->{filter}, $self->{filter}),
+    with_objects => [ 'customer' ],
+    launder_to   => $self->{filter},
+  );
+
+  $self->db_args(\%args);
+}
+
+# unfortunately ParseFilter can't handle compount filters.
+# so we clone the original filter (still need that for serializing)
+# rip out the options we know an replace them with the compound options.
+# ParseFilter will take care of the prefixing then.
+sub _pre_parse_filter {
+  my ($self, $orig_filter, $launder_to) = @_;
+
+  return undef unless $orig_filter;
+
+  my $filter = clone($orig_filter);
+
+  $launder_to->{active} = delete $filter->{active};
+  if ($orig_filter->{active} ne 'both') {
+    push @{ $filter->{and} }, $orig_filter->{active} eq 'active' ? (active => 1) : (or => [ active => 0, active => undef ]);
+  }
+
+  $launder_to->{valid} = delete $filter->{valid};
+  if ($orig_filter->{valid} ne 'both') {
+    push @{ $filter->{and} }, $orig_filter->{valid} eq 'valid' ? (valid => 1) : (or => [ valid => 0, valid => undef ]);
+  }
+
+  $launder_to->{status} = delete $filter->{status};
+  if ($orig_filter->{status} ne 'all') {
+    push @{ $filter->{and} }, SL::DB::Manager::Project->is_not_used_filter;
+  }
+
+  return $filter;
+}
+
+sub prepare_report {
+  my ($self)      = @_;
+
+  my $callback    = $self->get_callback;
+
+  my $report      = SL::ReportGenerator->new(\%::myconfig, $::form);
+  $self->{report} = $report;
+
+  my @columns     = qw(projectnumber description customer active valid type);
+  my @sortable    = qw(projectnumber description customer              type);
+
+  my %column_defs = (
+    projectnumber => { obj_link => sub { $self->url_for(action => 'edit', id => $_[0]->id, callback => $callback) } },
+    description   => { obj_link => sub { $self->url_for(action => 'edit', id => $_[0]->id, callback => $callback) } },
+    type          => { },
+    customer      => { sub  => sub { $_[0]->customer ? $_[0]->customer->name     : '' } },
+    active        => { sub  => sub { $_[0]->active   ? $::locale->text('Active') : $::locale->text('Inactive') },
+                       text => $::locale->text('Active') },
+    valid         => { sub  => sub { $_[0]->valid    ? $::locale->text('Valid')  : $::locale->text('Invalid')  },
+                       text => $::locale->text('Valid')  },
+  );
+
+  map { $column_defs{$_}->{text} ||= $::locale->text( $self->get_sort_spec->{$_}->{title} ) } keys %column_defs;
+
+  $report->set_options(
+    std_column_visibility => 1,
+    controller_class      => 'Project',
+    output_format         => 'HTML',
+    top_info_text         => $::locale->text('Projects'),
+    raw_bottom_info_text  => $self->render('project/report_bottom', { no_output => 1, partial => 1 }),
+    title                 => $::locale->text('Projects'),
+    allow_pdf_export      => 1,
+    allow_csv_export      => 1,
+  );
+  $report->set_columns(%column_defs);
+  $report->set_column_order(@columns);
+  $report->set_export_options(qw(list filter));
+  $report->set_options_from_form;
+  $self->set_report_generator_sort_options(report => $report, sortable_columns => \@sortable);
+
+  $self->disable_pagination if $report->{options}{output_format} =~ /^(pdf|csv)$/i;
+
+  $self->{report_data} = {
+    column_defs        => \%column_defs,
+    columns            => \@columns,
+  };
+}
+
+sub list_objects {
+  my ($self)      = @_;
+  my $column_defs = $self->{report_data}->{column_defs};
+
+  for my $obj (@{ $self->{projects} || [] }) {
+    my %data = map {
+      $_ => {
+        data => $column_defs->{$_}{sub} ? $column_defs->{$_}{sub}->($obj)
+              : $obj->can($_)           ? $obj->$_
+              :                           $obj->{$_},
+        link => $column_defs->{$_}{obj_link} ? $column_defs->{$_}{obj_link}->($obj) : '',
+      },
+    } @{ $self->{report_data}{columns} || {} };
+
+    $self->{report}->add_data(\%data);
+  }
+
+  return $self->{report}->generate_with_headers;
+}
+
+1;
diff --git a/SL/DB/Manager/Project.pm b/SL/DB/Manager/Project.pm
new file mode 100644 (file)
index 0000000..130e35c
--- /dev/null
@@ -0,0 +1,79 @@
+package SL::DB::Manager::Project;
+
+use strict;
+
+use parent qw(SL::DB::Helper::Manager);
+
+use SL::DB::Helper::Paginated;
+use SL::DB::Helper::Sorted;
+
+sub object_class { 'SL::DB::Project' }
+
+__PACKAGE__->make_manager_methods;
+
+our %project_id_column_prefixes = (
+  ar              => 'global',
+  ap              => 'global',
+  oe              => 'global',
+  delivery_orders => 'global',
+);
+
+our @tables_with_project_id_cols = qw(acc_trans ap ar delivery_order_items delivery_orders invoice oe orderitems rmaitems);
+
+sub _sort_spec {
+  return (
+    default    => [ 'projectnumber', 1 ],
+    columns    => {
+      SIMPLE   => 'ALL',
+      customer => 'customer.name',
+    });
+}
+
+sub is_not_used_filter {
+  my ($class, $prefix) = @_;
+
+  my $query = join ' UNION ', map {
+    my $column = $project_id_column_prefixes{$_} . 'project_id';
+    qq|SELECT DISTINCT ${column} FROM ${_} WHERE ${column} IS NOT NULL|
+  } @tables_with_project_id_cols;
+
+  return ("!${prefix}id" => [ \"(${query})" ]);
+}
+
+1;
+__END__
+
+=pod
+
+=encoding utf8
+
+=head1 NAME
+
+SL::DB::Manager::Project - Manager for models for the 'project' table
+
+=head1 SYNOPSIS
+
+This is a standard Rose::DB::Manager based model manager and can be
+used as such.
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item C<is_not_used_filter>
+
+Returns an array containing a partial filter suitable for the C<query>
+parameter that limits to projects that are not referenced from any
+other database table.
+
+=back
+
+=head1 BUGS
+
+Nothing here yet.
+
+=head1 AUTHOR
+
+Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
+
+=cut
index 1d1f1c4..ba6f12f 100644 (file)
@@ -2,16 +2,52 @@ package SL::DB::Project;
 
 use strict;
 
+use List::MoreUtils qw(any);
+
 use SL::DB::MetaSetup::Project;
+use SL::DB::Manager::Project;
 
 use SL::DB::Helper::CustomVariables(
   module      => 'Project',
   cvars_alias => 1,
 );
 
-__PACKAGE__->meta->make_manager_class;
 __PACKAGE__->meta->initialize;
 
+sub validate {
+  my ($self) = @_;
+
+  my @errors;
+  push @errors, $::locale->text('The project number is missing.')        if !$self->projectnumber;
+  push @errors, $::locale->text('The project number is already in use.') if !$self->is_projectnumber_unique;
+  push @errors, $::locale->text('The description is missing.')           if !$self->description;
+
+  return @errors;
+}
+
+sub is_used {
+  my ($self) = @_;
+
+  # Unsaved projects are never referenced.
+  return 0 unless $self->id;
+
+  return any {
+    my $column = $SL::DB::Manager::Project::project_id_column_prefixes{$_} . 'project_id';
+    $self->db->dbh->selectrow_arrayref(qq|SELECT EXISTS(SELECT * FROM ${_} WHERE ${column} = ?)|, undef, $self->id)->[0]
+  } @SL::DB::Manager::Project::tables_with_project_id_cols;
+}
+
+sub is_projectnumber_unique {
+  my ($self) = @_;
+
+  return 1 unless $self->projectnumber;
+
+  my @filter = (projectnumber => $self->projectnumber);
+  @filter    = (and => [ @filter, '!id' => $self->id ]) if $self->id;
+
+  return !SL::DB::Manager::Project->get_first(where => \@filter);
+}
+
 1;
 
 __END__
@@ -28,7 +64,26 @@ This is a standard Rose::DB::Object based model and can be used as one.
 
 =head1 FUNCTIONS
 
-None so far.
+=over 4
+
+=item C<validate>
+
+Checks whether or not all fields are set to valid values so that the
+object can be saved. If valid returns an empty list. Returns an array
+of translated error message otherwise.
+
+=item C<is_used>
+
+Checks whether or not the project is referenced from any other
+database table. Returns a boolean value.
+
+=item C<is_projectnumber_unique>
+
+Returns trueish if the project number is not used for any other
+project in the database. Also returns trueish if no project number has
+been set yet.
+
+=back
 
 =head1 AUTHOR
 
diff --git a/SL/Projects.pm b/SL/Projects.pm
deleted file mode 100644 (file)
index 4c145bb..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-#=====================================================================
-# LX-Office ERP
-# Copyright (C) 2004
-# Based on SQL-Ledger Version 2.1.9
-# Web http://www.lx-office.org
-#
-#=====================================================================
-# SQL-Ledger Accounting
-# Copyright (C) 1998-2002
-#
-#  Author: Dieter Simader
-#   Email: dsimader@sql-ledger.org
-#     Web: http://www.sql-ledger.org
-#
-#  Contributors:
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#======================================================================
-#
-# Project module
-#
-#======================================================================
-
-package Projects;
-
-use Data::Dumper;
-
-use SL::DBUtils;
-use SL::CVar;
-
-use strict;
-
-my %project_id_column_prefixes  = ("ar"              => "global",
-                                   "ap"              => "global",
-                                   "oe"              => "global",
-                                   "delivery_orders" => "global");
-
-my @tables_with_project_id_cols = qw(acc_trans
-                                     invoice
-                                     orderitems
-                                     rmaitems
-                                     ar
-                                     ap
-                                     oe
-                                     delivery_orders
-                                     delivery_order_items);
-
-sub search_projects {
-  $main::lxdebug->enter_sub();
-
-  my $self     = shift;
-  my %params   = @_;
-
-  my $myconfig = \%main::myconfig;
-  my $form     = $main::form;
-
-  my $dbh      = $params{dbh} || $form->get_standard_dbh($myconfig);
-
-  my (@filters, @values);
-
-  foreach my $column (qw(projectnumber description)) {
-    if ($params{$column}) {
-      push @filters, "p.$column ILIKE ?";
-      push @values, '%' . $params{$column} . '%';
-    }
-  }
-
-  if ($params{status} eq 'orphaned') {
-    my @sub_filters;
-
-    foreach my $table (@tables_with_project_id_cols) {
-      push @sub_filters, qq|SELECT DISTINCT $project_id_column_prefixes{$table}project_id FROM $table
-                            WHERE NOT $project_id_column_prefixes{$table}project_id ISNULL|;
-    }
-
-    push @filters, "p.id NOT IN (" . join(" UNION ", @sub_filters) . ")";
-  }
-
-  if ($params{active} eq "active") {
-    push @filters, 'p.active';
-
-  } elsif ($params{active} eq "inactive") {
-    push @filters, 'NOT COALESCE(p.active, FALSE)';
-  }
-
-  if ($params{valid} eq "valid") {
-    push @filters, 'p.valid';
-
-  } elsif ($params{valid} eq "invalid") {
-    push @filters, 'NOT COALESCE(p.valid, FALSE)';
-  }
-
-  if ($params{customer}) {
-    push @filters, 'c.name ILIKE ?';
-    push @values,  '%' . $params{customer} . '%';
-  }
-
-  if ($params{type}) {
-    push @filters, 'p.type ILIKE ?';
-    push @values,  '%' . $params{type} . '%';
-  }
-
-  my ($cvar_where, @cvar_values) = CVar->build_filter_query('module'         => 'Projects',
-                                                            'trans_id_field' => 'p.id',
-                                                            'filter'         => $form);
-
-  if ($cvar_where) {
-    push @filters, $cvar_where;
-    push @values,  @cvar_values;
-  }
-
-
-  my $where = @filters ? 'WHERE ' . join(' AND ', map { "($_)" } @filters) : '';
-
-  my $sortorder =  $params{sort} ? $params{sort} : "projectnumber";
-  $sortorder    =~ s/[^a-z_]//g;
-  my $query     = qq|SELECT p.id, p.projectnumber, p.description, p.active, p.valid, p.type,
-                       c.name AS customer
-                     FROM project p
-                     LEFT JOIN customer c ON (p.customer_id = c.id)
-                     $where
-                     ORDER BY $sortorder|;
-
-  $form->{project_list} = selectall_hashref_query($form, $dbh, $query, @values);
-
-  $main::lxdebug->leave_sub();
-
-  return scalar(@{ $form->{project_list} });
-}
-
-sub get_project {
-  $main::lxdebug->enter_sub();
-
-  my $self     = shift;
-  my %params   = @_;
-
-  if (!$params{id}) {
-    $main::lxdebug->leave_sub();
-    return { };
-  }
-
-  my $myconfig = \%main::myconfig;
-  my $form     = $main::form;
-
-  my $dbh      = $params{dbh} || $form->get_standard_dbh($myconfig);
-
-  my $project  = selectfirst_hashref_query($form, $dbh, qq|SELECT * FROM project WHERE id = ?|, conv_i($params{id})) || { };
-
-  if ($params{orphaned}) {
-    # check if it is orphaned
-    my (@values, $query);
-
-    foreach my $table (@tables_with_project_id_cols) {
-      $query .= " + " if ($query);
-      $query .= qq|(SELECT COUNT(*) FROM $table
-                    WHERE $project_id_column_prefixes{$table}project_id = ?) |;
-      push @values, conv_i($params{id});
-    }
-
-    $query = 'SELECT ' . $query;
-
-    ($project->{orphaned}) = selectrow_query($form, $dbh, $query, @values);
-    $project->{orphaned}   = !$project->{orphaned};
-  }
-
-  $main::lxdebug->leave_sub();
-
-  return $project;
-}
-
-sub save_project {
-  $main::lxdebug->enter_sub();
-
-  my $self     = shift;
-  my %params   = @_;
-
-  my $myconfig = \%main::myconfig;
-  my $form     = $main::form;
-
-  my $dbh      = $params{dbh} || $form->get_standard_dbh($myconfig);
-
-  my @values;
-
-  if (!$params{id}) {
-    ($params{id}) = selectfirst_array_query($form, $dbh, qq|SELECT nextval('id')|);
-    do_query($form, $dbh, qq|INSERT INTO project (id) VALUES (?)|, conv_i($params{id}));
-
-    $params{active} = 1;
-  }
-
-  my $query  = <<SQL;
-    UPDATE project
-    SET projectnumber = ?, description = ?, active = ?, customer_id = ?, type = ?, valid = ?
-    WHERE id = ?
-SQL
-
-  @values = ($params{projectnumber}, $params{description}, $params{active} ? 't' : 'f', conv_i($params{customer_id}), $params{type}, $params{valid} ? 't' : 'f', conv_i($params{id}));
-  do_query($form, $dbh, $query, @values);
-
-  CVar->save_custom_variables('dbh'       => $dbh,
-                              'module'    => 'Projects',
-                              'trans_id'  => $params{id},
-                              'variables' => $form,
-                              'always_valid' => 1);
-
-  $dbh->commit();
-
-  $main::lxdebug->leave_sub();
-
-  return $params{id};
-}
-
-sub delete_project {
-  $main::lxdebug->enter_sub();
-
-  my $self     = shift;
-  my %params   = @_;
-
-  Common::check_params(\%params, qw(id));
-
-  my $myconfig = \%main::myconfig;
-  my $form     = $main::form;
-
-  my $dbh      = $params{dbh} || $form->get_standard_dbh($myconfig);
-
-  do_query($form, $dbh, qq|DELETE FROM project WHERE id = ?|, conv_i($params{id}));
-
-  $dbh->commit();
-
-  $main::lxdebug->leave_sub();
-}
-
-1;
index fe5fa2d..347c152 100644 (file)
@@ -30,8 +30,6 @@
 # common routines for gl, ar, ap, is, ir, oe
 #
 
-use SL::Projects;
-
 use strict;
 
 # any custom scripts for this one
@@ -298,54 +296,6 @@ sub _reset_salesman_id {
   $::form->{salesman_id} = $current_employee->id if $current_employee && exists $::form->{salesman_id};
 }
 
-sub check_project {
-  $main::lxdebug->enter_sub();
-
-  my $form     = $main::form;
-  my $locale   = $main::locale;
-
-  $main::auth->assert('general_ledger         | vendor_invoice_edit  | sales_order_edit    | invoice_edit |' .
-                'request_quotation_edit | sales_quotation_edit | purchase_order_edit | cash         | report');
-
-  my $nextsub = shift || 'update';
-
-  for my $i (1 .. $form->{rowcount}) {
-    my $suffix = $i ? "_$i" : "";
-    my $prefix = $i ? "" : "global";
-    $form->{"${prefix}project_id${suffix}"} = "" unless $form->{"${prefix}projectnumber$suffix"};
-    if ($form->{"${prefix}projectnumber${suffix}"} ne $form->{"old${prefix}projectnumber${suffix}"}) {
-      if ($form->{"${prefix}projectnumber${suffix}"}) {
-
-        # get new project
-        $form->{projectnumber} = $form->{"${prefix}projectnumber${suffix}"};
-        my %params             = map { $_ => $form->{$_} } qw(projectnumber description active);
-        my $rows;
-        if (($rows = Projects->search_projects(%params)) > 1) {
-
-          # check form->{project_list} how many there are
-          $form->{rownumber} = $i;
-          &select_project($i ? undef : 1, $nextsub);
-          ::end_of_request();
-        }
-
-        if ($rows == 1) {
-          $form->{"${prefix}project_id${suffix}"}       = $form->{project_list}->[0]->{id};
-          $form->{"${prefix}projectnumber${suffix}"}    = $form->{project_list}->[0]->{projectnumber};
-          $form->{"old${prefix}projectnumber${suffix}"} = $form->{project_list}->[0]->{projectnumber};
-        } else {
-
-          # not on file
-          $form->error($locale->text('Project not on file!'));
-        }
-      } else {
-        $form->{"old${prefix}projectnumber${suffix}"} = "";
-      }
-    }
-  }
-
-  $main::lxdebug->leave_sub();
-}
-
 sub select_project {
   $::lxdebug->enter_sub;
 
@@ -420,7 +370,6 @@ arap.pl - helper functions or customer/vendor retrieval
 =head1 SYNOPSIS
 
  check_name('vendor')
- check_project();
 
 =head1 DESCRIPTION
 
diff --git a/bin/mozilla/projects.pl b/bin/mozilla/projects.pl
deleted file mode 100644 (file)
index c1b8b7d..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-#=====================================================================
-# LX-Office ERP
-# Copyright (C) 2004
-# Based on SQL-Ledger Version 2.1.9
-# Web http://www.lx-office.org
-#
-#=====================================================================
-# SQL-Ledger Accounting
-# Copyright (c) 1998-2002
-#
-#  Author: Dieter Simader
-#   Email: dsimader@sql-ledger.org
-#     Web: http://www.sql-ledger.org
-#
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#======================================================================
-#
-# project administration
-#======================================================================
-
-use POSIX qw(strftime);
-
-use SL::CVar;
-use SL::Projects;
-use SL::ReportGenerator;
-
-require "bin/mozilla/common.pl";
-require "bin/mozilla/reportgenerator.pl";
-
-use strict;
-
-sub add {
-  $main::lxdebug->enter_sub();
-
-  $main::auth->assert('project_edit');
-
-  my $form     = $main::form;
-  my $locale   = $main::locale;
-
-  # construct callback
-  $form->{callback} = build_std_url('action') unless $form->{callback};
-
-  display_project_form();
-
-  $main::lxdebug->leave_sub();
-}
-
-sub edit {
-  $main::lxdebug->enter_sub();
-
-  $main::auth->assert('project_edit');
-
-  my $form     = $main::form;
-  my $locale   = $main::locale;
-
-  # show history button
-  $form->{javascript} = qq|<script type="text/javascript" src="js/show_history.js"></script>|;
-  #/show hhistory button
-  $form->{title} = "Edit";
-
-  $form->{project} = Projects->get_project('id' => $form->{id}, 'orphaned' => 1);
-
-  display_project_form();
-
-  $main::lxdebug->leave_sub();
-}
-
-sub search {
-  $main::lxdebug->enter_sub();
-
-  $main::auth->assert('project_edit');
-
-  my $form     = $main::form;
-  my $locale   = $main::locale;
-
-  $form->{title} = $locale->text('Projects');
-
-  $form->{CUSTOM_VARIABLES}                  = CVar->get_configs('module' => 'Projects');
-  ($form->{CUSTOM_VARIABLES_FILTER_CODE},
-   $form->{CUSTOM_VARIABLES_INCLUSION_CODE}) = CVar->render_search_options('variables'      => $form->{CUSTOM_VARIABLES},
-                                                                           'include_prefix' => 'l_',
-                                                                           'include_value'  => 'Y');
-  $::request->{layout}->focus('#projectnumber');
-
-  $form->header();
-  print $form->parse_html_template('projects/search');
-
-  $main::lxdebug->leave_sub();
-}
-
-sub project_report {
-  $main::lxdebug->enter_sub();
-
-  $main::auth->assert('project_edit');
-
-  my $form     = $main::form;
-  my %myconfig = %main::myconfig;
-  my $locale   = $main::locale;
-
-  $form->{sort} ||= 'projectnumber';
-  my $filter      = $form->{filter} || { };
-
-  Projects->search_projects(%{ $filter }, 'sort' => $form->{sort});
-
-  my $cvar_configs = CVar->get_configs('module' => 'Projects');
-
-  my $report       = SL::ReportGenerator->new(\%myconfig, $form);
-
-  my @columns      = qw(projectnumber description customer type active valid);
-
-  my @includeable_custom_variables = grep { $_->{includeable} } @{ $cvar_configs };
-  my @searchable_custom_variables  = grep { $_->{searchable} }  @{ $cvar_configs };
-  my %column_defs_cvars            = ();
-  foreach (@includeable_custom_variables) {
-    $column_defs_cvars{"cvar_$_->{name}"} = {
-      'text'    => $_->{description},
-      'visible' => $form->{"l_cvar_$_->{name}"} eq 'Y',
-    };
-  }
-
-  push @columns, map { "cvar_$_->{name}" } @includeable_custom_variables;
-
-
-  my @hidden_vars  = (
-    'filter',
-    map({ ('cvar_'. $_->{name} , 'l_cvar_'. $_->{name}) } @includeable_custom_variables),
-    map({'cvar_'. $_->{name} .'_qtyop'} grep({$_->{type} eq 'number'} @searchable_custom_variables)),
-  );
-  my $href         = build_std_url('action=project_report', @hidden_vars);
-
-
-  my %column_defs  = (
-    'projectnumber'            => { 'text' => $locale->text('Number'), },
-    'description'              => { 'text' => $locale->text('Description'), },
-    'customer'                 => { 'text' => $locale->text('Customer'), },
-    'type'                     => { 'text' => $locale->text('Type'), },
-    'active'                   => { 'text' => $locale->text('Active'), 'visible' => 'both' eq $filter->{active}, },
-    'valid'                    => { 'text' => $locale->text('Valid'),  'visible' => 'both' eq $filter->{active}, },
-    %column_defs_cvars,
-    );
-
-  foreach (qw(projectnumber description customer type)) {
-    $column_defs{$_}->{link}    = $href . "&sort=$_";
-    $column_defs{$_}->{visible} = 1;
-  }
-
-  $report->set_columns(%column_defs);
-  $report->set_column_order(@columns);
-
-  $report->set_export_options('project_report', @hidden_vars, 'sort');
-
-  CVar->add_custom_variables_to_report('module'         => 'Project',
-                                       'trans_id_field' => 'id',
-                                       'configs'        => $cvar_configs,
-                                       'column_defs'    => \%column_defs,
-                                       'data'           => $form->{project_list},
-                                       );
-
-  $report->set_sort_indicator($form->{sort}, 1);
-
-  my @options;
-  push @options, $locale->text('All')                                            if ($filter->{all});
-  push @options, $locale->text('Orphaned')                                       if ($filter->{orphaned});
-  push @options, $locale->text('Project Number') . " : $filter->{projectnumber}" if ($filter->{projectnumber});
-  push @options, $locale->text('Description')    . " : $filter->{description}"   if ($filter->{description});
-  push @options, $locale->text('Customer')       . " : $filter->{customer}"      if ($filter->{customer});
-  push @options, $locale->text('Type')           . " : $filter->{type}"          if ($filter->{type});
-  push @options, $locale->text('Active')                                         if ($filter->{active} eq 'active');
-  push @options, $locale->text('Inactive')                                       if ($filter->{active} eq 'inactive');
-  push @options, $locale->text('Orphaned')                                       if ($filter->{status} eq 'orphaned');
-
-  $form->{title} = $locale->text('Projects');
-
-  $report->set_options('top_info_text'       => join("\n", @options),
-                       'output_format'       => 'HTML',
-                       'title'               => $form->{title},
-                       'attachment_basename' => $locale->text('project_list') . strftime('_%Y%m%d', localtime time),
-    );
-  $report->set_options_from_form();
-  $locale->set_numberformat_wo_thousands_separator(\%myconfig) if lc($report->{options}->{output_format}) eq 'csv';
-
-  CVar->add_custom_variables_to_report('module'         => 'Projects',
-                                       'trans_id_field' => 'id',
-                                       'configs'        => $cvar_configs,
-                                       'column_defs'    => \%column_defs,
-                                       'data'           => $form->{project_list});
-
-  my $edit_url = build_std_url('action=edit&type=project');
-  my $callback = $form->escape($href) . '&sort=' . E($form->{sort});
-
-  foreach my $project (@{ $form->{project_list} }) {
-    $project->{active} = $project->{active} ? $locale->text('Yes')  : $locale->text('No');
-    $project->{valid}  = $project->{valid} ? $locale->text('Yes')  : $locale->text('No');
-
-    my $row = { map { $_ => { 'data' => $project->{$_} } } keys %{ $project } };
-
-    $row->{projectnumber}->{link} = $edit_url . "&id=" . E($project->{id}) . "&callback=${callback}";
-
-    $report->add_data($row);
-  }
-
-  $report->generate_with_headers();
-
-  $main::lxdebug->leave_sub();
-}
-
-sub display_project_form {
-  $main::lxdebug->enter_sub();
-
-  $main::auth->assert('project_edit');
-
-  my $form     = $main::form;
-  my $locale   = $main::locale;
-
-  $form->{project} ||= { };
-
-  $form->{title}     = $form->{project}->{id} ? $locale->text("Edit Project") : $locale->text("Add Project");
-
-  $form->{ALL_CUSTOMERS}    = SL::DB::Manager::Customer->get_all_sorted(where => [ or => [ obsolete => 0, obsolete => undef, id => $form->{project}->{customer_id} ]]);
-  $form->{CUSTOM_VARIABLES} = CVar->get_custom_variables('module' => 'Projects', 'trans_id' => $form->{project}->{id});
-#  $main::lxdebug->dump(0, "cv", $form->{CUSTOM_VARIABLES});
-  CVar->render_inputs('variables' => $form->{CUSTOM_VARIABLES}) if (scalar @{ $form->{CUSTOM_VARIABLES} });
-
-  $form->header();
-  print $form->parse_html_template('projects/project_form');
-
-  $main::lxdebug->leave_sub();
-}
-
-sub save {
-  $main::lxdebug->enter_sub();
-
-  $main::auth->assert('project_edit');
-
-  my $form     = $main::form;
-  my %myconfig = %main::myconfig;
-  my $locale   = $main::locale;
-
-  $form->isblank("project.projectnumber", $locale->text('Project Number missing!'));
-
-  my $project    = $form->{project} || { };
-  my $is_new     = !$project->{id};
-  $project->{id} = Projects->save_project(%{ $project });
-
-  # saving the history
-  if(!exists $form->{addition} && $project->{id} ne "") {
-    $form->{id}       = $project->{id};
-    $form->{snumbers} = qq|projectnumber_| . $project->{projectnumber};
-    $form->{addition} = "SAVED";
-    $form->save_history;
-  }
-  # /saving the history
-
-  if ($form->{callback}) {
-    map { $form->{callback} .= "&new_${_}=" . $form->escape($project->{$_}); } qw(projectnumber description id);
-    my $message              = $is_new ? $locale->text('The project has been added.') : $locale->text('The project has been saved.');
-    $form->{callback}       .= "&message="  . E($message);
-  }
-
-  $form->redirect($locale->text('Project saved!'));
-
-  $main::lxdebug->leave_sub();
-}
-
-sub save_as_new {
-  $main::lxdebug->enter_sub();
-
-  my $form     = $main::form;
-  my $locale   = $main::locale;
-
-  delete $form->{project}->{id} if ($form->{project});
-  save();
-
-  $main::lxdebug->leave_sub();
-}
-
-sub delete {
-  $main::lxdebug->enter_sub();
-
-  $main::auth->assert('project_edit');
-
-  my $form     = $main::form;
-  my %myconfig = %main::myconfig;
-  my $locale   = $main::locale;
-
-  my $project = $form->{project} || { };
-  Projects->delete_project('id' => $project->{id});
-
-  # saving the history
-  if(!exists $form->{addition}) {
-    $form->{snumbers} = qq|projectnumber_| . $project->{projectnumber};
-    $form->{addition} = "DELETED";
-    $form->save_history;
-  }
-  # /saving the history
-
-  $form->redirect($locale->text('Project deleted!'));
-
-  $main::lxdebug->leave_sub();
-}
-
-sub continue {
-  call_sub($main::form->{nextsub});
-}
index bc2eab6..9f6d848 100644 (file)
 
 use POSIX qw(strftime);
 
+use SL::DB::Project;
 use SL::PE;
 use SL::RP;
 use SL::Iconv;
 use SL::ReportGenerator;
 use Data::Dumper;
+use List::MoreUtils qw(any);
 
 require "bin/mozilla/arap.pl";
 require "bin/mozilla/common.pl";
@@ -213,35 +215,6 @@ sub report {
 
 sub continue { call_sub($main::form->{"nextsub"}); }
 
-sub get_project {
-  $main::lxdebug->enter_sub();
-
-  $main::auth->assert('report');
-
-  my $form     = $main::form;
-  my %myconfig = %main::myconfig;
-  my $locale   = $main::locale;
-
-  my $nextsub = shift;
-
-  $form->{project_id} = $form->{project_id_1};
-  if ($form->{projectnumber} && !$form->{project_id}) {
-    $form->{rowcount} = 1;
-
-    # call this instead of update
-    $form->{update}          = $nextsub;
-    $form->{projectnumber_1} = $form->{projectnumber};
-
-    delete $form->{sort};
-    check_project('generate_projects');
-
-    # if there is one only, assign id
-    $form->{project_id} = $form->{project_id_1};
-  }
-
-  $main::lxdebug->leave_sub();
-}
-
 sub generate_income_statement {
   $main::lxdebug->enter_sub();
 
@@ -460,8 +433,8 @@ sub generate_projects {
   my %myconfig = %main::myconfig;
   my $locale   = $main::locale;
 
-  &get_project("generate_projects");
-  $form->{projectnumber} = $form->{projectnumber_1};
+  my $project            = $form->{project_id} ? SL::DB::Project->new(id => $form->{project_id})->load : undef;
+  $form->{projectnumber} = $project ? $project->projectnumber : '';
 
   $form->{nextsub} = "generate_projects";
   $form->{title}   = $locale->text('Project Transactions');
index ebafe70..61e7977 100644 (file)
@@ -468,6 +468,7 @@ $self->{texts} = {
   'Create a new business'       => 'Einen neuen Kunden-/Lieferantentyp erfassen',
   'Create a new department'     => 'Eine neue Abteilung erfassen',
   'Create a new payment term'   => 'Neue Zahlungsbedingungen anlegen',
+  'Create a new project'        => 'Neues Projekt anlegen',
   'Create a standard group'     => 'Eine Standard-Benutzergruppe anlegen',
   'Create and edit RFQs'        => 'Lieferantenanfragen erfassen und bearbeiten',
   'Create and edit dunnings'    => 'Mahnungen erfassen und bearbeiten',
@@ -741,7 +742,6 @@ $self->{texts} = {
   'Edit Price Factor'           => 'Preisfaktor bearbeiten',
   'Edit Pricegroup'             => 'Preisgruppe bearbeiten',
   'Edit Printer'                => 'Drucker bearbeiten',
-  'Edit Project'                => 'Projekt bearbeiten',
   'Edit Purchase Delivery Order' => 'Lieferschein (Einkauf) bearbeiten',
   'Edit Purchase Order'         => 'Lieferantenaufrag bearbeiten',
   'Edit Quotation'              => 'Angebot bearbeiten',
@@ -772,6 +772,8 @@ $self->{texts} = {
   'Edit note'                   => 'Notiz bearbeiten',
   'Edit payment term'           => 'Zahlungsbedingungen bearbeiten',
   'Edit prices and discount (if not used, textfield is ONLY set readonly)' => 'Preise und Rabatt in Formularen frei anpassen (falls deaktiviert, wird allerdings NUR das textfield auf READONLY gesetzt / kann je nach Browserversion und technischen Fähigkeiten des Anwenders noch umgangen werden)',
+  'Edit project'                => 'Projekt bearbeiten',
+  'Edit project #1'             => 'Projekt #1 bearbeiten',
   'Edit rights'                 => 'Rechte bearbeiten',
   'Edit templates'              => 'Vorlagen bearbeiten',
   'Edit the Delivery Order'     => 'Lieferschein bearbeiten',
@@ -1490,12 +1492,8 @@ $self->{texts} = {
   'Project'                     => 'Projekt',
   'Project Description'         => 'Projektbeschreibung',
   'Project Number'              => 'Projektnummer',
-  'Project Number missing!'     => 'Projektnummer fehlt!',
   'Project Numbers'             => 'Projektnummern',
   'Project Transactions'        => 'Projektbuchungen',
-  'Project deleted!'            => 'Projekt gelöscht!',
-  'Project not on file!'        => 'Dieses Projekt ist nicht in der Datenbank!',
-  'Project saved!'              => 'Projekt gespeichert!',
   'Projects'                    => 'Projekte',
   'Projecttransactions'         => 'Projektbuchungen',
   'Prozentual/Absolut'          => 'Prozentual/Absolut',
@@ -1655,6 +1653,7 @@ $self->{texts} = {
   'Search AP Aging'             => 'Offene Verbindlichkeiten',
   'Search AR Aging'             => 'Offene Forderungen',
   'Search contacts'             => 'Ansprechpersonensuche',
+  'Search projects'             => 'Projektsuche',
   'Search term'                 => 'Suchbegriff',
   'Searchable'                  => 'Durchsuchbar',
   'Secondary sorting'           => 'Untersortierung',
@@ -1990,8 +1989,12 @@ $self->{texts} = {
   'The profile \'#1\' has been deleted.' => 'Das Profil \'#1\' wurde gelöscht.',
   'The profile has been saved under the name \'#1\'.' => 'Das Profil wurde unter dem Namen \'#1\' gespeichert.',
   'The program\'s exit code was #1 (&quot;0&quot; usually means that everything went OK).' => 'Der Exitcode des Programms war #1 (&quot;0&quot; bedeutet normalerweise, dass die Wiederherstellung erfolgreich war).',
-  'The project has been added.' => 'Das Projekt wurde erfasst.',
+  'The project has been created.' => 'Das Projekt wurde angelegt.',
+  'The project has been deleted.' => 'Das Projekt wurde gelöscht.',
   'The project has been saved.' => 'Das Projekt wurde gespeichert.',
+  'The project is in use and cannot be deleted.' => 'Das Projekt ist in Verwendung und kann nicht gelöscht werden.',
+  'The project number is already in use.' => 'Die Projektnummer wird bereits verwendet.',
+  'The project number is missing.' => 'Die Projektnummer fehlt.',
   'The restoration process has started. Here\'s the output of the &quot;pg_restore&quot; command:' => 'Der Wiederherstellungsprozess wurde gestartet. Hier ist die Ausgabe des &quot;pg_restore&quot;-Programmes:',
   'The restoration process is complete. Please review &quot;pg_restore&quot;\'s output to find out if the restoration was successful.' => 'Die Wiederherstellung ist abgeschlossen. Bitte sehen Sie sich die Ausgabe von &quot;pg_restore&quot; an, um festzustellen, ob die Wiederherstellung erfolgreich war.',
   'The second reason is that kivitendo allowed the user to enter the tax amount manually regardless of the taxkey used.' => 'Der zweite Grund war, dass kivitendo zuließ, dass die Benutzer beliebige, von den tatsächlichen Steuerschlüsseln unabhängige Steuerbeträge eintrugen.',
@@ -2436,7 +2439,6 @@ $self->{texts} = {
   'prev'                        => 'zurück',
   'print'                       => 'drucken',
   'proforma'                    => 'Proforma',
-  'project_list'                => 'projektliste',
   'purchase_delivery_order_list' => 'lieferscheinliste_einkauf',
   'purchase_order'              => 'Auftrag',
   'purchase_order_list'         => 'lieferantenauftragsliste',
index 65a97c9..5f85eed 100644 (file)
--- a/menu.ini
+++ b/menu.ini
@@ -32,8 +32,8 @@ item=assembly
 
 [Master Data--Add Project]
 ACCESS=project_edit
-module=projects.pl
-action=add
+module=controller.pl
+action=Project/new
 
 [Master Data--Update Prices]
 ACCESS=part_service_assembly_edit
@@ -84,8 +84,8 @@ searchitems=assembly
 
 [Master Data--Reports--Projects]
 ACCESS=project_edit
-module=projects.pl
-action=search
+module=controller.pl
+action=Project/search
 
 [AR]
 
diff --git a/projects.pl b/projects.pl
deleted file mode 120000 (symlink)
index 385000d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-am.pl
\ No newline at end of file
diff --git a/templates/webpages/project/form.html b/templates/webpages/project/form.html
new file mode 100644 (file)
index 0000000..2ea52bc
--- /dev/null
@@ -0,0 +1,107 @@
+[%- USE T8 %]
+[%- USE L %]
+[%- USE HTML %][%- USE LxERP %]
+
+[%- INCLUDE 'common/flash.html' %]
+
+ <div class="listtop">[% title %]</div>
+
+ <form method="post" action="controller.pl">
+  [% L.hidden_tag("callback", callback) %]
+  [% L.hidden_tag("id", SELF.project.id) %]
+
+  <ul id="maintab" class="shadetabs">
+   <li class="selected"><a href="#" rel="basic_data">[% 'Basic Data' | $T8 %]</a></li>
+   [%- IF CUSTOM_VARIABLES.size %]
+   <li><a href="#" rel="custom_variables">[% 'Custom Variables' | $T8 %]</a></li>
+   [%- END %]
+  </ul>
+
+  <div class="tabcontentstyle">
+
+   <div id="basic_data" class="tabcontent">
+
+    <table>
+     <tr>
+      <th align="right">[% 'Number' | $T8 %]</th>
+      <td>[% L.input_tag("project.projectnumber", SELF.project.projectnumber, size=60) %]</td>
+     </tr>
+
+     <tr>
+      <th align="right">[% 'Description' | $T8 %]</th>
+      <td>
+       [%- SET rows = LxERP.numtextrows(SELF.project.description, 60) %]
+       [%- IF rows > 1 %]
+        [%- L.textarea_tag("project.description", SELF.project.description, rows=row, size=60, style="width: 100%", wrap="soft") %]
+       [%- ELSE %]
+        [%- L.input_tag("project.description", SELF.project.description, size=60) %]
+       [%- END %]
+      </td>
+     </tr>
+
+     <tr>
+      <th align="right">[% 'Type' | $T8 %]</th>
+      <td>[% L.input_tag('project.type', SELF.project.type, size=60) %]</td>
+     </tr>
+
+     <tr>
+      <th align="right">[% 'Customer' | $T8 %]</th>
+      <td>[% L.select_tag('project.customer_id', ALL_CUSTOMERS, default=SELF.project.customer_id, title_key='name', style='width: 300px') %]</td>
+     </tr>
+
+     <tr>
+      <th align="right">[% 'Valid' | $T8 %]</th>
+      <td>[% L.select_tag('project.valid', [ [ 1, LxERP.t8('Valid') ], [ 0, LxERP.t8('Invalid') ] ], default=SELF.project.valid, style='width: 300px') %]</td>
+     </tr>
+
+     [%- IF SELF.project.id %]
+     <tr>
+      <th align="right">[% 'Active' | $T8 %]</th>
+      <td>[% L.select_tag('project.active', [ [ 1, LxERP.t8('Active') ], [ 0, LxERP.t8('Inactive') ] ], default=SELF.project.active, style='width: 300px') %]</td>
+     </tr>
+     [%- END %]
+    </table>
+
+    <br style="clear: left" />
+   </div>
+
+   [%- IF CUSTOM_VARIABLES.size %]
+   <div id="custom_variables" class="tabcontent">
+
+    <p>
+     <table>
+      [%- FOREACH var = CUSTOM_VARIABLES %]
+      <tr>
+       <td align="right" valign="top">[% HTML.escape(var.description) %]</td>
+       <td valign="top">[% var.HTML_CODE %]</td>
+      </tr>
+      [%- END %]
+     </table>
+    </p>
+
+    <br style="clear: left" />
+   </div>
+   [%- END %]
+
+  </div>
+
+  <p>
+   [% L.online_help_tag('add_project') %]
+   [% L.hidden_tag("action", "Project/dispatch") %]
+   [% L.submit_tag("action_" _  (SELF.project.id ? "update" : "create"), LxERP.t8('Save')) %]
+   [%- IF SELF.project.id %]
+    [% L.submit_tag("action_create", LxERP.t8('Save as new')) %]
+    [% L.submit_tag("action_destroy", LxERP.t8('Delete'), confirm=LxERP.t8('Do you really want to delete this object?')) IF !SELF.project.is_used %]
+   [%- END %]
+   <a href="[% IF callback %][% callback %][% ELSE %][% SELF.url_for(action => 'search') %][% END %]">[%- LxERP.t8('Abort') %]</a>
+  </p>
+ </form>
+
+ <script type="text/javascript">
+  <!--
+      var maintab = new ddtabcontent("maintab");
+      maintab.setpersist(true);
+      maintab.setselectedClassTarget("link"); //"link" or "linkparent"
+      maintab.init();
+    -->
+ </script>
diff --git a/templates/webpages/project/report_bottom.html b/templates/webpages/project/report_bottom.html
new file mode 100644 (file)
index 0000000..79e1523
--- /dev/null
@@ -0,0 +1,2 @@
+[% USE L %]
+[%- L.paginate_controls %]
diff --git a/templates/webpages/project/search.html b/templates/webpages/project/search.html
new file mode 100644 (file)
index 0000000..e5d4ff4
--- /dev/null
@@ -0,0 +1,65 @@
+[%- USE T8 %]
+[%- USE HTML %]
+[%- USE L %]
+[%- USE LxERP %]
+
+[%- INCLUDE 'common/flash.html' %]
+
+ <form method="post" action="controller.pl">
+
+  <div class="listtop">[% 'Search projects' | $T8 %]</div>
+
+  <p>
+   <table>
+    <tr>
+     <th align="right">[% 'Number' | $T8 %]</th>
+     <td>[% L.input_tag('filter.projectnumber:substr::ilike', filter.projectnumber_substr__ilike, size=60) %]</td>
+    </tr>
+
+    <tr>
+     <th align="right">[% 'Description' | $T8 %]</th>
+     <td>[% L.input_tag('filter.description:substr::ilike', filter.description_substr__ilike, size=60) %]</td>
+    </tr>
+
+    <tr>
+     <th align="right">[% 'Customer' | $T8 %]</th>
+     <td>[% L.input_tag('filter.customer.name:substr::ilike', filter.customer.name_substr__ilike, size=60) %]</td>
+    </tr>
+
+    <tr>
+     <th align="right">[% 'Type' | $T8 %]</th>
+     <td>[% L.input_tag('filter.type:substr::ilike', filter.type_substr__ilike, size=20) %]</td>
+    </tr>
+
+    [% CUSTOM_VARIABLES_FILTER_CODE %]
+
+    <tr>
+     <th>[% 'Include in Report' | $T8 %]</th>
+     <td>
+      <table>
+       <tr>
+        <td>[% L.select_tag('filter.active', [ [ 'active', LxERP.t8('Active') ], [ 'inactive', LxERP.t8('Inactive') ], [ 'both', LxERP.t8('Both') ] ], default=filter.active, style="width: 200px") %]</td>
+       </tr>
+
+       <tr>
+        <td>[% L.select_tag('filter.valid', [ [ 'valid', LxERP.t8('Valid') ], [ 'invalid', LxERP.t8('Invalid') ], [ 'both', LxERP.t8('Both') ] ], default=filter.valid, style="width: 200px") %]</td>
+       </tr>
+
+       <tr>
+        <td>[% L.select_tag('filter.status', [ [ 'all', LxERP.t8('All') ], [ 'orphaned', LxERP.t8('Orphaned') ] ], default=filter.status, style="width: 200px") %]</td>
+       </tr>
+
+       [% CUSTOM_VARIABLES_INCLUSION_CODE %]
+
+      </table>
+     </td>
+    </tr>
+   </table>
+  </p>
+
+  <hr size="3" noshade>
+
+  [% L.hidden_tag('action', 'Project/list') %]
+
+  <p>[% L.submit_tag('dummy', LxERP.t8('Continue')) %]</p>
+ </form>
diff --git a/templates/webpages/projects/project_form.html b/templates/webpages/projects/project_form.html
deleted file mode 100644 (file)
index 3b6f7f4..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-[%- USE T8 %]
-[%- USE L %]
-[%- USE HTML %][%- USE LxERP %]
-
- [%- IF message %]
- <p>[% message %]</p>
-
- <hr>
- [%- END %]
-
- <p><div class="listtop">[% title %]  [% HTML.escape(project.projectnumber) %]</div></p>
-
- <form method="post" action="projects.pl">
-
-  <input type="hidden" name="project.id" value="[% HTML.escape(project.id) %]">
-  <input type="hidden" name="callback" value="[% HTML.escape(callback) %]">
-
-  <ul id="maintab" class="shadetabs">
-   <li class="selected"><a href="#" rel="basic_data">[% 'Basic Data' | $T8 %]</a></li>
-   [%- IF CUSTOM_VARIABLES.size %]
-   <li><a href="#" rel="custom_variables">[% 'Custom Variables' | $T8 %]</a></li>
-   [%- END %]
-  </ul>
-
-  <div class="tabcontentstyle">
-
-   <div id="basic_data" class="tabcontent">
-
-    <table>
-     <tr>
-      <th align="right">[% 'Number' | $T8 %]</th>
-      <td><input name="project.projectnumber" size="60" value="[% HTML.escape(project.projectnumber) %]"></td>
-     </tr>
-
-     <tr>
-      <th align="right">[% 'Description' | $T8 %]</th>
-      <td>
-       [%- SET rows = LxERP.numtextrows(project.description, 60) %]
-       [%- IF rows > 1 %]
-       <textarea name="project.description" rows="[% rows %]" cols="60" style="width: 100%" wrap="soft">[% HTML.escape(project.description) %]</textarea>
-       [%- ELSE %]
-       <input name="project.description" size="60" value="[% HTML.escape(project.description) %]">
-       [%- END %]
-      </td>
-     </tr>
-
-     <tr>
-      <th align="right">[% 'Type' | $T8 %]</th>
-      <td>[% L.input_tag('project.type', project.type, size=60) %]</td>
-     </tr>
-
-     <tr>
-      <th align="right">[% 'Customer' | $T8 %]</th>
-      <td>[% L.select_tag('project.customer_id', ALL_CUSTOMERS, default=project.customer_id, title_key='name', style='width: 300px') %]</td>
-     </tr>
-
-     <tr>
-      <th align="right">[% 'Valid' | $T8 %]</th>
-      <td>[% L.select_tag('project.valid', [ [ 1, LxERP.t8('Valid') ], [ 0, LxERP.t8('Invalid') ] ], default=project.valid, style='width: 300px') %]</td>
-     </tr>
-
-     [%- IF project.id %]
-     <tr>
-      <th align="right">[% 'Active' | $T8 %]</th>
-      <td>[% L.select_tag('project.active', [ [ 1, LxERP.t8('Active') ], [ 0, LxERP.t8('Inactive') ] ], default=project.valid, style='width: 300px') %]</td>
-     </tr>
-     [%- END %]
-    </table>
-
-    <br style="clear: left" />
-   </div>
-
-   [%- IF CUSTOM_VARIABLES.size %]
-   <div id="custom_variables" class="tabcontent">
-
-    <p>
-     <table>
-      [%- FOREACH var = CUSTOM_VARIABLES %]
-      <tr>
-       <td align="right" valign="top">[% HTML.escape(var.description) %]</td>
-       <td valign="top">[% var.HTML_CODE %]</td>
-      </tr>
-      [%- END %]
-     </table>
-    </p>
-
-    <br style="clear: left" />
-   </div>
-   [%- END %]
-
-  </div>
-
-  <p>
-  [% L.online_help_tag('add_project') %]
-   <input type="submit" class="submit" name="action" value="[% 'Save' | $T8 %]">
-   [%- IF project.id %]
-   <input type="submit" class="submit" name="action" value="[% 'Save as new' | $T8 %]">
-   [%- IF project.orphaned %]
-   <input type="submit" class="submit" name="action" value="[% 'Delete' | $T8 %]">
-   [%- END %]
-   <input type="button" onclick="set_history_window([% HTML.escape(project.id) %]);" name="history" id="history" value="[% 'history' | $T8 %]">
-   [%- END %]
-  </p>
- </form>
-
- <script type="text/javascript">
-  <!--
-      var maintab = new ddtabcontent("maintab");
-      maintab.setpersist(true);
-      maintab.setselectedClassTarget("link"); //"link" or "linkparent"
-      maintab.init();
-    -->
- </script>
diff --git a/templates/webpages/projects/search.html b/templates/webpages/projects/search.html
deleted file mode 100644 (file)
index 5eafb40..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-[%- USE T8 %]
-[%- USE HTML %]
- <form method="post" action="projects.pl" name="Form">
-
-  <div class="listtop">[% title %]</div>
-
-  <p>
-   <table>
-    <tr>
-     <th align="right">[% 'Number' | $T8 %]</th>
-     <td><input name="filter.projectnumber" id="projectnumber" size="20"></td>
-    </tr>
-
-    <tr>
-     <th align="right">[% 'Description' | $T8 %]</th>
-     <td><input name="filter.description" size="60"></td>
-    </tr>
-
-    <tr>
-     <th align="right">[% 'Customer' | $T8 %]</th>
-     <td><input name="filter.customer" size="60"></td>
-    </tr>
-
-    <tr>
-     <th align="right">[% 'Type' | $T8 %]</th>
-     <td><input name="filter.type" size="60"></td>
-    </tr>
-
-    [% CUSTOM_VARIABLES_FILTER_CODE %]
-
-    <tr>
-     <th>[% 'Include in Report' | $T8 %]</th>
-     <td>
-      <table>
-       <tr>
-        <td>
-         <input type="radio" name="filter.active" id="active_active" value="active" checked>
-         <label for="active_active">[% 'Active' | $T8 %]</label>
-        </td>
-        <td>
-         <input type="radio" name="filter.active" id="active_inactive" value="inactive">
-         <label for="active_inactive">[% 'Inactive' | $T8 %]</label>
-        </td>
-        <td>
-         <input type="radio" name="filter.active" id="active_both" value="both">
-         <label for="active_both">[% 'Both' | $T8 %]</label>
-        </td>
-       </tr>
-
-       <tr>
-        <td>
-         <input type="radio" name="filter.valid" id="valid_valid" value="valid" checked>
-         <label for="valid_valid">[% 'Valid' | $T8 %]</label>
-        </td>
-        <td>
-         <input type="radio" name="filter.valid" id="valid_invalid" value="invalid">
-         <label for="valid_invalid">[% 'Invalid' | $T8 %]</label>
-        </td>
-        <td>
-         <input type="radio" name="filter.valid" id="valid_both" value="both">
-         <label for="valid_both">[% 'Both' | $T8 %]</label>
-        </td>
-       </tr>
-
-       <tr>
-        <td>
-         <input type="radio" name="filter.status" id="status_all" value="all" checked>
-         <label for="status_all">[% 'All' | $T8 %]</label>
-        </td>
-        <td>
-         <input type="radio" name="filter.status" id="status_orphaned" value="orphaned">
-         <label for="status_orphaned">[% 'Orphaned' | $T8 %]</label>
-        </td>
-       </tr>
-
-       [% CUSTOM_VARIABLES_INCLUSION_CODE %]
-
-      </table>
-     </td>
-    </tr>
-   </table>
-  </p>
-
-  <hr size="3" noshade>
-
-  <input type="hidden" name="nextsub" value="project_report">
-
-  <p>
-   <input class="submit" type="submit" name="action" value="[% 'Continue' | $T8 %]">
-  </p>
- </form>
index c4e8692..afffd5c 100644 (file)
 [%- END %]
 
 [%- IF is_projects %]
-  <tr>
-    <th align=right nowrap>[% 'Project' | $T8 %]</th>
-    <td colspan=5><input name=projectnumber size=25</td>
-  </tr>
+  [% INCLUDE projectnumber %]
   <input type=hidden name=nextsub value=generate_projects>
   <tr>
     <th align=right>[% 'as at' | $T8 %]</th>
 <input type=submit class=submit name=action value="[% 'Continue' | $T8 %]">
 
 </form>
-