Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 7f8599c0

Von Moritz Bunkus vor etwa 12 Jahren hinzugefügt

  • ID 7f8599c0909affd56ad82fd842015bb51c6a3dbf
  • Vorgänger 5c5c1eef
  • Nachfolger 95eb8f3c

Projektverwaltung auf Rose- und Controller-Code umgestellt

Unterschiede anzeigen:

SL/Controller/Project.pm
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;
SL/DB/Manager/Project.pm
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
SL/DB/Project.pm
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__
......
=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
SL/Projects.pm
#=====================================================================
# 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;
bin/mozilla/arap.pl
# common routines for gl, ar, ap, is, ir, oe
#
use SL::Projects;
use strict;
# any custom scripts for this one
......
$::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;
......
=head1 SYNOPSIS
check_name('vendor')
check_project();
=head1 DESCRIPTION
bin/mozilla/projects.pl
#=====================================================================
# 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});
}
bin/mozilla/rp.pl
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";
......
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();
......
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');
locale/de/all
'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',
......
'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',
......
'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',
......
'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',
......
'Search AP Aging' => 'Offene Verbindlichkeiten',
'Search AR Aging' => 'Offene Forderungen',
'Search contacts' => 'Ansprechpersonensuche',
'Search projects' => 'Projektsuche',
'Search term' => 'Suchbegriff',
'Searchable' => 'Durchsuchbar',
'Secondary sorting' => 'Untersortierung',
......
'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.',
......
'prev' => 'zurück',
'print' => 'drucken',
'proforma' => 'Proforma',
'project_list' => 'projektliste',
'purchase_delivery_order_list' => 'lieferscheinliste_einkauf',
'purchase_order' => 'Auftrag',
'purchase_order_list' => 'lieferantenauftragsliste',
menu.ini
[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
......
[Master Data--Reports--Projects]
ACCESS=project_edit
module=projects.pl
action=search
module=controller.pl
action=Project/search
[AR]
projects.pl
am.pl
templates/webpages/project/form.html
[%- 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>
templates/webpages/project/report_bottom.html
[% USE L %]
[%- L.paginate_controls %]
templates/webpages/project/search.html
[%- 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>
templates/webpages/projects/project_form.html
[%- 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>
... Dieser Diff wurde abgeschnitten, weil er die maximale Anzahl anzuzeigender Zeilen überschreitet.

Auch abrufbar als: Unified diff