From 8165bc52de684ec8cd95a78515bb82a23d0dab5d Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Wed, 20 Feb 2013 16:02:49 +0100 Subject: [PATCH] =?utf8?q?Finanz=C3=BCbersichtsbericht:=20Finanz=C3=BCbers?= =?utf8?q?ichtsbericht:=20erste=20Implementation?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- SL/Controller/FinancialOverview.pm | 165 ++++++++++++++++++ locale/de/all | 10 ++ menus/erp.ini | 5 + .../financial_overview/report_top.html | 18 ++ 4 files changed, 198 insertions(+) create mode 100644 SL/Controller/FinancialOverview.pm create mode 100644 templates/webpages/financial_overview/report_top.html diff --git a/SL/Controller/FinancialOverview.pm b/SL/Controller/FinancialOverview.pm new file mode 100644 index 000000000..7779a0038 --- /dev/null +++ b/SL/Controller/FinancialOverview.pm @@ -0,0 +1,165 @@ +package SL::Controller::FinancialOverview; + +use strict; +use parent qw(SL::Controller::Base); + +use List::MoreUtils qw(none); + +use SL::DB::Invoice; +use SL::DB::Order; +use SL::DB::PurchaseInvoice; +use SL::Controller::Helper::ReportGenerator; +use SL::Locale::String; + +use Rose::Object::MakeMethods::Generic ( + scalar => [ qw(report number_columns year current_year types objects data subtotals_per_quarter) ], +); + +__PACKAGE__->run_before(sub { $::auth->assert('report'); }); + +sub action_list { + my ($self) = @_; + + $self->subtotals_per_quarter($::form->{subtotals_per_quarter}); + + $self->get_objects; + $self->calculate_data; + $self->prepare_report; + $self->list_data; +} + +# private functions + +sub prepare_report { + my ($self) = @_; + + $self->report(SL::ReportGenerator->new(\%::myconfig, $::form)); + + my @columns = qw(year quarter month sales_quotations sales_orders sales_invoices requests_for_quotation purchase_orders purchase_invoices); + + $self->number_columns([ grep { !m/^(?:month|year|quarter)$/ } @columns ]); + + my %column_defs = ( + month => { text => t8('Month') }, + year => { text => t8('Year') }, + quarter => { text => t8('Quarter') }, + sales_quotations => { text => t8('Sales Quotations') }, + sales_orders => { text => t8('Sales Orders') }, + sales_invoices => { text => t8('Invoices') }, + requests_for_quotation => { text => t8('Requests for Quotation') }, + purchase_orders => { text => t8('Purchase Orders') }, + purchase_invoices => { text => t8('Purchase Invoices') }, + ); + + map { $column_defs{$_}->{align} = 'right' } @columns; + + $self->report->set_options( + std_column_visibility => 1, + controller_class => 'FinancialOverview', + output_format => 'HTML', + raw_top_info_text => $self->render('financial_overview/report_top', { output => 0 }, YEARS_TO_LIST => [ reverse(2000..$self->current_year) ]), + title => t8('Financial overview for #1', $self->year), + allow_pdf_export => 1, + allow_csv_export => 1, + ); + $self->report->set_columns(%column_defs); + $self->report->set_column_order(@columns); + $self->report->set_export_options(qw(list year subtotals_per_quarter)); + $self->report->set_options_from_form; +} + +sub get_objects { + my ($self) = @_; + + $self->current_year(DateTime->today->year); + $self->year($::form->{year} || DateTime->today->year); + + my $start = DateTime->new(year => $self->year, month => 1, day => 1); + my $end = DateTime->new(year => $self->year, month => 12, day => 31); + + my @date_filter = (and => [ transdate => { ge => $start }, transdate => { le => $end } ]); + + $self->objects({ + sales_quotations => SL::DB::Manager::Order->get_all( where => [ and => [ @date_filter, SL::DB::Manager::Order->type_filter('sales_quotation') ]]), + sales_orders => SL::DB::Manager::Order->get_all( where => [ and => [ @date_filter, SL::DB::Manager::Order->type_filter('sales_order') ]]), + requests_for_quotation => SL::DB::Manager::Order->get_all( where => [ and => [ @date_filter, SL::DB::Manager::Order->type_filter('request_quotation') ]]), + purchase_orders => SL::DB::Manager::Order->get_all( where => [ and => [ @date_filter, SL::DB::Manager::Order->type_filter('purchase_order') ]]), + sales_invoices => SL::DB::Manager::Invoice->get_all( where => \@date_filter), + purchase_invoices => SL::DB::Manager::PurchaseInvoice->get_all(where => \@date_filter), + }); +} + +sub calculate_data { + my ($self) = @_; + + $self->types([ qw(sales_quotations sales_orders sales_invoices requests_for_quotation purchase_orders purchase_invoices) ]); + + my %data = ( + year => [ ($self->year) x 12 ], + month => [ (1..12) ], + quarter => [ (1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4) ], + map { + $_ => { + months => [ (0) x 12 ], + quarters => [ (0) x 4 ], + year => 0, + } + } @{ $self->types }, + ); + + foreach my $type (keys %{ $self->objects }) { + foreach my $object (@{ $self->objects->{ $type } }) { + my $month = $object->transdate->month - 1; + my $tdata = $data{$type}; + + $tdata->{months}->[$month] += $object->netamount; + $tdata->{quarters}->[int($month / 3)] += $object->netamount; + $tdata->{year} += $object->netamount; + } + } + + $self->data(\%data); +} + +sub list_data { + my ($self) = @_; + + my @visible_columns = $self->report->get_visible_columns; + my @type_columns = @{ $self->types }; + my @non_type_columns = grep { my $c = $_; none { $c eq $_ } @type_columns } @visible_columns; + + for my $month (1..12) { + my %data = ( + map({ ($_ => { data => $self->data->{$_}->[$month - 1] }) } @non_type_columns), + map({ ($_ => { data => $::form->format_amount(\%::myconfig, $self->data->{$_}->{months}->[$month - 1]) }) } @type_columns ), + ); + + $self->report->add_data(\%data); + + if ($self->subtotals_per_quarter && (($month % 3) == 0)) { + my %subtotal = ( + year => { data => $self->year }, + month => { data => $::locale->text('Total') }, + map { ($_ => { data => $::form->format_amount(\%::myconfig, $self->data->{$_}->{quarters}->[int(($month - 1) / 3)]) }) } @type_columns, + ); + + $subtotal{$_}->{class} = 'listsubtotal' for @visible_columns; + + $self->report->add_data(\%subtotal); + } + } + + my %data = ( + year => { data => $self->year }, + quarter => { data => $::locale->text('Total') }, + map { ($_ => { data => $::form->format_amount(\%::myconfig, $self->data->{$_}->{year}) }) } @type_columns, + ); + + $data{$_}->{class} = 'listtotal' for @visible_columns; + + $self->report->add_data(\%data); + + return $self->report->generate_with_headers; +} + +1; diff --git a/locale/de/all b/locale/de/all index 994ae9afa..4c17a6e55 100755 --- a/locale/de/all +++ b/locale/de/all @@ -569,6 +569,7 @@ $self->{texts} = { 'Current profile' => 'Aktuelles Profil', 'Current status' => 'Aktueller Status', 'Current value:' => 'Aktueller Wert:', + 'Current year' => 'Aktuelles Jahr', 'Custom Variables' => 'Benutzerdefinierte Variablen', 'Custom variables for module' => 'Benutzerdefinierte Variablen für Modul', 'Customer' => 'Kunde', @@ -964,6 +965,11 @@ $self->{texts} = { 'Filter for customer variables' => 'Filter für benutzerdefinierte Kundenvariablen', 'Filter for item variables' => 'Filter für benutzerdefinierte Artikelvariablen', 'Filter parts' => 'Artikel filtern', + 'Financial Controlling' => 'Finanzcontrolling', + 'Financial Controlling Report' => 'Finanzcontrollingbericht', + 'Financial Overview' => 'Finanzübersicht', + 'Financial controlling report for open sales orders' => 'Finanzcontrollingbericht für offene Aufträge', + 'Financial overview for #1' => 'Finanzübersicht für #1', 'Finish' => 'Abschließen', 'First 20 Lines' => 'Nur erste 20 Datensätze', 'Fix transaction' => 'Buchung korrigieren', @@ -978,6 +984,7 @@ $self->{texts} = { 'Follow-Up saved.' => 'Wiedervorlage gespeichert.', 'Follow-Ups' => 'Wiedervorlagen', 'Follow-up for' => 'Wiedervorlage für', + 'Following year' => 'Folgendes Jahr', 'Font' => 'Schriftart', 'Font size' => 'Schriftgröße', 'For AP transactions it will replace the sales taxkeys with input taxkeys with the same tax rate.' => 'Bei Kreditorenbuchungen werden die Umsatzsteuer-Steuerschlüssel durch Vorsteuer-Steuerschlüssel mit demselben Steuersatz ersetzt.', @@ -1629,6 +1636,7 @@ $self->{texts} = { 'Printer Management' => 'Druckeradministration', 'Printer management' => 'Druckerverwaltung', 'Printing ... ' => 'Es wird gedruckt.', + 'Prior year' => 'Vorheriges Jahr', 'Private E-mail' => 'Private E-Mail', 'Private Phone' => 'Privates Tel.', 'Problem' => 'Problem', @@ -1737,6 +1745,7 @@ $self->{texts} = { 'Requested execution date' => 'Gewünschtes Ausführungsdatum', 'Requested execution date from' => 'Gewünschtes Ausführungsdatum von', 'Requested execution date to' => 'Gewünschtes Ausführungsdatum bis', + 'Requests for Quotation' => 'Preisanfragen', 'Required by' => 'Lieferdatum', 'Reset' => 'Zurücksetzen', 'Result' => 'Ergebnis', @@ -1968,6 +1977,7 @@ $self->{texts} = { 'Subject:' => 'Betreff:', 'Subtotal' => 'Zwischensumme', 'Subtotal cannot distinguish betweens record types. Only one of the selected record types will be displayed: #1' => 'Zwischensummen können nicht zwischen den einzelnen Belegen unterscheiden, es wird nur "#1" angezeigt', + 'Subtotals per quarter' => 'Zwischensummen pro Quartal', 'Such entries cannot be exported into the DATEV format and have to be fixed as well.' => 'Solche Einträge sind aber nicht DATEV-exportiertbar und müssen ebenfalls korrigiert werden.', 'Sum Credit' => 'Summe Haben', 'Sum Debit' => 'Summe Soll', diff --git a/menus/erp.ini b/menus/erp.ini index b49a851a5..2232ec478 100644 --- a/menus/erp.ini +++ b/menus/erp.ini @@ -414,6 +414,11 @@ module=rp.pl action=report report=projects +[Reports--Financial Overview] +ACCESS=report +module=controller.pl +action=FinancialOverview/list + [Batch Printing] ACCESS=batch_printing diff --git a/templates/webpages/financial_overview/report_top.html b/templates/webpages/financial_overview/report_top.html new file mode 100644 index 000000000..ae362abf6 --- /dev/null +++ b/templates/webpages/financial_overview/report_top.html @@ -0,0 +1,18 @@ +[%- USE L %][% USE LxERP %] +
+ [% L.hidden_tag('action', 'FinancialOverview/list') %] + « [%- LxERP.t8("Prior year") %]: [% SELF.year - 1 %] + | + + [% LxERP.t8("Current year") %]: + [% L.select_tag('year', YEARS_TO_LIST, default=SELF.year, onchange='$("#form").submit();') %] + + [% IF SELF.year < SELF.current_year %] + | + [%- LxERP.t8("Following year") %]: [% SELF.year + 1 %] » + [% END %] + +
+ [% L.checkbox_tag('subtotals_per_quarter', checked=SELF.subtotals_per_quarter, label=LxERP.t8('Subtotals per quarter'), onchange='$("#form").submit();') %] +
+
-- 2.20.1