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