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
 
 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 Carp;
+use SL::X;
 
 my %list_spec;
 
 
 my %list_spec;
 
@@ -14,12 +15,13 @@ sub import {
   my ($class, @params)   = @_;
   my $importing = caller();
 
   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(@_) });
 
   $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) = @_;
 
 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
     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);
 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 {
 }
 
 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;
 
 
   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;
   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 $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;
   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
 
       ${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);
     $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 {
 }
 
 sub get_next_in_list {
@@ -123,6 +124,16 @@ sub get_previous_in_list {
   return get_previous_or_next($self, 'previous');
 }
 
   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) = @_;
 
 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 $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 $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)) {
 
     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;
     }
 
     $sth->finish;
+
+    1;
   });
 
   return $result;
   });
 
   return $result;
@@ -309,7 +322,7 @@ column
 =head1 SYNOPSIS
 
   package SL::DB::SomeObject;
 =head1 SYNOPSIS
 
   package SL::DB::SomeObject;
-  use SL::DB::Helper::ActsAsList;
+  use SL::DB::Helper::ActsAsList [ PARAMS ];
 
   package SL::Controller::SomeController;
   ...
 
   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.
 
 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
 
 
 =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>
 
 
 =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
 
 
 =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.
 
 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.
 
 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.
 
 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
 =item C<reorder_list @ids>
 
 Re-orders the objects given in C<@ids> by their position in C<@ids> by