From 38074cd7077b1db75d2df7e3671cb7794779edde Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Mon, 10 Sep 2012 17:06:00 +0200 Subject: [PATCH] Bug 8367: Add more granular level for ReservesMaxPickUpDelay Content-Type: text/plain; charset="utf-8" This patch adds: - a new column in the issuing rules - a new field issuingrules.holdspickupdelay You can now specify a pickup delay for an hold function of a patron category and/or a item type and/or a library. To test: Check there is no regression with a normal reserve workflow. Add one or more issuingrules. In 4 templates, you can see the max pickup delay for an hold (circ/circulation.tt, circ/waitingreserves.tt, members/moremember.tt, opac-user.tt). Signed-off-by: Kyle M Hall Rebased on Feb 15, 2013 (Marcel de Rooy): CONFLICT (content): Merge conflict in opac/opac-user.pl CONFLICT (content): Merge conflict in koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt CONFLICT (content): Merge conflict in installer/data/mysql/updatedatabase.pl CONFLICT (content): Merge conflict in circ/waitingreserves.pl --- C4/Reserves.pm | 83 +++++++++++++++++++- admin/smart-rules.pl | 9 +- circ/circulation.pl | 4 + circ/waitingreserves.pl | 53 ++++++------- installer/data/mysql/kohastructure.sql | 1 + installer/data/mysql/updatedatabase.pl | 9 ++ .../prog/en/modules/admin/smart-rules.tt | 9 ++- .../prog/en/modules/circ/circulation.tt | 4 +- .../prog/en/modules/circ/waitingreserves.tt | 11 ++- .../prog/en/modules/members/moremember.tt | 2 +- koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt | 2 +- members/moremember.pl | 1 + opac/opac-user.pl | 7 ++- 13 files changed, 147 insertions(+), 48 deletions(-) diff --git a/C4/Reserves.pm b/C4/Reserves.pm index a380bf0..2c9e042 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -23,6 +23,7 @@ package C4::Reserves; use strict; #use warnings; FIXME - Bug 2505 +use Date::Calc qw( Add_Delta_Days ); use C4::Context; use C4::Biblio; use C4::Members; @@ -116,7 +117,7 @@ BEGIN { &CheckReserves &CanBookBeReserved - &CanItemBeReserved + &CanItemBeReserved &CancelReserve &CancelExpiredReserves @@ -130,6 +131,9 @@ BEGIN { &ReserveSlip &ToggleSuspend &SuspendAll + &GetMaxPickupDelay + &GetMaxPickupDate + &GetReservesControlBranch ); @EXPORT_OK = qw( MergeHolds ); } @@ -497,6 +501,79 @@ sub CanItemBeReserved{ return 0; } } + +=item GetMaxPickupDelay + +$resallowed = &GetMaxPickupDelay($borrowernumber, $item) + +this function return the max delay for an hold + +=cut + +sub GetMaxPickupDelay { + my ( $borrowernumber, $item ) = @_; + + my $dbh = C4::Context->dbh; + my $allowedreserves = 0; + + my $borrower = C4::Members::GetMember( 'borrowernumber' => $borrowernumber ); + + my $controlbranch = GetReservesControlBranch( $borrower, $item ); + + my $issuingrule = C4::Circulation::GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $controlbranch ); + + return $issuingrule->{holdspickupdelay} + if defined($issuingrule) + and defined $issuingrule->{holdspickupdelay}; + + # if nothing found, return the syspref value + return C4::Context->preference("ReservesMaxPickUpDelay") || 0; +} + +=item GetMaxPickupDate + +$maxpickupdate = &GetMaxPickupDate($item, $borrowernumber); +$item->{waitingdate} is a string or a DateTime. + +this function returns the max pickup date (DateTime format). +(e.g. : the date after which the hold will be considered cancelled) + +=cut + +sub GetMaxPickupDate { + my ( $item, $borrowernumber ) = @_; + return unless $item->{waitingdate}; + + my $date = ref $item->{waitingdate} eq 'DateTime' + ? $item->{waitingdate} + : dt_from_string $item->{waitingdate}; + + my $delay = GetMaxPickupDelay( $borrowernumber, $item ); + $date->add( days => $delay ); + return $date; +} + +=item GetReservesControlBranch + +$branchcode = &GetReservesControlBranch($borrower, $item) + +Returns the branchcode to consider to check hold rules against + +=cut + +sub GetReservesControlBranch { + my ( $borrower, $item ) = @_; + my $controlbranch = C4::Context->preference('ReservesControlBranch'); + my $hbr = C4::Context->preference('HomeOrHoldingBranch') || "homebranch"; + my $branchcode = "*"; + if ( $controlbranch eq "ItemHomeLibrary" ) { + $branchcode = $item->{$hbr}; + } elsif ( $controlbranch eq "PatronLibrary" ) { + $branchcode = $borrower->{branchcode}; + } + return $branchcode; +} + #-------------------------------------------------------------------------------- =head2 GetReserveCount @@ -882,8 +959,10 @@ sub CancelExpiredReserves { while ( my $res = $sth->fetchrow_hashref() ) { CancelReserve( $res->{'biblionumber'}, '', $res->{'borrowernumber'} ); } - + # Cancel reserves that have been waiting too long + # FIXME The only way I see to do this job with the issuingrules.holdspickupdelay value would be to + # get all reserves and to get the related borrower and item. So we could call GetMaxPickupDelay for each reserve. if ( C4::Context->preference("ExpireReservesMaxPickUpDelay") ) { my $max_pickup_delay = C4::Context->preference("ReservesMaxPickUpDelay"); my $charge = C4::Context->preference("ExpireReservesMaxPickUpDelayCharge"); diff --git a/admin/smart-rules.pl b/admin/smart-rules.pl index c221d71..2cd7c11 100755 --- a/admin/smart-rules.pl +++ b/admin/smart-rules.pl @@ -101,8 +101,8 @@ elsif ($op eq 'delete-branch-item') { # save the values entered elsif ($op eq 'add') { my $sth_search = $dbh->prepare('SELECT COUNT(*) AS total FROM issuingrules WHERE branchcode=? AND categorycode=? AND itemtype=?'); - my $sth_insert = $dbh->prepare('INSERT INTO issuingrules (branchcode, categorycode, itemtype, maxissueqty, renewalsallowed, reservesallowed, issuelength, lengthunit, hardduedate, hardduedatecompare, fine, finedays, firstremind, chargeperiod,rentaldiscount, overduefinescap) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'); - my $sth_update=$dbh->prepare("UPDATE issuingrules SET fine=?, finedays=?, firstremind=?, chargeperiod=?, maxissueqty=?, renewalsallowed=?, reservesallowed=?, issuelength=?, lengthunit = ?, hardduedate=?, hardduedatecompare=?, rentaldiscount=?, overduefinescap=? WHERE branchcode=? AND categorycode=? AND itemtype=?"); + my $sth_insert = $dbh->prepare('INSERT INTO issuingrules (branchcode, categorycode, itemtype, maxissueqty, renewalsallowed, reservesallowed, holdspickupdelay, issuelength, lengthunit, hardduedate, hardduedatecompare, fine, finedays, firstremind, chargeperiod,rentaldiscount, overduefinescap) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'); + my $sth_update=$dbh->prepare("UPDATE issuingrules SET fine=?, finedays=?, firstremind=?, chargeperiod=?, maxissueqty=?, renewalsallowed=?, reservesallowed=?, holdspickupdelay=?, issuelength=?, lengthunit = ?, hardduedate=?, hardduedatecompare=?, rentaldiscount=?, overduefinescap=? WHERE branchcode=? AND categorycode=? AND itemtype=?"); my $br = $branch; # branch my $bor = $input->param('categorycode'); # borrower category @@ -114,6 +114,7 @@ elsif ($op eq 'add') { my $maxissueqty = $input->param('maxissueqty'); my $renewalsallowed = $input->param('renewalsallowed'); my $reservesallowed = $input->param('reservesallowed'); + my $holdspickupdelay = $input->param('holdspickupdelay'); $maxissueqty =~ s/\s//g; $maxissueqty = undef if $maxissueqty !~ /^\d+/; my $issuelength = $input->param('issuelength'); @@ -128,9 +129,9 @@ elsif ($op eq 'add') { $sth_search->execute($br,$bor,$cat); my $res = $sth_search->fetchrow_hashref(); if ($res->{total}) { - $sth_update->execute($fine, $finedays,$firstremind, $chargeperiod, $maxissueqty, $renewalsallowed,$reservesallowed, $issuelength,$lengthunit, $hardduedate,$hardduedatecompare,$rentaldiscount,$overduefinescap, $br,$bor,$cat); + $sth_update->execute($fine, $finedays,$firstremind, $chargeperiod, $maxissueqty, $renewalsallowed,$reservesallowed, $holdspickupdelay, $issuelength,$lengthunit, $hardduedate,$hardduedatecompare,$rentaldiscount,$overduefinescap, $br,$bor,$cat); } else { - $sth_insert->execute($br,$bor,$cat,$maxissueqty,$renewalsallowed,$reservesallowed,$issuelength,$lengthunit,$hardduedate,$hardduedatecompare,$fine,$finedays,$firstremind,$chargeperiod,$rentaldiscount,$overduefinescap); + $sth_insert->execute($br,$bor,$cat,$maxissueqty,$renewalsallowed,$reservesallowed, $holdspickupdelay, $issuelength,$lengthunit,$hardduedate,$hardduedatecompare,$fine,$finedays,$firstremind,$chargeperiod,$rentaldiscount,$overduefinescap); } } elsif ($op eq "set-branch-defaults") { diff --git a/circ/circulation.pl b/circ/circulation.pl index bdf0362..cb70189 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -367,6 +367,10 @@ if ($borrowernumber) { if ( $num_res->{'found'} eq 'W' ) { $getreserv{color} = 'reserved'; $getreserv{waiting} = 1; + my $maxpickupdate = GetMaxPickupDate( $num_res, $borrowernumber ); + $getWaitingReserveInfo{maxpickupdate} = $maxpickupdate; + $getreserv{maxpickupdate} = $maxpickupdate; + # genarate information displaying only waiting reserves $getWaitingReserveInfo{title} = $getiteminfo->{'title'}; $getWaitingReserveInfo{biblionumber} = $getiteminfo->{'biblionumber'}; diff --git a/circ/waitingreserves.pl b/circ/waitingreserves.pl index 158b847..ab8bac3 100755 --- a/circ/waitingreserves.pl +++ b/circ/waitingreserves.pl @@ -21,23 +21,20 @@ use strict; use warnings; use CGI; +use DateTime; use C4::Context; use C4::Output; use C4::Branch; # GetBranchName use C4::Auth; use C4::Dates qw/format_date/; use C4::Circulation; +use C4::Reserves; use C4::Members; use C4::Biblio; use C4::Items; - -use Date::Calc qw( - Today - Add_Delta_Days - Date_to_Days -); use C4::Reserves; use C4::Koha; +use Koha::DateUtils; my $input = new CGI; @@ -86,7 +83,7 @@ my ($reservcount, $overcount); my @getreserves = $all_branches ? GetReservesForBranch() : GetReservesForBranch($default); # get reserves for the branch we are logged into, or for all branches -my $today = Date_to_Days(&Today); +my $today = dt_from_string; foreach my $num (@getreserves) { next unless ($num->{'waitingdate'} && $num->{'waitingdate'} ne '0000-00-00'); @@ -105,12 +102,25 @@ foreach my $num (@getreserves) { $gettitle->{'itemtype'} = C4::Context->preference('item-level_itypes') ? $gettitle->{'itype'} : $gettitle->{'itemtype'}; my $getborrower = GetMember(borrowernumber => $num->{'borrowernumber'}); my $itemtypeinfo = getitemtypeinfo( $gettitle->{'itemtype'} ); # using the fixed up itype/itemtype - $getreserv{'waitingdate'} = format_date( $num->{'waitingdate'} ); - my ( $waiting_year, $waiting_month, $waiting_day ) = split (/-/, $num->{'waitingdate'}); - ( $waiting_year, $waiting_month, $waiting_day ) = - Add_Delta_Days( $waiting_year, $waiting_month, $waiting_day, - C4::Context->preference('ReservesMaxPickUpDelay')); - my $calcDate = Date_to_Days( $waiting_year, $waiting_month, $waiting_day ); + + if ( $num->{waitingdate} ) { + my $maxpickupdate = GetMaxPickupDate( $num, $borrowernumber ); + $getreserv{waitingdate} = $num->{waitingdate}; + $getreserv{maxpickupdate} = $maxpickupdate; + if ( DateTime->compare( $today, $maxpickupdate ) == 1 ) { + if ($cancelall) { + my $res = cancel( $itemnumber, $borrowernum, $holdingbranch, $homebranch, !$transfer_when_cancel_all ); + push @cancel_result, $res if $res; + next; + } else { + push @overloop, \%getreserv; + $overcount++; + } + }else{ + push @reservloop, \%getreserv; + $reservcount++; + } + } $getreserv{'itemtype'} = $itemtypeinfo->{'description'}; $getreserv{'title'} = $gettitle->{'title'}; @@ -131,21 +141,6 @@ foreach my $num (@getreserves) { if ( $getborrower->{'emailaddress'} ) { $getreserv{'borrowermail'} = $getborrower->{'emailaddress'}; } - - if ($today > $calcDate) { - if ($cancelall) { - my $res = cancel( $itemnumber, $borrowernum, $holdingbranch, $homebranch, !$transfer_when_cancel_all ); - push @cancel_result, $res if $res; - next; - } else { - push @overloop, \%getreserv; - $overcount++; - } - }else{ - push @reservloop, \%getreserv; - $reservcount++; - } - } $template->param(cancel_result => \@cancel_result) if @cancel_result; @@ -155,7 +150,7 @@ $template->param( overloop => \@overloop, overcount => $overcount, show_date => format_date(C4::Dates->today('iso')), - ReservesMaxPickUpDelay => C4::Context->preference('ReservesMaxPickUpDelay') + dateformat => C4::Context->preference("dateformat"), ); if ($cancelall) { diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index ed673da..a2ab7ac 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -1017,6 +1017,7 @@ CREATE TABLE `issuingrules` ( -- circulation and fine rules `hardduedatecompare` tinyint NOT NULL default "0", -- type of hard due date (1 = after, 0 = on, -1 = before) `renewalsallowed` smallint(6) NOT NULL default "0", -- how many renewals are allowed `reservesallowed` smallint(6) NOT NULL default "0", -- how many holds are allowed + `holdspickupdelay` int(11) default NULL, -- after how many days a hold is problematic (in days) `branchcode` varchar(10) NOT NULL default '', -- the branch this rule is for (branches.branchcode) overduefinescap decimal default NULL, -- the maximum amount of an overdue fine PRIMARY KEY (`branchcode`,`categorycode`,`itemtype`), diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index ed922b8..16c4161 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -6399,6 +6399,15 @@ if ( CheckVersion($DBversion) ) { SetVersion($DBversion); } +$DBversion = "3.11.00.XXX"; +if ( CheckVersion($DBversion) ) { + $dbh->do(qq{ + ALTER TABLE issuingrules ADD COLUMN holdspickupdelay INT(11) NULL default NULL AFTER reservesallowed; + }); + print "Upgrade to $DBversion done (8367: Add colum issuingrules.holdspickupdelay)\n"; + SetVersion($DBversion); +} + =head1 FUNCTIONS diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt index 586d72f..1f51193 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt @@ -76,8 +76,9 @@ for="tobranch">Clone these rules to: Clone these rules to: Delete @@ -167,7 +169,8 @@ for="tobranch">Clone these rules to: - + + diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt index cb5a548..6d42ba0 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -679,7 +679,7 @@ No patron matched [% message %]

Holds waiting:

[% FOREACH WaitingReserveLoo IN WaitingReserveLoop %]