From d437486216d9fa7fa9068c1d4ec6e5dcfd7e6920 Mon Sep 17 00:00:00 2001 From: Srdjan Jankovic Date: Mon, 15 Aug 2011 18:17:52 +1200 Subject: [PATCH] Bug 6721 - improve searching in the acquisitions system This allows a basket to be searched for by name or invoice number from anywhere in the acquisitions system. It is accessible by clicking on "orders search", clicking the '[+]' and filling in the basket or invoice no. fields. Author: Srdjan Jankovic Author: Robin Sheat --- C4/Acquisition.pm | 186 ++++++++++++-------- acqui/histsearch.pl | 44 ++++-- .../en/includes/acquisitions-history-search.inc | 24 --- .../prog/en/includes/acquisitions-search.inc | 8 +- .../prog/en/modules/acqui/histsearch.tt | 4 +- t/db_dependent/lib/KohaTest.pm | 6 +- t/db_dependent/lib/KohaTest/Acquisition.pm | 38 ++--- .../lib/KohaTest/Acquisition/GetHistory.pm | 50 ++++-- 8 files changed, 207 insertions(+), 153 deletions(-) delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-history-search.inc diff --git a/C4/Acquisition.pm b/C4/Acquisition.pm index 738fe16..f682256 100644 --- a/C4/Acquisition.pm +++ b/C4/Acquisition.pm @@ -20,6 +20,7 @@ package C4::Acquisition; use strict; use warnings; +use Carp; use C4::Context; use C4::Debug; use C4::Dates qw(format_date format_date_in_iso); @@ -897,7 +898,7 @@ sub NewOrder { # if these parameters are missing, we can't continue for my $key (qw/basketno quantity biblionumber budget_id/) { - die "Mandatory parameter $key missing" unless $orderinfo->{$key}; + croak "Mandatory parameter $key missing" unless $orderinfo->{$key}; } if ( defined $orderinfo->{subscription} && $orderinfo->{'subscription'} eq 'yes' ) { @@ -1486,10 +1487,19 @@ sub GetLateOrders { =head3 GetHistory - (\@order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( $title, $author, $name, $from_placed_on, $to_placed_on ); + (\@order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( %params ); Retreives some acquisition history information +params: + title + author + name + from_placed_on + to_placed_on + basket - search both basket name and number + booksellerinvoicenumber + returns: $order_loop is a list of hashrefs that each look like this: { @@ -1515,94 +1525,116 @@ returns: =cut sub GetHistory { - my ( $title, $author, $name, $from_placed_on, $to_placed_on ) = @_; +# don't run the query if there are no parameters (list would be too long for sure !) + croak "No search params" unless @_; + my %params = @_; + my $title = $params{title}; + my $author = $params{author}; + my $name = $params{name}; + my $from_placed_on = $params{from_placed_on}; + my $to_placed_on = $params{to_placed_on}; + my $basket = $params{basket}; + my $booksellerinvoicenumber = $params{booksellerinvoicenumber}; + my @order_loop; my $total_qty = 0; my $total_qtyreceived = 0; my $total_price = 0; -# don't run the query if there are no parameters (list would be too long for sure !) - if ( $title || $author || $name || $from_placed_on || $to_placed_on ) { - my $dbh = C4::Context->dbh; - my $query =" - SELECT - biblio.title, - biblio.author, - aqorders.basketno, - aqbasket.basketname, - aqbasket.basketgroupid, - aqbasketgroups.name as groupname, - aqbooksellers.name, - aqbasket.creationdate, - aqorders.datereceived, - aqorders.quantity, - aqorders.quantityreceived, - aqorders.ecost, - aqorders.ordernumber, - aqorders.booksellerinvoicenumber as invoicenumber, - aqbooksellers.id as id, - aqorders.biblionumber - FROM aqorders - LEFT JOIN aqbasket ON aqorders.basketno=aqbasket.basketno - LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid=aqbasketgroups.id - LEFT JOIN aqbooksellers ON aqbasket.booksellerid=aqbooksellers.id - LEFT JOIN biblio ON biblio.biblionumber=aqorders.biblionumber"; - - $query .= " LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber" - if ( C4::Context->preference("IndependantBranches") ); - - $query .= " WHERE (datecancellationprinted is NULL or datecancellationprinted='0000-00-00') "; - - my @query_params = (); - - if ( defined $title ) { - $query .= " AND biblio.title LIKE ? "; - $title =~ s/\s+/%/g; - push @query_params, "%$title%"; - } + my $dbh = C4::Context->dbh; + my $query =" + SELECT + biblio.title, + biblio.author, + aqorders.basketno, + aqbasket.basketname, + aqbasket.basketgroupid, + aqbasketgroups.name as groupname, + aqbooksellers.name, + aqbasket.creationdate, + aqorders.datereceived, + aqorders.quantity, + aqorders.quantityreceived, + aqorders.ecost, + aqorders.ordernumber, + aqorders.booksellerinvoicenumber as invoicenumber, + aqbooksellers.id as id, + aqorders.biblionumber + FROM aqorders + LEFT JOIN aqbasket ON aqorders.basketno=aqbasket.basketno + LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid=aqbasketgroups.id + LEFT JOIN aqbooksellers ON aqbasket.booksellerid=aqbooksellers.id + LEFT JOIN biblio ON biblio.biblionumber=aqorders.biblionumber"; - if ( defined $author ) { - $query .= " AND biblio.author LIKE ? "; - push @query_params, "%$author%"; - } + $query .= " LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber" + if ( C4::Context->preference("IndependantBranches") ); - if ( defined $name ) { - $query .= " AND aqbooksellers.name LIKE ? "; - push @query_params, "%$name%"; - } + $query .= " WHERE (datecancellationprinted is NULL or datecancellationprinted='0000-00-00') "; - if ( defined $from_placed_on ) { - $query .= " AND creationdate >= ? "; - push @query_params, $from_placed_on; - } + my @query_params = (); - if ( defined $to_placed_on ) { - $query .= " AND creationdate <= ? "; - push @query_params, $to_placed_on; - } + if ( defined $title ) { + $query .= " AND biblio.title LIKE ? "; + $title =~ s/\s+/%/g; + push @query_params, "%$title%"; + } - if ( C4::Context->preference("IndependantBranches") ) { - my $userenv = C4::Context->userenv; - if ( ($userenv) && ( $userenv->{flags} != 1 ) ) { - $query .= " AND (borrowers.branchcode = ? OR borrowers.branchcode ='' ) "; - push @query_params, $userenv->{branch}; - } + if ( defined $author ) { + $query .= " AND biblio.author LIKE ? "; + push @query_params, "%$author%"; + } + + if ( defined $name ) { + $query .= " AND aqbooksellers.name LIKE ? "; + push @query_params, "%$name%"; + } + + if ( defined $from_placed_on ) { + $query .= " AND creationdate >= ? "; + push @query_params, $from_placed_on; + } + + if ( defined $to_placed_on ) { + $query .= " AND creationdate <= ? "; + push @query_params, $to_placed_on; + } + + if ($basket) { + if ($basket =~ m/^\d+$/) { + $query .= " AND aqorders.basketno = ? "; + push @query_params, $basket; + } else { + $query .= " AND aqbasket.basketname LIKE ? "; + push @query_params, "%$basket%"; } - $query .= " ORDER BY id"; - my $sth = $dbh->prepare($query); - $sth->execute( @query_params ); - my $cnt = 1; - while ( my $line = $sth->fetchrow_hashref ) { - $line->{count} = $cnt++; - $line->{toggle} = 1 if $cnt % 2; - push @order_loop, $line; - $line->{creationdate} = format_date( $line->{creationdate} ); - $line->{datereceived} = format_date( $line->{datereceived} ); - $total_qty += $line->{'quantity'}; - $total_qtyreceived += $line->{'quantityreceived'}; - $total_price += $line->{'quantity'} * $line->{'ecost'}; + } + + if ($booksellerinvoicenumber) { + $query .= " AND (aqorders.booksellerinvoicenumber LIKE ? OR aqbasket.booksellerinvoicenumber LIKE ?)"; + push @query_params, "%$booksellerinvoicenumber%", "%$booksellerinvoicenumber%"; + } + + if ( C4::Context->preference("IndependantBranches") ) { + my $userenv = C4::Context->userenv; + if ( $userenv && ($userenv->{flags} || 0) != 1 ) { + $query .= " AND (borrowers.branchcode = ? OR borrowers.branchcode ='' ) "; + push @query_params, $userenv->{branch}; } } + $query .= " ORDER BY id"; + my $sth = $dbh->prepare($query); + $sth->execute( @query_params ); + my $cnt = 1; + while ( my $line = $sth->fetchrow_hashref ) { + $line->{count} = $cnt++; + $line->{toggle} = 1 if $cnt % 2; + push @order_loop, $line; + $line->{creationdate} = format_date( $line->{creationdate} ); + $line->{datereceived} = format_date( $line->{datereceived} ); + $total_qty += $line->{'quantity'}; + $total_qtyreceived += $line->{'quantityreceived'}; + $total_price += $line->{'quantity'} * $line->{'ecost'}; + } return \@order_loop, $total_qty, $total_price, $total_qtyreceived; } diff --git a/acqui/histsearch.pl b/acqui/histsearch.pl index 2c41742..e158842 100755 --- a/acqui/histsearch.pl +++ b/acqui/histsearch.pl @@ -2,6 +2,8 @@ # This file is part of Koha. # +# Parts copyright 2011 Catalyst IT Ltd. +# # Koha is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License as published by the Free Software # Foundation; either version 2 of the License, or (at your option) any later @@ -56,12 +58,14 @@ use C4::Acquisition; use C4::Dates; use C4::Debug; -my $input = new CGI; -my $title = $input->param( 'title'); -my $author = $input->param('author'); -my $name = $input->param( 'name' ); -my $from_placed_on = C4::Dates->new($input->param('from')); -my $to_placed_on = C4::Dates->new($input->param( 'to')); +my $input = new CGI; +my $title = $input->param( 'title'); +my $author = $input->param('author'); +my $name = $input->param( 'name' ); +my $basket = $input->param( 'basket' ); +my $booksellerinvoicenumber = $input->param( 'booksellerinvoicenumber' ); +my $from_placed_on = C4::Dates->new($input->param('from')) if $input->param('from'); +my $to_placed_on = C4::Dates->new($input->param( 'to')) if $input->param('to'); my $dbh = C4::Context->dbh; my ( $template, $loggedinuser, $cookie ) = get_template_and_user( @@ -83,20 +87,38 @@ if ( $d = $input->param('iso') ) { $to_iso = C4::Dates->new($d)->output('iso'); } -my ( $order_loop, $total_qty, $total_price, $total_qtyreceived ) = - GetHistory( $title, $author, $name, $from_iso, $to_iso ); +my ( $order_loop, $total_qty, $total_price, $total_qtyreceived ); +# If we're supplied any value then we do a search. Otherwise we don't. +my $do_search = $title || $author || $name || $basket || $booksellerinvoicenumber || + $from_placed_on || $to_placed_on; +if ($do_search) { + ( $order_loop, $total_qty, $total_price, $total_qtyreceived ) = GetHistory( + title => $title, + author => $author, + name => $name, + from_placed_on => $from_iso, + to_placed_on => $to_iso, + basket => $basket, + booksellerinvoicenumber => $booksellerinvoicenumber, + ); +} + +my $from_date = $from_placed_on->output('syspref') if $from_placed_on; +my $to_date = $to_placed_on->output('syspref') if $to_placed_on; $template->param( suggestions_loop => $order_loop, total_qty => $total_qty, total_qtyreceived => $total_qtyreceived, total_price => sprintf( "%.2f", $total_price ), - numresults => scalar(@$order_loop), + numresults => $order_loop ? scalar(@$order_loop) : undef, title => $title, author => $author, name => $name, - from_placed_on => $from_placed_on->output('syspref'), - to_placed_on => $to_placed_on->output('syspref'), + basket => $basket, + booksellerinvoicenumber => $booksellerinvoicenumber, + from_placed_on => $from_date, + to_placed_on => $to_date, DHTMLcalendar_dateformat=> C4::Dates->DHTMLcalendar(), dateformat => C4::Dates->new()->format(), debug => $debug || $input->param('debug') || 0, diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-history-search.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-history-search.inc deleted file mode 100644 index 213d693..0000000 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-history-search.inc +++ /dev/null @@ -1,24 +0,0 @@ - -

[% LibraryName %]

- - - diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-search.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-search.inc index dd3d325..ddf6f8d 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-search.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-search.inc @@ -12,10 +12,16 @@
+ + [+] Advanced Search +
-
    + diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/histsearch.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/histsearch.tt index be26a14..495f313 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/histsearch.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/histsearch.tt @@ -5,7 +5,7 @@ [% INCLUDE 'header.inc' %] -[% INCLUDE 'acquisitions-history-search.inc' %] +[% INCLUDE 'acquisitions-search.inc' %] @@ -22,6 +22,8 @@
  • +
  • +
  • Show Calendar diff --git a/t/db_dependent/lib/KohaTest.pm b/t/db_dependent/lib/KohaTest.pm index 47f7538..70c963d 100644 --- a/t/db_dependent/lib/KohaTest.pm +++ b/t/db_dependent/lib/KohaTest.pm @@ -201,8 +201,6 @@ sub startup_15_truncate_tables : Test( startup => 1 ) { ethnicity issues issuingrules - labels - labels_profile matchchecks notifys nozebra @@ -268,8 +266,6 @@ we need a bookfund for many of the tests. This currently uses one that is in the skeleton database. free to use this one, or insert your own. -=cut - sub startup_22_add_bookfund : Test(startup => 2) { my $self = shift; @@ -283,6 +279,8 @@ sub startup_22_add_bookfund : Test(startup => 2) { return; } +=cut + =head2 startup_24_add_branch =cut diff --git a/t/db_dependent/lib/KohaTest/Acquisition.pm b/t/db_dependent/lib/KohaTest/Acquisition.pm index eca0b16..e7618c9 100644 --- a/t/db_dependent/lib/KohaTest/Acquisition.pm +++ b/t/db_dependent/lib/KohaTest/Acquisition.pm @@ -7,6 +7,7 @@ use warnings; use Test::More; use C4::Acquisition; +use C4::Budgets; use C4::Context; use C4::Members; use Time::localtime; @@ -25,7 +26,6 @@ sub methods : Test( 1 ) { GetOrder NewOrder ModOrder - ModOrderBiblioNumber ModReceiveOrder SearchOrder DelOrder @@ -71,27 +71,21 @@ sub create_new_basket { $self->add_biblios( add_items => 1 ); ok( scalar @{$self->{'biblios'}} > 0, 'we have added at least one biblio' ); - my ( $basketno, $ordernumber ) = NewOrder( undef, # $basketno, - $self->{'biblios'}[0], # $bibnum, - undef, # $title, - 1, # $quantity, - undef, # $listprice, - $self->{'booksellerid'}, # $booksellerid, - $param{'authorizedby'}, # $authorisedby, - undef, # $notes, - $self->{'bookfundid'}, # $bookfund, - undef, # $bibitemnum, - 1, # $rrp, - 1, # $ecost, - undef, # $gst, - undef, # $budget, - undef, # $cost, - undef, # $sub, - $param{'invoice'}, # $invoice, - undef, # $sort1, - undef, # $sort2, - undef, # $purchaseorder - ); + my $rand = int(rand(10000)); + my $basketno = NewBasket( $self->{'booksellerid'}, $param{'authorizedby'}, "Basket $rand"); +# $basketnote, $basketbooksellernote, $basketcontractnumber ); +# The following keys are used: "biblionumber", "title", "basketno", "quantity", "notes", "biblioitemnumber", "rrp", "ecost", "gst", "unitprice", "subscription", "sort1", "sort2", "booksellerinvoicenumber", "listprice", "budgetdate", "purchaseordernumber", "branchcode", "booksellerinvoicenumber", "bookfundid". + my $budget_id = AddBudget( { budget_name => "Budget $rand" } ); + my ( undef, $ordernumber ) = NewOrder( { + basketno => $basketno, + budget_id => $budget_id, + biblionumber => $self->{'biblios'}[0], + quantity => 1, + bookfundid => $self->{'bookfundid'}, + rrp => 1, + ecost => 1, + booksellerinvoicenumber => $param{'invoice'}, + } ); ok( $basketno, "my basket number is $basketno" ); ok( $ordernumber, "my order number is $ordernumber" ); diff --git a/t/db_dependent/lib/KohaTest/Acquisition/GetHistory.pm b/t/db_dependent/lib/KohaTest/Acquisition/GetHistory.pm index 8c7c475..63ef7a9 100644 --- a/t/db_dependent/lib/KohaTest/Acquisition/GetHistory.pm +++ b/t/db_dependent/lib/KohaTest/Acquisition/GetHistory.pm @@ -38,22 +38,20 @@ sub no_history : Test( 4 ) { =cut -sub one_order : Test( 50 ) { +my $INVOICE = "1234-56 AB"; +sub one_order : Test( 55 ) { my $self = shift; - my ( $basketno, $ordernumber ) = $self->create_new_basket(); + my ( $basketno, $ordernumber ) = $self->create_new_basket(invoice => $INVOICE); ok( $basketno, "basketno is $basketno" ); ok( $ordernumber, "ordernumber is $ordernumber" ); # No arguments fetches no history. { - my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory(); + my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = eval { GetHistory() }; # diag( Data::Dumper->Dump( [ $order_loop, $total_qty, $total_price, $total_qtyreceived ], [ qw( order_loop total_qty total_price total_qtyreceived ) ] ) ); - is( scalar @$order_loop, 0, 'order_loop is empty' ); - is( $total_qty, 0, 'total_qty' ); - is( $total_price, 0, 'total_price' ); - is( $total_qtyreceived, 0, 'total_qtyreceived' ); + is( $order_loop, undef, 'order_loop is empty' ); } my $bibliodata = GetBiblioData( $self->{'biblios'}[0] ); @@ -62,7 +60,7 @@ sub one_order : Test( 50 ) { # searching by title should find it. { - my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( $bibliodata->{'title'} ); + my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( title => $bibliodata->{'title'} ); # diag( Data::Dumper->Dump( [ $order_loop, $total_qty, $total_price, $total_qtyreceived ], [ qw( order_loop total_qty total_price total_qtyreceived ) ] ) ); is( scalar @$order_loop, 1, 'order_loop searched by title' ); @@ -73,9 +71,35 @@ sub one_order : Test( 50 ) { # diag( Data::Dumper->Dump( [ $order_loop ], [ 'order_loop' ] ) ); } + # searching by basket number + { + my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( basket => $basketno ); + # diag( Data::Dumper->Dump( [ $order_loop, $total_qty, $total_price, $total_qtyreceived ], [ qw( order_loop total_qty total_price total_qtyreceived ) ] ) ); + + is( scalar @$order_loop, 1, 'order_loop searched by basket no' ); + is( $total_qty, 1, 'total_qty searched by basket no' ); + is( $total_price, 1, 'total_price searched by basket no' ); + is( $total_qtyreceived, 0, 'total_qtyreceived searched by basket no' ); + + # diag( Data::Dumper->Dump( [ $order_loop ], [ 'order_loop' ] ) ); + } + + # searching by invoice number + { + my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( booksellerinvoicenumber => $INVOICE ); + # diag( Data::Dumper->Dump( [ $order_loop, $total_qty, $total_price, $total_qtyreceived ], [ qw( order_loop total_qty total_price total_qtyreceived ) ] ) ); + + is( scalar @$order_loop, 1, 'order_loop searched by invoice no' ); + is( $total_qty, 1, 'total_qty searched by invoice no' ); + is( $total_price, 1, 'total_price searched by invoice no' ); + is( $total_qtyreceived, 0, 'total_qtyreceived searched by invoice no' ); + + # diag( Data::Dumper->Dump( [ $order_loop ], [ 'order_loop' ] ) ); + } + # searching by author { - my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( undef, $bibliodata->{'author'} ); + my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( author => $bibliodata->{'author'} ); # diag( Data::Dumper->Dump( [ $order_loop, $total_qty, $total_price, $total_qtyreceived ], [ qw( order_loop total_qty total_price total_qtyreceived ) ] ) ); is( scalar @$order_loop, 1, 'order_loop searched by author' ); @@ -92,7 +116,7 @@ sub one_order : Test( 50 ) { ok( $bookseller->{'name'}, 'bookseller name' ) or diag( Data::Dumper->Dump( [ $bookseller ], [ 'bookseller' ] ) ); - my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( undef, undef, $bookseller->{'name'} ); + my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( name => $bookseller->{'name'} ); # diag( Data::Dumper->Dump( [ $order_loop, $total_qty, $total_price, $total_qtyreceived ], [ qw( order_loop total_qty total_price total_qtyreceived ) ] ) ); is( scalar @$order_loop, 1, 'order_loop searched by name' ); @@ -106,7 +130,7 @@ sub one_order : Test( 50 ) { my $tomorrow = $self->tomorrow(); # diag( "tomorrow is $tomorrow" ); - my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( undef, undef, undef, undef, $tomorrow ); + my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( to_placed_on => $tomorrow ); # diag( Data::Dumper->Dump( [ $order_loop, $total_qty, $total_price, $total_qtyreceived ], [ qw( order_loop total_qty total_price total_qtyreceived ) ] ) ); is( scalar @$order_loop, 1, 'order_loop searched by to_date' ); @@ -120,7 +144,7 @@ sub one_order : Test( 50 ) { my $yesterday = $self->yesterday(); # diag( "yesterday was $yesterday" ); - my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( undef, undef, undef, $yesterday ); + my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( from_placed_on => $yesterday ); # diag( Data::Dumper->Dump( [ $order_loop, $total_qty, $total_price, $total_qtyreceived ], [ qw( order_loop total_qty total_price total_qtyreceived ) ] ) ); is( scalar @$order_loop, 1, 'order_loop searched by from_date' ); @@ -134,7 +158,7 @@ sub one_order : Test( 50 ) { # just search by title here, we need to search by something. { - my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( $bibliodata->{'title'} ); + my ( $order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( title => $bibliodata->{'title'} ); # diag( Data::Dumper->Dump( [ $order_loop, $total_qty, $total_price, $total_qtyreceived ], [ qw( order_loop total_qty total_price total_qtyreceived ) ] ) ); is( scalar @$order_loop, 1, 'order_loop searched by title' ); -- 1.7.4.1