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