1bfd3905df43ba5db0d9228555034c87b3da775f
[kivitendo-erp.git] / SL / Controller / Reconciliation.pm
1 package SL::Controller::Reconciliation;
2
3 use strict;
4
5 use parent qw(SL::Controller::Base);
6
7 use SL::Locale::String;
8 use SL::JSON;
9 use SL::Controller::Helper::ParseFilter;
10 use SL::Helper::Flash;
11
12 use SL::DB::BankTransaction;
13 use SL::DB::Manager::BankAccount;
14 use SL::DB::AccTransaction;
15 use SL::DB::ReconciliationLink;
16 use List::Util qw(sum);
17
18 use Rose::Object::MakeMethods::Generic (
19   'scalar --get_set_init' => [ qw(cleared BANK_ACCOUNTS) ],
20 );
21
22 __PACKAGE__->run_before('check_auth');
23 __PACKAGE__->run_before('_bank_account');
24
25 #
26 # actions
27 #
28
29 sub action_search {
30   my ($self) = @_;
31
32   $self->render('reconciliation/search');
33 }
34
35 sub action_reconciliation {
36   my ($self) = @_;
37
38   $self->_get_proposals;
39
40   $self->_get_linked_transactions;
41
42   $self->_get_balances;
43
44   $self->render('reconciliation/form',
45                 ui_tab => scalar(@{$self->{PROPOSALS}}) > 0?1:0,
46                 title => t8('Reconciliation'));
47 }
48
49 sub action_load_overview {
50   my ($self) = @_;
51
52   $self->_get_proposals;
53
54   $self->_get_linked_transactions;
55
56   $self->_get_balances;
57
58   my $output = $self->render('reconciliation/tabs/overview', { output => 0 });
59   my %result = ( html => $output );
60
61   $self->render(\to_json(\%result), { type => 'json', process => 0 });
62 }
63
64 sub action_filter_overview {
65   my ($self) = @_;
66
67   $self->_get_linked_transactions;
68   $self->_get_balances;
69
70   my $output = $self->render('reconciliation/_linked_transactions', { output => 0 });
71   my %result = ( html               => $output,
72                  absolut_bt_balance => $::form->format_amount(\%::myconfig,      $self->{absolut_bt_balance}, 2),
73                  absolut_bb_balance => $::form->format_amount(\%::myconfig, -1 * $self->{absolut_bb_balance}, 2),
74                  bt_balance         => $::form->format_amount(\%::myconfig,      $self->{bt_balance}, 2),
75                  bb_balance         => $::form->format_amount(\%::myconfig, -1 * $self->{bb_balance}, 2)
76                  );
77
78   $self->render(\to_json(\%result), { type => 'json', process => 0 });
79 }
80
81 sub action_update_reconciliation_table {
82   my ($self) = @_;
83
84   my @errors = $self->_get_elements_and_validate();
85
86   my $output = $self->render('reconciliation/assigning_table', { output => 0 },
87                  bt_sum => $::form->format_amount(\%::myconfig, $self->{bt_sum}, 2),
88                  bb_sum => $::form->format_amount(\%::myconfig, -1 * $self->{bb_sum}, 2),
89                  show_button => !@errors
90                  );
91
92   my %result = ( html => $output );
93
94   $self->render(\to_json(\%result), { type => 'json', process => 0 });
95 }
96
97 sub action_reconcile {
98   my ($self) = @_;
99
100   #Check elements
101   my @errors = $self->_get_elements_and_validate;
102
103   if (@errors) {
104     unshift(@errors, (t8('Could not reconcile chosen elements!')));
105     flash('error', @errors);
106     $self->action_reconciliation;
107     return;
108   }
109
110   $self->_reconcile;
111
112   $self->action_reconciliation;
113 }
114
115 sub action_delete_reconciliation {
116   my ($self) = @_;
117
118   my $rec_links = SL::DB::Manager::ReconciliationLink->get_all(where => [ rec_group => $::form->{rec_group} ]);
119
120   foreach my $rec_link (@{ $rec_links }) {
121     my $bank_transaction = SL::DB::Manager::BankTransaction->find_by( id           => $rec_link->bank_transaction_id );
122     my $acc_transaction  = SL::DB::Manager::AccTransaction ->find_by( acc_trans_id => $rec_link->acc_trans_id        );
123
124     $bank_transaction->cleared('0');
125     $acc_transaction->cleared('0');
126
127     $bank_transaction->save;
128     $acc_transaction->save;
129
130     $rec_link->delete;
131   }
132
133   $self->_get_linked_transactions;
134   $self->_get_balances;
135
136   my $output = $self->render('reconciliation/_linked_transactions', { output => 0 });
137   my %result = ( html               => $output,
138                  absolut_bt_balance => $::form->format_amount(\%::myconfig,      $self ->{absolut_bt_balance}, 2),
139                  absolut_bb_balance => $::form->format_amount(\%::myconfig, -1 * $self ->{absolut_bb_balance}, 2),
140                  bt_balance         => $::form->format_amount(\%::myconfig,      $self ->{bt_balance}, 2),
141                  bb_balance         => $::form->format_amount(\%::myconfig, -1 * $self ->{bb_balance}, 2)
142                  );
143
144   $self->render(\to_json(\%result), { type => 'json', process => 0 });
145 }
146
147 sub action_load_proposals {
148   my ($self) = @_;
149
150   $self->_get_proposals;
151
152   my $output = $self->render('reconciliation/tabs/automatic', { output => 0 });
153   my %result = ( html => $output );
154
155   $self->render(\to_json(\%result), { type => 'json', process => 0 });
156 }
157
158 sub action_filter_proposals {
159   my ($self) = @_;
160
161   $self->_get_balances;
162   $self->_get_proposals;
163
164   my $output = $self->render('reconciliation/proposals', { output => 0 });
165   my %result = ( html               => $output,
166                  absolut_bt_balance => $::form->format_amount(\%::myconfig,      $self ->{absolut_bt_balance}, 2),
167                  absolut_bb_balance => $::form->format_amount(\%::myconfig, -1 * $self ->{absolut_bb_balance}, 2),
168                  bt_balance         => $::form->format_amount(\%::myconfig,      $self ->{bt_balance}, 2),
169                  bb_balance         => $::form->format_amount(\%::myconfig, -1 * $self ->{bb_balance}, 2)
170                  );
171
172   $self->render(\to_json(\%result), { type => 'json', process => 0 });
173 }
174
175 sub action_reconcile_proposals {
176   my ($self) = @_;
177
178   my $counter = 0;
179
180   foreach my $bt_id ( @{ $::form->{bt_ids} }) {
181     my $rec_group = SL::DB::Manager::ReconciliationLink->get_new_rec_group();
182     my $bank_transaction = SL::DB::Manager::BankTransaction->find_by(id => $bt_id);
183     $bank_transaction->cleared('1');
184     if ( $bank_transaction->isa('SL::DB::BankTransaction') ) {
185       $bank_transaction->invoice_amount($bank_transaction->amount);
186     }
187     $bank_transaction->save;
188     foreach my $acc_trans_id (@{ $::form->{proposal_list}->{$bt_id}->{BB} }) {
189       SL::DB::ReconciliationLink->new(
190         rec_group => $rec_group,
191         bank_transaction_id => $bt_id,
192         acc_trans_id => $acc_trans_id
193       )->save;
194       my $acc_trans = SL::DB::Manager::AccTransaction->find_by(acc_trans_id => $acc_trans_id);
195       $acc_trans->cleared('1');
196       $acc_trans->save;
197     }
198     $counter++;
199   }
200
201   flash('ok', t8('#1 proposal(s) saved.', $counter));
202
203   $self->action_reconciliation;
204 }
205
206 #
207 # filters
208 #
209
210 sub check_auth {
211   $::auth->assert('bank_transaction');
212 }
213
214 sub _bank_account {
215   my ($self) = @_;
216   $self->{bank_account} = SL::DB::Manager::BankAccount->find_by(id => $::form->{filter}->{"local_bank_account_id:number"});
217 }
218
219 #
220 # helpers
221 #
222
223 sub _get_proposals {
224   my ($self) = @_;
225
226   # reconciliation suggestion is based on:
227   # * record_link exists (was paid by bank transaction)
228   # or acc_trans entry exists where
229   # * amount is exactly the same
230   # * date is the same
231   # * IBAN or account number have to match exactly (cv details, no spaces)
232   # * not a gl storno
233   # * there is exactly one match for all conditions
234
235   $self->_filter_to_where;
236
237   my $bank_transactions = SL::DB::Manager::BankTransaction->get_all(where => [ @{ $self->{bt_where} }, cleared => '0' ]);
238
239   my $check_sum;
240
241   my @proposals;
242
243   foreach my $bt (@{ $bank_transactions }) {
244     $check_sum = $bt->amount;
245     my $proposal;
246     $proposal->{BT} = $bt;
247     $proposal->{BB} = [];
248
249     # first of all check if any of the bank_transactions are already linked (i.e. were paid via bank transactions)
250     my $linked_records = SL::DB::Manager::RecordLink->get_all(where => [ from_table => 'bank_transactions', from_id => $bt->id ]);
251     foreach my $linked_record (@{ $linked_records }) {
252       my $invoice;
253       if ($linked_record->to_table eq 'ar') {
254         $invoice = SL::DB::Manager::Invoice->find_by(id => $linked_record->to_id);
255         #find payments
256         my $payments = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, chart_link => { like => '%AR_paid%' }, transdate => $bt->transdate ]);
257         foreach my $payment (@{ $payments }) {
258           $check_sum += $payment->amount;
259           push @{ $proposal->{BB} }, $payment;
260         }
261       }
262       if ($linked_record->to_table eq 'ap') {
263         $invoice = SL::DB::Manager::PurchaseInvoice->find_by(id => $linked_record->to_id);
264         #find payments
265         my $payments = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, chart_link => { like => '%AP_paid%' }, transdate => $bt->transdate ]);
266         foreach my $payment (@{ $payments }) {
267           $check_sum += $payment->amount;
268           push @{ $proposal->{BB} }, $payment;
269         }
270       }
271     }
272
273     #add proposal if something in acc_trans was found
274     #otherwise try to find another entry in acc_trans and add it
275     # for linked_records we allow a slight difference / imprecision, for acc_trans search we don't
276     if (scalar @{ $proposal->{BB} } and abs($check_sum) <= 0.01 ) {
277       push @proposals, $proposal;
278     } elsif (!scalar @{ $proposal->{BB} }) {
279       # use account_number and iban for matching remote account number
280       # don't suggest gl stornos (ar and ap stornos shouldn't have any payments)
281
282       my @account_number_match = (
283         ( 'ar.customer.iban'           => $bt->remote_account_number ),
284         ( 'ar.customer.account_number' => $bt->remote_account_number ),
285         ( 'ap.vendor.iban'             => $bt->remote_account_number ),
286         ( 'ap.vendor.account_number'   => $bt->remote_account_number ),
287         ( 'gl.storno'                  => '0' ),
288       );
289
290       my $acc_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ @{ $self->{bb_where} },
291                                                                                  amount => -1 * $bt->amount,
292                                                                                  cleared => '0',
293                                                                                  'transdate' => $bt->transdate,
294                                                                                  or => [ @account_number_match ]
295                                                                                ],
296                                                                        with_objects => [ 'ar', 'ap', 'ar.customer', 'ap.vendor', 'gl' ]);
297       if (scalar @{ $acc_transactions } == 1) {
298         push @{ $proposal->{BB} }, @{ $acc_transactions }[0];
299         push @proposals, $proposal;
300       }
301     }
302   }
303
304   $self->{PROPOSALS} = \@proposals;
305 }
306
307 sub _get_elements_and_validate {
308   my ($self) = @_;
309
310   my @errors;
311
312   if ( not defined $::form->{bt_ids} ) {
313     push @errors, t8('No bank account chosen!');
314   }
315
316   if ( not defined $::form->{bb_ids} ) {
317     push @errors, t8('No transaction on chart bank chosen!');
318   }
319
320   if (!@errors) {
321     if (scalar @{ $::form->{bt_ids} } > 1 and scalar @{ $::form->{bb_ids} } > 1) {
322       push @errors, t8('No 1:n or n:1 relation');
323     }
324   }
325
326   my @elements;
327   my ($bt_sum, $bb_sum) = (0,0);
328
329   foreach my $bt_id (@{ $::form->{bt_ids} }) {
330     my $bt = SL::DB::Manager::BankTransaction->find_by(id => $bt_id);
331     $bt->{type} = 'BT';
332     $bt_sum += $bt->amount;
333     push @elements, $bt;
334   }
335
336   foreach my $bb_id (@{ $::form->{bb_ids} }) {
337     my $bb = SL::DB::Manager::AccTransaction->find_by(acc_trans_id => $bb_id);
338     $bb->{type} = 'BB';
339     $bb->{id} = $bb->acc_trans_id;
340     $bb_sum += $bb->amount;
341     push @elements, $bb;
342   }
343
344   if ($::form->round_amount($bt_sum + $bb_sum, 2) != 0) {
345     push @errors, t8('Out of balance!');
346   }
347
348   $self->{ELEMENTS} = \@elements;
349   $self->{bt_sum} = $bt_sum;
350   $self->{bb_sum} = $bb_sum;
351
352   return @errors;
353 }
354
355 sub _reconcile {
356   my ($self) = @_;
357
358   # 1. step: set AccTrans and BankTransactions to 'cleared'
359   foreach my $element (@{ $self->{ELEMENTS} }) {
360     $element->cleared('1');
361     $element->invoice_amount($element->amount) if $element->isa('SL::DB::BankTransaction');
362     $element->save;
363   }
364
365   # 2. step: insert entry in reconciliation_links
366   my $rec_group = SL::DB::Manager::ReconciliationLink->get_new_rec_group();
367   #There is either a 1:n relation or a n:1 relation
368   if (scalar @{ $::form->{bt_ids} } == 1) {
369     my $bt_id = @{ $::form->{bt_ids} }[0];
370     foreach my $bb_id (@{ $::form->{bb_ids} }) {
371       my $rec_link = SL::DB::ReconciliationLink->new(bank_transaction_id => $bt_id,
372                                                      acc_trans_id        => $bb_id,
373                                                      rec_group           => $rec_group);
374       $rec_link->save;
375     }
376   } else {
377     my $bb_id = @{ $::form->{bb_ids} }[0];
378     foreach my $bt_id (@{ $::form->{bt_ids} }) {
379       my $rec_link = SL::DB::ReconciliationLink->new(bank_transaction_id => $bt_id,
380                                                      acc_trans_id        => $bb_id,
381                                                      rec_group           => $rec_group);
382       $rec_link->save;
383     }
384   }
385 }
386
387 sub _filter_to_where {
388   my ($self) = @_;
389
390   my %parse_filter = parse_filter($::form->{filter});
391   my %filter = @{ $parse_filter{query} };
392
393   my (@rl_where, @bt_where, @bb_where);
394   @rl_where = ('bank_transaction.local_bank_account_id' => $filter{local_bank_account_id});
395   @bt_where = (local_bank_account_id => $filter{local_bank_account_id});
396   @bb_where = (chart_id              => $self->{bank_account}->chart_id);
397
398   if ($filter{fromdate} and $filter{todate}) {
399
400     push @rl_where, (or => [ and => [ 'acc_trans.transdate'        => $filter{fromdate},
401                                       'acc_trans.transdate'        => $filter{todate}   ],
402                              and => [ 'bank_transaction.transdate' => $filter{fromdate},
403                                       'bank_transaction.transdate' => $filter{todate}   ] ] );
404
405     push @bt_where, (transdate => $filter{todate} );
406     push @bt_where, (transdate => $filter{fromdate} );
407     push @bb_where, (transdate => $filter{todate} );
408     push @bb_where, (transdate => $filter{fromdate} );
409   }
410
411   if ( $self->{bank_account}->reconciliation_starting_date ) {
412     push @bt_where, (transdate => { ge => $self->{bank_account}->reconciliation_starting_date });
413     push @bb_where, (transdate => { ge => $self->{bank_account}->reconciliation_starting_date });
414   }
415
416   # don't try to reconcile opening and closing balance transactions
417   push @bb_where, ('acc_trans.ob_transaction' => 0);
418   push @bb_where, ('acc_trans.cb_transaction' => 0);
419
420   if ($filter{fromdate} and not $filter{todate}) {
421     push @rl_where, (or => [ 'acc_trans.transdate'        => $filter{fromdate},
422                              'bank_transaction.transdate' => $filter{fromdate} ] );
423     push @bt_where, (transdate                    => $filter{fromdate} );
424     push @bb_where, (transdate                    => $filter{fromdate} );
425   }
426
427   if ($filter{todate} and not $filter{fromdate}) {
428     push @rl_where, ( or => [ 'acc_trans.transdate'        => $filter{todate} ,
429                               'bank_transaction.transdate' => $filter{todate} ] );
430     push @bt_where, (transdate                    => $filter{todate} );
431     push @bb_where, (transdate                    => $filter{todate} );
432   }
433
434   if ($filter{cleared}) {
435     $filter{cleared} = $filter{cleared} eq 'FALSE' ? '0' : '1';
436     push @rl_where, ('acc_trans.cleared'        => $filter{cleared} );
437
438     push @bt_where, (cleared                    => $filter{cleared} );
439     push @bb_where, (cleared                    => $filter{cleared} );
440   }
441
442   $self->{rl_where} = \@rl_where;
443   $self->{bt_where} = \@bt_where;
444   $self->{bb_where} = \@bb_where;
445 }
446
447 sub _get_linked_transactions {
448   my ($self) = @_;
449
450   $self->_filter_to_where;
451
452   my (@where, @bt_where, @bb_where);
453   # don't try to reconcile opening and closing balances
454   # instead use an offset in configuration
455
456   @where    = (@{ $self->{rl_where} });
457   @bt_where = (@{ $self->{bt_where} }, cleared => '0');
458   @bb_where = (@{ $self->{bb_where} }, cleared => '0');
459
460   my @rows;
461
462   my $reconciliation_groups = SL::DB::Manager::ReconciliationLink->get_all(distinct => 1,
463                                                                            select => ['rec_group'],
464                                                                            where => \@where,
465                                                                            with_objects => ['bank_transaction', 'acc_trans']);
466
467   my $fromdate = $::locale->parse_date_to_object($::form->{filter}->{fromdate_date__ge});
468   my $todate   = $::locale->parse_date_to_object($::form->{filter}->{todate_date__le});
469
470   foreach my $rec_group (@{ $reconciliation_groups }) {
471     my $linked_transactions = SL::DB::Manager::ReconciliationLink->get_all(where => [rec_group => $rec_group->rec_group], with_objects => ['bank_transaction', 'acc_trans']);
472     my $line;
473     my $first_transaction = shift @{ $linked_transactions };
474     my $first_bt = $first_transaction->bank_transaction;
475     my $first_bb = $first_transaction->acc_trans;
476
477     if (defined $fromdate) {
478       $first_bt->{class} = 'out_of_balance' if ( $first_bt->transdate lt $fromdate );
479       $first_bb->{class} = 'out_of_balance' if ( $first_bb->transdate lt $fromdate );
480     }
481     if (defined $todate) {
482       $first_bt->{class} = 'out_of_balance' if ( $first_bt->transdate gt $todate );
483       $first_bb->{class} = 'out_of_balance' if ( $first_bb->transdate gt $todate );
484     }
485     $line->{BT} = [ $first_bt ];
486     $line->{BB} = [ $first_bb ];
487     $line->{rec_group} = $first_transaction->rec_group;
488     $line->{type} = 'Link';
489
490     #add the rest of transaction of this group
491     my ($previous_bt_id, $previous_acc_trans_id) = ($first_transaction->bank_transaction_id, $first_transaction->acc_trans_id);
492     foreach my $linked_transaction (@{ $linked_transactions }) {
493       my $bank_transaction = $linked_transaction->bank_transaction;
494       my $acc_transaction  = $linked_transaction->acc_trans;
495       if (defined $fromdate) {
496         $bank_transaction->{class} = 'out_of_balance' if ( $bank_transaction->transdate lt $fromdate );
497         $acc_transaction->{class}  = 'out_of_balance' if ( $acc_transaction->transdate  lt $fromdate );
498       }
499       if (defined $todate) {
500         $bank_transaction->{class} = 'out_of_balance' if ( $bank_transaction->transdate gt $todate );
501         $acc_transaction->{class}  = 'out_of_balance' if ( $acc_transaction->transdate  gt $todate );
502       }
503       if ($bank_transaction->id != $previous_bt_id) {
504         push @{ $line->{BT} }, $bank_transaction;
505       }
506       if ($acc_transaction->acc_trans_id != $previous_acc_trans_id) {
507         push @{ $line->{BB} }, $acc_transaction;
508       }
509     }
510     push @rows, $line;
511   }
512
513   # add non-cleared bank transactions
514   my $bank_transactions = SL::DB::Manager::BankTransaction->get_all(where => \@bt_where);
515   foreach my $bt (@{ $bank_transactions }) {
516     my $line;
517     $line->{BT} = [ $bt ];
518     $line->{type} = 'BT';
519     $line->{id} = $bt->id;
520     push @rows, $line;
521   }
522
523   # add non-cleared bookings on bank
524   my $bookings_on_bank = SL::DB::Manager::AccTransaction->get_all(where => \@bb_where);
525   foreach my $bb (@{ $bookings_on_bank }) {
526     if ($::form->{filter}->{show_stornos} or !$bb->record->storno) {
527       my $line;
528       $line->{BB} = [ $bb ];
529       $line->{type} = 'BB';
530       $line->{id} = $bb->acc_trans_id;
531       push @rows, $line;
532     }
533   }
534
535   #sort lines
536   @rows = sort sort_by_transdate @rows;
537
538   $self->{LINKED_TRANSACTIONS} = \@rows;
539 }
540
541 sub sort_by_transdate {
542   if ($a->{BT} and $b->{BT}) {
543     return $a->{BT}[0]->amount <=> $b->{BT}[0]->amount if $a->{BT}[0]->transdate eq $b->{BT}[0]->transdate;
544     return $a->{BT}[0]->transdate cmp $b->{BT}[0]->transdate;
545   }
546   if ($a->{BT}) {
547     return $a->{BT}[0]->amount <=> (-1 * $b->{BB}[0]->amount) if $a->{BT}[0]->transdate eq $b->{BB}[0]->transdate;
548     return $a->{BT}[0]->transdate cmp $b->{BB}[0]->transdate;
549   }
550   if ($b->{BT}) {
551     return (-1 * $a->{BB}[0]->amount) <=> $b->{BT}[0]->amount if $a->{BB}[0]->transdate eq $b->{BT}[0]->transdate;
552     return $a->{BB}[0]->transdate cmp $b->{BT}[0]->transdate;
553   }
554   return (-1 * $a->{BB}[0]->amount) <=> (-1 * $b->{BB}[0]->amount) if $a->{BB}[0]->transdate eq $b->{BB}[0]->transdate;
555   return $a->{BB}[0]->transdate cmp $b->{BB}[0]->transdate;
556 }
557
558 sub _get_balances {
559   my ($self) = @_;
560
561   $self->_filter_to_where;
562
563   my (@bt_where, @bb_where);
564   @bt_where = @{ $self->{bt_where} };
565   @bb_where = @{ $self->{bb_where} };
566
567   my @all_bt_where = (local_bank_account_id => $self->{bank_account}->id);
568   my @all_bb_where = (chart_id              => $self->{bank_account}->chart_id);
569
570   my ($bt_balance, $bb_balance) = (0,0);
571   my ($absolut_bt_balance, $absolut_bb_balance) = (0,0);
572
573   if ( $self->{bank_account}->reconciliation_starting_date ) {
574     $bt_balance         = $self->{bank_account}->reconciliation_starting_balance;
575     $bb_balance         = $self->{bank_account}->reconciliation_starting_balance * -1;
576     $absolut_bt_balance = $self->{bank_account}->reconciliation_starting_balance;
577     $absolut_bb_balance = $self->{bank_account}->reconciliation_starting_balance * -1;
578
579     push @all_bt_where, ( transdate => { gt => $self->{bank_account}->reconciliation_starting_date });
580     push @all_bb_where, ( transdate => { gt => $self->{bank_account}->reconciliation_starting_date });
581   }
582
583   my $bank_transactions = SL::DB::Manager::BankTransaction->get_all(where => \@bt_where );
584   my $payments          = SL::DB::Manager::AccTransaction ->get_all(where => \@bb_where );
585
586   # for absolute balance get all bookings until todate
587   my $todate   = $::locale->parse_date_to_object($::form->{filter}->{todate_date__le});
588   my $fromdate = $::locale->parse_date_to_object($::form->{filter}->{fromdate_date__le});
589
590   if ($todate) {
591     push @all_bt_where, (transdate => { le => $todate });
592     push @all_bb_where, (transdate => { le => $todate });
593   }
594
595   my $all_bank_transactions = SL::DB::Manager::BankTransaction->get_all(where => \@all_bt_where);
596   my $all_payments          = SL::DB::Manager::AccTransaction ->get_all(where => \@all_bb_where);
597
598   $bt_balance += sum map { $_->amount } @{ $bank_transactions };
599   $bb_balance += sum map { $_->amount if ($::form->{filter}->{show_stornos} or !$_->record->storno) } @{ $payments };
600
601   $absolut_bt_balance += sum map { $_->amount } @{ $all_bank_transactions };
602   $absolut_bb_balance += sum map { $_->amount } @{ $all_payments };
603
604
605   $self->{bt_balance}         = $bt_balance || 0;
606   $self->{bb_balance}         = $bb_balance || 0;
607   $self->{absolut_bt_balance} = $absolut_bt_balance || 0;
608   $self->{absolut_bb_balance} = $absolut_bb_balance || 0;
609
610   $self->{difference} = $bt_balance + $bb_balance;
611 }
612
613 sub init_cleared {
614   [ { title => t8("all"),       value => ''           },
615     { title => t8("cleared"),   value => 'TRUE'       },
616     { title => t8("uncleared"), value => 'FALSE'      }, ]
617 }
618
619 sub init_BANK_ACCOUNTS {
620   SL::DB::Manager::BankAccount->get_all_sorted( query => [ obsolete => 0 ] );
621 }
622
623 1;