# along with Koha; if not, see <http://www.gnu.org/licenses>.
use Modern::Perl;
-use Test::More tests => 6;
-use Koha::AuthorisedValues;
+use Test::More tests => 7;
+use t::lib::TestBuilder;
+
+use List::MoreUtils qw( any none );
-$| = 1;
+use C4::Biblio qw(AddBiblio);
+use C4::Reserves qw( AddReserve );
+use C4::ClassSource qw( GetClassSort );
+use Koha::AuthorisedValues;
+use Koha::Biblios;
+use Koha::Database;
+use MARC::Record;
BEGIN {
use_ok('C4::Context');
- use_ok('C4::Items');
+ use_ok('C4::Items', qw( GetItemsForInventory ));
use_ok('C4::Biblio');
use_ok('C4::Koha');
}
can_ok('C4::Items','GetItemsForInventory');
-my $dbh = C4::Context->dbh;
-$dbh->{AutoCommit} = 0;
-$dbh->{RaiseError} = 1;
-
-my ($oldResults, $oldCount) = OldWay($dbh);
-my ($newResults, $newCount) = GetItemsForInventory( { interface => 'staff' } );
-
-is_deeply($newResults,$oldResults,"Inventory results unchanged.");
-
-$dbh->rollback;
-
-sub OldWay {
- my ($tdbh) = @_;
- my $ldbh = $tdbh;
- my $minlocation = '';
- my $maxlocation = '';
- my $location = '';
- my $itemtype = '';
- my $ignoreissued = '';
- my $datelastseen = '';
- my $branchcode = '';
- my $branch = '';
- my $offset = '';
- my $size = '';
- my $statushash = '';
- my $interface = '';
-
- my ( @bind_params, @where_strings );
-
- my $select_columns = q{
- SELECT items.itemnumber, barcode, itemcallnumber, title, author, biblio.biblionumber, biblio.frameworkcode, datelastseen, homebranch, location, notforloan, damaged, itemlost, withdrawn, stocknumber
- };
- my $select_count = q{SELECT COUNT(*)};
- my $query = q{
- FROM items
- LEFT JOIN biblio ON items.biblionumber = biblio.biblionumber
- LEFT JOIN biblioitems on items.biblionumber = biblioitems.biblionumber
- };
- if ($statushash){
- for my $authvfield (keys %$statushash){
- if ( scalar @{$statushash->{$authvfield}} > 0 ){
- my $joinedvals = join ',', @{$statushash->{$authvfield}};
- push @where_strings, "$authvfield in (" . $joinedvals . ")";
+my $schema = Koha::Database->new->schema;
+my $builder = t::lib::TestBuilder->new;
+
+subtest 'Skip items with waiting holds' => sub {
+
+ plan tests => 8;
+
+ $schema->storage->txn_begin;
+
+ my $library = $builder->build_object( { class => 'Koha::Libraries' } );
+ my $itemtype
+ = $builder->build_object( { class => 'Koha::ItemTypes', value => { rentalcharge => 0 } } );
+ my $patron_1 = $builder->build_object(
+ { class => 'Koha::Patrons', value => { branchcode => $library->id } } );
+ my $patron_2 = $builder->build_object(
+ { class => 'Koha::Patrons', value => { branchcode => $library->id } } );
+
+
+ my $title_1 = 'Title 1, ';
+ my $title_2 = 'Title 2, bizzarre one so doesn\'t already exist';
+
+ my $biblio_1 = $builder->build_sample_biblio({ itemtype => $itemtype->itemtype, title => $title_1 });
+ my $biblio_2 = $builder->build_sample_biblio({ itemtype => $itemtype->itemtype, title => $title_2 });
+
+ my ( $items_1, $first_items_count ) = GetItemsForInventory();
+ is( scalar @{$items_1}, $first_items_count, 'Results and count match' );
+
+ # Add two items, so we don't depend on existing data
+ my $item_1 = $builder->build_object(
+ { class => 'Koha::Items',
+ value => {
+ biblionumber => $biblio_1->biblionumber,
+ biblioitemnumber => $biblio_1->biblioitem->biblioitemnumber,
+ homebranch => $library->id,
+ holdingbranch => $library->id,
+ itype => $itemtype->itemtype,
+ reserves => undef
}
}
- }
-
- if ($minlocation) {
- push @where_strings, 'itemcallnumber >= ?';
- push @bind_params, $minlocation;
- }
-
- if ($maxlocation) {
- push @where_strings, 'itemcallnumber <= ?';
- push @bind_params, $maxlocation;
- }
-
- if ($datelastseen) {
- $datelastseen = output_pref({ str => $datelastseen, dateformat => 'iso', dateonly => 1 });
- push @where_strings, '(datelastseen < ? OR datelastseen IS NULL)';
- push @bind_params, $datelastseen;
- }
-
- if ( $location ) {
- push @where_strings, 'items.location = ?';
- push @bind_params, $location;
- }
-
- if ( $branchcode ) {
- if($branch eq "homebranch"){
- push @where_strings, 'items.homebranch = ?';
- }else{
- push @where_strings, 'items.holdingbranch = ?';
- }
- push @bind_params, $branchcode;
- }
-
- if ( $itemtype ) {
- push @where_strings, 'biblioitems.itemtype = ?';
- push @bind_params, $itemtype;
- }
-
- if ( $ignoreissued) {
- $query .= "LEFT JOIN issues ON items.itemnumber = issues.itemnumber ";
- push @where_strings, 'issues.date_due IS NULL';
- }
-
- if ( @where_strings ) {
- $query .= 'WHERE ';
- $query .= join ' AND ', @where_strings;
- }
- $query .= ' ORDER BY items.cn_sort, itemcallnumber, title';
- my $count_query = $select_count . $query;
- $query .= " LIMIT $offset, $size" if ($offset and $size);
- $query = $select_columns . $query;
- my $sth = $ldbh->prepare($query);
- $sth->execute( @bind_params );
-
- my @results = ();
- my $tmpresults = $sth->fetchall_arrayref({});
- $sth = $ldbh->prepare( $count_query );
- $sth->execute( @bind_params );
- my ($iTotalRecords) = $sth->fetchrow_array();
-
- foreach my $row (@$tmpresults) {
-
- # Auth values
- foreach my $field (sort keys %$row) {
- # If the koha field is mapped to a marc field
- my ($f, $sf) = C4::Biblio::GetMarcFromKohaField("items.$field", $row->{'frameworkcode'});
- if (defined($f) and defined($sf)) {
- # We replace the code with it's description
- my $av = Koha::AuthorisedValues->search_by_marc_field({ frameworkcode => $row->{frameworkcode}, tagfield => $f, tagsubfield => $sf, });
- $av = $av->count ? $av->unblessed : [];
- my $authvals = { map { ( $_->{authorised_value} => $_->{lib} ) } @$av };
- $row->{$field} = $authvals->{$row->{$field}} if defined $authvals && defined $row->{$field} && defined $authvals->{$row->{$field}};
+ );
+
+ my $item_2 = $builder->build_object(
+ { class => 'Koha::Items',
+ value => {
+ biblionumber => $biblio_2->biblionumber,
+ biblioitemnumber => $biblio_2->biblioitem->biblioitemnumber,
+ homebranch => $library->id,
+ holdingbranch => $library->id,
+ itype => $itemtype->itemtype,
+ reserves => undef
}
}
- push @results, $row;
- }
+ );
+
+ my ( $items_2, $second_items_count ) = GetItemsForInventory();
+ is( scalar @{$items_2}, $second_items_count, 'Results and count match' );
+ is( $first_items_count + 2, $second_items_count, 'Two items added, count makes sense' );
+
+ my $real_itemtype_count = Koha::Items->search({ itype => $itemtype->itemtype })->count;
+ my $itype_str = "'" . $itemtype->itemtype . "'"; # manipulate string for db query
+ my ( $items_3, $itemtype_count ) = GetItemsForInventory({ itemtypes => [ $itype_str ] });
+ is( $itemtype_count, $real_itemtype_count, 'Itemtype filter gets correct number of inventory items' );
+
+ # Add 2 waiting holds
+ C4::Reserves::AddReserve(
+ {
+ branchcode => $library->branchcode,
+ borrowernumber => $patron_1->borrowernumber,
+ biblionumber => $item_1->biblionumber,
+ priority => 1,
+ itemnumber => $item_1->itemnumber,
+ found => 'W'
+ }
+ );
+ C4::Reserves::AddReserve(
+ {
+ branchcode => $library->branchcode,
+ borrowernumber => $patron_1->borrowernumber,
+ biblionumber => $item_2->biblionumber,
+ priority => 1,
+ itemnumber => $item_2->itemnumber,
+ }
+ );
+ C4::Reserves::AddReserve(
+ {
+ branchcode => $library->branchcode,
+ borrowernumber => $patron_2->borrowernumber,
+ biblionumber => $item_2->biblionumber,
+ priority => 2,
+ itemnumber => $item_2->itemnumber,
+ }
+ );
+
+ my ( $new_items, $new_items_count ) = GetItemsForInventory( { ignore_waiting_holds => 1 } );
+ is( $new_items_count, $first_items_count + 1, 'Item on hold skipped, count makes sense' );
+ ok( (any { $_->{title} eq $title_2 } @{$new_items}),
+ 'Item on hold skipped, the other one we added is present' );
+ ok( (none { $_->{title} eq $title_1 } @{$new_items}),
+ 'Item on hold skipped, no one matches' );
+ is( scalar(@$new_items), $new_items_count, 'total and number of items is the same');
+
+ $schema->storage->txn_rollback;
+};
+
+subtest 'Use cn_sort rather than callnumber to determine correct location' => sub {
+ $schema->storage->txn_begin;
+ plan tests => 1;
+
+ my $builder = t::lib::TestBuilder->new;
+
+ my $class_rule = $builder->build({
+ source => 'ClassSortRule',
+ value => { sort_routine => "LCC" }
+ });
+ my $class_source = $builder->build({
+ source => 'ClassSource',
+ value => {
+ class_sort_rule => $class_rule->{class_sort_rule},
+ }
+ });
+
+ #Find if we have any items in our test range before we start
+ my( undef, $pre_item_count) = GetItemsForInventory({
+ maxlocation => 'GT100',
+ minlocation => 'GT90',
+ class_source => $class_source->{cn_source},
+ });
+
+ my $item_1 = $builder->build({ # Cannot call build_sample_item or cn_sort will be replaced by Koha::Item->store
+ source => 'Item',
+ value => {
+ itemcallnumber => 'GT95',
+ cn_sort => GetClassSort($class_source->{cn_source},undef,'GT95'),
+ }
+ });
- return (\@results, $iTotalRecords);
-}
+ my( undef, $item_count) = GetItemsForInventory({
+ maxlocation => 'GT100',
+ minlocation => 'GT90',
+ class_source => $class_source->{cn_source},
+ });
+ is($item_count,$pre_item_count + 1,"We should return GT95 as between GT90 and GT100");
+ $schema->storage->txn_rollback;
+
+};