@@ -, +, @@ overlap... PreventChechoutOnSameReservePeriod and PreventReservesOnSamePeriod --- C4/Circulation.pm | 23 +++ C4/Reserves.pm | 48 ++++++ Koha/DateUtils.pm | 44 +++++- circ/circulation.pl | 4 + ...entchechoutonsamereserveperiod_syspref.sql | 1 + ...dd_preventreservesonsameperiod_syspref.sql | 1 + installer/data/mysql/sysprefs.sql | 4 +- .../admin/preferences/circulation.pref | 12 ++ .../prog/en/modules/circ/circulation.tt | 2 + .../prog/en/modules/reserve/placerequest.tt | 66 ++++++++ opac/opac-reserve.pl | 9 ++ reserve/placerequest.pl | 144 ++++++++++-------- t/db_dependent/Circulation/CanBookBeIssued.t | 106 +++++++++++++ t/db_dependent/Reserves/ReserveDate.t | 108 +++++++++++++ 14 files changed, 508 insertions(+), 64 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug_15261-add_preventchechoutonsamereserveperiod_syspref.sql create mode 100644 installer/data/mysql/atomicupdate/bug_15261-add_preventreservesonsameperiod_syspref.sql create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/reserve/placerequest.tt create mode 100644 t/db_dependent/Circulation/CanBookBeIssued.t create mode 100644 t/db_dependent/Reserves/ReserveDate.t --- a/C4/Circulation.pm +++ a/C4/Circulation.pm @@ -1028,6 +1028,7 @@ sub CanBookBeIssued { $needsconfirmation{'resborrowernumber'} = $patron->borrowernumber; $needsconfirmation{'resbranchcode'} = $res->{branchcode}; $needsconfirmation{'reswaitingdate'} = $res->{'waitingdate'}; + $needsconfirmation{resreserveid} = $res->{reserve_id}; } elsif ( $restype eq "Reserved" ) { # The item is on reserve for someone else. @@ -1038,9 +1039,31 @@ sub CanBookBeIssued { $needsconfirmation{'resborrowernumber'} = $patron->borrowernumber; $needsconfirmation{'resbranchcode'} = $patron->branchcode; $needsconfirmation{'resreservedate'} = $res->{reservedate}; + $needsconfirmation{resreserveid} = $res->{reserve_id}; } } } + + my $now = dt_from_string(); + my $preventCheckoutOnSameReservePeriod = + C4::Context->preference("PreventCheckoutOnSameReservePeriod"); + my $reserves_on_same_period = + ReservesOnSamePeriod($item_object->biblionumber, $item_object->itemnumber, $now->ymd, $duedate->ymd); + if ($preventCheckoutOnSameReservePeriod && $reserves_on_same_period) { + my $reserve = $reserves_on_same_period->[0]; + my $patron = Koha::Patrons->find( $reserve->{borrowernumber} ); + my $branchname = Koha::Libraries->find($reserve->{branchcode})->branchname; + + $needsconfirmation{RESERVED} = 1; + $needsconfirmation{resfirstname} = $patron->firstname; + $needsconfirmation{ressurname} = $patron->surname; + $needsconfirmation{rescardnumber} = $patron->cardnumber; + $needsconfirmation{resborrowernumber} = $patron->borrowernumber; + $needsconfirmation{resbranchname} = $branchname; + $needsconfirmation{resreservedate} = $reserve->{reservedate}; + $needsconfirmation{resreserveid} = $reserve->{reserve_id}; + } + } ## CHECK AGE RESTRICTION --- a/C4/Reserves.pm +++ a/C4/Reserves.pm @@ -133,6 +133,7 @@ BEGIN { &SuspendAll &GetReservesControlBranch + &ReservesOnSamePeriod IsItemOnHoldAndFound @@ -2171,6 +2172,53 @@ sub GetHoldRule { return $sth->fetchrow_hashref(); } +=head2 ReservesOnSamePeriod + + my $reserve = ReservesOnSamePeriod( $biblionumber, $itemnumber, $resdate, $expdate); + + Return the reserve that match the period ($resdate => $expdate), + undef if no reserve match. + +=cut + +sub ReservesOnSamePeriod { + my ($biblionumber, $itemnumber, $resdate, $expdate) = @_; + + unless ($resdate && $expdate) { + return; + } + + my @reserves = Koha::Holds->search({ biblionumber => $biblionumber }); + + $resdate = output_pref({ str => $resdate, dateonly => 1, dateformat => 'iso' }); + $expdate = output_pref({ str => $expdate, dateonly => 1, dateformat => 'iso' }); + + my @reserves_overlaps; + foreach my $reserve ( @reserves ) { + + unless ($reserve->reservedate && $reserve->expirationdate) { + next; + } + + if (date_ranges_overlap($resdate, $expdate, + $reserve->reservedate, + $reserve->expirationdate)) { + + # If reserve is item level and the requested periods overlap. + if ($itemnumber && $reserve->itemnumber == $itemnumber ) { + return [$reserve->unblessed]; + } + push @reserves_overlaps, $reserve->unblessed; + } + } + + if ( @reserves_overlaps >= Koha::Items->search({ biblionumber => $biblionumber })->count() ) { + return \@reserves_overlaps; + } + + return; +} + =head1 AUTHOR Koha Development Team --- a/Koha/DateUtils.pm +++ a/Koha/DateUtils.pm @@ -24,7 +24,7 @@ use Koha::Exceptions; use base 'Exporter'; our @EXPORT = ( - qw( dt_from_string output_pref format_sqldatetime ) + qw( dt_from_string output_pref format_sqldatetime date_ranges_overlap ) ); =head1 DateUtils @@ -322,4 +322,46 @@ sub format_sqldatetime { return q{}; } +=head2 date_ranges_overlap + + $bool = date_ranges_overlap($start1, $end1, $start2, $end2); + + Tells if first range ($start1 => $end1) overlaps + the second one ($start2 => $end2) + +=cut + +sub date_ranges_overlap { + my ($start1, $end1, $start2, $end2) = @_; + + $start1 = dt_from_string( $start1, 'iso' ); + $end1 = dt_from_string( $end1, 'iso' ); + $start2 = dt_from_string( $start2, 'iso' ); + $end2 = dt_from_string( $end2, 'iso' ); + + if ( + # Start of range 2 is in the range 1. + ( + DateTime->compare($start2, $start1) >= 0 + && DateTime->compare($start2, $end1) <= 0 + ) + || + # End of range 2 is in the range 1. + ( + DateTime->compare($end2, $start1) >= 0 + && DateTime->compare($end2, $end1) <= 0 + ) + || + # Range 2 start before and end after range 1. + ( + DateTime->compare($start2, $start1) < 0 + && DateTime->compare($end2, $end1) > 0 + ) + ) { + return 1; + } + + return; +} + 1; --- a/circ/circulation.pl +++ a/circ/circulation.pl @@ -419,6 +419,10 @@ if (@$barcodes) { } unless($confirm_required) { my $switch_onsite_checkout = exists $messages->{ONSITE_CHECKOUT_WILL_BE_SWITCHED}; + if ( $cancelreserve eq 'cancel' ) { + CancelReserve({ reserve_id => $query->param('reserveid') }); + } + $cancelreserve = $cancelreserve eq 'revert' ? 'revert' : undef; my $issue = AddIssue( $patron->unblessed, $barcode, $datedue, $cancelreserve, undef, undef, { onsite_checkout => $onsite_checkout, auto_renew => $session->param('auto_renew'), switch_onsite_checkout => $switch_onsite_checkout, } ); $template_params->{issue} = $issue; $session->clear('auto_renew'); --- a/installer/data/mysql/atomicupdate/bug_15261-add_preventchechoutonsamereserveperiod_syspref.sql +++ a/installer/data/mysql/atomicupdate/bug_15261-add_preventchechoutonsamereserveperiod_syspref.sql @@ -0,0 +1, @@ +INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES ('PreventCheckoutOnSameReservePeriod', '0', 'Prevent to checkout a document if a reserve on same period exists', NULL, 'YesNo'); --- a/installer/data/mysql/atomicupdate/bug_15261-add_preventreservesonsameperiod_syspref.sql +++ a/installer/data/mysql/atomicupdate/bug_15261-add_preventreservesonsameperiod_syspref.sql @@ -0,0 +1, @@ +INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES ('PreventReservesOnSamePeriod', '0', 'Prevent to hold a document if a reserve on same period exists', NULL, 'YesNo'); --- a/installer/data/mysql/sysprefs.sql +++ a/installer/data/mysql/sysprefs.sql @@ -649,5 +649,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('XSLTListsDisplay','default','','Enable XSLT stylesheet control over lists pages display on intranet','Free'), ('XSLTResultsDisplay','default','','Enable XSL stylesheet control over results page display on intranet','Free'), ('z3950AuthorAuthFields','701,702,700',NULL,'Define the MARC biblio fields for Personal Name Authorities to fill biblio.author','free'), -('z3950NormalizeAuthor','0','','If ON, Personal Name Authorities will replace authors in biblio.author','YesNo') +('z3950NormalizeAuthor','0','','If ON, Personal Name Authorities will replace authors in biblio.author','YesNo'), +('PreventCheckoutOnSameReservePeriod','0','','Prevent to checkout a document if a reserve on same period exists','YesNo'), +('PreventReservesOnSamePeriod','0','','Prevent to hold a document if a reserve on same period exists','YesNo') ; --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref @@ -499,6 +499,12 @@ Circulation: - "
ccode: [NEWFIC,NULL,DVD]" - "
itype: [NEWBK,\"\"]" - "
Note: the word 'NULL' can be used to block renewal on undefined fields, while an empty string \"\" will block on an empty (but defined) field." + - + - pref: PreventCheckoutOnSameReservePeriod + choices: + yes: Do + no: "Don't" + - If yes, checkouts periods can't overlap with a reserve period. Checkin Policy: - - pref: HoldsAutoFill @@ -783,6 +789,12 @@ Circulation: - 'Example: "itemlost: 1" to set items.itemlost to 1 when the item is marked as lost' - pref: UpdateItemWhenLostFromHoldList type: textarea + - + - pref: PreventReservesOnSamePeriod + choices: + yes: Do + no: "Don't" + - If yes, Reserves periods for the same document can't overlap. Interlibrary Loans: - - pref: ILLModule --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -213,6 +213,7 @@ [% IF ( RESERVED ) %]

+

[% END %] @@ -221,6 +222,7 @@


+

--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/placerequest.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/placerequest.tt @@ -0,0 +1,66 @@ +[% INCLUDE 'doc-head-open.inc' %] + Koha › Circulation › Holds › Confirm holds +[% INCLUDE 'doc-head-close.inc' %] + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'circ-search.inc' %] + + + +
+ +
+
+
+ +

Confirm holds

+ +
+

+ Some of the reserves you are trying to do overlaps with existing reserves. + Please confirm you want to proceed. +

+
+ +
+ + [% IF multi_hold %] + + + [% ELSE %] + + [% END %] + + + + + + + [% FOREACH biblionumber IN overlap_reserves.keys %] + [% input_id = "confirm_$biblionumber" %] +
+ + [% IF (overlap_reserves.$biblionumber.checkitem) %] + + [% END %] + + +
+ [% END %] + + +
+ +
+
+ +
+[% INCLUDE 'intranet-bottom.inc' %] --- a/opac/opac-reserve.pl +++ a/opac/opac-reserve.pl @@ -287,6 +287,15 @@ if ( $query->param('place_reserve') ) { # Inserts a null into the 'itemnumber' field of 'reserves' table. $itemNum = undef; } + + if ($canreserve) { + if (C4::Context->preference("PreventReservesOnSamePeriod") && + ReservesOnSamePeriod($biblioNum, $itemNum, $startdate, $expiration_date)) { + $canreserve = 0; + $failed_holds++; + } + } + my $notes = $query->param('notes_'.$biblioNum)||''; if ( $maxreserves --- a/reserve/placerequest.pl +++ a/reserve/placerequest.pl @@ -30,89 +30,116 @@ use C4::Output; use C4::Reserves; use C4::Circulation; use C4::Members; -use C4::Auth qw/checkauth/; +use C4::Auth; use Koha::Items; use Koha::Patrons; my $input = CGI->new(); -checkauth($input, 0, { reserveforothers => 'place_holds' }, 'intranet'); - -my @bibitems = $input->multi_param('biblioitem'); -my @reqbib = $input->multi_param('reqbib'); -my $biblionumber = $input->param('biblionumber'); -my $borrowernumber = $input->param('borrowernumber'); -my $notes = $input->param('notes'); -my $branch = $input->param('pickup'); -my $startdate = $input->param('reserve_date') || ''; -my @rank = $input->multi_param('rank-request'); -my $type = $input->param('type'); -my $title = $input->param('title'); -my $checkitem = $input->param('checkitem'); +my ( $template, $loggedinuser, $cookie, $flags ) = get_template_and_user( + { + template_name => "reserve/placerequest.tt", + query => $input, + type => "intranet", + authnotrequired => 0, + flagsrequired => { reserveforothers => 'place_holds' }, + } +); + +my $biblionumber=$input->param('biblionumber'); +my $borrowernumber=$input->param('borrowernumber'); +my $notes=$input->param('notes'); +my $branch=$input->param('pickup'); +my $startdate=$input->param('reserve_date') || ''; +my @rank=$input->param('rank-request'); +my $title=$input->param('title'); +my $checkitem=$input->param('checkitem'); my $expirationdate = $input->param('expiration_date'); my $itemtype = $input->param('itemtype') || undef; - -my $borrower = Koha::Patrons->find( $borrowernumber ); -$borrower = $borrower->unblessed if $borrower; +my $confirm = $input->param('confirm'); +my @confirm_biblionumbers = $input->param('confirm_biblionumbers'); my $multi_hold = $input->param('multi_hold'); my $biblionumbers = $multi_hold ? $input->param('biblionumbers') : ($biblionumber . '/'); my $bad_bibs = $input->param('bad_bibs'); my $holds_to_place_count = $input->param('holds_to_place_count') || 1; +my $borrower = Koha::Patrons->find( $borrowernumber ); +$borrower = $borrower->unblessed if $borrower; +unless ($borrower) { + print $input->header(); + print "Invalid borrower number please try again"; + exit; +} + my %bibinfos = (); my @biblionumbers = split '/', $biblionumbers; foreach my $bibnum (@biblionumbers) { - my %bibinfo = (); + my %bibinfo; $bibinfo{title} = $input->param("title_$bibnum"); + $bibinfo{rank} = $input->param("rank_$bibnum"); $bibinfos{$bibnum} = \%bibinfo; } my $found; -if ( $type eq 'str8' && $borrower ) { - - foreach my $biblionumber ( keys %bibinfos ) { - my $count = @bibitems; - @bibitems = sort @bibitems; - my $i2 = 1; - my @realbi; - $realbi[0] = $bibitems[0]; - for ( my $i = 1 ; $i < $count ; $i++ ) { - my $i3 = $i2 - 1; - if ( $realbi[$i3] ne $bibitems[$i] ) { - $realbi[$i2] = $bibitems[$i]; - $i2++; - } - } +my $overlap_reserves = {}; +foreach my $biblionumber (keys %bibinfos) { + next if ($confirm && !grep { $_ eq $biblionumber } @confirm_biblionumbers); - if ( defined $checkitem && $checkitem ne '' ) { - my $item = Koha::Items->find($checkitem); - if ( $item->biblionumber ne $biblionumber ) { - $biblionumber = $item->biblionumber; - } - } + my ($reserve_title, $reserve_rank); + if ($multi_hold) { + my $bibinfo = $bibinfos{$biblionumber}; + $reserve_rank = $bibinfo->{rank}; + $reserve_title = $bibinfo->{title}; + } else { + $reserve_rank = $rank[0]; + $reserve_title = $title; + } - if ($multi_hold) { - my $bibinfo = $bibinfos{$biblionumber}; - if ( CanBookBeReserved($borrower->{'borrowernumber'}, $biblionumber)->{status} eq 'OK' ) { - AddReserve($branch,$borrower->{'borrowernumber'},$biblionumber,[$biblionumber], - $bibinfo->{rank},$startdate,$expirationdate,$notes,$bibinfo->{title},$checkitem,$found); - } - } else { - # place a request on 1st available - for ( my $i = 0 ; $i < $holds_to_place_count ; $i++ ) { - if ( CanBookBeReserved($borrower->{'borrowernumber'}, $biblionumber)->{status} eq 'OK' ) { - AddReserve( $branch, $borrower->{'borrowernumber'}, - $biblionumber, \@realbi, $rank[0], $startdate, $expirationdate, $notes, $title, - $checkitem, $found, $itemtype ); - } - } + if (defined $checkitem && $checkitem ne '') { + my $item = Koha::Items->find($checkitem); + if ($item->biblionumber ne $biblionumber) { + $biblionumber = $item->biblionumber; } } + if (!$confirm && + ReservesOnSamePeriod($biblionumber, $checkitem, $startdate, $expirationdate) && + C4::Context->preference("PreventReservesOnSamePeriod")) { + $overlap_reserves->{$biblionumber} = { + title => $reserve_title , + checkitem => $checkitem, + rank => $reserve_rank + }; + next; + } + + if ( CanBookBeReserved($borrower->{borrowernumber}, $biblionumber)->{status} eq 'OK' ) { + AddReserve($branch, $borrower->{'borrowernumber'}, $biblionumber, undef, + $reserve_rank, $startdate, $expirationdate, $notes, $reserve_title, + $checkitem, $found); + } +} + +if (scalar keys %$overlap_reserves) { + $template->param( + borrowernumber => $borrowernumber, + biblionumbers => $biblionumbers, + biblionumber => $biblionumber, + overlap_reserves => $overlap_reserves, + reserve_date => $startdate, + expiration_date => $expirationdate, + notes => $notes, + rank_request => \@rank, + pickup => $branch, + multi_hold => $multi_hold, + ); + + output_html_with_http_headers $input, $cookie, $template->output; +} else { if ($multi_hold) { if ($bad_bibs) { $biblionumbers .= $bad_bibs; @@ -122,12 +149,5 @@ if ( $type eq 'str8' && $borrower ) { else { print $input->redirect("request.pl?biblionumber=$biblionumber"); } -} -elsif ( $borrowernumber eq '' ) { - print $input->header(); - print "Invalid borrower number please try again"; - - # Not sure that Dump() does HTML escaping. Use firebug or something to trace - # instead. - #print $input->Dump; + exit; } --- a/t/db_dependent/Circulation/CanBookBeIssued.t +++ a/t/db_dependent/Circulation/CanBookBeIssued.t @@ -0,0 +1,106 @@ +#!/usr/bin/env perl + +# This file is part of Koha. +# +# 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 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use Test::More tests => 1; +use C4::Members; +use C4::Reserves; +use C4::Circulation; +use Koha::DateUtils; + +use t::lib::TestBuilder; + +my $schema = Koha::Database->new->schema; +$schema->storage->txn_begin; + +my $builder = t::lib::TestBuilder->new(); + +subtest 'Tests for CanBookBeIssued with overlap reserves' => sub { + plan tests => 6; + + my $categorycode = $builder->build({ source => 'Category' })->{ categorycode }; + my $branch = $builder->build({ source => 'Branch' }); + my $branchcode = $branch->{branchcode}; + + my $borrower = $builder->build_object({ + class => 'Koha::Patrons', + value => { + branchcode => $branchcode, + categorycode => $categorycode, + } + }); + my $borrowernumber = $borrower->borrowernumber; + + my $biblio = $builder->build({source => 'Biblio'}); + my $biblioitem = $builder->build({ + source => 'Biblioitem', + value => { + biblionumber => $biblio->{biblionumber}, + }, + }); + my $item = $builder->build({ + source => 'Item', + value => { + biblionumber => $biblio->{biblionumber}, + biblioitemnumber => $biblioitem->{biblioitemnumber}, + withdrawn => 0, + itemlost => 0, + notforloan => 0, + }, + }); + + + my $startdate = dt_from_string(); + $startdate->add_duration(DateTime::Duration->new(days => 4)); + my $expdate = $startdate->clone(); + $expdate->add_duration(DateTime::Duration->new(days => 10)); + + my $reserveid = AddReserve($branchcode, $borrowernumber, + $item->{biblionumber}, undef, 1, $startdate->ymd(), $expdate->ymd, + undef, undef, undef, undef); + + my $non_overlap_duedate = dt_from_string(); + $non_overlap_duedate->add_duration(DateTime::Duration->new(days => 2)); + my ($error, $question, $alerts ) = + CanBookBeIssued($borrower, $item->{barcode}, $non_overlap_duedate, 1, 0); + + is_deeply($error, {}, ""); + is_deeply($question, {}, ""); + is_deeply($alerts, {}, ""); + + my $overlap_duedate = dt_from_string(); + $overlap_duedate->add_duration(DateTime::Duration->new(days => 5)); + ($error, $question, $alerts ) = + CanBookBeIssued($borrower, $item->{barcode}, $overlap_duedate, 1, 0); + + is_deeply($error, {}, ""); + my $expected = { + RESERVED => 1, + resfirstname => $borrower->firstname, + ressurname => $borrower->surname, + rescardnumber => $borrower->cardnumber, + resborrowernumber => $borrower->borrowernumber, + resbranchname => $branch->{branchname}, + resreservedate => $startdate->ymd, + resreserveid => $reserveid, + }; + is_deeply($question, $expected, ""); + is_deeply($alerts, {}, ""); +}; + +$schema->storage->txn_rollback; --- a/t/db_dependent/Reserves/ReserveDate.t +++ a/t/db_dependent/Reserves/ReserveDate.t @@ -0,0 +1,108 @@ +#!/usr/bin/perl + +# This file is part of Koha. +# +# 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 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use Test::More tests => 6; +use Test::Warn; + +use MARC::Record; +use DateTime::Duration; + +use C4::Biblio; +use C4::Items; +use C4::Members; +use C4::Circulation; +use Koha::Holds; +use t::lib::TestBuilder; + +use Koha::DateUtils; + + +use_ok('C4::Reserves'); + +my $dbh = C4::Context->dbh; + +# Start transaction +$dbh->{AutoCommit} = 0; +$dbh->{RaiseError} = 1; + +my $builder = t::lib::TestBuilder->new(); +my $categorycode = $builder->build({ source => 'Category' })->{ categorycode }; +my $branchcode = $builder->build({ source => 'Branch' })->{ branchcode }; + +my $borrower = $builder->build({ + source => 'Borrower', + value => { + branchcode => $branchcode, + categorycode => $categorycode, + } +}); + +my $borrower2 = $builder->build({ + source => 'Borrower', + value => { + branchcode => $branchcode, + categorycode => $categorycode, + } +}); + +my $borrowernumber = $borrower->{borrowernumber}; +my $borrowernumber2 = $borrower2->{borrowernumber}; + +# Create a helper biblio +my $biblio = MARC::Record->new(); +my $title = 'Alone in the Dark'; +my $author = 'Karen Rose'; +if( C4::Context->preference('marcflavour') eq 'UNIMARC' ) { + $biblio->append_fields( + MARC::Field->new('600', '', '1', a => $author), + MARC::Field->new('200', '', '', a => $title), + ); +} +else { + $biblio->append_fields( + MARC::Field->new('100', '', '', a => $author), + MARC::Field->new('245', '', '', a => $title), + ); +} +my ($bibnum, $bibitemnum); +($bibnum, $title, $bibitemnum) = AddBiblio($biblio, ''); + +my ($item_bibnum, $item_bibitemnum, $itemnumber) = AddItem({ homebranch => $branchcode, holdingbranch => $branchcode, barcode => '333' } , $bibnum); + +C4::Context->set_preference('AllowHoldDateInFuture', 1); + +AddReserve($branchcode, $borrowernumber, $bibnum, + $bibitemnum, 1, '2015-11-01', '2015-11-20', undef, + undef, undef, undef); + +is(ReservesOnSamePeriod($bibnum, undef, '2015-11-25', '2015-11-30'), undef, "Period doesn't overlaps"); + +ok(ReservesOnSamePeriod($bibnum, undef, '2015-11-02', '2015-11-10'), "Period overlaps"); + +my ($item_bibnum2, $item_bibitemnum2, $itemnumber2) = AddItem({ homebranch => $branchcode, holdingbranch => $branchcode, barcode => '444' } , $bibnum); +is(ReservesOnSamePeriod($bibnum, undef, '2015-11-02', '2015-11-10'), undef, "Period overlaps but there is 2 items"); + +AddReserve($branchcode, $borrowernumber2, $bibnum, + $bibitemnum, 1, '2016-02-01', '2016-02-10', undef, + undef, $itemnumber, undef); +is(ReservesOnSamePeriod($bibnum, $itemnumber, '02/12/2015', '10/12/2015'), undef, "Period on item does not overlap (with metric date format)"); + +my $reserve = ReservesOnSamePeriod($bibnum, $itemnumber, '2016-01-31', '2016-02-05'); +is($reserve->[0]->{itemnumber}, $itemnumber, 'Period on item overlaps'); +$dbh->rollback; --