From: Moritz Bunkus Date: Wed, 12 Jan 2011 15:02:14 +0000 (+0100) Subject: Sortieren von verknüpften Dokumenten X-Git-Tag: release-2.6.3~61^2~7^2~1^2~2^2~91 X-Git-Url: http://wagnertech.de/git?a=commitdiff_plain;h=6b87206e563b5d00ce48025f6ec79b2ab59653d1;p=kivitendo-erp.git Sortieren von verknüpften Dokumenten --- diff --git a/SL/DB/Helper/LinkedRecords.pm b/SL/DB/Helper/LinkedRecords.pm index 3712cc206..9dbee05ec 100644 --- a/SL/DB/Helper/LinkedRecords.pm +++ b/SL/DB/Helper/LinkedRecords.pm @@ -4,9 +4,10 @@ use strict; require Exporter; our @ISA = qw(Exporter); -our @EXPORT = qw(linked_records link_to_record); +our @EXPORT = qw(linked_records link_to_record linked_records_sorted); use Carp; +use Sort::Naturally; use SL::DB::Helpers::Mappings; use SL::DB::RecordLink; @@ -16,6 +17,20 @@ sub linked_records { my %params = @_; my $wanted = $params{direction} || croak("Missing parameter `direction'"); + + if ($wanted eq 'both') { + my $both = delete($params{both}); + my %from_to = ( from => delete($params{from}) || $both, + to => delete($params{to}) || $both); + + my @records = (@{ $self->linked_records(%params, direction => 'from', from => $from_to{from}) }, + @{ $self->linked_records(%params, direction => 'to', to => $from_to{to} ) }); + + my %record_map = map { ( ref($_) . $_->id => $_ ) } @records; + + return [ values %record_map ]; + } + my $myself = $wanted eq 'from' ? 'to' : $wanted eq 'to' ? 'from' : croak("Invalid parameter `direction'"); my $my_table = SL::DB::Helpers::Mappings::get_table_for_package(ref($self)); @@ -38,8 +53,10 @@ sub linked_records { @query = ref($params{query}) eq 'ARRAY' ? @{ $params{query} } : (); foreach my $link (@{ $links }) { - my $class = SL::DB::Helpers::Mappings::get_manager_package_for_table($link->$sub_wanted_table); - push @{ $records }, @{ $class->get_all(query => [ id => $link->$sub_wanted_id, @query ]) }; + my $manager_class = SL::DB::Helpers::Mappings::get_manager_package_for_table($link->$sub_wanted_table); + my $object_class = SL::DB::Helpers::Mappings::get_package_for_table($link->$sub_wanted_table); + eval "require " . $object_class . "; 1;"; + push @{ $records }, @{ $manager_class->get_all(query => [ id => $link->$sub_wanted_id, @query ]) }; } return $records; @@ -62,6 +79,83 @@ sub link_to_record { return $link ? $link : SL::DB::RecordLink->new(%params)->save; } +sub linked_records_sorted { + my ($self, $sort_by, $sort_dir, %params) = @_; + + return sort_linked_records($self, $sort_by, $sort_dir, $self->linked_records(%params)); +} + +sub sort_linked_records { + my ($self_or_class, $sort_by, $sort_dir, @records) = @_; + + @records = @{ $records[0] } if (1 == scalar(@records)) && (ref($records[0]) eq 'ARRAY'); + $sort_dir = $sort_dir * 1 ? 1 : -1; + + my %numbers = ( 'SL::DB::SalesProcess' => sub { $_[0]->id }, + 'SL::DB::Order' => sub { $_[0]->quotation ? $_[0]->quonumber : $_[0]->ordnumber }, + 'SL::DB::DeliveryOrder' => sub { $_[0]->donumber }, + 'SL::DB::Invoice' => sub { $_[0]->invnumber }, + 'SL::DB::PurchaseInvoice' => sub { $_[0]->invnumber }, + UNKNOWN => '9999999999999999', + ); + my $number_xtor = sub { + my $number = $numbers{ ref($_[0]) }; + $number = $number->($_[0]) if ref($number) eq 'CODE'; + return $number || $numbers{UNKNOWN}; + }; + my $number_comparator = sub { + my $number_a = $number_xtor->($a); + my $number_b = $number_xtor->($b); + + ncmp($number_a, $number_b) * $sort_dir; + }; + + my %scores; + %scores = ( 'SL::DB::SalesProcess' => 10, + 'SL::DB::Order' => sub { $scores{ $_[0]->type } }, + sales_quotation => 20, + sales_order => 30, + sales_delivery_order => 40, + 'SL::DB::DeliveryOrder' => sub { $scores{ $_[0]->type } }, + 'SL::DB::Invoice' => 50, + request_quotation => 120, + purchase_order => 130, + purchase_delivery_order => 140, + 'SL::DB::PurchaseInvoice' => 150, + UNKNOWN => 999, + ); + my $score_xtor = sub { + my $score = $scores{ ref($_[0]) }; + $score = $score->($_[0]) if ref($score) eq 'CODE'; + return $score || $scores{UNKNOWN}; + }; + my $type_comparator = sub { + my $score_a = $score_xtor->($a); + my $score_b = $score_xtor->($b); + + $score_a == $score_b ? $number_comparator->() : ($score_a <=> $score_b) * $sort_dir; + }; + + my $today = DateTime->today_local; + my $date_xtor = sub { + $_[0]->can('transdate_as_date') ? $_[0]->transdate_as_date + : $_[0]->can('itime_as_date') ? $_[0]->itime_as_date + : $today; + }; + my $date_comparator = sub { + my $date_a = $date_xtor->($a); + my $date_b = $date_xtor->($b); + + ($date_a <=> $date_b) * $sort_dir; + }; + + my $comparator = $sort_by eq 'number' ? $number_comparator + : $sort_by eq 'date' ? $date_comparator + : $type_comparator; + + return [ sort($comparator @records) ]; +} + 1; __END__ @@ -79,10 +173,11 @@ SL::DB::Helpers::LinkedRecords - Mixin for retrieving linked records via the tab =item C Retrieves records linked from or to C<$self> via the table -C. The mandatory parameter C (either C -or C) determines whether the function retrieves records that link -to C<$self> (for C = C) or that are linked from -C<$self> (for C = C). +C. The mandatory parameter C (either C, +C or C) determines whether the function retrieves records +that link to C<$self> (for C = C) or that are linked +from C<$self> (for C = C). For C +all records linked from or to C<$self> are returned. The optional parameter C or C (same as C) contains the package names of Rose models for table limitation. It can @@ -115,8 +210,54 @@ insert a new entry if such a link does not already exist. Returns either the existing link or the newly created one as an instance of C. +=item C + +Sorts linked records by C<$sort_by> in the direction given by +C<$sort_dir> (trueish = ascending, falsish = descending). C<@records> +can be either a single array reference or or normal array. + +C<$sort_by> can be one of the following strings: + +=over 2 + +=item * C + +Sort by type first and by record number second. The type order +reflects the order in which records are usually processed by the +employees: sales processes, sales quotations, sales orders, sales +delivery orders, invoices; requests for quotation, purchase orders, +purchase delivery orders, purchase invoices. + +=item * C + +Sort by the record's running number. + +=item * C + +Sort by the date the record was created or applies to. + =back +Returns a hash reference. + +Can be called both as a class or as an instance function. + +This function is not exported. + +=item C + +Returns the result of L sorted by +L. C<%params> is passed to +L. C<$sort_by> and C<$sort_dir> are passed to +L. + +=back + +=head1 EXPORTS + +This mixin exports the functions L, +L and L. + =head1 BUGS Nothing here yet.