From 958c1727a1453b28feaf8c4bfa40ef25f8bcc3ea Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bernd=20Ble=C3=9Fmann?= Date: Fri, 7 May 2021 21:34:11 +0200 Subject: [PATCH] S:C:H:ReportGenerator: Interface und Impmentierung von Kontroll-Zeilen MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Es wurde eine Schnittstelle geschaffen, um Kontroll-Zeilen an den ReportGenerator-Helfer zu übergeben. Umgesetzt sind Kontroll-Zeilen für einen Separator und für eigene Daten. --- SL/Controller/Helper/ReportGenerator.pm | 37 +++++-- .../Helper/ReportGenerator/ControlRow.pm | 103 ++++++++++++++++++ .../Helper/ReportGenerator/ControlRow/ALL.pm | 15 +++ .../Helper/ReportGenerator/ControlRow/Base.pm | 98 +++++++++++++++++ .../Helper/ReportGenerator/ControlRow/Data.pm | 94 ++++++++++++++++ .../ReportGenerator/ControlRow/Separator.pm | 69 ++++++++++++ .../ReportGenerator/ControlRow/SimpleData.pm | 86 +++++++++++++++ 7 files changed, 492 insertions(+), 10 deletions(-) create mode 100644 SL/Controller/Helper/ReportGenerator/ControlRow.pm create mode 100644 SL/Controller/Helper/ReportGenerator/ControlRow/ALL.pm create mode 100644 SL/Controller/Helper/ReportGenerator/ControlRow/Base.pm create mode 100644 SL/Controller/Helper/ReportGenerator/ControlRow/Data.pm create mode 100644 SL/Controller/Helper/ReportGenerator/ControlRow/Separator.pm create mode 100644 SL/Controller/Helper/ReportGenerator/ControlRow/SimpleData.pm diff --git a/SL/Controller/Helper/ReportGenerator.pm b/SL/Controller/Helper/ReportGenerator.pm index 513eda85b..be9b8306d 100644 --- a/SL/Controller/Helper/ReportGenerator.pm +++ b/SL/Controller/Helper/ReportGenerator.pm @@ -4,6 +4,7 @@ use strict; use Carp; use List::Util qw(max); +use Scalar::Util qw(blessed); use SL::Common; use SL::MoreCommon; @@ -126,16 +127,24 @@ sub report_generator_list_objects { my @columns = $params{report}->get_visible_columns('HTML'); for my $obj (@{ $params{objects} || [] }) { - my %data = map { - my $def = $column_defs->{$_}; - my $tmp; - $tmp->{raw_data} = $def->{raw_data} ? $def->{raw_data}->($obj) : ''; - $tmp->{data} = $def->{sub} ? $def->{sub}->($obj) - : $obj->can($_) ? $obj->$_ - : $obj->{$_}; - $tmp->{link} = $def->{obj_link} ? $def->{obj_link}->($obj) : ''; - $_ => $tmp; - } @columns; + my %data; + + if (blessed($obj) && $obj->isa('SL::Controller::Helper::ReportGenerator::ControlRow::Base')) { + $obj->set_data($params{report}); + next; + + } else { + %data = map { + my $def = $column_defs->{$_}; + my $tmp; + $tmp->{raw_data} = $def->{raw_data} ? $def->{raw_data}->($obj) : ''; + $tmp->{data} = $def->{sub} ? $def->{sub}->($obj) + : $obj->can($_) ? $obj->$_ + : $obj->{$_}; + $tmp->{link} = $def->{obj_link} ? $def->{obj_link}->($obj) : ''; + $_ => $tmp; + } @columns; + } $params{data_callback}->(\%data) if $params{data_callback}; @@ -251,6 +260,14 @@ already (column definitions, title, sort handling etc). Mandatory. An array reference of RDBO models to output. +An element of the array can also be an instance of a control row, i.e. +an instance of a class derived from +C. +See also: + +L +L + =item C Optional. A callback handler (code reference) that gets called for diff --git a/SL/Controller/Helper/ReportGenerator/ControlRow.pm b/SL/Controller/Helper/ReportGenerator/ControlRow.pm new file mode 100644 index 000000000..536dd342f --- /dev/null +++ b/SL/Controller/Helper/ReportGenerator/ControlRow.pm @@ -0,0 +1,103 @@ +package SL::Controller::Helper::ReportGenerator::ControlRow; + +use strict; +use Carp; + +use SL::Controller::Helper::ReportGenerator::ControlRow::ALL; + +use Exporter 'import'; +our @EXPORT = qw( + make_control_row +); + + +sub make_control_row { + my ($type, %args) = @_; + + my $class = $SL::Controller::Helper::ReportGenerator::ControlRow::ALL::type_to_class{$type} // croak "unknown type $type"; + my $obj = $class->new(params => \%args); + my @errors = $obj->validate_params; + croak join("\n", @errors) if @errors; + + return $obj; +} + + +1; + +__END__ + +=encoding utf-8 + +=head1 NAME + +SL::Controller::Helper::ReportGenerator::ControlRow - an interface for +report generator control rows + +=head1 DESCRIPTION + +ControlRow is an interface that allows generic control rows to be added +to objects for the C. + +Each control row implementation can access the report and add data for a row. + +=head1 SYNOPSIS + + package SL::Controller::TimeRecording; + + use SL::Controller::Helper::ReportGenerator; + use SL::Controller::Helper::ReportGenerator::ControlRow qw(make_control_row); + + sub action_list { + my ($self) = @_; + + # Set up the report generator instance. In this example this is + # hidden in "prepare_report". + my $report = $self->prepare_report; + + # Get objects from database. + my $objects = SL::DB::Manager::TimeRecording->get_all(...); + + # Add a separator + push @$objects, make_control_row("separator"); + + # And a simple total + my $total = sum0 map { _round_total($_->duration_in_hours) } @$objects; + push @$objects, make_control_row("simple_data", data => {duration => $total}); + + # Let report generator create the output. + $self->report_generator_list_objects( + report => $report, + objects => $objects, + ); + } + + +=head1 WRITING OWN CONTROL ROW CLASSES + +See C. + +=head1 FUNCTIONS + +=over 4 + +=item C + +Returns an instance of the control row class for the given type. This +object can be used as an element of objects to the report generator helper +(see C). + +Available types are 'separator', 'data, 'simple_data' for now. + +C<%PARAMS> depends on the type. See also: + +L +L + +=back + +=head1 AUTHOR + +Bernd Bleßmann Ebernd@kivitendo-premium.deE + +=cut diff --git a/SL/Controller/Helper/ReportGenerator/ControlRow/ALL.pm b/SL/Controller/Helper/ReportGenerator/ControlRow/ALL.pm new file mode 100644 index 000000000..6ac367af2 --- /dev/null +++ b/SL/Controller/Helper/ReportGenerator/ControlRow/ALL.pm @@ -0,0 +1,15 @@ +package SL::Controller::Helper::ReportGenerator::ControlRow::ALL; + +use strict; + +use SL::Controller::Helper::ReportGenerator::ControlRow::Data; +use SL::Controller::Helper::ReportGenerator::ControlRow::Separator; +use SL::Controller::Helper::ReportGenerator::ControlRow::SimpleData; + +our %type_to_class = ( + data => 'SL::Controller::Helper::ReportGenerator::ControlRow::Data', + separator => 'SL::Controller::Helper::ReportGenerator::ControlRow::Separator', + simple_data => 'SL::Controller::Helper::ReportGenerator::ControlRow::SimpleData', +); + +1; diff --git a/SL/Controller/Helper/ReportGenerator/ControlRow/Base.pm b/SL/Controller/Helper/ReportGenerator/ControlRow/Base.pm new file mode 100644 index 000000000..ea11e972a --- /dev/null +++ b/SL/Controller/Helper/ReportGenerator/ControlRow/Base.pm @@ -0,0 +1,98 @@ +package SL::Controller::Helper::ReportGenerator::ControlRow::Base; + +use strict; + +use parent qw(SL::DB::Object); + +use Rose::Object::MakeMethods::Generic ( + scalar => [ qw(params) ], +); + + +sub validate_params { die 'name needs to be implemented' } +sub set_data { die 'name needs to be implemented' } + + +1; + + +__END__ + +=encoding utf-8 + +=head1 NAME + +SL::Controller::Helper::ReportGenerator::ControlRow::Base - a base class +for report generator control row classes + +=head1 DESCRIPTION + +ControlRow is an interface that allows generic control rows to be added +to objects for the C. This is a +base class from which all control row classes are derived. + +=head1 SYNOPSIS + +Adding your own new control row of the type "only_dashes": + + package SL::Controller::Helper::ReportGenerator::ControlRow::OnlyDashes; + + use parent qw(SL::Controller::Helper::ReportGenerator::ControlRow::Base); + + sub validate_params { return; } # no params + + sub set_data { + my ($self, $report) = @_; + + my %data = map { $_ => {data => '---'} } keys %{ $report->{columns} }; + + $report->add_data(\%data); + } + +After that, you have to register your new class in +C: + + use SL::Controller::Helper::ReportGenerator::ControlRow::OnlyDashes; + + our %type_to_class = ( + ..., + only_dashes => 'SL::Controller::Helper::ReportGenerator::ControlRow::OnlyDashes', + ); + + +=head1 WRITING OWN CONTROL ROW CLASSES + +You can use C +as parent of your module. You have to provide two methods: + +=over 4 + +=item C + +This method is used to validate any params used for your module. +You can access the params through the method C which contains all +remaining params after the type of the call to make_control_row (see +C). + +The method should return an array of error messages if there are any +errors. Otherwise it should return C. + +=item C + +This method sould set the data for the report generator, which is handeled +over as argument. + +=back + +=head1 REGISTERING OWN CONTROL ROW CLASSES + +See C. Here your +class should be included with C and entered in the map C<%type_to_class> +with an appropiate name for it's type. + + +=head1 AUTHOR + +Bernd Bleßmann Ebernd@kivitendo-premium.deE + +=cut diff --git a/SL/Controller/Helper/ReportGenerator/ControlRow/Data.pm b/SL/Controller/Helper/ReportGenerator/ControlRow/Data.pm new file mode 100644 index 000000000..159249d1a --- /dev/null +++ b/SL/Controller/Helper/ReportGenerator/ControlRow/Data.pm @@ -0,0 +1,94 @@ +package SL::Controller::Helper::ReportGenerator::ControlRow::Data; + +use strict; + +use parent qw(SL::Controller::Helper::ReportGenerator::ControlRow::Base); + + +sub validate_params { + my ($self) = @_; + + my @errors; + push @errors, 'type "data" needs a parameter "row" as hash ref' if !$self->params->{row} || ('HASH' ne ref $self->params->{row}); + + return @errors;; +} + +sub set_data { + my ($self, $report) = @_; + + my %data; + %data = map { + my $def = $self->params->{row}->{$_}; + my $tmp; + + foreach my $attr (qw(raw_data data link class align)) { + $tmp->{$attr} = $def->{$attr} if defined $def->{$attr}; + } + $_ => $tmp; + } keys %{ $self->params->{row} }; + + $report->add_data(\%data); +} + + +1; + +__END__ + +=encoding utf-8 + +=head1 NAME + +SL::Controller::Helper::ReportGenerator::ControlRow::Data - an +implementaion of a control row class to display data + +=head1 DESCRIPTION + +This class implements a control row for the report generator helper to display +data. You can configure the way the data is displayed. + +=head1 SYNOPSIS + + use SL::Controller::Helper::ReportGenerator; + use SL::Controller::Helper::ReportGenerator::ControlRow qw(make_control_row); + + sub action_list { + my ($self) = @_; + + # Set up the report generator instance. In this example this is + # hidden in "prepare_report". + my $report = $self->prepare_report; + + # Get objects from database. + my $objects = SL::DB::Manager::TimeRecording->get_all(...); + + # Add a simple data + my $total = $self->get_total($objects); + push @$objects, make_control_row( + "data", + row => { duration => { data => $total, + class => 'listtotal', + link => '#info_for_total' } } + ); + + # Let report generator create the output. + $self->report_generator_list_objects( + report => $report, + objects => $objects, + ); + } + +=head1 PARAMETERS + +This control row gets the paramter C, which must a hash ref. +The keys are the column names for the fields you want to show your +data. The values are hash refs itself and can contain the keys +C, C, C, C and C which are passed +in the data added to the report. + +=head1 AUTHOR + +Bernd Bleßmann Ebernd@kivitendo-premium.deE + +=cut diff --git a/SL/Controller/Helper/ReportGenerator/ControlRow/Separator.pm b/SL/Controller/Helper/ReportGenerator/ControlRow/Separator.pm new file mode 100644 index 000000000..a7e7bf9e2 --- /dev/null +++ b/SL/Controller/Helper/ReportGenerator/ControlRow/Separator.pm @@ -0,0 +1,69 @@ +package SL::Controller::Helper::ReportGenerator::ControlRow::Separator; + +use strict; + +use parent qw(SL::Controller::Helper::ReportGenerator::ControlRow::Base); + + +sub validate_params { + return; +} + +sub set_data { + my ($self, $report) = @_; + + $report->add_separator(); +} + + +1; + + +__END__ + +=encoding utf-8 + +=head1 NAME + +SL::Controller::Helper::ReportGenerator::ControlRow::Separator - an +implementaion of a control row class to display a separator + +=head1 DESCRIPTION + +This class implements a control row for the report generator helper to display +a separator. + +=head1 SYNOPSIS + + use SL::Controller::Helper::ReportGenerator; + use SL::Controller::Helper::ReportGenerator::ControlRow qw(make_control_row); + + sub action_list { + my ($self) = @_; + + # Set up the report generator instance. In this example this is + # hidden in "prepare_report". + my $report = $self->prepare_report; + + # Get objects from database. + my $objects = SL::DB::Manager::TimeRecording->get_all(...); + + # Add a separator + push @$objects, make_control_row("separator"); + + # Let report generator create the output. + $self->report_generator_list_objects( + report => $report, + objects => $objects, + ); + } + +=head1 PARAMETERS + +This control row does not use any parameters. + +=head1 AUTHOR + +Bernd Bleßmann Ebernd@kivitendo-premium.deE + +=cut diff --git a/SL/Controller/Helper/ReportGenerator/ControlRow/SimpleData.pm b/SL/Controller/Helper/ReportGenerator/ControlRow/SimpleData.pm new file mode 100644 index 000000000..7d625d33b --- /dev/null +++ b/SL/Controller/Helper/ReportGenerator/ControlRow/SimpleData.pm @@ -0,0 +1,86 @@ +package SL::Controller::Helper::ReportGenerator::ControlRow::SimpleData; + +use strict; + +use parent qw(SL::Controller::Helper::ReportGenerator::ControlRow::Base); + + +sub validate_params { + my ($self) = @_; + + my @errors; + push @errors, 'type "simple_data" needs a parameter "data" as hash ref' if !$self->params->{data} || ('HASH' ne ref $self->params->{data}); + + return @errors; +} + +sub set_data { + my ($self, $report) = @_; + + my %data = map { + my $tmp; + $tmp->{data} = $self->params->{data}->{$_}; + $_ => $tmp; + } keys %{ $self->params->{data} }; + + $report->add_data(\%data); +} + + +1; + + +__END__ + +=encoding utf-8 + +=head1 NAME + +SL::Controller::Helper::ReportGenerator::ControlRow::SimpleData - an +implementaion of a control row class to display simple data + +=head1 DESCRIPTION + +This class implements a control row for the report generator helper to display +simple data. C because you only have to provide the column and your data +as a string. + +=head1 SYNOPSIS + + use SL::Controller::Helper::ReportGenerator; + use SL::Controller::Helper::ReportGenerator::ControlRow qw(make_control_row); + + sub action_list { + my ($self) = @_; + + # Set up the report generator instance. In this example this is + # hidden in "prepare_report". + my $report = $self->prepare_report; + + # Get objects from database. + my $objects = SL::DB::Manager::TimeRecording->get_all(...); + + # Add a simple data + push @$objects, make_control_row( + "simple_data", + data => { duration => 'Total sum of duration is not implemeted yet' } + ); + + # Let report generator create the output. + $self->report_generator_list_objects( + report => $report, + objects => $objects, + ); + } + +=head1 PARAMETERS + +This control row gets the paramter C, which must a hash ref. +The keys are the column names for the fields you want to show your +data. The values are the data. + +=head1 AUTHOR + +Bernd Bleßmann Ebernd@kivitendo-premium.deE + +=cut -- 2.20.1