EB/SB Buchungen minimale Kindersicherung für Datumswerte
[kivitendo-erp.git] / SL / Controller / YearEndTransactions.pm
1 package SL::Controller::YearEndTransactions;
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 SL::Presenter::Tag qw(checkbox_tag);
19
20 use Rose::Object::MakeMethods::Generic (
21   'scalar --get_set_init' => [ qw(charts charts9000 cbob_chart cb_date cb_startdate ob_date cb_reference ob_reference cb_description ob_description) ],
22 );
23
24 __PACKAGE__->run_before('check_auth');
25
26 sub action_filter {
27   my ($self) = @_;
28   $self->ob_date(DateTime->today->truncate(to => 'year'))                  if !$self->ob_date;
29   $self->cb_date(DateTime->today->truncate(to => 'year')->add(days => -1)) if !$self->cb_date;
30   $self->ob_reference(t8('OB Transaction'))   if !$self->ob_reference;
31   $self->cb_reference(t8('CB Transaction'))   if !$self->cb_reference;
32   $self->ob_description(t8('OB Transaction')) if !$self->ob_description;
33   $self->cb_description(t8('CB Transaction')) if !$self->cb_description;
34
35   $self->setup_filter_action_bar;
36   $self->render('gl/yearend_filter',
37                 title               => t8('CB/OB Transactions'),
38                 make_title_of_chart => sub { $_[0]->accno.' '.$_[0]->description }
39                );
40
41 }
42
43 sub action_list {
44   my ($self) = @_;
45   $main::lxdebug->enter_sub();
46
47   my $report     = SL::ReportGenerator->new(\%::myconfig, $::form);
48
49   $self->prepare_report($report);
50
51   $report->set_options(
52     output_format        => 'HTML',
53     raw_top_info_text    => $::form->parse_html_template('gl/yearend_top',    { SELF => $self }),
54     raw_bottom_info_text => $::form->parse_html_template('gl/yearend_bottom', { SELF => $self }),
55     allow_pdf_export     => 0,
56     allow_csv_export     => 0,
57     title                => $::locale->text('CB/OB Transactions'),
58   );
59
60   $self->setup_list_action_bar;
61   $report->generate_with_headers();
62   $main::lxdebug->leave_sub();
63 }
64
65 sub action_generate {
66   my ($self) = @_;
67
68   if ($self->cb_date > $self->ob_date) {
69     flash ('error', $::locale->text('CB date #1 is higher than OB date #2. Please select again.', $self->cb_date, $self->ob_date));
70   } else {
71     my $cnt = $self->make_booking();
72     flash('info', $::locale->text('#1 CB transactions and #1 OB transactions generated.',$cnt)) if $cnt > 0;
73   }
74   $self->action_list;
75 }
76
77 sub check_auth {
78   $::auth->assert('general_ledger');
79 }
80
81 #
82 # helpers
83 #
84
85 sub make_booking {
86   my ($self) = @_;
87   $main::lxdebug->enter_sub();
88   my @ids = map { $::form->{"multi_id_$_"} } grep { $::form->{"multi_id_$_"} } (1..$::form->{rowcount});
89   my $cnt = 0;
90   $main::lxdebug->message(LXDebug->DEBUG2(),"generate for ".$::form->{cbob_chart}." # ".scalar(@ids)." charts");
91   if (scalar(@ids) && $::form->{cbob_chart}) {
92     my $carryoverchart = SL::DB::Manager::Chart->get_first(  query => [ id => $::form->{cbob_chart} ] );
93     my $charts = SL::DB::Manager::Chart->get_all(  query => [ id => \@ids ] );
94     foreach my $chart (@{ $charts }) {
95       $main::lxdebug->message(LXDebug->DEBUG2(),"chart_id=".$chart->id." accno=".$chart->accno);
96       my $balance = $self->get_balance($chart);
97       if ( $balance != 0 ) {
98         # SB
99         $self->gl_booking($balance,$self->cb_date,$::form->{cb_reference},$::form->{cb_description},$chart,$carryoverchart,0,1);
100         # EB
101         $self->gl_booking($balance,$self->ob_date,$::form->{ob_reference},$::form->{ob_description},$carryoverchart,$chart,1,0);
102         $cnt++;
103       }
104     }
105   }
106   $main::lxdebug->leave_sub();
107   return $cnt;
108 }
109
110
111 sub prepare_report {
112   my ($self,$report) = @_;
113   $main::lxdebug->enter_sub();
114   my $idx = 1;
115
116   my %column_defs = (
117     'ids'         => { raw_header_data => checkbox_tag("", id => "check_all",
118                                                                           checkall => "[data-checkall=1]"), 'align' => 'center' },
119     'chart'       => { text => $::locale->text('Account'), },
120     'description' => { text => $::locale->text('Description'), },
121     'saldo'       => { text => $::locale->text('Saldo'),  'align' => 'right'},
122     'sum_cb'      => { text => $::locale->text('Sum CB Transactions'), 'align' => 'right'},  ##close == Schluss
123     'sum_ob'      => { text => $::locale->text('Sum OB Transactions'), 'align' => 'right'},  ##open  == Eingang
124   );
125   my @columns      = qw(ids chart description saldo sum_cb sum_ob);
126   map { $column_defs{$_}->{visible} = 1 } @columns;
127
128   my $ob_next_date = $self->ob_date->clone();
129   $ob_next_date->add(years => 1)->add(days => -1);
130
131   $self->cb_startdate($::locale->parse_date_to_object($self->get_balance_starting_date($self->cb_date)));
132
133   my @custom_headers = ();
134   # Zeile 1:
135   push @custom_headers, [
136       { 'text' => '   ', 'colspan' => 3 },
137       { 'text' => $::locale->text("Timerange")."<br />".$self->cb_startdate->to_kivitendo." - ".$self->cb_date->to_kivitendo, 'colspan' => 2, 'align' => 'center'},
138       { 'text' => $::locale->text("Timerange")."<br />".$self->ob_date->to_kivitendo." - ".$ob_next_date->to_kivitendo, 'align' => 'center'},
139     ];
140
141   # Zeile 2:
142   my @line_2 = ();
143   map { push @line_2 , $column_defs{$_} } grep { $column_defs{$_}->{visible} } @columns;
144   push @custom_headers, [ @line_2 ];
145
146   $report->set_custom_headers(@custom_headers);
147   $report->set_columns(%column_defs);
148   $report->set_column_order(@columns);
149
150   my $chart9actual = SL::DB::Manager::Chart->get_first( query => [ id => $self->cbob_chart ] );
151   $self->{cbob_chartaccno} = $chart9actual->accno.' '.$chart9actual->description;
152
153   foreach my $chart (@{ $self->charts }) {
154     my $balance = $self->get_balance($chart);
155     if ( $balance != 0 ) {
156       my $chart_id = $chart->id;
157       my $row = { map { $_ => { 'data' => '' } } @columns };
158       $row->{ids}  = {
159         'raw_data' => checkbox_tag("multi_id_${idx}", value => $chart_id, "data-checkall" => 1),
160         'valign'   => 'center',
161         'align'    => 'center',
162       };
163       $row->{chart}->{data}       = $chart->accno;
164       $row->{description}->{data} = $chart->description;
165       if ( $balance > 0 ) {
166         $row->{saldo}->{data} = $::form->format_amount(\%::myconfig, $balance, 2)." H";
167       } elsif ( $balance < 0 )  {
168         $row->{saldo}->{data} = $::form->format_amount(\%::myconfig,-$balance, 2)." S";
169       } else {
170         $row->{saldo}->{data} = $::form->format_amount(\%::myconfig,0, 2)."  ";
171       }
172       my $sum_cb = 0;
173       foreach my $acc ( @{ SL::DB::Manager::AccTransaction->get_all(where => [ chart_id  => $chart->id, cb_transaction => 't',
174                                                                                transdate => { ge => $self->cb_startdate},
175                                                                                transdate => { le => $self->cb_date }
176                                                                              ]) }) {
177         $sum_cb += $acc->amount;
178       }
179       my $sum_ob = 0;
180       foreach my $acc ( @{ SL::DB::Manager::AccTransaction->get_all(where => [ chart_id  => $chart->id, ob_transaction => 't',
181                                                                                transdate => { ge => $self->ob_date},
182                                                                                transdate => { le => $ob_next_date }
183                                                                              ]) }) {
184         $sum_ob += $acc->amount;
185       }
186       if ( $sum_cb > 0 ) {
187         $row->{sum_cb}->{data} = $::form->format_amount(\%::myconfig, $sum_cb, 2)." H";
188       } elsif ( $sum_cb < 0 )  {
189         $row->{sum_cb}->{data} = $::form->format_amount(\%::myconfig,-$sum_cb, 2)." S";
190       } else {
191         $row->{sum_cb}->{data} = $::form->format_amount(\%::myconfig,0, 2)."  ";
192       }
193       if ( $sum_ob > 0 ) {
194         $row->{sum_ob}->{data} = $::form->format_amount(\%::myconfig, $sum_ob, 2)." H";
195       } elsif ( $sum_ob < 0 )  {
196         $row->{sum_ob}->{data} = $::form->format_amount(\%::myconfig,-$sum_ob, 2)." S";
197       } else {
198         $row->{sum_ob}->{data} = $::form->format_amount(\%::myconfig,0, 2)."  ";
199       }
200       $report->add_data($row);
201     }
202     $idx++;
203   }
204
205   $self->{row_count} = $idx;
206   $main::lxdebug->leave_sub();
207 }
208
209 sub get_balance {
210   $main::lxdebug->enter_sub();
211   my ($self,$chart) = @_;
212
213   #$main::lxdebug->message(LXDebug->DEBUG2(),"get_balance from=".$self->cb_startdate->to_kivitendo." to=".$self->cb_date->to_kivitendo);
214   my $balance = $chart->get_balance(fromdate => $self->cb_startdate, todate => $self->cb_date);
215   $main::lxdebug->leave_sub();
216   return 0 if !defined $balance || $balance == 0;
217   return $balance;
218 }
219
220 sub gl_booking {
221   my ($self, $amount, $transdate, $reference, $description, $konto, $gegenkonto, $ob, $cb) = @_;
222   $::form->get_employee();
223   my $employee_id = $::form->{employee_id};
224   $main::lxdebug->message(LXDebug->DEBUG2(),"employee_id=".$employee_id." ob=".$ob." cb=".$cb);
225   my $gl_entry = SL::DB::GLTransaction->new(
226     employee_id    => $employee_id,
227     transdate      => $transdate,
228     reference      => $reference,
229     description    => $description,
230     ob_transaction => $ob,
231     cb_transaction => $cb,
232   );
233   #$gl_entry->save;
234   my $kto_trans1 = SL::DB::AccTransaction->new(
235     trans_id       => $gl_entry->id,
236     transdate      => $transdate,
237     ob_transaction => $ob,
238     cb_transaction => $cb,
239     chart_id       => $gegenkonto->id,
240     chart_link     => $konto->link,
241     tax_id         => 0,
242     taxkey         => 0,
243     amount         => $amount,
244   );
245   #$kto_trans1->save;
246   my $kto_trans2 = SL::DB::AccTransaction->new(
247     trans_id       => $gl_entry->id,
248     transdate      => $transdate,
249     ob_transaction => $ob,
250     cb_transaction => $cb,
251     chart_id       => $konto->id,
252     chart_link     => $konto->link,
253     tax_id         => 0,
254     taxkey         => 0,
255     amount         => -$amount,
256   );
257   #$kto_trans2->save;
258   $gl_entry->add_transactions($kto_trans1);
259   $gl_entry->add_transactions($kto_trans2);
260   $gl_entry->save;
261 }
262
263 sub init_cbob_chart     { $::form->{cbob_chart}                                    }
264 sub init_ob_date        { $::locale->parse_date_to_object($::form->{ob_date})      }
265 sub init_ob_reference   { $::form->{ob_reference}                                  }
266 sub init_ob_description { $::form->{ob_description}                                }
267 sub init_cb_startdate   { $::locale->parse_date_to_object($::form->{cb_startdate}) }
268 sub init_cb_date        { $::locale->parse_date_to_object($::form->{cb_date})      }
269 sub init_cb_reference   { $::form->{cb_reference}                                  }
270 sub init_cb_description { $::form->{cb_description}                                }
271
272 sub init_charts9000 {
273   SL::DB::Manager::Chart->get_all(  query => [ accno => { like => '9%'}] );
274 }
275
276 sub init_charts {
277   # wie geht 'not like' in rose ?
278   SL::DB::Manager::Chart->get_all(  query => [ \ "accno not like '9%'"], sort_by => 'accno ASC' );
279 }
280
281 sub setup_filter_action_bar {
282   my ($self) = @_;
283
284   for my $bar ($::request->layout->get('actionbar')) {
285     $bar->add(
286       action => [
287         t8('Continue'),
288         submit    => [ '#filter_form', { action => 'YearEndTransactions/list' } ],
289         accesskey => 'enter',
290       ],
291     );
292   }
293 }
294
295 sub setup_list_action_bar {
296   my ($self) = @_;
297
298   for my $bar ($::request->layout->get('actionbar')) {
299     $bar->add(
300       action => [
301         t8('Post'),
302         submit    => [ '#form', { action => 'YearEndTransactions/generate' } ],
303         tooltip   => t8('generate cb/ob transactions for selected charts'),
304         confirm   => t8('Are you sure to generate cb/ob transactions?'),
305         accesskey => 'enter',
306       ],
307       action => [
308         t8('Back'),
309         call => [ 'kivi.history_back' ],
310       ],
311     );
312   }
313 }
314
315 1;