Payment-Helper pay_invoice case 'difference_as_skonto' entfernt
[kivitendo-erp.git] / SL / DB / Helper / ActsAsList.pm
index 566422a..7ca63a3 100644 (file)
@@ -4,9 +4,10 @@ use strict;
 
 use parent qw(Exporter);
 our @EXPORT = qw(move_position_up move_position_down add_to_list remove_from_list reorder_list configure_acts_as_list
-                 get_previous_in_list get_next_in_list);
+                 get_previous_in_list get_next_in_list get_full_list);
 
 use Carp;
+use SL::X;
 
 my %list_spec;
 
@@ -14,12 +15,13 @@ sub import {
   my ($class, @params)   = @_;
   my $importing = caller();
 
+  configure_acts_as_list($importing, @params);
+
   $importing->before_save(  sub { SL::DB::Helper::ActsAsList::set_position(@_)    });
   $importing->before_delete(sub { SL::DB::Helper::ActsAsList::remove_position(@_) });
 
-  # Use 'goto' so that Exporter knows which module to import into via
-  # 'caller()'.
-  goto &Exporter::import;
+  # Don't 'goto' to Exporters import, it would try to parse @params
+  __PACKAGE__->export_to_level(1, $class, @EXPORT);
 }
 
 #
@@ -39,7 +41,7 @@ sub move_position_down {
 sub remove_from_list {
   my ($self) = @_;
 
-  my $worker = sub {
+  return $self->db->with_transaction(sub {
     remove_position($self);
 
     # Set to -1 manually because $self->update_attributes() would
@@ -55,9 +57,7 @@ sub remove_from_list {
 SQL
     $self->db->dbh->do($sql, undef, $self->$primary_key_col);
     $self->$column(undef);
-  };
-
-  return $self->db->in_transaction ? $worker->() : $self->db->do_transaction($worker);
+  });
 }
 
 sub add_to_list {
@@ -65,6 +65,10 @@ sub add_to_list {
 
   croak "Invalid parameter 'position'" unless ($params{position} || '') =~ m/^ (?: before | after | first | last ) $/x;
 
+  my $column = column_name($self);
+
+  $self->remove_from_list if ($self->$column // -1) != -1;
+
   if ($params{position} eq 'last') {
     set_position($self);
     $self->save;
@@ -73,7 +77,6 @@ sub add_to_list {
 
   my $table               = $self->meta->table;
   my $primary_key_col     = ($self->meta->primary_key)[0];
-  my $column              = column_name($self);
   my ($group_by, @values) = get_group_by_where($self);
   $group_by               = " AND ${group_by}" if $group_by;
   my $new_position;
@@ -105,12 +108,10 @@ sub add_to_list {
       ${group_by}
 SQL
 
-  my $worker = sub {
+  return $self->db->with_transaction(sub {
     $self->db->dbh->do($query, undef, $new_position - 1, @values);
     $self->update_attributes($column => $new_position);
-  };
-
-  return $self->db->in_transaction ? $worker->() : $self->db->do_transaction($worker);
+  });
 }
 
 sub get_next_in_list {
@@ -123,6 +124,16 @@ sub get_previous_in_list {
   return get_previous_or_next($self, 'previous');
 }
 
+sub get_full_list {
+  my ($self) = @_;
+
+  my $group_by = get_spec(ref $self, 'group_by') || [];
+  $group_by    = [ $group_by ] if $group_by && !ref $group_by;
+  my @where    = map { ($_ => $self->$_) } @{ $group_by };
+
+  return $self->_get_manager_class->get_all(where => \@where, sort_by => column_name($self) . ' ASC');
+}
+
 sub reorder_list {
   my ($class_or_self, @ids) = @_;
 
@@ -130,15 +141,17 @@ sub reorder_list {
 
   my $self   = ref($class_or_self) ? $class_or_self : $class_or_self->new;
   my $column = column_name($self);
-  my $result = $self->db->do_transaction(sub {
+  my $result = $self->db->with_transaction(sub {
     my $query = qq|UPDATE | . $self->meta->table . qq| SET ${column} = ? WHERE id = ?|;
-    my $sth   = $self->db->dbh->prepare($query) || die $self->db->dbh->errstr;
+    my $sth   = $self->db->dbh->prepare($query) || SL::X::DBUtilsError->throw(msg => 'reorder_list error', db_error => $self->db->dbh->errstr);
 
     foreach my $new_position (1 .. scalar(@ids)) {
-      $sth->execute($new_position, $ids[$new_position - 1]) || die $sth->errstr;
+      $sth->execute($new_position, $ids[$new_position - 1]) || SL::X::DBUtilsError->throw(msg => 'reorder_list error', db_error => $sth->errstr);
     }
 
     $sth->finish;
+
+    1;
   });
 
   return $result;
@@ -309,7 +322,7 @@ column
 =head1 SYNOPSIS
 
   package SL::DB::SomeObject;
-  use SL::DB::Helper::ActsAsList;
+  use SL::DB::Helper::ActsAsList [ PARAMS ];
 
   package SL::Controller::SomeController;
   ...
@@ -334,7 +347,8 @@ in the table plus one.
 When the object is deleted all positions greater than the object's old
 position are decreased by one.
 
-The column name to use can be configured via L<configure_acts_as_list>.
+C<PARAMS> will be given to L<configure_acts_as_list> and can be used to
+set the column name.
 
 =head1 CLASS FUNCTIONS
 
@@ -342,8 +356,8 @@ The column name to use can be configured via L<configure_acts_as_list>.
 
 =item C<configure_acts_as_list %params>
 
-Configures the mixin's behaviour. C<%params> can contain the following
-values:
+Configures the mixin's behaviour. Will get called automatically with the
+include parameters. C<%params> can contain the following values:
 
 =over 2
 
@@ -399,6 +413,10 @@ one. The current item will then be inserted either before or after the
 referenced item by shifting all the appropriate item positions up by
 one.
 
+If C<$self>'s positional column is already set when this function is
+called then L</remove_from_list> will be called first before anything
+else is done.
+
 After this function C<$self>'s positional column has been set and
 saved to the database.
 
@@ -417,6 +435,11 @@ already the first one.
 Fetches the next item in the list. Returns C<undef> if C<$self> is
 already the last one.
 
+=item C<get_full_list>
+
+Fetches all items in the same list as C<$self> and returns them as an
+array reference.
+
 =item C<reorder_list @ids>
 
 Re-orders the objects given in C<@ids> by their position in C<@ids> by