]> wagnertech.de Git - mfinanz.git/blobdiff - SL/DB/Helper/LinkedRecords.pm
kivitendo 3.9.2-0.2
[mfinanz.git] / SL / DB / Helper / LinkedRecords.pm
index 4614e5a8dc526ff006ad7ff66db28ef548c35b5b..206d40f48ecca30c451d9072f764be05dba5a5fc 100644 (file)
@@ -4,10 +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 sales_order_centric_linked_records);
 
 use Carp;
-use List::MoreUtils qw(any);
+use List::MoreUtils qw(any none);
 use List::UtilsBy qw(uniq_by);
 use Sort::Naturally;
 use SL::DBUtils;
@@ -306,7 +306,7 @@ sub sort_linked_records {
   $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::Order'           => sub { $_[0]->record_number },
                   'SL::DB::DeliveryOrder'   => sub { $_[0]->donumber },
                   'SL::DB::Invoice'         => sub { $_[0]->invnumber },
                   'SL::DB::PurchaseInvoice' => sub { $_[0]->invnumber },
@@ -331,24 +331,27 @@ sub sort_linked_records {
   };
 
   my %scores;
-  %scores = ( 'SL::DB::SalesProcess'    =>  10,
-              'SL::DB::RequirementSpec' =>  15,
-              '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,
-              'SL::DB::GLTransaction'   => 170,
-              'SL::DB::Letter'          => 200,
-              'SL::DB::ShopOrder'       => 250,
-              'SL::DB::EmailJournal'    => 300,
-              'SL::DB::Dunning'         => 350,
-              UNKNOWN                   => 999,
+  %scores = ( 'SL::DB::SalesProcess'      => 10,
+              'SL::DB::RequirementSpec'   => 15,
+              'SL::DB::Order'             => sub { $scores{ $_[0]->type } },
+              sales_quotation             => 20,
+              sales_order_intake          => 25,
+              sales_order                 => 30,
+              sales_delivery_order        => 40,
+              'SL::DB::DeliveryOrder'     => sub { $scores{ $_[0]->type } },
+              'SL::DB::Invoice'           => 50,
+              request_quotation           => 120,
+              purchase_quotation_intake   => 125,
+              purchase_order              => 130,
+              purchase_order_confirmation => 135,
+              purchase_delivery_order     => 140,
+              'SL::DB::PurchaseInvoice'   => 150,
+              'SL::DB::GLTransaction'     => 170,
+              'SL::DB::Letter'            => 200,
+              'SL::DB::ShopOrder'         => 250,
+              'SL::DB::EmailJournal'      => 300,
+              'SL::DB::Dunning'           => 350,
+              UNKNOWN                     => 999,
             );
   my $score_xtor = sub {
     my $score = $scores{ ref($_[0]) };
@@ -395,6 +398,61 @@ sub filter_linked_records {
   return \@records;
 }
 
+sub sales_order_centric_linked_records {
+  my ($self, %params) = @_;
+
+  my $with_sales_quotations = $params{with_sales_quotations};
+  my $with_myself           = $params{with_myself};
+
+  my $all_linked_records = $self->linked_records(direction => 'both', recursive => 1, save_path => 1);
+
+  if (!$with_sales_quotations) {
+    $all_linked_records = [ grep { !('SL::DB::Order' eq ref $_ && $_->is_sales && $_->quotation) } @$all_linked_records ];
+  }
+
+  if ($with_myself) {
+    $self->{_record_link_to_myself} = 1;
+    push @$all_linked_records, $self;
+  }
+
+  my $filtered_orders = [ grep {
+    'SL::DB::Order' eq ref $_ &&
+    ($_->is_type('sales_order') || $_->is_type('sales_order_intake')) &&
+    $_->{_record_link_direction} eq 'from'
+  } @$all_linked_records ];
+
+  # no orders no call to linked_records via batch mode
+  # but instead return default list
+  return $all_linked_records unless scalar @$filtered_orders;
+
+  # we have an order, therefore get the tree view from the top (order)
+  my $id_ref = [ map { $_->id } @$filtered_orders ];
+
+  my $linked_records = SL::DB::Order->new->linked_records(direction => 'to', recursive => 1, batch => $id_ref);
+
+  # Remove entries that are already in all_linked_records.
+  $linked_records = [ grep { my $id = $_->id; none { $_->id == $id } @$all_linked_records } @$linked_records ];
+
+  # Remove quotations if requested.
+  if (!$with_sales_quotations) {
+    $linked_records = [ grep { !('SL::DB::Order' eq ref $_ && $_->is_sales && $_->quotation) } @$linked_records ];
+  }
+
+  # Mark or remove myself.
+  if ($with_myself) {
+    $_->{_record_link_to_myself}  = 1 for grep { $_->id == $self->id } @$linked_records;
+  } else {
+    $linked_records = [ grep { $_->id != $self->id } @$linked_records ];
+  }
+
+  # All remaining links found via order are two more steps away from myself.
+  $_->{_record_link_depth} += 2 for @{ $linked_records };
+
+  push @{ $linked_records }, @$all_linked_records;
+
+  return $linked_records;
+}
+
 1;
 
 __END__
@@ -405,7 +463,7 @@ __END__
 
 SL::DB::Helper::LinkedRecords - Mixin for retrieving linked records via the table C<record_links>
 
-SYNOPSIS
+=head1 SYNOPSIS
 
   # In SL::DB::<Object>
   use SL::DB::Helper::LinkedRecords;
@@ -458,6 +516,12 @@ SYNOPSIS
     %params,
   );
 
+  # get order centric linked records
+  $invoice->sales_order_centric_linked_records(
+    with_myself           => 1,
+    with_sales_quotations => 1
+  );
+
   # add a new link
   $order->link_to_record($invoice);
   $order->link_to_record($purchase_order, bidirectional => 1);
@@ -680,13 +744,40 @@ Note: If the latter has a default setting it will always mask the creation time.
 
 Returns an array reference.
 
-Can only be called both as a class function since it is not exported.
+Can only be called as a class function since it is not exported.
+
+=item C<sales_order_centric_linked_records %params>
+
+Get linked records from the view of a reachable sales order in the path
+prior to this record. If no sales order is found, recursive linked records
+for both directions are returned.
+
+=over 2
+
+=item * C<with_sales_quotations>
+
+Since the view from a sales order is requested, normally no sales quotation
+prior to the sales order will be returned. If this parameter is truish, then
+a sales quotation would be included.
+This parameter is optional and defaults to false.
+
+=item * C<with_myself>
+
+The records returned by L</linked_records> do not include the requesting record
+itself. However, if you want to display the same linked records for every
+record in the same workflow, it can be usefull to include the record itself.
+C<_record_link_to_myself> will be set to a truish value in that record in
+that case.
+This parameter is optional and defaults to false.
+
+=back
 
 =back
 
 =head1 EXPORTS
 
-This mixin exports the functions L</linked_records> and
+This mixin exports the functions L</linked_records>,
+L</sales_order_centric_linked_records> and
 L</link_to_record>.
 
 =head1 BUGS