Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 9af3e192

Von Jan Büren vor fast 6 Jahren hinzugefügt

  • ID 9af3e1927c6fe3c631b63310888f1909039f24b6
  • Vorgänger 5172a3be
  • Nachfolger eb087bc8

BankTransaction: Neue Funktion um Bankverbuchungen wieder rückgängig zu machen

action_unlink_bank_transaction inkl. POD
Der Bericht Bankbewegungen erhält im Presenter Anhakboxen (ähnlich wie bei SEPA)

Unterschiede anzeigen:

SL/Controller/BankTransaction.pm
17 17
use SL::DB::Invoice;
18 18
use SL::DB::PurchaseInvoice;
19 19
use SL::DB::RecordLink;
20
use SL::DB::ReconciliationLink;
20 21
use SL::JSON;
21 22
use SL::DB::Chart;
22 23
use SL::DB::AccTransaction;
......
25 26
use SL::DB::BankAccount;
26 27
use SL::DB::RecordTemplate;
27 28
use SL::DB::SepaExportItem;
28
use SL::DBUtils qw(like);
29
use SL::DBUtils qw(like do_query);
29 30

  
31
use SL::Presenter::Tag qw(checkbox_tag);
32
use Carp;
30 33
use List::UtilsBy qw(partition_by);
31 34
use List::MoreUtils qw(any);
32 35
use List::Util qw(max);
......
711 714

  
712 715
  return grep { $_ } ($error, @warnings);
713 716
}
717
sub action_unlink_bank_transaction {
718
  my ($self) = @_;
719

  
720
  croak("No bank transaction ids") unless scalar @{ $::form->{ids}} > 0;
721

  
722
  my $closedto = $::locale->parse_date_to_object($::instance_conf->get_closedto);
723
  my $success_count;
724

  
725
  foreach my $bt_id (@{ $::form->{ids}} )  {
726

  
727
    my $bank_transaction = SL::DB::Manager::BankTransaction->find_by(id => $bt_id);
728
    croak("No valid bank transaction found") unless (ref($bank_transaction)  eq 'SL::DB::BankTransaction');
729

  
730
    # everything in one transaction
731
    my $rez = $bank_transaction->db->with_transaction(sub {
732
      # 1. remove all reconciliations (due to underlying trigger, this has to be the first step)
733
      my $rec_links = SL::DB::Manager::ReconciliationLink->get_all(where => [ bank_transaction_id => $bt_id ]);
734
      $_->delete for @{ $rec_links };
735

  
736
      my %trans_ids;
737
      foreach my $acc_trans_id_entry (@{ SL::DB::Manager::BankTransactionAccTrans->get_all(where => [bank_transaction_id => $bt_id ] )}) {
738

  
739
        my $acc_trans = SL::DB::Manager::AccTransaction->get_all(where => [acc_trans_id => $acc_trans_id_entry->acc_trans_id]);
740
        # check closedto for acc trans entries
741
        croak t8('Cannot unlink payment for a closed period!') if (ref $closedto && grep { $_->transdate < $closedto } @{ $acc_trans } );
742

  
743
        # save trans_id and type
744
        die "no type" unless ($acc_trans_id_entry->ar_id || $acc_trans_id_entry->ap_id || $acc_trans_id_entry->gl_id);
745
        $trans_ids{$acc_trans_id_entry->ar_id} = 'ar' if $acc_trans_id_entry->ar_id;
746
        $trans_ids{$acc_trans_id_entry->ap_id} = 'ap' if $acc_trans_id_entry->ap_id;
747
        $trans_ids{$acc_trans_id_entry->gl_id} = 'gl' if $acc_trans_id_entry->gl_id;
748

  
749
        # 2. all good -> ready to delete acc_trans and bt_acc link
750
        $acc_trans_id_entry->delete;
751
        $_->delete for @{ $acc_trans };
752
      }
753
      # 3. update arap.paid (may not be 0, yet)
754
      while (my ($trans_id, $type) = each %trans_ids) {
755
        next if $type eq 'gl';
756
        die ("invalid type") unless $type =~ m/^(ar|ap)$/;
757

  
758
        # recalc and set paid via database query
759
        my $query = qq|UPDATE $type SET paid =
760
                        (SELECT COALESCE(abs(sum(amount)),0) FROM acc_trans
761
                         WHERE trans_id = ?
762
                         AND chart_link ilike '%paid%')|;
763

  
764
        die if (do_query($::form, $bank_transaction->db->dbh, $query, $trans_id) == -1);
765
      }
766
      # 4. and delete all (if any) record links
767
      my $rl = SL::DB::Manager::RecordLink->delete_all(where => [ from_id => $bt_id, from_table => 'bank_transactions' ]);
768

  
769
      # 5. finally reset  this bank transaction
770
      $bank_transaction->invoice_amount(0);
771
      $bank_transaction->cleared(0);
772
      $bank_transaction->save;
714 773

  
774
      1;
775

  
776
    }) || die t8('error while unlinking payment #1 : ', $bank_transaction->purpose) . $bank_transaction->db->error . "\n";
777

  
778
    $success_count++;
779
  }
780

  
781
  flash('ok', t8('#1 bank transaction bookings undone.', $success_count));
782
  $self->action_list_all();
783
}
715 784
#
716 785
# filters
717 786
#
......
754 823
  my $report      = SL::ReportGenerator->new(\%::myconfig, $::form);
755 824
  $self->{report} = $report;
756 825

  
757
  my @columns     = qw(local_bank_name transdate valudate remote_name remote_account_number remote_bank_code amount invoice_amount invoices currency purpose local_account_number local_bank_code id);
826
  my @columns     = qw(ids local_bank_name transdate valudate remote_name remote_account_number remote_bank_code amount invoice_amount invoices currency purpose local_account_number local_bank_code id);
758 827
  my @sortable    = qw(local_bank_name transdate valudate remote_name remote_account_number remote_bank_code amount                                  purpose local_account_number local_bank_code);
759 828

  
760 829
  my %column_defs = (
830
    ids                 => { raw_header_data => checkbox_tag("", id => "check_all", checkall  => "[data-checkall=1]"),
831
                             'align'         => 'center',
832
                             raw_data        => sub { if (@{ $_[0]->linked_invoices } && !(grep {ref ($_) eq 'SL::DB::GLTransaction' } @{ $_[0]->linked_invoices })) {
833
                                                         checkbox_tag("ids[]", value => $_[0]->id, "data-checkall" => 1); } } },
761 834
    transdate             => { sub   => sub { $_[0]->transdate_as_date } },
762 835
    valutadate            => { sub   => sub { $_[0]->valutadate_as_date } },
763 836
    remote_name           => { },
......
815 888
        by  => 'transdate',
816 889
        dir => 0,   # 1 = ASC, 0 = DESC : default sort is newest at top
817 890
      },
891
      id                    => t8('ID'),
818 892
      transdate             => t8('Transdate'),
819 893
      remote_name           => t8('Remote name'),
820 894
      amount                => t8('Amount'),
......
884 958

  
885 959
  for my $bar ($::request->layout->get('actionbar')) {
886 960
    $bar->add(
887
      action => [
888
        t8('Filter'),
889
        submit    => [ '#filter_form', { action => 'BankTransaction/list_all' } ],
961
      combobox => [
962
        action => [ t8('Actions') ],
963
        action => [
964
          t8('Unlink bank transactions'),
965
            submit => [ '#form', { action => 'BankTransaction/unlink_bank_transaction' } ],
966
            checks => [ [ 'kivi.check_if_entries_selected', '[name="ids[]"]' ] ],
967
            disabled  => $::instance_conf->get_payments_changeable ? t8('Cannot safely unlink bank transactions, please set the posting configuration for payments to unchangeable.') : undef,
968
          ],
969
        ],
970
        action => [
971
          t8('Filter'),
972
          submit    => [ '#filter_form', { action => 'BankTransaction/list_all' } ],
890 973
        accesskey => 'enter',
891 974
      ],
892 975
    );
......
961 1044

  
962 1045
=back
963 1046

  
1047
=item C<action_unlink_bank_transaction>
1048

  
1049
Takes one or more bank transaction ID (as parameter C<form::ids>) and
1050
tries to revert all payment bookings including already cleared bookings.
1051

  
1052
This method won't undo payments that are in a closed period and assumes
1053
that payments are not manually changed, i.e. only imported payments.
1054

  
1055
GL-records will be deleted completely if a bank transaction was the source.
1056

  
1057
TODO: we still rely on linked_records for the check boxes
1058

  
964 1059
=back
965 1060

  
966 1061
=head1 AUTHOR
templates/webpages/bank_transactions/report_bottom.html
1 1
[% USE L %]
2 2
[%- L.paginate_controls(models=SELF.models) %]
3
</form>
templates/webpages/bank_transactions/report_top.html
1 1
[%- USE L %]
2 2
[%- PROCESS 'bank_transactions/_filter.html' filter=SELF.models.filtered.laundered %]
3 3
 <hr>
4
<form method="post" action="controller.pl" id="form">

Auch abrufbar als: Unified diff