2639ef66ce773df5078063e06a1459d4a8a87e5b
[kivitendo-erp.git] / SL / Controller / YearlyTransactions.pm
1 package SL::Controller::YearlyTransactions;
2
3 use strict;
4
5 use parent qw(SL::Controller::Base);
6
7 use DateTime;
8 use SL::Locale::String qw(t8);
9 use SL::ReportGenerator;
10 use SL::Helper::Flash;
11 use SL::DBUtils;
12
13 use SL::DB::Chart;
14 use SL::DB::GLTransaction;
15 use SL::DB::AccTransaction;
16 use SL::DB::Helper::AccountingPeriod qw(get_balance_starting_date);
17
18 use Rose::Object::MakeMethods::Generic (
19   'scalar --get_set_init' => [ qw(charts charts9000 cbob_chart cb_date cb_startdate ob_date cb_reference ob_reference cb_description ob_description) ],
20 );
21
22 __PACKAGE__->run_before('check_auth');
23
24 sub action_filter {
25   my ($self) = @_;
26
27   $self->ob_date(DateTime->today->truncate(to => 'year'))                  if !$self->ob_date;
28   $self->cb_date(DateTime->today->truncate(to => 'year')->add(days => -1)) if !$self->cb_date;
29   $self->ob_reference(t8('OB Transaction')) if !$self->ob_reference;
30   $self->cb_reference(t8('CB Transaction')) if !$self->cb_reference;
31   $self->ob_description(t8('OB Transaction')) if !$self->ob_description;
32   $self->cb_description(t8('CB Transaction')) if !$self->cb_description;
33   $self->render('gl/yearly_filter', 
34                 title => t8('CB/OB Transactions'),
35                 make_title_of_chart => sub { $_[0]->accno.' '.$_[0]->description }
36                );
37
38 }
39
40 sub action_list {
41   my ($self) = @_;
42   $main::lxdebug->enter_sub();
43
44   my $report     = SL::ReportGenerator->new(\%::myconfig, $::form);
45
46   $self->prepare_report($report);
47
48   $report->set_options(
49     output_format    => 'HTML',
50     raw_top_info_text    => $::form->parse_html_template('gl/yearly_top', { SELF => $self }),
51     raw_bottom_info_text => $::form->parse_html_template('gl/yearly_bottom', { SELF => $self }),
52     allow_pdf_export => 0,
53     allow_csv_export => 0,
54     title            => $::locale->text('CB/OB Transactions'),
55     );
56   $report->generate_with_headers();
57   $main::lxdebug->leave_sub();
58 }
59
60 sub action_generate {
61   my ($self) = @_;
62
63   my $cnt = $self->make_booking();
64
65   flash('info', $::locale->text('#1 CB transactions and #1 OB transactions generated.',$cnt)) if $cnt > 0;
66
67   $self->action_list;
68 }
69
70 sub check_auth {
71   $::auth->assert('general_ledger');
72 }
73
74 #
75 # helpers
76 #
77
78 sub make_booking {
79   my ($self) = @_;
80   $main::lxdebug->enter_sub();
81   my @ids = map { $::form->{"trans_id_$_"} } grep { $::form->{"multi_id_$_"} } (1..$::form->{rowcount});
82   my $cnt = 0;
83   $main::lxdebug->message(LXDebug->DEBUG2(),"generate for ".$::form->{cbob_chart}." # ".scalar(@ids)." charts");
84   if (scalar(@ids) && $::form->{cbob_chart}) {
85     my $carryoverchart = SL::DB::Manager::Chart->get_first(  query => [ id => $::form->{cbob_chart} ] );
86     my $charts = SL::DB::Manager::Chart->get_all(  query => [ id => \@ids ] );
87     foreach my $chart (@{ $charts }) {
88       $main::lxdebug->message(LXDebug->DEBUG2(),"chart_id=".$chart->id." accno=".$chart->accno);
89       my $balance = $self->get_balance($chart);
90       if ( $balance != 0 ) {
91         # SB
92         $self->gl_booking($balance,$self->cb_date,$::form->{cb_reference},$::form->{cb_description},$chart,$carryoverchart,0,1);
93         # EB
94         $self->gl_booking($balance,$self->ob_date,$::form->{ob_reference},$::form->{ob_description},$carryoverchart,$chart,1,0);
95         $cnt++;
96       }
97     }
98   }
99   $main::lxdebug->leave_sub();
100   return $cnt;
101 }
102
103
104 sub prepare_report {
105   my ($self,$report) = @_;
106   $main::lxdebug->enter_sub();
107   my $idx = 1;
108   my $cgi = $::request->{cgi};
109
110   my %column_defs = (
111     'ids'                     => { 'text' => '<input type="checkbox" id="multi_all" value="1">', 'align' => 'center' },
112     'chart'                   => { 'text' => $::locale->text('Account'), },
113     'description'             => { 'text' => $::locale->text('Description'), },
114     'saldo'                   => { 'text' => $::locale->text('Saldo'),  'align' => 'right'},
115     'sum_cb'                  => { 'text' => $::locale->text('Sum CB Transactions'), 'align' => 'right'},  ##close == Schluss
116     'sum_ob'                  => { 'text' => $::locale->text('Sum OB Transactions'), 'align' => 'right'},  ##open  == Eingang
117   );
118   my @columns    = qw(ids chart description saldo sum_cb sum_ob);
119   map { $column_defs{$_}->{visible} = 1 } @columns;
120   my $ob_next_date = $::locale->parse_date_to_object($self->ob_date)->add(years => 1)->add(days => -1)->to_kivitendo;
121
122   $self->cb_startdate($self->get_balance_starting_date($self->cb_date));
123
124   my @custom_headers = ();
125   # Zeile 1:
126   push @custom_headers, [
127       { 'text' => '   ', 'colspan' => 3 },
128       { 'text' => $::locale->text("Timerange")."<br />".$self->cb_startdate." - ".$self->cb_date, 'colspan' => 2, 'align' => 'center'},
129       { 'text' => $::locale->text("Timerange")."<br />".$self->ob_date." - ".$ob_next_date, 'align' => 'center'},
130     ];
131
132   # Zeile 2:
133   my @line_2 = ();
134   map { push @line_2 , $column_defs{$_} } grep { $column_defs{$_}->{visible} } @columns;
135   push @custom_headers, [ @line_2 ];
136
137   $report->set_custom_headers(@custom_headers);
138   $report->set_columns(%column_defs);
139   $report->set_column_order(@columns);
140
141   my $chart9actual = SL::DB::Manager::Chart->get_first( query => [ id => $self->cbob_chart ] );
142   $self->{cbob_chartaccno} = $chart9actual->accno.' '.$chart9actual->description;
143
144   foreach my $chart (@{ $self->charts }) {
145     my $balance = $self->get_balance($chart);
146     if ( $balance != 0 ) {
147       my $chart_id = $chart->id;
148       my $row = { map { $_ => { 'data' => '' } } @columns };
149       $row->{ids}  = {
150         'raw_data' =>   $cgi->hidden('-name' => "trans_id_${idx}", '-value' => $chart_id)
151                     . $cgi->checkbox('-name' => "multi_id_${idx}",' id' => "multi_id_id_".$chart_id, '-value' => 1, '-label' => ''),
152             'valign'   => 'center',
153             'align'    => 'center',
154       };
155       $row->{chart}->{data}        = $chart->accno;
156       $row->{description}->{data}  = $chart->description;
157       if ( $balance > 0 ) {
158         $row->{saldo}->{data} = $::form->format_amount(\%::myconfig, $balance, 2)." H";
159       } elsif ( $balance < 0 )  {
160         $row->{saldo}->{data} = $::form->format_amount(\%::myconfig,-$balance, 2)." S";
161       } else {
162         $row->{saldo}->{data} = $::form->format_amount(\%::myconfig,0, 2)."  ";
163       }
164       my $sum_cb = 0;
165       foreach my $acc ( @{ SL::DB::Manager::AccTransaction->get_all(where => [ chart_id => $chart->id, cb_transaction => 't',
166                                                                                transdate => { ge => $self->cb_startdate},
167                                                                                transdate => { le => $self->cb_date }]) }) {
168         $sum_cb += $acc->amount;
169       }
170       my $sum_ob = 0;
171       foreach my $acc ( @{ SL::DB::Manager::AccTransaction->get_all(where => [ chart_id => $chart->id, ob_transaction => 't',
172                                                                                transdate => { ge => $self->ob_date},
173                                                                                transdate => { le => $ob_next_date }]) }) {
174         $sum_ob += $acc->amount;
175       }
176       if ( $sum_cb > 0 ) {
177         $row->{sum_cb}->{data} = $::form->format_amount(\%::myconfig, $sum_cb, 2)." H";
178       } elsif ( $sum_cb < 0 )  {
179         $row->{sum_cb}->{data} = $::form->format_amount(\%::myconfig,-$sum_cb, 2)." S";
180       } else {
181         $row->{sum_cb}->{data} = $::form->format_amount(\%::myconfig,0, 2)."  ";
182       }
183       if ( $sum_ob > 0 ) {
184         $row->{sum_ob}->{data} = $::form->format_amount(\%::myconfig, $sum_ob, 2)." H";
185       } elsif ( $sum_ob < 0 )  {
186         $row->{sum_ob}->{data} = $::form->format_amount(\%::myconfig,-$sum_ob, 2)." S";
187       } else {
188         $row->{sum_ob}->{data} = $::form->format_amount(\%::myconfig,0, 2)."  ";
189       }
190       $report->add_data($row);
191     }
192     $idx++;
193   }
194
195   $self->{row_count} = $idx;
196   $main::lxdebug->leave_sub();
197 }
198
199 sub get_balance {
200   $main::lxdebug->enter_sub();
201   my ($self,$chart) = @_;
202
203 ## eigene Abfrage da SL:DB:Chart->get_balance keine cb_transactions mitzählt
204 ## Alternative in Chart cb_transaction abfrage per neuem Parameter 'with_cb' disablen:
205 #  my %balance_params = ( fromdate   => $self->startdate,
206 #                         todate     => $self->cb_date,
207 #                         accounting_method => 'accrual',
208 #                         with_cb    => 1, ## in Chart cb_transaction abfrage disablen
209 #                       );
210 #  return $chart->get_balance(%balance_params);
211
212   $main::lxdebug->message(LXDebug->DEBUG2(),"get_balance from=".$self->cb_startdate." to=".$self->cb_date);
213   my $query = qq|SELECT SUM(amount) AS sum FROM acc_trans WHERE chart_id = ? | .
214               qq| AND transdate >= ? AND transdate <= ? |;
215   my @query_args = ( $chart->id, $self->cb_startdate, $self->cb_date);
216   my ($balance)  = selectfirst_array_query($::form, $chart->db->dbh, $query, @query_args);
217
218   $main::lxdebug->leave_sub();
219   return 0 unless $balance != 0;
220   return $balance;
221 }
222
223 sub gl_booking {
224   my ($self, $amount, $transdate, $reference, $description, $konto, $gegenkonto, $ob, $cb) = @_;
225   $::form->get_employee();
226   my $employee_id = $::form->{employee_id};
227   $main::lxdebug->message(LXDebug->DEBUG2(),"employee_id=".$employee_id." ob=".$ob." cb=".$cb);
228   my $gl_entry = SL::DB::GLTransaction->new();
229   $gl_entry->assign_attributes(
230     employee_id => $employee_id,
231     transdate   => $transdate,
232     reference   => $reference,
233     description => $description,
234     ob_transaction => $ob,
235     cb_transaction => $cb,
236   );
237   $gl_entry->save;
238   my $kto_trans1 = SL::DB::AccTransaction->new();
239   $kto_trans1->assign_attributes(
240     trans_id    => $gl_entry->id,
241     transdate   => $transdate,
242     ob_transaction => $ob,
243     cb_transaction => $cb,
244     chart_id       => $gegenkonto->id,
245     chart_link     => $konto->link,
246     tax_id         => 0,
247     taxkey         => 0,
248     amount         => $amount,
249   );
250   $kto_trans1->save;
251   my $kto_trans2 = SL::DB::AccTransaction->new();
252   $kto_trans2->assign_attributes(
253     trans_id    => $gl_entry->id,
254     transdate   => $transdate,
255     ob_transaction => $ob,
256     cb_transaction => $cb,
257     chart_id       => $konto->id,
258     chart_link     => $konto->link,
259     tax_id         => 0,
260     taxkey         => 0,
261     amount         => -$amount,
262   );
263   $kto_trans2->save;
264 }
265
266 sub init_cbob_chart { $::form->{cbob_chart} }
267 sub init_ob_date { $::form->{ob_date} }
268 sub init_ob_reference { $::form->{ob_reference} }
269 sub init_ob_description { $::form->{ob_description} }
270 sub init_cb_startdate { $::form->{cb_startdate} }
271 sub init_cb_date { $::form->{cb_date} }
272 sub init_cb_reference { $::form->{cb_reference} }
273 sub init_cb_description { $::form->{cb_description} }
274
275 sub init_charts9000 { 
276   # wie geht prüfen von länge auf 4 in rose ?
277   SL::DB::Manager::Chart->get_all(  query => [ \ "accno like '9%' and length(accno) = 4"] );
278   #SL::DB::Manager::Chart->get_all(  query => [ accno => { like => '9%'}] );
279 }
280
281 sub init_charts { 
282   # wie geht 'not like' in rose ?
283   SL::DB::Manager::Chart->get_all(  query => [ \ "accno not like '9%'"], sort_by => 'accno ASC' );
284 }
285
286 1;