Finanzübersicht: Filtermöglichkeit nach VerkäuferIn
[kivitendo-erp.git] / SL / Controller / FinancialOverview.pm
1 package SL::Controller::FinancialOverview;
2
3 use strict;
4 use parent qw(SL::Controller::Base);
5
6 use List::MoreUtils qw(none);
7
8 use SL::DB::Employee;
9 use SL::DB::Invoice;
10 use SL::DB::Order;
11 use SL::DB::PurchaseInvoice;
12 use SL::Controller::Helper::ReportGenerator;
13 use SL::Locale::String;
14
15 use Rose::Object::MakeMethods::Generic (
16   scalar                  => [ qw(report number_columns year current_year types objects data subtotals_per_quarter salesman_id) ],
17   'scalar --get_set_init' => [ qw(employees) ],
18 );
19
20 __PACKAGE__->run_before(sub { $::auth->assert('report'); });
21
22 sub action_list {
23   my ($self) = @_;
24
25   $self->$_($::form->{$_}) for qw(subtotals_per_quarter salesman_id);
26
27   $self->get_objects;
28   $self->calculate_data;
29   $self->prepare_report;
30   $self->list_data;
31 }
32
33 # private functions
34
35 sub prepare_report {
36   my ($self)      = @_;
37
38   $self->report(SL::ReportGenerator->new(\%::myconfig, $::form));
39
40   my @columns = qw(year quarter month sales_quotations sales_orders sales_invoices requests_for_quotation purchase_orders purchase_invoices);
41
42   $self->number_columns([ grep { !m/^(?:month|year|quarter)$/ } @columns ]);
43
44   my %column_defs          = (
45     month                  => { text => t8('Month')                  },
46     year                   => { text => t8('Year')                   },
47     quarter                => { text => t8('Quarter')                },
48     sales_quotations       => { text => t8('Sales Quotations')       },
49     sales_orders           => { text => t8('Sales Orders')           },
50     sales_invoices         => { text => t8('Invoices')               },
51     requests_for_quotation => { text => t8('Requests for Quotation') },
52     purchase_orders        => { text => t8('Purchase Orders')        },
53     purchase_invoices      => { text => t8('Purchase Invoices')      },
54   );
55
56   map { $column_defs{$_}->{align} = 'right' } @columns;
57
58   $self->report->set_options(
59     std_column_visibility => 1,
60     controller_class      => 'FinancialOverview',
61     output_format         => 'HTML',
62     raw_top_info_text     => $self->render('financial_overview/report_top', { output => 0 }, YEARS_TO_LIST => [ reverse(2000..$self->current_year) ]),
63     title                 => t8('Financial overview for #1', $self->year),
64     allow_pdf_export      => 1,
65     allow_csv_export      => 1,
66   );
67   $self->report->set_columns(%column_defs);
68   $self->report->set_column_order(@columns);
69   $self->report->set_export_options(qw(list year subtotals_per_quarter salesman_id));
70   $self->report->set_options_from_form;
71 }
72
73 sub get_objects {
74   my ($self) = @_;
75
76   $self->current_year(DateTime->today->year);
77   $self->year($::form->{year} || DateTime->today->year);
78
79   my $start       = DateTime->new(year => $self->year, month => 1, day => 1);
80   my $end         = DateTime->new(year => $self->year, month => 12, day => 31);
81
82   my @f_date      = (transdate => { ge => $start }, transdate => { le => $end });
83   my @f_salesman  = $self->salesman_id ? (salesman_id => $self->salesman_id) : ();
84
85   $self->objects({
86     sales_quotations       => SL::DB::Manager::Order->get_all(          where => [ and => [ @f_date, @f_salesman, SL::DB::Manager::Order->type_filter('sales_quotation')   ]]),
87     sales_orders           => SL::DB::Manager::Order->get_all(          where => [ and => [ @f_date, @f_salesman, SL::DB::Manager::Order->type_filter('sales_order')       ]]),
88     requests_for_quotation => SL::DB::Manager::Order->get_all(          where => [ and => [ @f_date, @f_salesman, SL::DB::Manager::Order->type_filter('request_quotation') ]]),
89     purchase_orders        => SL::DB::Manager::Order->get_all(          where => [ and => [ @f_date, @f_salesman, SL::DB::Manager::Order->type_filter('purchase_order')    ]]),
90     sales_invoices         => SL::DB::Manager::Invoice->get_all(        where => [ and => [ @f_date, @f_salesman, ]]),
91     purchase_invoices      => SL::DB::Manager::PurchaseInvoice->get_all(where => [ and =>  \@f_date ]),
92   });
93 }
94
95 sub calculate_data {
96   my ($self) = @_;
97
98   $self->types([ qw(sales_quotations sales_orders sales_invoices requests_for_quotation purchase_orders purchase_invoices) ]);
99
100   my %data  = (
101     year    => [ ($self->year) x 12                   ],
102     month   => [ (1..12)                              ],
103     quarter => [ (1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4) ],
104     map {
105       $_ => {
106         months   => [ (0) x 12 ],
107         quarters => [ (0) x  4 ],
108         year     => 0,
109       }
110     } @{ $self->types },
111   );
112
113   foreach my $type (keys %{ $self->objects }) {
114     foreach my $object (@{ $self->objects->{ $type } }) {
115       my $month                              = $object->transdate->month - 1;
116       my $tdata                              = $data{$type};
117
118       $tdata->{months}->[$month]            += $object->netamount;
119       $tdata->{quarters}->[int($month / 3)] += $object->netamount;
120       $tdata->{year}                        += $object->netamount;
121     }
122   }
123
124   $self->data(\%data);
125 }
126
127 sub list_data {
128   my ($self)           = @_;
129
130   my @visible_columns  = $self->report->get_visible_columns;
131   my @type_columns     = @{ $self->types };
132   my @non_type_columns = grep { my $c = $_; none { $c eq $_ } @type_columns } @visible_columns;
133
134   for my $month (1..12) {
135     my %data  = (
136       map({ ($_ => { data => $self->data->{$_}->[$month - 1]                                                    }) } @non_type_columns),
137       map({ ($_ => { data => $::form->format_amount(\%::myconfig, $self->data->{$_}->{months}->[$month - 1], 2) }) } @type_columns    ),
138     );
139
140     $self->report->add_data(\%data);
141
142     if ($self->subtotals_per_quarter && (($month % 3) == 0)) {
143       my %subtotal =  (
144         year       => { data => $self->year },
145         month      => { data => $::locale->text('Total') },
146         map { ($_ => { data => $::form->format_amount(\%::myconfig, $self->data->{$_}->{quarters}->[int(($month - 1) / 3)], 2) }) } @type_columns,
147       );
148
149       $subtotal{$_}->{class} = 'listsubtotal' for @visible_columns;
150
151       $self->report->add_data(\%subtotal);
152     }
153   }
154
155   my %data  =  (
156     year    => { data => $self->year },
157     quarter => { data => $::locale->text('Total') },
158     map { ($_ => { data => $::form->format_amount(\%::myconfig, $self->data->{$_}->{year}, 2) }) } @type_columns,
159   );
160
161   $data{$_}->{class} = 'listtotal' for @visible_columns;
162
163   $self->report->add_data(\%data);
164
165   return $self->report->generate_with_headers;
166 }
167
168 sub init_employees { SL::DB::Manager::Employee->get_all_sorted }
169
170 1;