X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FDB%2FObject.pm;h=89d15c67101874c05c486005aedf0fc4691328fd;hb=40df01939f53719f4f7c167ed2bf7fa67c509291;hp=06596dd4f9aad706ffb444163c63ad701330db62;hpb=972b87711cb3c7543d585ceedca0eda2058aa6d7;p=kivitendo-erp.git diff --git a/SL/DB/Object.pm b/SL/DB/Object.pm index 06596dd4f..89d15c671 100755 --- a/SL/DB/Object.pm +++ b/SL/DB/Object.pm @@ -7,6 +7,7 @@ use English qw(-no_match_vars); use Rose::DB::Object; use Rose::DB::Object::Constants qw(); use List::MoreUtils qw(any pairwise); +use List::Util qw(first); use SL::DB; use SL::DB::Helper::Attr; @@ -22,6 +23,13 @@ my @rose_reserved_methods = qw( not_found save update import ); +my %db_to_presenter_mapping = ( + Customer => 'CustomerVendor', + PurchaseInvoice => 'Invoice', + Vendor => 'CustomerVendor', + GLTransaction => 'GL', +); + sub new { my $class = shift; my $self = $class->SUPER::new(); @@ -98,6 +106,50 @@ sub update_attributes { return $self; } +sub update_collection { + my ($self, $attribute, $entries) = @_; + + my $self_primary_key = "" . ($self->meta->primary_key_columns)[0]; + + croak "\$self hasn't been saved yet" if !$self->$self_primary_key; + + my $relationship = first { $_->name eq $attribute } @{ $self->meta->relationships }; + + croak "No relationship found for attribute '$attribute'" if !$relationship; + + my @primary_key_columns = $relationship->class->meta->primary_key_columns; + + croak "Classes with multiple primary key columns are not supported" if scalar(@primary_key_columns) > 1; + + my $class = $relationship->class; + my $manager_class = "SL::DB::Manager::" . substr($class, 8); + my $other_primary_key = "" . $primary_key_columns[0]; + my $column_map = $relationship->column_map; + my @new_entries = @{ $entries // [] }; + my @existing_entries = @{ $self->$attribute // [] }; + my @to_delete = grep { my $value = $_->$other_primary_key; !any { $_->{$other_primary_key} == $value } @new_entries } @existing_entries; + + $_->delete for @to_delete; + + foreach my $entry (@new_entries) { + if (!$entry->{$other_primary_key}) { + my $new_instance = $class->new(%{ $entry }); + + foreach my $self_attribute (keys %{ $column_map }) { + my $other_attribute = $column_map->{$self_attribute}; + $new_instance->$other_attribute($self->$self_attribute); + } + + $new_instance->save; + + next; + } + + my $existing = first { $_->$other_primary_key == $entry->{$other_primary_key} } @existing_entries; + $existing->update_attributes(%{ $entry }) if $existing; + } +} + sub call_sub { my $self = shift; my $sub = shift; @@ -240,16 +292,26 @@ sub clone_and_reset { } sub presenter { - my ($class_or_self) = @_; - - if (ref $class_or_self) { - my $class = ref $class_or_self; - $class =~ s{^SL::DB::}{SL::Presenter::}; - return SL::DB::Helper::Presenter->new($class, $class_or_self); - } else { - $class_or_self =~ s{^SL::DB::}{SL::Presenter::}; - return $class_or_self; - } + my ($self) = @_; + + my $class = ref $self; + $class =~ s{^SL::DB::}{}; + $class = "SL::Presenter::" . ($db_to_presenter_mapping{$class} // $class); + + return SL::DB::Helper::Presenter->new($class, $self); +} + +sub as_debug_info { + my ($self) = @_; + + return { + map { + my $column_name = $_->name; + my $value = $self->$column_name; + $value = !defined($value) ? undef : "${value}"; + ($_ => $value) + } $self->meta->columns + }; } 1; @@ -301,6 +363,28 @@ Assigns the attributes from C<%attributes> by calling the C function and saves the object afterwards. Returns the object itself. +=item C + +Updates a one-to-many relationship named C<$attribute> to match the +entries in C<$entries>. C<$entries> is supposed to be an array ref of +hash refs. + +For each hash ref in C<$entries> that does not contain a field for the +relationship's primary key column, this function creates a new entry +in the database with its attributes set to the data in the entry. + +For each hash ref in C<$entries> that contains a field for the +relationship's primary key column, this function looks up the +corresponding entry in C<$self->$attribute> & updates its +attributes with the data in the entry. + +All objects in C<$self->$attribute> for which no corresponding +entry exists in C<$entries> are deleted by calling the object's +C method. + +In all cases the relationship itself C<$self->$attribute> is not +changed. + =item _get_manager_class Returns the manager package for the object or class that it is called @@ -383,6 +467,12 @@ with the same name as the class of the involking object. For the full documentation about its capabilites see L +=item C + +Returns a hash containing solely the essentials for dumping it with +L. The returned hash consists of the column names with +associated column values in stringified form. + =back =head1 AUTHOR