Bugzilla – Attachment 3310 Details for
Bug 5872
Enhancements to circulation (see comment 23 for details)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Proposed Patch
0001-Bug-5872-Circulation-management-enhancements.patch (text/plain), 298.17 KB, created by
Chris Cormack
on 2011-03-16 00:47:48 UTC
(
hide
)
Description:
Proposed Patch
Filename:
MIME Type:
Creator:
Chris Cormack
Created:
2011-03-16 00:47:48 UTC
Size:
298.17 KB
patch
obsolete
>From 5d1f5f8cb4583080aeea491e700bb32961371281 Mon Sep 17 00:00:00 2001 >From: Chris Cormack <chrisc@catalyst.net.nz> >Date: Wed, 16 Mar 2011 13:34:34 +1300 >Subject: [PATCH] Bug 5872 : Circulation management enhancements > >See http://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=5872 for >details >--- > C4/Circulation.pm | 932 +++++++++----------- > C4/Overdues.pm | 81 +-- > C4/Reserves.pm | 632 ++++++++++---- > admin/branch_transfer_limits.pl | 22 +- > admin/smart-rules.pl | 565 +++---------- > circ/branchtransfers.pl | 4 +- > circ/circulation.pl | 282 +++++-- > circ/returns.pl | 137 +++- > .../en/modules/admin/branch_transfer_limits.tmpl | 15 +- > .../prog/en/modules/admin/clone-rules.tmpl | 3 +- > .../prog/en/modules/admin/smart-rules.tmpl | 639 ++++++++------ > .../prog/en/modules/circ/circulation.tmpl | 439 ++++++---- > .../prog/en/modules/circ/returns.tmpl | 151 ++-- > .../prog/en/modules/reserve/request.tmpl | 30 +- > .../opac-tmpl/prog/en/modules/opac-reserve.tmpl | 93 ++- > members/member.pl | 22 +- > opac/opac-modrequest.pl | 4 +- > opac/opac-reserve.pl | 63 +- > reserve/modrequest.pl | 19 +- > reserve/placerequest.pl | 92 +- > reserve/renewscript.pl | 57 ++- > reserve/request.pl | 48 +- > t/db_dependent/lib/KohaTest/Circulation.pm | 2 - > .../lib/KohaTest/Members/GetMemberDetails.pm | 6 +- > t/db_dependent/lib/KohaTest/Overdues.pm | 1 - > 25 files changed, 2380 insertions(+), 1959 deletions(-) > >diff --git a/C4/Circulation.pm b/C4/Circulation.pm >index 2b4e86c..0c8fb5b 100644 >--- a/C4/Circulation.pm >+++ b/C4/Circulation.pm >@@ -27,13 +27,16 @@ use C4::Koha; > use C4::Biblio; > use C4::Items; > use C4::Members; >-use C4::Dates; >+use C4::IssuingRules; >+use C4::Dates qw/format_date/; > use C4::Calendar; > use C4::Accounts; >+use C4::Overdues ; > use C4::ItemCirculationAlertPreference; > use C4::Dates qw(format_date); > use C4::Message; > use C4::Debug; >+use YAML; > use Date::Calc qw( > Today > Today_and_Now >@@ -42,6 +45,9 @@ use Date::Calc qw( > Date_to_Days > Day_of_Week > Add_Delta_Days >+ Delta_Days >+ check_date >+ Add_Delta_Days > ); > use POSIX qw(strftime); > use C4::Branch; # GetBranches >@@ -73,9 +79,6 @@ BEGIN { > &GetItemIssues > &GetBorrowerIssues > &GetIssuingCharges >- &GetIssuingRule >- &GetBranchBorrowerCircRule >- &GetBranchItemRule > &GetBiblioIssues > &GetOpenIssue > &AnonymiseIssueHistory >@@ -98,6 +101,15 @@ BEGIN { > &CreateBranchTransferLimit > &DeleteBranchTransferLimits > ); >+ >+ # subs to deal with offline circulation >+ push @EXPORT, qw( >+ &GetOfflineOperations >+ &GetOfflineOperation >+ &AddOfflineOperation >+ &DeleteOfflineOperation >+ &ProcessOfflineOperation >+ ); > } > > =head1 NAME >@@ -346,116 +358,97 @@ sub TooMany { > my $item = shift; > my $cat_borrower = $borrower->{'categorycode'}; > my $dbh = C4::Context->dbh; >- my $branch; >+ my $exactbranch; > # Get which branchcode we need >- $branch = _GetCircControlBranch($item,$borrower); >- my $type = (C4::Context->preference('item-level_itypes')) >+ $exactbranch = _GetCircControlBranch($item,$borrower); >+ my $itype = (C4::Context->preference('item-level_itypes')) > ? $item->{'itype'} # item-level > : $item->{'itemtype'}; # biblio-level > > # given branch, patron category, and item type, determine > # applicable issuing rule >- my $issuing_rule = GetIssuingRule($cat_borrower, $type, $branch); >- >- # if a rule is found and has a loan limit set, count >- # how many loans the patron already has that meet that >- # rule >- if (defined($issuing_rule) and defined($issuing_rule->{'maxissueqty'})) { >- my @bind_params; >- my $count_query = "SELECT COUNT(*) FROM issues >- JOIN items USING (itemnumber) "; >- >- my $rule_itemtype = $issuing_rule->{itemtype}; >- if ($rule_itemtype eq "*") { >- # matching rule has the default item type, so count only >- # those existing loans that don't fall under a more >- # specific rule >- if (C4::Context->preference('item-level_itypes')) { >- $count_query .= " WHERE items.itype NOT IN ( >- SELECT itemtype FROM issuingrules >- WHERE branchcode = ? >- AND (categorycode = ? OR categorycode = ?) >- AND itemtype <> '*' >- ) "; >- } else { >- $count_query .= " JOIN biblioitems USING (biblionumber) >- WHERE biblioitems.itemtype NOT IN ( >- SELECT itemtype FROM issuingrules >- WHERE branchcode = ? >- AND (categorycode = ? OR categorycode = ?) >- AND itemtype <> '*' >- ) "; >- } >- push @bind_params, $issuing_rule->{branchcode}; >- push @bind_params, $issuing_rule->{categorycode}; >- push @bind_params, $cat_borrower; >- } else { >- # rule has specific item type, so count loans of that >- # specific item type >- if (C4::Context->preference('item-level_itypes')) { >- $count_query .= " WHERE items.itype = ? "; >- } else { >- $count_query .= " JOIN biblioitems USING (biblionumber) >- WHERE biblioitems.itemtype= ? "; >- } >- push @bind_params, $type; >- } >- >- $count_query .= " AND borrowernumber = ? "; >- push @bind_params, $borrower->{'borrowernumber'}; >- my $rule_branch = $issuing_rule->{branchcode}; >- if ($rule_branch ne "*") { >- if (C4::Context->preference('CircControl') eq 'PickupLibrary') { >- $count_query .= " AND issues.branchcode = ? "; >- push @bind_params, $branch; >- } elsif (C4::Context->preference('CircControl') eq 'PatronLibrary') { >- ; # if branch is the patron's home branch, then count all loans by patron >- } else { >- $count_query .= " AND items.homebranch = ? "; >- push @bind_params, $branch; >- } >- } >- >- my $count_sth = $dbh->prepare($count_query); >- $count_sth->execute(@bind_params); >- my ($current_loan_count) = $count_sth->fetchrow_array; >+ my $branchfield = C4::Context->Preference('HomeOrHoldingBranch') || "homebranch"; >+ #By default, Patron is supposed not to be able to borrow >+ my $toomany = 1; >+ >+ foreach my $branch ( $exactbranch, '*' ) { >+ foreach my $type ( $itype, '*' ) { >+ my $issuing_rule = GetIssuingRule( $cat_borrower, $type, $branch ); >+ >+ # if a rule is found and has a loan limit set, count >+ # how many loans the patron already has that meet that >+ # rule >+ if ( defined($issuing_rule) and defined( $issuing_rule->{'maxissueqty'} ) ) { >+ my @bind_params; >+ my $count_query = "SELECT COUNT(*) FROM issues >+ JOIN items USING (itemnumber) "; >+ >+ my $rule_itemtype = $issuing_rule->{itemtype}; >+ if ($rule_itemtype eq "*") { >+ # matching rule has the default item type, so count all the items issued for that branch no >+ # those existing loans that don't fall under a more >+ # specific rule Not QUITE >+ if (C4::Context->preference('item-level_itypes')) { >+ $count_query .= " WHERE items.itype NOT IN ( >+ SELECT itemtype FROM issuingrules >+ WHERE branchcode = ? >+ AND (categorycode = ? OR categorycode = ?) >+ AND itemtype <> '*' >+ )"; >+ } else { >+ $count_query .= " JOIN biblioitems USING (biblionumber) >+ WHERE biblioitems.itemtype NOT IN ( >+ SELECT itemtype FROM issuingrules >+ WHERE branchcode = ? >+ AND (categorycode = ? OR categorycode = ?) >+ AND itemtype <> '*' >+ )"; >+ } >+ push @bind_params, $issuing_rule->{branchcode}; >+ push @bind_params, $issuing_rule->{categorycode}; >+ push @bind_params, $cat_borrower; >+ } else { >+ # rule has specific item type, so count loans of that >+ # specific item type >+ if (C4::Context->preference('item-level_itypes')) { >+ $count_query .= " WHERE items.itype = ? "; >+ } else { >+ $count_query .= " JOIN biblioitems USING (biblionumber) >+ WHERE biblioitems.itemtype= ? "; >+ } >+ push @bind_params, $type; >+ } > >- my $max_loans_allowed = $issuing_rule->{'maxissueqty'}; >- if ($current_loan_count >= $max_loans_allowed) { >- return ($current_loan_count, $max_loans_allowed); >- } >- } >+ $count_query .= " AND borrowernumber = ? "; >+ push @bind_params, $borrower->{'borrowernumber'}; >+ my $rule_branch = $issuing_rule->{branchcode}; >+ if ( $rule_branch ne "*" ) { >+ if ( C4::Context->preference('CircControl') eq 'PickupLibrary' ) { >+ $count_query .= " AND issues.branchcode = ? "; >+ push @bind_params, $branch; >+ } elsif ( C4::Context->preference('CircControl') eq 'PatronLibrary' ) { >+ ; # if branch is the patron's home branch, then count all loans by patron >+ } else { >+ $count_query .= " AND items.$branchfield = ? "; >+ push @bind_params, $branch; >+ } >+ } > >- # Now count total loans against the limit for the branch >- my $branch_borrower_circ_rule = GetBranchBorrowerCircRule($branch, $cat_borrower); >- if (defined($branch_borrower_circ_rule->{maxissueqty})) { >- my @bind_params = (); >- my $branch_count_query = "SELECT COUNT(*) FROM issues >- JOIN items USING (itemnumber) >- WHERE borrowernumber = ? "; >- push @bind_params, $borrower->{borrowernumber}; >- >- if (C4::Context->preference('CircControl') eq 'PickupLibrary') { >- $branch_count_query .= " AND issues.branchcode = ? "; >- push @bind_params, $branch; >- } elsif (C4::Context->preference('CircControl') eq 'PatronLibrary') { >- ; # if branch is the patron's home branch, then count all loans by patron >- } else { >- $branch_count_query .= " AND items.homebranch = ? "; >- push @bind_params, $branch; >- } >- my $branch_count_sth = $dbh->prepare($branch_count_query); >- $branch_count_sth->execute(@bind_params); >- my ($current_loan_count) = $branch_count_sth->fetchrow_array; >+ my $count_sth = $dbh->prepare($count_query); >+ $count_sth->execute(@bind_params); >+ my ($current_loan_count) = $count_sth->fetchrow_array; > >- my $max_loans_allowed = $branch_borrower_circ_rule->{maxissueqty}; >- if ($current_loan_count >= $max_loans_allowed) { >- return ($current_loan_count, $max_loans_allowed); >+ my $max_loans_allowed = $issuing_rule->{'maxissueqty'}; >+ if ( $current_loan_count >= $max_loans_allowed ) { >+ return 1,$current_loan_count,$max_loans_allowed; >+ } >+ else { >+ $toomany=0; >+ } >+ } > } > } >- >- # OK, the patron can issue !!! >- return; >+ return $toomany; > } > > =head2 itemissues >@@ -684,7 +677,10 @@ sub CanBookBeIssued { > my $branch = _GetCircControlBranch($item,$borrower); > my $itype = ( C4::Context->preference('item-level_itypes') ) ? $item->{'itype'} : $biblioitem->{'itemtype'}; > my $loanlength = GetLoanLength( $borrower->{'categorycode'}, $itype, $branch ); >- $duedate = CalcDateDue( C4::Dates->new( $issuedate, 'iso' ), $loanlength, $branch, $borrower ); >+ unless ($loanlength or C4::Context->preference("AllowNotForLoanOverride")) { >+ $issuingimpossible{LOAN_LENGTH_UNDEFINED} = "$borrower->{'categorycode'}, $itype, $branch"; >+ } >+ $duedate = CalcDateDue( C4::Dates->new( $issuedate, 'iso' ), $loanlength, $branch, $borrower ) ; > > # Offline circ calls AddIssue directly, doesn't run through here > # So issuingimpossible should be ok. >@@ -712,15 +708,22 @@ sub CanBookBeIssued { > $issuingimpossible{CARD_LOST} = 1; > } > if ( $borrower->{flags}->{'DBARRED'} ) { >- $issuingimpossible{DEBARRED} = 1; >+ if (my $dateenddebarred=$borrower->{flags}->{'DBARRED'}->{'dateend'}){ >+ $issuingimpossible{DEBARRED} = format_date($dateenddebarred); >+ } >+ else { >+ $issuingimpossible{DEBARRED} = 1; >+ } > } > if ( $borrower->{'dateexpiry'} eq '0000-00-00') { > $issuingimpossible{EXPIRED} = 1; > } else { >- my @expirydate= split /-/,$borrower->{'dateexpiry'}; >- if($expirydate[0]==0 || $expirydate[1]==0|| $expirydate[2]==0 || >- Date_to_Days(Today) > Date_to_Days( @expirydate )) { >- $issuingimpossible{EXPIRED} = 1; >+ my @expirydate = split (/-/, $borrower->{'dateexpiry'}); >+ if ( $expirydate[0] == 0 >+ || $expirydate[1] == 0 >+ || $expirydate[2] == 0 >+ || Date_to_Days(Today) > Date_to_Days(@expirydate) ) { >+ $issuingimpossible{EXPIRED} = 1; > } > } > # >@@ -769,18 +772,15 @@ sub CanBookBeIssued { > # > # JB34 CHECKS IF BORROWERS DONT HAVE ISSUE TOO MANY BOOKS > # >- my ($current_loan_count, $max_loans_allowed) = TooMany( $borrower, $item->{biblionumber}, $item ); >- # if TooMany max_loans_allowed returns 0 the user doesn't have permission to check out this book >- if ($max_loans_allowed eq 0) { >+ my @toomany = TooMany( $borrower, $item->{biblionumber}, $item ); >+ >+ if ( $toomany[0] == 1 && scalar(@toomany)<3) { > $needsconfirmation{PATRON_CANT} = 1; >- } else { >- if($max_loans_allowed){ >- $needsconfirmation{TOO_MANY} = 1; >- $needsconfirmation{current_loan_count} = $current_loan_count; >- $needsconfirmation{max_loans_allowed} = $max_loans_allowed; >- } >+ } elsif (scalar(@toomany)==3) { >+ $needsconfirmation{TOO_MANY} = "$toomany[1] / $toomany[2]"; > } > >+ > # > # ITEM CHECKING > # >@@ -817,8 +817,18 @@ sub CanBookBeIssued { > } > } > } >- if ( $item->{'wthdrawn'} && $item->{'wthdrawn'} == 1 ) >- { >+ if ( $item->{'damaged'} && $item->{'damaged'} > 0 ){ >+ $needsconfirmation{DAMAGED} = $item->{'damaged'}; >+ my $fw = GetFrameworkCode($item->{biblionumber}); >+ my $category = GetAuthValCode('items.damaged',$fw); >+ my $authorizedvalues = GetAuthorisedValues($category, $item->{damaged}); >+ >+ foreach my $authvalue (@$authorizedvalues){ >+ $needsconfirmation{DAMAGED} = $authvalue->{lib} if $authvalue->{'authorised_value'} eq $item->{'damaged'}; >+ } >+ >+ } >+ if ( $item->{'wthdrawn'} && $item->{'wthdrawn'} == 1 ) { > $issuingimpossible{WTHDRAWN} = 1; > } > if ( $item->{'restricted'} >@@ -826,15 +836,23 @@ sub CanBookBeIssued { > { > $issuingimpossible{RESTRICTED} = 1; > } >+ my $userenv = C4::Context->userenv; >+ my $branch=$userenv->{branch}; >+ my $hbr= $item->{ C4::Context->preference("HomeOrHoldingBranch") }; > if ( C4::Context->preference("IndependantBranches") ) { >- my $userenv = C4::Context->userenv; > if ( ($userenv) && ( $userenv->{flags} % 2 != 1 ) ) { > $issuingimpossible{ITEMNOTSAMEBRANCH} = 1 >- if ( $item->{C4::Context->preference("HomeOrHoldingBranch")} ne $userenv->{branch} ); >+ if ( $hbr ne $branch ); > $needsconfirmation{BORRNOTSAMEBRANCH} = GetBranchName( $borrower->{'branchcode'} ) > if ( $borrower->{'branchcode'} ne $userenv->{branch} ); > } > } >+ my $branchtransferfield=C4::Context->preference("BranchTransferLimitsType") eq "ccode" ? "ccode" : "itype"; >+ if ( C4::Context->preference("UseBranchTransferLimits") >+ and !IsBranchTransferAllowed( $branch, $hbr, $item->{ $branchtransferfield } ) ) { >+ $needsconfirmation{BRANCH_TRANSFER_NOT_ALLOWED} = $hbr; >+ } >+ > > # > # CHECK IF BOOK ALREADY ISSUED TO THIS BORROWER >@@ -875,30 +893,21 @@ sub CanBookBeIssued { > my ( $resborrower ) = C4::Members::GetMemberDetails( $resbor, 0 ); > my $branches = GetBranches(); > my $branchname = $branches->{ $res->{'branchcode'} }->{'branchname'}; >- if ( $resbor ne $borrower->{'borrowernumber'} && $restype eq "Waiting" ) >- { >- # The item is on reserve and waiting, but has been >- # reserved by some other patron. >- $needsconfirmation{RESERVE_WAITING} = 1; >- $needsconfirmation{'resfirstname'} = $resborrower->{'firstname'}; >- $needsconfirmation{'ressurname'} = $resborrower->{'surname'}; >- $needsconfirmation{'rescardnumber'} = $resborrower->{'cardnumber'}; >- $needsconfirmation{'resborrowernumber'} = $resborrower->{'borrowernumber'}; >- $needsconfirmation{'resbranchname'} = $branchname; >- $needsconfirmation{'reswaitingdate'} = format_date($res->{'waitingdate'}); >- } >- elsif ( $restype eq "Reserved" ) { >- # The item is on reserve for someone else. >- $needsconfirmation{RESERVED} = 1; >- $needsconfirmation{'resfirstname'} = $resborrower->{'firstname'}; >- $needsconfirmation{'ressurname'} = $resborrower->{'surname'}; >- $needsconfirmation{'rescardnumber'} = $resborrower->{'cardnumber'}; >- $needsconfirmation{'resborrowernumber'} = $resborrower->{'borrowernumber'}; >- $needsconfirmation{'resbranchname'} = $branchname; >- $needsconfirmation{'resreservedate'} = format_date($res->{'reservedate'}); >+ if( $resbor ne $borrower->{'borrowernumber'}){ >+ if ( $restype eq "Waiting" ) { >+ # The item is on reserve and waiting, but has been >+ # reserved by some other patron. >+ $needsconfirmation{RESERVE_WAITING} = >+ "$resborrower->{'firstname'} $resborrower->{'surname'} ($resborrower->{'cardnumber'}, $branchname)"; >+ } >+ elsif ( $restype eq "Reserved" ) { >+ # The item is on reserve for someone else. >+ $needsconfirmation{RESERVED} = >+ "$res->{'reservedate'} : $resborrower->{'firstname'} $resborrower->{'surname'} ($resborrower->{'cardnumber'})"; >+ } > } > } >- return ( \%issuingimpossible, \%needsconfirmation ); >+ return ( \%issuingimpossible, \%needsconfirmation ); > } > > =head2 AddIssue >@@ -979,7 +988,10 @@ sub AddIssue { > # who wants to borrow it now. mark it returned before issuing to the new borrower > AddReturn( > $item->{'barcode'}, >- C4::Context->userenv->{'branch'} >+ C4::Context->userenv->{'branch'}, >+ undef, >+ undef, >+ 1 > ); > } > >@@ -1012,7 +1024,9 @@ sub AddIssue { > ModReserve(1, > $res->{'biblionumber'}, > $res->{'borrowernumber'}, >- $res->{'branchcode'} >+ $res->{'branchcode'}, >+ undef, >+ $res->{'reservenumber'} > ); > } > } >@@ -1102,10 +1116,11 @@ sub AddIssue { > branch => $branch, > }); > } >+ >+ logaction( "CIRCULATION", "ISSUE", $borrower->{'borrowernumber'}, $item->{'itemnumber'} ) >+ if C4::Context->preference("IssueLog"); > } > >- logaction("CIRCULATION", "ISSUE", $borrower->{'borrowernumber'}, $biblio->{'biblionumber'}) >- if C4::Context->preference("IssueLog"); > } > return ($datedue); # not necessarily the same as when it came in! > } >@@ -1120,254 +1135,8 @@ Get loan length for an itemtype, a borrower type and a branch > > sub GetLoanLength { > my ( $borrowertype, $itemtype, $branchcode ) = @_; >- my $dbh = C4::Context->dbh; >- my $sth = >- $dbh->prepare( >-"select issuelength from issuingrules where categorycode=? and itemtype=? and branchcode=? and issuelength is not null" >- ); >-# warn "in get loan lenght $borrowertype $itemtype $branchcode "; >-# try to find issuelength & return the 1st available. >-# check with borrowertype, itemtype and branchcode, then without one of those parameters >- $sth->execute( $borrowertype, $itemtype, $branchcode ); >- my $loanlength = $sth->fetchrow_hashref; >- return $loanlength->{issuelength} >- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL'; >- >- $sth->execute( $borrowertype, "*", $branchcode ); >- $loanlength = $sth->fetchrow_hashref; >- return $loanlength->{issuelength} >- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL'; >- >- $sth->execute( "*", $itemtype, $branchcode ); >- $loanlength = $sth->fetchrow_hashref; >- return $loanlength->{issuelength} >- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL'; >- >- $sth->execute( "*", "*", $branchcode ); >- $loanlength = $sth->fetchrow_hashref; >- return $loanlength->{issuelength} >- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL'; >- >- $sth->execute( $borrowertype, $itemtype, "*" ); >- $loanlength = $sth->fetchrow_hashref; >- return $loanlength->{issuelength} >- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL'; >- >- $sth->execute( $borrowertype, "*", "*" ); >- $loanlength = $sth->fetchrow_hashref; >- return $loanlength->{issuelength} >- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL'; >- >- $sth->execute( "*", $itemtype, "*" ); >- $loanlength = $sth->fetchrow_hashref; >- return $loanlength->{issuelength} >- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL'; >- >- $sth->execute( "*", "*", "*" ); >- $loanlength = $sth->fetchrow_hashref; >- return $loanlength->{issuelength} >- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL'; >- >- # if no rule is set => 21 days (hardcoded) >- return 21; >-} >- >-=head2 GetIssuingRule >- >- my $irule = &GetIssuingRule($borrowertype,$itemtype,branchcode) >- >-FIXME - This is a copy-paste of GetLoanLength >-as a stop-gap. Do not wish to change API for GetLoanLength >-this close to release, however, Overdues::GetIssuingRules is broken. >- >-Get the issuing rule for an itemtype, a borrower type and a branch >-Returns a hashref from the issuingrules table. >- >-=cut >- >-sub GetIssuingRule { >- my ( $borrowertype, $itemtype, $branchcode ) = @_; >- my $dbh = C4::Context->dbh; >- my $sth = $dbh->prepare( "select * from issuingrules where categorycode=? and itemtype=? and branchcode=? and issuelength is not null" ); >- my $irule; >- >- $sth->execute( $borrowertype, $itemtype, $branchcode ); >- $irule = $sth->fetchrow_hashref; >- return $irule if defined($irule) ; >- >- $sth->execute( $borrowertype, "*", $branchcode ); >- $irule = $sth->fetchrow_hashref; >- return $irule if defined($irule) ; >- >- $sth->execute( "*", $itemtype, $branchcode ); >- $irule = $sth->fetchrow_hashref; >- return $irule if defined($irule) ; >- >- $sth->execute( "*", "*", $branchcode ); >- $irule = $sth->fetchrow_hashref; >- return $irule if defined($irule) ; >- >- $sth->execute( $borrowertype, $itemtype, "*" ); >- $irule = $sth->fetchrow_hashref; >- return $irule if defined($irule) ; >- >- $sth->execute( $borrowertype, "*", "*" ); >- $irule = $sth->fetchrow_hashref; >- return $irule if defined($irule) ; >- >- $sth->execute( "*", $itemtype, "*" ); >- $irule = $sth->fetchrow_hashref; >- return $irule if defined($irule) ; >- >- $sth->execute( "*", "*", "*" ); >- $irule = $sth->fetchrow_hashref; >- return $irule if defined($irule) ; >- >- # if no rule matches, >- return undef; >-} >- >-=head2 GetBranchBorrowerCircRule >- >- my $branch_cat_rule = GetBranchBorrowerCircRule($branchcode, $categorycode); >- >-Retrieves circulation rule attributes that apply to the given >-branch and patron category, regardless of item type. >-The return value is a hashref containing the following key: >- >-maxissueqty - maximum number of loans that a >-patron of the given category can have at the given >-branch. If the value is undef, no limit. >- >-This will first check for a specific branch and >-category match from branch_borrower_circ_rules. >- >-If no rule is found, it will then check default_branch_circ_rules >-(same branch, default category). If no rule is found, >-it will then check default_borrower_circ_rules (default >-branch, same category), then failing that, default_circ_rules >-(default branch, default category). >- >-If no rule has been found in the database, it will default to >-the buillt in rule: >- >-maxissueqty - undef >- >-C<$branchcode> and C<$categorycode> should contain the >-literal branch code and patron category code, respectively - no >-wildcards. >- >-=cut >- >-sub GetBranchBorrowerCircRule { >- my $branchcode = shift; >- my $categorycode = shift; >- >- my $branch_cat_query = "SELECT maxissueqty >- FROM branch_borrower_circ_rules >- WHERE branchcode = ? >- AND categorycode = ?"; >- my $dbh = C4::Context->dbh(); >- my $sth = $dbh->prepare($branch_cat_query); >- $sth->execute($branchcode, $categorycode); >- my $result; >- if ($result = $sth->fetchrow_hashref()) { >- return $result; >- } >- >- # try same branch, default borrower category >- my $branch_query = "SELECT maxissueqty >- FROM default_branch_circ_rules >- WHERE branchcode = ?"; >- $sth = $dbh->prepare($branch_query); >- $sth->execute($branchcode); >- if ($result = $sth->fetchrow_hashref()) { >- return $result; >- } >- >- # try default branch, same borrower category >- my $category_query = "SELECT maxissueqty >- FROM default_borrower_circ_rules >- WHERE categorycode = ?"; >- $sth = $dbh->prepare($category_query); >- $sth->execute($categorycode); >- if ($result = $sth->fetchrow_hashref()) { >- return $result; >- } >- >- # try default branch, default borrower category >- my $default_query = "SELECT maxissueqty >- FROM default_circ_rules"; >- $sth = $dbh->prepare($default_query); >- $sth->execute(); >- if ($result = $sth->fetchrow_hashref()) { >- return $result; >- } >- >- # built-in default circulation rule >- return { >- maxissueqty => undef, >- }; >-} >- >-=head2 GetBranchItemRule >- >- my $branch_item_rule = GetBranchItemRule($branchcode, $itemtype); >- >-Retrieves circulation rule attributes that apply to the given >-branch and item type, regardless of patron category. >- >-The return value is a hashref containing the following key: >- >-holdallowed => Hold policy for this branch and itemtype. Possible values: >- 0: No holds allowed. >- 1: Holds allowed only by patrons that have the same homebranch as the item. >- 2: Holds allowed from any patron. >- >-This searches branchitemrules in the following order: >- >- * Same branchcode and itemtype >- * Same branchcode, itemtype '*' >- * branchcode '*', same itemtype >- * branchcode and itemtype '*' >- >-Neither C<$branchcode> nor C<$categorycode> should be '*'. >- >-=cut >- >-sub GetBranchItemRule { >- my ( $branchcode, $itemtype ) = @_; >- my $dbh = C4::Context->dbh(); >- my $result = {}; >- >- my @attempts = ( >- ['SELECT holdallowed >- FROM branch_item_rules >- WHERE branchcode = ? >- AND itemtype = ?', $branchcode, $itemtype], >- ['SELECT holdallowed >- FROM default_branch_circ_rules >- WHERE branchcode = ?', $branchcode], >- ['SELECT holdallowed >- FROM default_branch_item_rules >- WHERE itemtype = ?', $itemtype], >- ['SELECT holdallowed >- FROM default_circ_rules'], >- ); >- >- foreach my $attempt (@attempts) { >- my ($query, @bind_params) = @{$attempt}; >- >- # Since branch/category and branch/itemtype use the same per-branch >- # defaults tables, we have to check that the key we want is set, not >- # just that a row was returned >- return $result if ( defined( $result->{'holdallowed'} = $dbh->selectrow_array( $query, {}, @bind_params ) ) ); >- } >- >- # built-in default circulation rule >- return { >- holdallowed => 2, >- }; >+ my $loanlength=GetIssuingRule($borrowertype,$itemtype,$branchcode); >+ return $loanlength->{issuelength}; > } > > =head2 AddReturn >@@ -1445,8 +1214,8 @@ patron who last borrowed the book. > =cut > > sub AddReturn { >- my ( $barcode, $branch, $exemptfine, $dropbox ) = @_; >- if ($branch and not GetBranchDetail($branch)) { >+ my ( $barcode, $branch, $exemptfine, $dropbox, $force) = @_; >+ if ( $branch and not GetBranchDetail($branch) ) { > warn "AddReturn error: branch '$branch' not found. Reverting to " . C4::Context->userenv->{'branch'}; > undef $branch; > } >@@ -1490,9 +1259,17 @@ sub AddReturn { > my $branches = GetBranches(); # a potentially expensive call for a non-feature. > $branches->{$hbr}->{PE} and $messages->{'IsPermanent'} = $hbr; > } >- >+ my $branchtransferfield=C4::Context->preference("BranchTransferLimitsType") eq "ccode" ? "ccode" : "itype"; >+ $debug && warn "$branch, $hbr, ",C4::Context->preference("BranchTransferLimitsType")," ,",$item->{ $branchtransferfield } ; >+ $debug && warn Dump($item); >+ $debug && warn IsBranchTransferAllowed( $branch, $hbr, $item->{ C4::Context->preference("BranchTransferLimitsType") } ); > # if indy branches and returning to different branch, refuse the return >- if ($hbr ne $branch && C4::Context->preference("IndependantBranches")){ >+ if ( !$force && ($hbr ne $branch) >+ && (C4::Context->preference("IndependantBranches") >+ or ( C4::Context->preference("UseBranchTransferLimits") >+ and !IsBranchTransferAllowed( $branch, $hbr, $item->{$branchtransferfield } ) ) >+ ) >+ ){ > $messages->{'Wrongbranch'} = { > Wrongbranch => $branch, > Rightbranch => $hbr, >@@ -1503,7 +1280,6 @@ sub AddReturn { > # FIXME - even in an indy branches situation, there should > # still be an option for the library to accept the item > # and transfer it to its owning library. >- return ( $doreturn, $messages, $issue, $borrower ); > } > > if ( $item->{'wthdrawn'} ) { # book has been cancelled >@@ -1514,12 +1290,11 @@ sub AddReturn { > # case of a return of document (deal with issues and holdingbranch) > if ($doreturn) { > $borrower or warn "AddReturn without current borrower"; >- my $circControlBranch; >+ my $circControlBranch; > if ($dropbox) { >- # define circControlBranch only if dropbox mode is set >- # don't allow dropbox mode to create an invalid entry in issues (issuedate > today) >- # FIXME: check issuedate > returndate, factoring in holidays >- $circControlBranch = _GetCircControlBranch($item,$borrower) unless ( $item->{'issuedate'} eq C4::Dates->today('iso') );; >+ $circControlBranch = _GetCircControlBranch( $item, $borrower ); >+ # don't allow dropbox mode to create an invalid entry in issues (issuedate > returndate) FIXME: actually checks eq, not gt >+ undef($dropbox) if ( $item->{'issuedate'} eq C4::Dates->today('iso') ); > } > > if ($borrowernumber) { >@@ -1527,15 +1302,15 @@ sub AddReturn { > $messages->{'WasReturned'} = 1; # FIXME is the "= 1" right? This could be the borrower hash. > } > >- ModItem({ onloan => undef }, $issue->{'biblionumber'}, $item->{'itemnumber'}); >+ ModItem( { renewals=>0, onloan => undef }, $issue->{'biblionumber'}, $item->{'itemnumber'} ); >+ # the holdingbranch is updated if the document is returned to another location. >+ # this is always done regardless of whether the item was on loan or not >+ if ( $item->{'holdingbranch'} ne $branch ) { >+ UpdateHoldingbranch( $branch, $item->{'itemnumber'} ); >+ $item->{'holdingbranch'} = $branch; # update item data holdingbranch too >+ } > } > >- # the holdingbranch is updated if the document is returned to another location. >- # this is always done regardless of whether the item was on loan or not >- if ($item->{'holdingbranch'} ne $branch) { >- UpdateHoldingbranch($branch, $item->{'itemnumber'}); >- $item->{'holdingbranch'} = $branch; # update item data holdingbranch too >- } > ModDateLastSeen( $item->{'itemnumber'} ); > > # check if we have a transfer for this document >@@ -1562,11 +1337,26 @@ sub AddReturn { > _FixAccountForLostAndReturned($item->{'itemnumber'}, $borrowernumber, $barcode); # can tolerate undef $borrowernumber > $messages->{'WasLost'} = 1; > } >+ if ($item->{'notforloan'}){ >+ $messages->{'NotForLoan'} = $item->{'notforloan'}; >+ } >+ if ($item->{'damaged'}){ >+ $messages->{'Damaged'} = $item->{'damaged'}; >+ } > >- # fix up the overdues in accounts... >- if ($borrowernumber) { >+ if ($borrowernumber && $doreturn) { >+ # fix up the overdues in accounts... > my $fix = _FixOverduesOnReturn($borrowernumber, $item->{itemnumber}, $exemptfine, $dropbox); > defined($fix) or warn "_FixOverduesOnReturn($borrowernumber, $item->{itemnumber}...) failed!"; # zero is OK, check defined >+ >+ # fix fine days >+ my $debardate = _FixFineDaysOnReturn($borrower, $item, $issue->{date_due}); >+ $messages->{'Debarred'} = $debardate if($debardate); >+ >+ # get fines for the borrower >+ my $fineamount = C4::Overdues::GetFine($borrowernumber); >+ $messages->{'HaveFines'} = $fineamount if($fineamount); >+ > } > > # find reserves..... >@@ -1602,20 +1392,20 @@ sub AddReturn { > branch => $branch, > }); > } >- >- logaction("CIRCULATION", "RETURN", $borrowernumber, $item->{'biblionumber'}) >- if C4::Context->preference("ReturnLog"); >- >+ >+ logaction( "CIRCULATION", "RETURN", $borrowernumber, $item->{'itemnumber'} ) >+ if C4::Context->preference("ReturnLog"); >+ > # FIXME: make this comment intelligible. > #adding message if holdingbranch is non equal a userenv branch to return the document to homebranch > #we check, if we don't have reserv or transfert for this document, if not, return it to homebranch . > >- if ($doreturn and ($branch ne $hbr) and not $messages->{'WrongTransfer'} and ($validTransfert ne 1) ){ >- if ( C4::Context->preference("AutomaticItemReturn" ) or >- (C4::Context->preference("UseBranchTransferLimits") and >- ! IsBranchTransferAllowed($branch, $hbr, $item->{C4::Context->preference("BranchTransferLimitsType")} ) >- )) { >- $debug and warn sprintf "about to call ModItemTransfer(%s, %s, %s)", $item->{'itemnumber'},$branch, $hbr; >+ if ( $doreturn and ( $branch ne $hbr ) and not $messages->{'WrongTransfer'} and ( $validTransfert ne 1 ) ) { >+ if (C4::Context->preference("AutomaticItemReturn") >+ or ( C4::Context->preference("UseBranchTransferLimits") >+ and !IsBranchTransferAllowed( $branch, $hbr, $item->{ $branchtransferfield } ) ) >+ ) { >+ $debug and warn sprintf "about to call ModItemTransfer(%s, %s, %s)", $item->{'itemnumber'}, $branch, $hbr; > $debug and warn "item: " . Dumper($item); > ModItemTransfer($item->{'itemnumber'}, $branch, $hbr); > $messages->{'WasTransfered'} = 1; >@@ -1690,6 +1480,61 @@ sub MarkIssueReturned { > $sth_del->execute($borrowernumber, $itemnumber); > } > >+=head2 _FixFineDaysOnReturn >+ >+ &_FixFineDaysOnReturn($borrower, $item, $datedue); >+ >+C<$borrower> borrower hashref >+ >+C<$item> item hashref >+ >+C<$datedue> date due >+ >+Internal function, called only by AddReturn that calculate and update the user fine days, and debars him >+ >+=cut >+ >+sub _FixFineDaysOnReturn { >+ my ($borrower, $item, $datedue) = @_; >+ >+ if($datedue){ >+ $datedue = C4::Dates->new($datedue,"iso"); >+ }else{ >+ return; >+ } >+ >+ my $branchcode =_GetCircControlBranch($item, $borrower); >+ my $calendar = C4::Calendar->new( branchcode => $branchcode ); >+ my $today = C4::Dates->new(); >+ >+ my $deltadays = $calendar->daysBetween($datedue, C4::Dates->new()); >+ >+ my $circcontrol = C4::Context::preference('CircControl'); >+ my $issuingrule = GetIssuingRule($borrower->{categorycode}, $item->{itype}, $branchcode); >+ my $finedays = $issuingrule->{finedays}; >+ # exit if no finedays defined >+ return unless $finedays; >+ my $grace = $issuingrule->{firstremind}; >+ >+ if( $deltadays - $grace > 0){ >+ my @newdate = Add_Delta_Days(Today(), $deltadays * $finedays ); >+ my $isonewdate = join('-',@newdate); >+ my ($deby, $debm, $debd) = split(/-/,$borrower->{debarred}); >+ if(check_date($deby, $debm, $debd)){ >+ my @olddate = split(/-/, $borrower->{debarred}); >+ >+ if(Delta_Days(@olddate,@newdate) > 0){ >+ C4::Members::DebarMember($borrower->{borrowernumber}, $isonewdate); >+ return $isonewdate; >+ } >+ }else{ >+ C4::Members::DebarMember($borrower->{borrowernumber}, $isonewdate); >+ return $isonewdate; >+ } >+ } >+} >+ >+ > =head2 _FixOverduesOnReturn > > &_FixOverduesOnReturn($brn,$itm, $exemptfine, $dropboxmode); >@@ -1864,7 +1709,7 @@ sub _GetCircControlBranch { > my $circcontrol = C4::Context->preference('CircControl'); > my $branch; > >- if ($circcontrol eq 'PickupLibrary') { >+ if ($circcontrol eq 'PickupLibrary' && C4::Context->userenv->{'branch'}) { > $branch= C4::Context->userenv->{'branch'}; > } elsif ($circcontrol eq 'PatronLibrary') { > $branch=$borrower->{branchcode}; >@@ -1901,7 +1746,7 @@ sub GetItemIssue { > my ($itemnumber) = @_; > return unless $itemnumber; > my $sth = C4::Context->dbh->prepare( >- "SELECT * >+ "SELECT *, issues.renewals as 'issues.renewals' > FROM issues > LEFT JOIN items ON issues.itemnumber=items.itemnumber > WHERE issues.itemnumber=?"); >@@ -1972,7 +1817,7 @@ sub GetItemIssues { > } > my $results = $sth->fetchall_arrayref({}); > foreach (@$results) { >- $_->{'overdue'} = ($_->{'date_due'} lt $today) ? 1 : 0; >+ $_->{'overdue'} = ( $_->{'date_due'} lt $today && !defined($_->{return_date}) ) ? 1 : 0; > } > return $results; > } >@@ -2078,69 +1923,42 @@ already renewed the loan. $error will contain the reason the renewal can not pro > sub CanBookBeRenewed { > > # check renewal status >- my ( $borrowernumber, $itemnumber, $override_limit ) = @_; >+ my ( $borrowernumber, $itemnumber ) = @_; > my $dbh = C4::Context->dbh; > my $renews = 1; >- my $renewokay = 0; >- my $error; >+ my $renewokay = 1; >+ my $error; > > # Look in the issues table for this item, lent to this borrower, > # and not yet returned. > > # Look in the issues table for this item, lent to this borrower, > # and not yet returned. >- my %branch = ( >- 'ItemHomeLibrary' => 'items.homebranch', >- 'PickupLibrary' => 'items.holdingbranch', >- 'PatronLibrary' => 'borrowers.branchcode' >- ); >- my $controlbranch = $branch{C4::Context->preference('CircControl')}; >- my $itype = C4::Context->preference('item-level_itypes') ? 'items.itype' : 'biblioitems.itemtype'; >+ my $borrower = C4::Members::GetMemberDetails( $borrowernumber, 0 ) or return undef; >+ my $item = GetItem($itemnumber) or return undef; >+ my $itemissue = GetItemIssue($itemnumber) or return undef; >+ my $branchcode = _GetCircControlBranch($item, $borrower); >+ if ($itemissue->{'overdue'}){ >+ $renewokay=0; >+ $error->{message}='overdue'; >+ } > >- my $sthcount = $dbh->prepare(" >- SELECT >- borrowers.categorycode, biblioitems.itemtype, issues.renewals, renewalsallowed, $controlbranch >- FROM issuingrules, >- issues >- LEFT JOIN items USING (itemnumber) >- LEFT JOIN borrowers USING (borrowernumber) >- LEFT JOIN biblioitems USING (biblioitemnumber) >- >- WHERE >- (issuingrules.categorycode = borrowers.categorycode OR issuingrules.categorycode = '*') >- AND >- (issuingrules.itemtype = $itype OR issuingrules.itemtype = '*') >- AND >- (issuingrules.branchcode = $controlbranch OR issuingrules.branchcode = '*') >- AND >- borrowernumber = ? >- AND >- itemnumber = ? >- ORDER BY >- issuingrules.categorycode desc, >- issuingrules.itemtype desc, >- issuingrules.branchcode desc >- LIMIT 1; >- "); >- >- $sthcount->execute( $borrowernumber, $itemnumber ); >- if ( my $data1 = $sthcount->fetchrow_hashref ) { >- >- if ( ( $data1->{renewalsallowed} && $data1->{renewalsallowed} > $data1->{renewals} ) || $override_limit ) { >- $renewokay = 1; >- } >- else { >- $error="too_many"; >- } >- >- my ( $resfound, $resrec ) = C4::Reserves::CheckReserves($itemnumber); >- if ($resfound) { >- $renewokay = 0; >- $error="on_reserve" >- } >+ my $issuingrule = GetIssuingRule($borrower->{categorycode}, $item->{itype}, $branchcode); >+ >+ if ( $issuingrule->{renewalsallowed} <= $itemissue->{'issues.renewals'} ) { >+ $renewokay=0; >+ $error->{message} = "too_many"; >+ } > >+ my ( $resfound, $resrec ) = C4::Reserves::CheckReserves($itemnumber); >+ if ($resfound) { >+ $renewokay = 0; >+ $error->{message} = "on_reserve"; > } >- return ($renewokay,$error); >+ $error->{renewals} = $itemissue->{'issues.renewals'}; >+ $error->{renewalsallowed}= $issuingrule->{renewalsallowed}; >+ >+ return ( $renewokay, $error ); > } > > =head2 AddRenewal >@@ -2195,22 +2013,28 @@ sub AddRenewal { > # based on the value of the RenewalPeriodBase syspref. > unless ($datedue) { > >- my $borrower = C4::Members::GetMemberDetails( $borrowernumber, 0 ) or return undef; >- my $loanlength = GetLoanLength( >- $borrower->{'categorycode'}, >- (C4::Context->preference('item-level_itypes')) ? $biblio->{'itype'} : $biblio->{'itemtype'} , >- $issuedata->{'branchcode'} ); # that's the circ control branch. >+ my $borrower = C4::Members::GetMemberDetails( $borrowernumber, 0 ) or return undef; >+ my $branchcode = _GetCircControlBranch($item, $borrower); >+ my $loanlength = GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $branchcode ); >+ >+ $datedue = >+ ( C4::Context->preference('RenewalPeriodBase') eq 'date_due' ) >+ ? C4::Dates->new( $issuedata->{date_due}, 'iso' ) >+ : C4::Dates->new(); >+ >+ my $itype = ( C4::Context->preference('item-level_itypes') ) ? $biblio->{'itype'} : $biblio->{'itemtype'}; >+ my $controlbranch = _GetCircControlBranch( $item, $borrower ); >+ my $renewalperiod = $loanlength->{renewalperiod} || GetLoanLength( $borrower->{'categorycode'}, $itype, $controlbranch ); >+ >+ $datedue = CalcDateDue( $datedue, $renewalperiod, $issuedata->{'branchcode'}, $borrower ); > >- $datedue = (C4::Context->preference('RenewalPeriodBase') eq 'date_due') ? >- C4::Dates->new($issuedata->{date_due}, 'iso') : >- C4::Dates->new(); >- $datedue = CalcDateDue($datedue,$loanlength,$issuedata->{'branchcode'},$borrower); > } > > # Update the issues record to have the new due date, and a new count > # of how many times it has been renewed. > my $renews = $issuedata->{'renewals'} + 1; >- $sth = $dbh->prepare("UPDATE issues SET date_due = ?, renewals = ?, lastreneweddate = ? >+ $sth = $dbh->prepare( >+ "UPDATE issues SET date_due = ?, renewals = ?, lastreneweddate = ? > WHERE borrowernumber=? > AND itemnumber=?" > ); >@@ -2218,8 +2042,8 @@ sub AddRenewal { > $sth->finish; > > # Update the renewal count on the item, and tell zebra to reindex >- $renews = $biblio->{'renewals'} + 1; >- ModItem({ renewals => $renews, onloan => $datedue->output('iso') }, $biblio->{'biblionumber'}, $itemnumber); >+ $renews = $item->{'renewals'} + 1; >+ ModItem( { renewals => $renews, onloan => $datedue->output('iso') }, undef, $itemnumber ); > > # Charge a new rental fee, if applicable? > my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber ); >@@ -2600,15 +2424,8 @@ sub CalcDateDue { > my ($startdate,$loanlength,$branch,$borrower) = @_; > my $datedue; > >- if(C4::Context->preference('useDaysMode') eq 'Days') { # ignoring calendar >- my $timedue = time + ($loanlength) * 86400; >- #FIXME - assumes now even though we take a startdate >- my @datearr = localtime($timedue); >- $datedue = C4::Dates->new( sprintf("%04d-%02d-%02d", 1900 + $datearr[5], $datearr[4] + 1, $datearr[3]), 'iso'); >- } else { >- my $calendar = C4::Calendar->new( branchcode => $branch ); >- $datedue = $calendar->addDate($startdate, $loanlength); >- } >+ my $calendar = C4::Calendar->new( branchcode => $branch ); >+ $datedue = $calendar->addDate($startdate, $loanlength); > > # if ReturnBeforeExpiry ON the datedue can't be after borrower expirydate > if ( C4::Context->preference('ReturnBeforeExpiry') && $datedue->output('iso') gt $borrower->{dateexpiry} ) { >@@ -2818,18 +2635,121 @@ sub CreateBranchTransferLimit { > > =head2 DeleteBranchTransferLimits > >- DeleteBranchTransferLimits(); >+ DeleteBranchTransferLimits($tobranch); > > =cut > > sub DeleteBranchTransferLimits { >- my $dbh = C4::Context->dbh; >- my $sth = $dbh->prepare("TRUNCATE TABLE branch_transfer_limits"); >- $sth->execute(); >+ my $branch = shift; >+ my $dbh = C4::Context->dbh; >+ my $sth = $dbh->prepare("DELETE FROM branch_transfer_limits WHERE toBranch = ?"); >+ $sth->execute($branch); >+} >+ >+sub GetOfflineOperations { >+ my $dbh = C4::Context->dbh; >+ my $sth = $dbh->prepare("SELECT * FROM pending_offline_operations WHERE branchcode=? ORDER BY timestamp"); >+ $sth->execute(C4::Context->userenv->{'branch'}); >+ my $results = $sth->fetchall_arrayref({}); >+ $sth->finish; >+ return $results; >+} >+ >+sub GetOfflineOperation { >+ my $dbh = C4::Context->dbh; >+ my $sth = $dbh->prepare("SELECT * FROM pending_offline_operations WHERE operationid=?"); >+ $sth->execute( shift ); >+ my $result = $sth->fetchrow_hashref; >+ $sth->finish; >+ return $result; >+} >+ >+sub AddOfflineOperation { >+ my $dbh = C4::Context->dbh; >+ warn Data::Dumper::Dumper(@_); >+ my $sth = $dbh->prepare("INSERT INTO pending_offline_operations VALUES('',?,?,?,?,?,?)"); >+ $sth->execute( @_ ); >+ return "Added."; >+} >+ >+sub DeleteOfflineOperation { >+ my $dbh = C4::Context->dbh; >+ my $sth = $dbh->prepare("DELETE FROM pending_offline_operations WHERE operationid=?"); >+ $sth->execute( shift ); >+ return "Deleted."; >+} >+ >+sub ProcessOfflineOperation { >+ my $operation = shift; >+ >+ my $report; >+ if ( $operation->{action} eq 'return' ) { >+ $report = ProcessOfflineReturn( $operation ); >+ } elsif ( $operation->{action} eq 'issue' ) { >+ $report = ProcessOfflineIssue( $operation ); >+ } >+ >+ DeleteOfflineOperation( $operation->{operationid} ) if $operation->{operationid}; >+ >+ return $report; >+} >+ >+sub ProcessOfflineReturn { >+ my $operation = shift; >+ >+ my $itemnumber = C4::Items::GetItemnumberFromBarcode( $operation->{barcode} ); >+ >+ if ( $itemnumber ) { >+ my $issue = GetOpenIssue( $itemnumber ); >+ if ( $issue ) { >+ MarkIssueReturned( >+ $issue->{borrowernumber}, >+ $itemnumber, >+ undef, >+ $operation->{timestamp}, >+ ); >+ return "Success."; >+ } else { >+ return "Item not issued."; >+ } >+ } else { >+ return "Item not found."; >+ } >+} >+ >+sub ProcessOfflineIssue { >+ my $operation = shift; >+ >+ my $borrower = C4::Members::GetMemberDetails( undef, $operation->{cardnumber} ); # Get borrower from operation cardnumber >+ >+ if ( $borrower->{borrowernumber} ) { >+ my $itemnumber = C4::Items::GetItemnumberFromBarcode( $operation->{barcode} ); >+ my $issue = GetOpenIssue( $itemnumber ); >+ >+ if ( $issue and ( $issue->{borrowernumber} ne $borrower->{borrowernumber} ) ) { # Item already issued to another borrower, mark it returned >+ MarkIssueReturned( >+ $issue->{borrowernumber}, >+ $itemnumber, >+ undef, >+ $operation->{timestamp}, >+ ); >+ } >+ AddIssue( >+ $borrower, >+ $operation->{'barcode'}, >+ undef, >+ 1, >+ $operation->{timestamp}, >+ undef, >+ ); >+ return "Success."; >+ } else { >+ return "Borrower not found."; >+ } > } > > >- 1; >+1; > > __END__ > >diff --git a/C4/Overdues.pm b/C4/Overdues.pm >index b5e3cdf..f781b82 100644 >--- a/C4/Overdues.pm >+++ b/C4/Overdues.pm >@@ -23,6 +23,7 @@ use strict; > use Date::Calc qw/Today Date_to_Days/; > use Date::Manip qw/UnixDate/; > use C4::Circulation; >+use C4::IssuingRules; > use C4::Context; > use C4::Accounts; > use C4::Log; # logaction >@@ -71,9 +72,6 @@ BEGIN { > push @EXPORT, qw( > &GetIssuesIteminfo > ); >- # >- # &GetIssuingRules - delete. >- # use C4::Circulation::GetIssuingRule instead. > > # subs to move to Members.pm > push @EXPORT, qw( >@@ -124,7 +122,7 @@ sub Getoverdues { > SELECT issues.*, items.itype as itemtype, items.homebranch, items.barcode > FROM issues > LEFT JOIN items USING (itemnumber) >- WHERE date_due < CURDATE() >+ WHERE DATE(date_due) < CURDATE() > "; > } else { > $statement = " >@@ -132,7 +130,7 @@ LEFT JOIN items USING (itemnumber) > FROM issues > LEFT JOIN items USING (itemnumber) > LEFT JOIN biblioitems USING (biblioitemnumber) >- WHERE date_due < CURDATE() >+ WHERE DATE(date_due) < CURDATE() > "; > } > >@@ -170,7 +168,7 @@ sub checkoverdues { > LEFT JOIN biblio ON items.biblionumber = biblio.biblionumber > LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber > WHERE issues.borrowernumber = ? >- AND issues.date_due < CURDATE()" >+ AND DATE(issues.date_due) < CURDATE()" > ); > # FIXME: SELECT * across 4 tables? do we really need the marc AND marcxml blobs?? > $sth->execute($borrowernumber); >@@ -245,7 +243,7 @@ sub CalcFine { > my $daystocharge; > # get issuingrules (fines part will be used) > $debug and warn sprintf("CalcFine calling GetIssuingRule(%s, %s, %s)", $bortype, $item->{'itemtype'}, $branchcode); >- my $data = C4::Circulation::GetIssuingRule($bortype, $item->{'itemtype'}, $branchcode); >+ my $data = GetIssuingRule($bortype, $item->{'itemtype'}, $branchcode); > if($difference) { > # if $difference is supplied, the difference has already been calculated, but we still need to adjust for the calendar. > # use copy-pasted functions from calendar module. (deprecated -- these functions will be removed from C4::Overdues ). >@@ -269,7 +267,7 @@ sub CalcFine { > } else { > # a zero (or null) chargeperiod means no charge. > } >- $amount = C4::Context->preference('maxFine') if(C4::Context->preference('maxFine') && ( $amount > C4::Context->preference('maxFine'))); >+ $amount = C4::Context->preference('MaxFine') if ( C4::Context->preference('MaxFine') && ( $amount > C4::Context->preference('MaxFine') ) ); > $debug and warn sprintf("CalcFine returning (%s, %s, %s, %s)", $amount, $data->{'chargename'}, $days_minus_grace, $daystocharge); > return ($amount, $data->{'chargename'}, $days_minus_grace, $daystocharge); > # FIXME: chargename is NEVER populated anywhere. >@@ -585,7 +583,7 @@ Returns the replacement cost of the item with the given item number. > > =cut > >-#' >+ > sub ReplacementCost { > my ($itemnum) = @_; > my $dbh = C4::Context->dbh; >@@ -604,60 +602,22 @@ sub ReplacementCost { > > return the total of fine > >-C<$itemnum> is item number >- > C<$borrowernumber> is the borrowernumber > >-=cut >- >+=cut > > sub GetFine { >- my ( $itemnum, $borrowernumber ) = @_; >+ my ( $borrowernumber ) = @_; > my $dbh = C4::Context->dbh(); > my $query = "SELECT sum(amountoutstanding) FROM accountlines > where accounttype like 'F%' >- AND amountoutstanding > 0 AND itemnumber = ? AND borrowernumber=?"; >+ AND amountoutstanding > 0 AND borrowernumber=?"; > my $sth = $dbh->prepare($query); >- $sth->execute( $itemnum, $borrowernumber ); >+ $sth->execute( $borrowernumber ); > my $data = $sth->fetchrow_hashref(); > return ( $data->{'sum(amountoutstanding)'} ); > } > >- >-=head2 GetIssuingRules >- >-FIXME - This sub should be deprecated and removed. >-It ignores branch and defaults. >- >- $data = &GetIssuingRules($itemtype,$categorycode); >- >-Looks up for all issuingrules an item info >- >-C<$itemnumber> is a reference-to-hash whose keys are all of the fields >-from the borrowers and categories tables of the Koha database. Thus, >- >-C<$categorycode> contains information about borrowers category >- >-C<$data> contains all information about both the borrower and >-category he or she belongs to. >-=cut >- >-sub GetIssuingRules { >- warn "GetIssuingRules is deprecated: use GetIssuingRule from C4::Circulation instead."; >- my ($itemtype,$categorycode)=@_; >- my $dbh = C4::Context->dbh(); >- my $query=qq|SELECT * >- FROM issuingrules >- WHERE issuingrules.itemtype=? >- AND issuingrules.categorycode=? >- |; >- my $sth = $dbh->prepare($query); >- # print $query; >- $sth->execute($itemtype,$categorycode); >- return $sth->fetchrow_hashref; >-} >- >- > sub ReplacementCost2 { > my ( $itemnum, $borrowernumber ) = @_; > my $dbh = C4::Context->dbh(); >@@ -956,7 +916,7 @@ returns a list of branch codes for branches with overdue rules defined. > > sub GetBranchcodesWithOverdueRules { > my $dbh = C4::Context->dbh; >- my $rqoverduebranches = $dbh->prepare("SELECT DISTINCT branchcode FROM overduerules WHERE delay1 IS NOT NULL AND branchcode <> ''"); >+ my $rqoverduebranches = $dbh->prepare("SELECT DISTINCT branchcode FROM overduerules WHERE delay1 IS NOT NULL "); > $rqoverduebranches->execute; > my @branches = map { shift @$_ } @{ $rqoverduebranches->fetchall_arrayref }; > return @branches; >@@ -1029,7 +989,7 @@ sub GetOverduerules { > > Check if the borrowers is already debarred > >-C<$debarredstatus> return 0 for not debarred and return 1 for debarred >+C<$debarredstatus> return undef for not debarred and return end of debar date for debarred > > C<$borrowernumber> contains the borrower number > >@@ -1043,32 +1003,35 @@ sub CheckBorrowerDebarred { > SELECT debarred > FROM borrowers > WHERE borrowernumber=? >+ AND debarred > NOW() > |; > my $sth = $dbh->prepare($query); > $sth->execute($borrowernumber); >- my ($debarredstatus) = $sth->fetchrow; >- return ( $debarredstatus eq '1' ? 1 : 0 ); >+ my $debarredstatus= $sth->fetchrow; >+ return $debarredstatus; >+ > } > > =head2 UpdateBorrowerDebarred > >- ($borrowerstatut) = &UpdateBorrowerDebarred($borrowernumber); >+ ($borrowerstatut) = &UpdateBorrowerDebarred($borrowernumber, $todate); > > update status of borrowers in borrowers table (field debarred) > > C<$borrowernumber> borrower number >+C<$todate> end of bare > > =cut > > sub UpdateBorrowerDebarred{ >- my($borrowernumber) = @_; >+ my($borrowernumber, $todate) = @_; > my $dbh = C4::Context->dbh; > my $query=qq|UPDATE borrowers >- SET debarred='1' >+ SET debarred=? > WHERE borrowernumber=? > |; > my $sth=$dbh->prepare($query); >- $sth->execute($borrowernumber); >+ $sth->execute($todate, $borrowernumber); > $sth->finish; > return 1; > } >diff --git a/C4/Reserves.pm b/C4/Reserves.pm >index 2dd2688..12756ee 100644 >--- a/C4/Reserves.pm >+++ b/C4/Reserves.pm >@@ -22,6 +22,7 @@ package C4::Reserves; > > use strict; > #use warnings; FIXME - Bug 2505 >+use Date::Calc qw( Add_Delta_Days Time_to_Date Today); > use C4::Context; > use C4::Biblio; > use C4::Members; >@@ -32,10 +33,11 @@ use C4::Accounts; > > # for _koha_notify_reserve > use C4::Members::Messaging; >-use C4::Members qw(); >+use C4::Members ; > use C4::Letters; > use C4::Branch qw( GetBranchDetail ); > use C4::Dates qw( format_date_in_iso ); >+use C4::IssuingRules; > use List::MoreUtils qw( firstidx ); > > use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); >@@ -91,11 +93,14 @@ BEGIN { > @EXPORT = qw( > &AddReserve > >+ &GetMaxPickupDelay >+ &GetMaxPickupDate > &GetReservesFromItemnumber > &GetReservesFromBiblionumber > &GetReservesFromBorrowernumber > &GetReservesForBranch > &GetReservesToBranch >+ &GetReservesControlBranch > &GetReserveCount > &GetReserveFee > &GetReserveInfo >@@ -113,13 +118,16 @@ BEGIN { > &CheckReserves > &CanBookBeReserved > &CanItemBeReserved >- &CancelReserve >- &CancelExpiredReserves >+ &CanHoldOnShelf >+ &CancelReserve >+ &CancelExpiredReserves > >- &IsAvailableForItemLevelRequest >- >- &AlterPriority >- &ToggleLowestPriority >+ &IsAvailableForItemLevelRequest >+ >+ &AlterPriority >+ &ToggleLowestPriority >+ &CanHoldMultipleItems >+ &BorrowerHasReserve > ); > } > >@@ -142,11 +150,17 @@ sub AddReserve { > my $const = lc substr( $constraint, 0, 1 ); > $resdate = format_date_in_iso( $resdate ) if ( $resdate ); > $resdate = C4::Dates->today( 'iso' ) unless ( $resdate ); >+ my $item = C4::Items::GetItem($checkitem); >+ my @maxPickupDate = GetMaxPickupDate($resdate, $borrowernumber, $item); >+ my $maxpickupdate = sprintf( "%d-%02d-%02d", @maxPickupDate ); > if ($expdate) { > $expdate = format_date_in_iso( $expdate ); >+ my @expdate = split("-", $expdate); >+ $expdate = $maxpickupdate if Delta_Days(@expdate[ 0 .. 2 ], @maxPickupDate[ 0 .. 2 ]) < 0; > } else { >- undef $expdate; # make reserves.expirationdate default to null rather than '0000-00-00' >+ $expdate = $maxpickupdate; > } >+ undef $expdate if $resdate eq $maxpickupdate; # make reserves.expirationdate default to null rather than '0000-00-00' > if ( C4::Context->preference( 'AllowHoldDateInFuture' ) ) { > # Make room in reserves for this before those of a later reserve date > $priority = _ShiftPriorityByDateAndPriority( $biblionumber, $resdate, $priority ); >@@ -250,24 +264,27 @@ sub GetReservesFromBiblionumber { > > # Find the desired items in the reserves > my $query = " >- SELECT branchcode, >- timestamp AS rtimestamp, >- priority, >- biblionumber, >- borrowernumber, >- reservedate, >- constrainttype, >- found, >- itemnumber, >- reservenotes, >- expirationdate, >- lowestPriority >+ SELECT reserves.reservenumber, >+ reserves.branchcode, >+ reserves.timestamp AS rtimestamp, >+ reserves.priority, >+ reserves.biblionumber, >+ reserves.borrowernumber, >+ reserves.reservedate, >+ reserves.constrainttype, >+ reserves.found, >+ reserves.itemnumber, >+ reserves.reservenotes, >+ reserves.expirationdate, >+ reserves.lowestPriority, >+ biblioitems.itemtype > FROM reserves >- WHERE biblionumber = ? "; >+ LEFT JOIN biblioitems ON biblioitems.biblionumber = reserves.biblionumber >+ WHERE reserves.biblionumber = ? "; > unless ( $all_dates ) { > $query .= "AND reservedate <= CURRENT_DATE()"; > } >- $query .= "ORDER BY priority"; >+ $query .= "ORDER BY reserves.priority"; > my $sth = $dbh->prepare($query); > $sth->execute($biblionumber); > my @results; >@@ -373,9 +390,40 @@ sub GetReservesFromBorrowernumber { > return @$data; > } > #------------------------------------------------------------------------------------- >+sub BorrowerHasReserve { >+ my ( $borrowernumber, $biblionumber, $itemnumber ) = @_; >+ my $dbh = C4::Context->dbh; >+ my $sth; >+ >+ if ( $biblionumber ) { >+ $sth = $dbh->prepare(" >+ SELECT COUNT(*) AS hasReserve >+ FROM reserves >+ WHERE borrowernumber = ? >+ AND biblionumber = ? >+ ORDER BY reservedate >+ "); >+ $sth->execute( $borrowernumber, $biblionumber ); >+ } elsif ( $itemnumber ) { >+ $sth = $dbh->prepare(" >+ SELECT COUNT(*) AS hasReserve >+ FROM reserves >+ WHERE borrowernumber = ? >+ AND itemnumber = ? >+ ORDER BY reservedate >+ "); >+ $sth->execute( $borrowernumber, $itemnumber ); >+ } else { >+ return -1; >+ } >+ >+ my $data = $sth->fetchrow_hashref(); >+ return $data->{'hasReserve'}; >+} >+ > =head2 CanBookBeReserved > >- $error = &CanBookBeReserved($borrowernumber, $biblionumber) >+$error = &CanBookBeReserved($borrowernumber, $biblionumber) > > =cut > >@@ -399,7 +447,7 @@ This function return 1 if an item can be issued by this borrower. > > sub CanItemBeReserved{ > my ($borrowernumber, $itemnumber) = @_; >- >+ > my $dbh = C4::Context->dbh; > my $allowedreserves = 0; > >@@ -407,7 +455,7 @@ sub CanItemBeReserved{ > my $itype = C4::Context->preference('item-level_itypes') ? "itype" : "itemtype"; > > # we retrieve borrowers and items informations # >- my $item = GetItem($itemnumber); >+ my $item = C4::Items::GetItem($itemnumber); > my $borrower = C4::Members::GetMember('borrowernumber'=>$borrowernumber); > > # we retrieve user rights on this itemtype and branchcode >@@ -438,22 +486,31 @@ sub CanItemBeReserved{ > my $branchfield = "reserves.branchcode"; > > if( $controlbranch eq "ItemHomeLibrary" ){ >- $branchfield = "items.homebranch"; >- $branchcode = $item->{homebranch}; >+ my $field=C4::Context->preference("HomeOrHoldingBranch")||"homebranch"; >+ $branchfield = "items.$field"; >+ $branchcode = $item->{$field}; > }elsif( $controlbranch eq "PatronLibrary" ){ > $branchfield = "borrowers.branchcode"; > $branchcode = $borrower->{branchcode}; > } > >- # we retrieve rights >- $sth->execute($categorycode, $itemtype, $branchcode); >- if(my $rights = $sth->fetchrow_hashref()){ >- $itemtype = $rights->{itemtype}; >- $allowedreserves = $rights->{reservesallowed}; >+ # we retrieve user rights on this itemtype and branchcode >+ my $issuingrule = GetIssuingRule($borrower->{categorycode}, $item->{$itype}, $branchcode); >+ return 0 if( defined $issuingrule->{reservesallowed} && not $issuingrule->{reservesallowed} ); >+ >+ # We retrieve the count of reserves allowed for this category code >+ $issuingrule = GetIssuingRule ($borrower->{categorycode}, "*", "*"); >+ >+ if($issuingrule){ >+ $itemtype = $issuingrule->{itemtype}; >+ $allowedreserves = $issuingrule->{reservesallowed}; > }else{ > $itemtype = '*'; > } > >+ return 0 if ($issuingrule->{reservesallowed}==0 || >+ ($issuingrule->{holdrestricted}== 1 && !($branchcode eq $borrower->{branchcode})) >+ ); > # we retrieve count > > $querycount .= "AND $branchfield = ?"; >@@ -479,6 +536,106 @@ sub CanItemBeReserved{ > return 0; > } > } >+ >+=item GetMaxPickupDelay >+ >+$resallowed = &GetMaxPickupDelay($borrowernumber, $itemnumber) >+ >+this function return the number of allowed reserves. >+ >+=cut >+ >+sub GetMaxPickupDelay { >+ my ($borrowernumber, $itemnumber) = @_; >+ >+ my $dbh = C4::Context->dbh; >+ my $allowedreserves = 0; >+ >+ my $itype = C4::Context->preference('item-level_itypes') ? "itype" : "itemtype"; >+ >+ # we retrieve borrowers and items informations # >+ my $item = C4::Items::GetItem($itemnumber); >+ my $borrower = C4::Members::GetMember('borrowernumber'=>$borrowernumber); >+ my $controlbranch = GetReservesControlBranch($borrower,$item); >+ >+ # we retrieve user rights on this itemtype and branchcode >+ my $sth = $dbh->prepare("SELECT holdspickupdelay >+ FROM issuingrules >+ WHERE categorycode=? >+ AND itemtype=? >+ AND branchcode=? >+ AND holdspickupdelay IS NOT NULL" >+ ); >+ >+ my $itemtype = $item->{$itype}; >+ my $borrowertype = $borrower->{categorycode}; >+ my $branchcode = $controlbranch; >+ >+ $sth->execute( $borrowertype, $itemtype, $branchcode ); >+ my $pickupdelay = $sth->fetchrow_hashref; >+ return $pickupdelay->{holdspickupdelay} >+ if defined($pickupdelay) && $pickupdelay->{holdspickupdelay} ne 'NULL'; >+ >+ $sth->execute( $borrowertype, "*", $branchcode ); >+ $pickupdelay = $sth->fetchrow_hashref; >+ return $pickupdelay->{holdspickupdelay} >+ if defined($pickupdelay) && $pickupdelay->{holdspickupdelay} ne 'NULL'; >+ >+ $sth->execute( "*", $itemtype, $branchcode ); >+ $pickupdelay = $sth->fetchrow_hashref; >+ return $pickupdelay->{holdspickupdelay} >+ if defined($pickupdelay) && $pickupdelay->{holdspickupdelay} ne 'NULL'; >+ >+ $sth->execute( "*", "*", $branchcode ); >+ $pickupdelay = $sth->fetchrow_hashref; >+ return $pickupdelay->{holdspickupdelay} >+ if defined($pickupdelay) && $pickupdelay->{holdspickupdelay} ne 'NULL'; >+ >+ $sth->execute( $borrowertype, $itemtype, "*" ); >+ $pickupdelay = $sth->fetchrow_hashref; >+ return $pickupdelay->{holdspickupdelay} >+ if defined($pickupdelay) && $pickupdelay->{holdspickupdelay} ne 'NULL'; >+ >+ $sth->execute( $borrowertype, "*", "*" ); >+ $pickupdelay = $sth->fetchrow_hashref; >+ return $pickupdelay->{holdspickupdelay} >+ if defined($pickupdelay) && $pickupdelay->{holdspickupdelay} ne 'NULL'; >+ >+ $sth->execute( "*", $itemtype, "*" ); >+ $pickupdelay = $sth->fetchrow_hashref; >+ return $pickupdelay->{holdspickupdelay} >+ if defined($pickupdelay) && $pickupdelay->{holdspickupdelay} ne 'NULL'; >+ >+ $sth->execute( "*", "*", "*" ); >+ $pickupdelay = $sth->fetchrow_hashref; >+ return $pickupdelay->{holdspickupdelay} >+ if defined($pickupdelay) && $pickupdelay->{holdspickupdelay} ne 'NULL'; >+ >+ # if nothing found, return no rights >+ return 0; >+} >+ >+=item GetMaxPickupDate >+ >+$maxpickupdate = &GetMaxPickupDate($date); >+ >+this function return the max pickup date. >+(e.g. : the date after which the hold will be considered cancelled) >+ >+=cut >+ >+sub GetMaxPickupDate{ >+ my $inputdate=shift; >+ my $borrowernumber=shift; >+ my $item=shift; >+ return unless $inputdate; >+ my @date = split(/-/,$inputdate); >+ my $delay = GetMaxPickupDelay($borrowernumber, $item->{'itemnumber'}); >+ ( @date ) = >+ Add_Delta_Days( @date[0..2], $delay); >+ return @date; >+} >+ > #-------------------------------------------------------------------------------- > =head2 GetReserveCount > >@@ -518,21 +675,22 @@ sub GetOtherReserves { > my $nextreservinfo; > my ( $restype, $checkreserves ) = CheckReserves($itemnumber); > if ($checkreserves) { >- my $iteminfo = GetItem($itemnumber); >+ my $iteminfo = C4::Items::GetItem($itemnumber); > if ( $iteminfo->{'holdingbranch'} ne $checkreserves->{'branchcode'} ) { > $messages->{'transfert'} = $checkreserves->{'branchcode'}; > #minus priorities of others reservs > ModReserveMinusPriority( > $itemnumber, > $checkreserves->{'borrowernumber'}, >- $iteminfo->{'biblionumber'} >+ $iteminfo->{'biblionumber'}, >+ $checkreserves->{'reservenumber'} > ); > > #launch the subroutine dotransfer > C4::Items::ModItemTransfer( > $itemnumber, > $iteminfo->{'holdingbranch'}, >- $checkreserves->{'branchcode'} >+ $checkreserves->{'branchcode'}, > ), > ; > } >@@ -543,7 +701,8 @@ sub GetOtherReserves { > ModReserveMinusPriority( > $itemnumber, > $checkreserves->{'borrowernumber'}, >- $iteminfo->{'biblionumber'} >+ $iteminfo->{'biblionumber'}, >+ $checkreserves->{'reservenumber'} > ); > ModReserveStatus($itemnumber,'W'); > } >@@ -657,6 +816,26 @@ sub GetReserveFee { > return $fee; > } > >+=head2 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 GetReservesToBranch > > @transreserv = GetReservesToBranch( $frombranch ); >@@ -840,23 +1019,18 @@ sub CancelExpiredReserves { > $sth->execute(); > > while ( my $res = $sth->fetchrow_hashref() ) { >- CancelReserve( $res->{'biblionumber'}, '', $res->{'borrowernumber'} ); >+ CancelReserve( $res->{'reservenumber'}, $res->{'biblionumber'} ); > } > > } > > =head2 CancelReserve > >- &CancelReserve($biblionumber, $itemnumber, $borrowernumber); >+ &CancelReserve( $reservenumber, $biblionumber ); > > Cancels a reserve. > >-Use either C<$biblionumber> or C<$itemnumber> to specify the item to >-cancel, but not both: if both are given, C<&CancelReserve> does >-nothing. >- >-C<$borrowernumber> is the borrower number of the patron on whose >-behalf the book was reserved. >+C<$reservenumber> is the unique key for the reserve to be canceled. > > If C<$biblionumber> was given, C<&CancelReserve> also adjusts the > priorities of the other people who are waiting on the book. >@@ -864,9 +1038,14 @@ priorities of the other people who are waiting on the book. > =cut > > sub CancelReserve { >- my ( $biblio, $item, $borr ) = @_; >+ my ( $reservenumber, $biblio ) = @_; > my $dbh = C4::Context->dbh; >- if ( $item and $borr ) { >+ >+ my $sth = $dbh->prepare('SELECT * FROM reserves WHERE reservenumber = ?'); >+ $sth->execute( $reservenumber ); >+ my $reserve = $sth->fetchrow_hashref(); >+ >+ if ( $reserve->{'found'} eq 'W' ) { > # removing a waiting reserve record.... > # update the database... > my $query = " >@@ -874,27 +1053,46 @@ sub CancelReserve { > SET cancellationdate = now(), > found = Null, > priority = 0 >- WHERE itemnumber = ? >- AND borrowernumber = ? >+ WHERE reservenumber = ? > "; > my $sth = $dbh->prepare($query); >- $sth->execute( $item, $borr ); >- $sth->finish; >+ $sth->execute( $reservenumber ); >+ >+ # get reserve information to place into old_reserves > $query = " > INSERT INTO old_reserves > SELECT * FROM reserves >- WHERE itemnumber = ? >- AND borrowernumber = ? >+ WHERE reservenumber = ? > "; > $sth = $dbh->prepare($query); >- $sth->execute( $item, $borr ); >+ $sth->execute( $reservenumber ); >+ my $holditem = $sth->fetchrow_hashref; >+ my $insert_fields = ''; >+ my $value_fields = ''; >+ foreach my $column ('borrowernumber','reservedate','biblionumber','constrainttype','branchcode','notificationdate','reminderdate','cancellationdate','reservenotes','priority','found','itemnumber','waitingdate','expirationdate') { >+ if (defined($holditem->{$column})) { >+ if (length($insert_fields)) { >+ $insert_fields .= ",$column"; >+ $value_fields .= ",\'$holditem->{$column}\'"; >+ } >+ else { >+ $insert_fields .= "$column"; >+ $value_fields .= "\'$holditem->{$column}\'"; >+ } >+ } >+ } >+ $query = qq/ >+ INSERT INTO old_reserves ($insert_fields) >+ VALUES ($value_fields) >+ /; >+ $sth = $dbh->prepare($query); >+ $sth->execute(); > $query = " > DELETE FROM reserves >- WHERE itemnumber = ? >- AND borrowernumber = ? >+ WHERE reservenumber = ? > "; > $sth = $dbh->prepare($query); >- $sth->execute( $item, $borr ); >+ $sth->execute( $reservenumber ); > } > else { > # removing a reserve record.... >@@ -902,52 +1100,72 @@ sub CancelReserve { > my $priority; > my $query = qq/ > SELECT priority FROM reserves >- WHERE biblionumber = ? >- AND borrowernumber = ? >+ WHERE reservenumber = ? > AND cancellationdate IS NULL > AND itemnumber IS NULL > /; > my $sth = $dbh->prepare($query); >- $sth->execute( $biblio, $borr ); >+ $sth->execute( $reservenumber ); > ($priority) = $sth->fetchrow_array; > $sth->finish; > $query = qq/ > UPDATE reserves > SET cancellationdate = now(), > found = Null, >- priority = 0 >- WHERE biblionumber = ? >- AND borrowernumber = ? >+ priority = 0, >+ expirationdate = NULL >+ WHERE reservenumber = ? > /; > > # update the database, removing the record... > $sth = $dbh->prepare($query); >- $sth->execute( $biblio, $borr ); >- $sth->finish; >+ $sth->execute( $reservenumber ); > > $query = qq/ > INSERT INTO old_reserves > SELECT * FROM reserves >- WHERE biblionumber = ? >- AND borrowernumber = ? >+ WHERE reservenumber = ? >+ /; >+ $sth = $dbh->prepare($query); >+ $sth->execute( $reservenumber ); >+ my $holditem = $sth->fetchrow_hashref; >+ >+ my $insert_fields = ''; >+ my $value_fields = ''; >+ foreach my $column ('borrowernumber','reservedate','biblionumber','constrainttype','branchcode','notificationdate','reminderdate','cancellationdate','reservenotes','priority','found','itemnumber','waitingdate','expirationdate') { >+ if (defined($holditem->{$column})) { >+ if (length($insert_fields)) { >+ $insert_fields .= ",$column"; >+ $value_fields .= ",\'$holditem->{$column}\'"; >+ } >+ else { >+ $insert_fields .= "$column"; >+ $value_fields .= "\'$holditem->{$column}\'"; >+ } >+ } >+ } >+ $query = qq/ >+ INSERT INTO old_reserves ($insert_fields) >+ VALUES ($value_fields) > /; > $sth = $dbh->prepare($query); >- $sth->execute( $biblio, $borr ); >+ $sth->execute(); > > $query = qq/ > DELETE FROM reserves >- WHERE biblionumber = ? >- AND borrowernumber = ? >+ WHERE reservenumber = ? > /; > $sth = $dbh->prepare($query); >- $sth->execute( $biblio, $borr ); >+ $sth->execute( $reservenumber ); > > # now fix the priority on the others.... >- _FixPriority( $biblio, $borr ); >+ _FixPriority( '', '', $priority,'', $reservenumber ); > } > } > >-=head2 ModReserve >+=item ModReserve >+ >+=over 4 > > ModReserve($rank, $biblio, $borrower, $branch[, $itemnumber]) > >@@ -980,52 +1198,48 @@ itemnumber and supplying itemnumber. > > sub ModReserve { > #subroutine to update a reserve >- my ( $rank, $biblio, $borrower, $branch , $itemnumber) = @_; >+ my ( $rank, $biblio, $borrower, $branch , $itemnumber, $reservenumber) = @_; > return if $rank eq "W"; > return if $rank eq "n"; > my $dbh = C4::Context->dbh; > if ( $rank eq "del" ) { > my $query = qq/ > UPDATE reserves >- SET cancellationdate=now() >- WHERE biblionumber = ? >- AND borrowernumber = ? >+ SET cancellationdate=now(), >+ expirationdate = NULL >+ WHERE reservenumber = ? > /; > my $sth = $dbh->prepare($query); >- $sth->execute( $biblio, $borrower ); >+ $sth->execute( $reservenumber ); > $sth->finish; > $query = qq/ > INSERT INTO old_reserves >- SELECT * >- FROM reserves >- WHERE biblionumber = ? >- AND borrowernumber = ? >+ SELECT * FROM reserves >+ WHERE reservenumber = ? > /; > $sth = $dbh->prepare($query); >- $sth->execute( $biblio, $borrower ); >+ $sth->execute( $reservenumber ); > $query = qq/ > DELETE FROM reserves >- WHERE biblionumber = ? >- AND borrowernumber = ? >+ WHERE reservenumber = ? > /; > $sth = $dbh->prepare($query); >- $sth->execute( $biblio, $borrower ); >+ $sth->execute( $reservenumber ); > > } > elsif ($rank =~ /^\d+/ and $rank > 0) { > my $query = qq/ > UPDATE reserves SET priority = ? ,branchcode = ?, itemnumber = ?, found = NULL, waitingdate = NULL >- WHERE biblionumber = ? >- AND borrowernumber = ? >+ WHERE reservenumber = ? > /; > my $sth = $dbh->prepare($query); >- $sth->execute( $rank, $branch,$itemnumber, $biblio, $borrower); >+ $sth->execute( $rank, $branch, $itemnumber, $reservenumber ); > $sth->finish; >- _FixPriority( $biblio, $borrower, $rank); >+ _FixPriority( $biblio, $borrower, $rank, '', $reservenumber); > } > } > >-=head2 ModReserveFill >+=item ModReserveFill > > &ModReserveFill($reserve); > >@@ -1044,16 +1258,17 @@ sub ModReserveFill { > my $biblionumber = $res->{'biblionumber'}; > my $borrowernumber = $res->{'borrowernumber'}; > my $resdate = $res->{'reservedate'}; >+ my $resnumber = $res->{'reservenumber'}; > > # get the priority on this record.... > my $priority; > my $query = "SELECT priority > FROM reserves >- WHERE biblionumber = ? >- AND borrowernumber = ? >+ WHERE borrowernumber = ? >+ AND reservenumber = ? > AND reservedate = ?"; > my $sth = $dbh->prepare($query); >- $sth->execute( $biblionumber, $borrowernumber, $resdate ); >+ $sth->execute( $resnumber, $borrowernumber, $resdate ); > ($priority) = $sth->fetchrow_array; > $sth->finish; > >@@ -1061,35 +1276,35 @@ sub ModReserveFill { > $query = "UPDATE reserves > SET found = 'F', > priority = 0 >- WHERE biblionumber = ? >+ WHERE reservenumber = ? > AND reservedate = ? > AND borrowernumber = ? > "; > $sth = $dbh->prepare($query); >- $sth->execute( $biblionumber, $resdate, $borrowernumber ); >+ $sth->execute( $resnumber, $resdate, $borrowernumber ); > $sth->finish; > > # move to old_reserves > $query = "INSERT INTO old_reserves > SELECT * FROM reserves >- WHERE biblionumber = ? >+ WHERE reservenumber = ? > AND reservedate = ? > AND borrowernumber = ? > "; > $sth = $dbh->prepare($query); >- $sth->execute( $biblionumber, $resdate, $borrowernumber ); >+ $sth->execute( $resnumber, $resdate, $borrowernumber ); > $query = "DELETE FROM reserves >- WHERE biblionumber = ? >+ WHERE reservenumber = ? > AND reservedate = ? > AND borrowernumber = ? > "; > $sth = $dbh->prepare($query); >- $sth->execute( $biblionumber, $resdate, $borrowernumber ); >+ $sth->execute( $resnumber, $resdate, $borrowernumber ); > > # now fix the priority on the others (if the priority wasn't > # already sorted!).... > unless ( $priority == 0 ) { >- _FixPriority( $biblionumber, $borrowernumber ); >+ _FixPriority( $priority, $biblionumber,undef,undef, $res->{reservenumber} ); > } > } > >@@ -1106,7 +1321,6 @@ $newstatus is the new status. > =cut > > sub ModReserveStatus { >- > #first : check if we have a reservation for this item . > my ($itemnumber, $newstatus) = @_; > my $dbh = C4::Context->dbh; >@@ -1140,9 +1354,8 @@ take care of the waiting status > =cut > > sub ModReserveAffect { >- my ( $itemnumber, $borrowernumber,$transferToDo ) = @_; >+ my ( $itemnumber, $borrowernumber,$transferToDo, $reservenumber ) = @_; > my $dbh = C4::Context->dbh; >- > # we want to attach $itemnumber to $borrowernumber, find the biblionumber > # attached to $itemnumber > my $sth = $dbh->prepare("SELECT biblionumber FROM items WHERE itemnumber=?"); >@@ -1160,27 +1373,52 @@ sub ModReserveAffect { > $query = " > UPDATE reserves > SET priority = 0, >- itemnumber = ?, >- found = 'T' >- WHERE borrowernumber = ? >- AND biblionumber = ? >+ itemnumber = ? >+ WHERE reservenumber = ? > "; > } > else { > # affect the reserve to Waiting as well. >- $query = " >- UPDATE reserves >- SET priority = 0, >- found = 'W', >- waitingdate=now(), >- itemnumber = ? >- WHERE borrowernumber = ? >- AND biblionumber = ? >- "; >+ my $holdperiod = C4::Context->preference('ReservesMaxPickUpDelay'); >+ if ((!defined($holdperiod)) || ($holdperiod eq '') || ($holdperiod == 0)) { >+ $query = " >+ UPDATE reserves >+ SET priority = 0, >+ found = 'W', >+ waitingdate=now(), >+ itemnumber = ? >+ WHERE reservenumber = ? >+ "; >+ } >+ else { >+ my ($holdexpyear,$holdexpmonth,$holdexpday) = Today(); >+ my $holdstartdate = C4::Dates->new(sprintf "%02d/%02d/%04d",$holdexpmonth,$holdexpday,$holdexpyear, 'us'); >+ >+ # Grab branch for calendar purposes >+ $sth = $dbh->prepare("SELECT branchcode FROM reserves WHERE borrowernumber=? AND biblionumber=?"); >+ $sth->execute($borrowernumber,$biblionumber); >+ my ($branch) = $sth->fetchrow; >+ >+ # Check to see if hold expiration date falls on a closed library day. >+ # Note the useDaysMode syspref will need to be set to Calendar for >+ # the code to advance to the next non-closed day. >+ my $calendar = C4::Calendar->new( branchcode => $branch); >+ my $holdexpdate = $calendar->addDate($holdstartdate, $holdperiod); >+ my $sqlexpdate = $holdexpdate->output('iso'); >+ $query = " >+ UPDATE reserves >+ SET priority = 0, >+ found = 'W', >+ waitingdate=now(), >+ itemnumber = ?, >+ expirationdate='$sqlexpdate' >+ WHERE reservenumber = ? >+ "; >+ } > } > $sth = $dbh->prepare($query); >- $sth->execute( $itemnumber, $borrowernumber,$biblionumber); >- _koha_notify_reserve( $itemnumber, $borrowernumber, $biblionumber ) if ( !$transferToDo && !$already_on_shelf ); >+ $sth->execute( $itemnumber, $reservenumber ); >+ _koha_notify_reserve( $itemnumber, $borrowernumber, $biblionumber, $reservenumber ) if ( !$transferToDo && !$already_on_shelf ); > > if ( C4::Context->preference("ReturnToShelvingCart") ) { > CartToShelf( $itemnumber ); >@@ -1220,23 +1458,21 @@ Reduce the values of queuded list > =cut > > sub ModReserveMinusPriority { >- my ( $itemnumber, $borrowernumber, $biblionumber ) = @_; >- >+ my ( $itemnumber, $borrowernumber, $biblionumber, $reservenumber ) = @_; > #first step update the value of the first person on reserv > my $dbh = C4::Context->dbh; > my $query = " > UPDATE reserves > SET priority = 0 , itemnumber = ? >- WHERE borrowernumber=? >- AND biblionumber=? >+ WHERE reservenumber=? > "; > my $sth_upd = $dbh->prepare($query); >- $sth_upd->execute( $itemnumber, $borrowernumber, $biblionumber ); >+ $sth_upd->execute( $itemnumber, $reservenumber ); > # second step update all others reservs >- _FixPriority($biblionumber, $borrowernumber, '0'); >+ _FixPriority($biblionumber, $borrowernumber, '0', '', $reservenumber); > } > >-=head2 GetReserveInfo >+=item GetReserveInfo > > &GetReserveInfo($borrowernumber,$biblionumber); > >@@ -1321,7 +1557,7 @@ and canreservefromotherbranches. > sub IsAvailableForItemLevelRequest { > my $itemnumber = shift; > >- my $item = GetItem($itemnumber); >+ my $item = C4::Items::GetItem($itemnumber); > > # must check the notforloan setting of the itemtype > # FIXME - a lot of places in the code do this >@@ -1356,10 +1592,10 @@ sub IsAvailableForItemLevelRequest { > $notforloan_per_itemtype; > > >- if (C4::Context->preference('AllowOnShelfHolds')) { >+ if (CanHoldOnShelf($itemnumber)) { > return $available_per_item; > } else { >- return ($available_per_item and ($item->{onloan} or GetReserveStatus($itemnumber) eq "W")); >+ return ($available_per_item and ($item->{onloan} or GetReserveStatus($itemnumber) eq "W")); > } > } > >@@ -1387,15 +1623,15 @@ sub AlterPriority { > > my $priority = $reserve->{'priority'}; > $priority = $where eq 'up' ? $priority - 1 : $priority + 1; >- _FixPriority( $biblionumber, $borrowernumber, $priority ) >+ _FixPriority( $biblionumber, $borrowernumber, $priority ,undef,$reserve->{reservenumber}) > > } elsif ( $where eq 'top' ) { > >- _FixPriority( $biblionumber, $borrowernumber, '1' ) >+ _FixPriority( $biblionumber, $borrowernumber, '1',undef,$reserve->{reservenumber} ) > > } elsif ( $where eq 'bottom' ) { > >- _FixPriority( $biblionumber, $borrowernumber, '999999' ) >+ _FixPriority( $biblionumber, $borrowernumber, '999999',undef,$reserve->{reservenumber} ) > > } > } >@@ -1418,18 +1654,50 @@ sub ToggleLowestPriority { > WHERE biblionumber = ? > AND borrowernumber = ?" > ); >- $sth->execute( >- $biblionumber, >- $borrowernumber, >- ); >+ $sth->execute( $biblionumber, $borrowernumber, ); > $sth->finish; > > _FixPriority( $biblionumber, $borrowernumber, '999999' ); > } > >+=head2 CanHoldOnShelf >+ >+my $canhold = &CanHoldOnShelf($itemnumber); >+ >+ Check if a book can be hold on shelf. >+ >+=cut >+ >+sub CanHoldOnShelf { >+ my ($itemnumber) = @_; >+ >+ my $item = C4::Items::GetItem($itemnumber); >+ my $itemtype = C4::Context->preference('item-level_itypes'); >+ $itemtype = $itemtype ? $item->{itype} : $item->{itemtype} ; >+ my $branch = $item->{C4::Context->preference('HomeOrHoldingBranch')}; >+ >+ my $issuingrule = GetIssuingRule('*', $itemtype, $branch); >+ return $issuingrule->{allowonshelfholds}; >+ >+} >+ >+sub CanHoldMultipleItems { >+ my ( $itemtype ) = @_; >+ >+ my @multi_itemtypes = split( / /, C4::Context->preference('AllowMultipleHoldsPerBib') ); >+ for my $mtype ( @multi_itemtypes ) { >+ if ( $itemtype eq $mtype ) { >+ return 1; >+ } >+ } >+ >+ return 0; >+} >+ > =head2 _FixPriority >+>>>>>>> [MT2355] Ergonomy improvement in smart rule management > >- &_FixPriority($biblio,$borrowernumber,$rank,$ignoreSetLowestRank); >+&_FixPriority($biblio,$borrowernumber,$rank,$ignoreSetLowestRank,$reservenumber); > > Only used internally (so don't export it) > Changed how this functions works # >@@ -1441,7 +1709,7 @@ in new priority rank > =cut > > sub _FixPriority { >- my ( $biblio, $borrowernumber, $rank, $ignoreSetLowestRank ) = @_; >+ my ( $biblio, $borrowernumber, $rank, $ignoreSetLowestRank, $reservenumber ) = @_; > my $dbh = C4::Context->dbh; > if ( $rank eq "del" ) { > CancelReserve( $biblio, undef, $borrowernumber ); >@@ -1452,12 +1720,11 @@ sub _FixPriority { > my $query = qq/ > UPDATE reserves > SET priority = 0 >- WHERE biblionumber = ? >- AND borrowernumber = ? >- AND found IN ('W', 'T') >+ WHERE reservenumber = ? >+ AND found IN ('W',"T") > /; > my $sth = $dbh->prepare($query); >- $sth->execute( $biblio, $borrowernumber ); >+ $sth->execute( $reservenumber ); > } > my @priority; > my @reservedates; >@@ -1468,7 +1735,7 @@ sub _FixPriority { > # This is wrong a waiting reserve has W set > # The assumption that having an itemnumber set means waiting is wrong and should be corrected any place it occurs > my $query = qq/ >- SELECT borrowernumber, reservedate, constrainttype >+ SELECT borrowernumber, reservedate, constrainttype, reservenumber > FROM reserves > WHERE biblionumber = ? > AND ((found <> 'W' AND found <> 'T') or found is NULL) >@@ -1503,16 +1770,15 @@ sub _FixPriority { > $query = " > UPDATE reserves > SET priority = ? >- WHERE biblionumber = ? >- AND borrowernumber = ? >+ WHERE reservenumber = ? > AND reservedate = ? > AND found IS NULL > "; > $sth = $dbh->prepare($query); > for ( my $j = 0 ; $j < @priority ; $j++ ) { > $sth->execute( >- $j + 1, $biblio, >- $priority[$j]->{'borrowernumber'}, >+ $j + 1, >+ $priority[$j]->{'reservenumber'}, > $priority[$j]->{'reservedate'} > ); > $sth->finish; >@@ -1552,15 +1818,16 @@ sub _Findgroupreserve { > # TODO: consolidate at least the SELECT portion of the first 2 queries to a common $select var. > # check for exact targetted match > my $item_level_target_query = qq/ >- SELECT reserves.biblionumber AS biblionumber, >- reserves.borrowernumber AS borrowernumber, >- reserves.reservedate AS reservedate, >- reserves.branchcode AS branchcode, >- reserves.cancellationdate AS cancellationdate, >- reserves.found AS found, >- reserves.reservenotes AS reservenotes, >- reserves.priority AS priority, >- reserves.timestamp AS timestamp, >+ SELECT reserves.reservenumber AS reservenumber, >+ reserves.biblionumber AS biblionumber, >+ reserves.borrowernumber AS borrowernumber, >+ reserves.reservedate AS reservedate, >+ reserves.branchcode AS branchcode, >+ reserves.cancellationdate AS cancellationdate, >+ reserves.found AS found, >+ reserves.reservenotes AS reservenotes, >+ reserves.priority AS priority, >+ reserves.timestamp AS timestamp, > biblioitems.biblioitemnumber AS biblioitemnumber, > reserves.itemnumber AS itemnumber > FROM reserves >@@ -1582,15 +1849,16 @@ sub _Findgroupreserve { > > # check for title-level targetted match > my $title_level_target_query = qq/ >- SELECT reserves.biblionumber AS biblionumber, >- reserves.borrowernumber AS borrowernumber, >- reserves.reservedate AS reservedate, >- reserves.branchcode AS branchcode, >- reserves.cancellationdate AS cancellationdate, >- reserves.found AS found, >- reserves.reservenotes AS reservenotes, >- reserves.priority AS priority, >- reserves.timestamp AS timestamp, >+ SELECT reserves.reservenumber AS reservenumber, >+ reserves.biblionumber AS biblionumber, >+ reserves.borrowernumber AS borrowernumber, >+ reserves.reservedate AS reservedate, >+ reserves.branchcode AS branchcode, >+ reserves.cancellationdate AS cancellationdate, >+ reserves.found AS found, >+ reserves.reservenotes AS reservenotes, >+ reserves.priority AS priority, >+ reserves.timestamp AS timestamp, > biblioitems.biblioitemnumber AS biblioitemnumber, > reserves.itemnumber AS itemnumber > FROM reserves >@@ -1611,16 +1879,16 @@ sub _Findgroupreserve { > return @results if @results; > > my $query = qq/ >- SELECT reserves.biblionumber AS biblionumber, >- reserves.borrowernumber AS borrowernumber, >- reserves.reservedate AS reservedate, >- reserves.waitingdate AS waitingdate, >- reserves.branchcode AS branchcode, >- reserves.cancellationdate AS cancellationdate, >- reserves.found AS found, >- reserves.reservenotes AS reservenotes, >- reserves.priority AS priority, >- reserves.timestamp AS timestamp, >+ SELECT reserves.reservenumber AS reservenumber, >+ reserves.biblionumber AS biblionumber, >+ reserves.borrowernumber AS borrowernumber, >+ reserves.reservedate AS reservedate, >+ reserves.branchcode AS branchcode, >+ reserves.cancellationdate AS cancellationdate, >+ reserves.found AS found, >+ reserves.reservenotes AS reservenotes, >+ reserves.priority AS priority, >+ reserves.timestamp AS timestamp, > reserveconstraints.biblioitemnumber AS biblioitemnumber, > reserves.itemnumber AS itemnumber > FROM reserves >@@ -1652,30 +1920,29 @@ ModReserveAffect, _not_ ModReserveFill) > =cut > > sub _koha_notify_reserve { >- my ($itemnumber, $borrowernumber, $biblionumber) = @_; >+ my ($itemnumber, $borrowernumber, $biblionumber, $reservenumber) = @_; > >- my $dbh = C4::Context->dbh; >- my $borrower = C4::Members::GetMember(borrowernumber => $borrowernumber); >+ my $dbh = C4::Context->dbh; >+ my $borrower = C4::Members::GetMember( 'borrowernumber'=> $borrowernumber ); > my $letter_code; > my $print_mode = 0; > my $messagingprefs; >- if ( $borrower->{'email'} || $borrower->{'smsalertnumber'} ) { >+ if ( C4::Members::GetFirstValidEmailAddress($borrowernumber) || $borrower->{'smsalertnumber'} ) { > $messagingprefs = C4::Members::Messaging::GetMessagingPreferences( { borrowernumber => $borrowernumber, message_name => 'Hold Filled' } ); > > return if ( !defined( $messagingprefs->{'letter_code'} ) ); > $letter_code = $messagingprefs->{'letter_code'}; > } else { >- $letter_code = 'HOLD_PRINT'; >+ $letter_code = 'HOLD'; > $print_mode = 1; > } > > my $sth = $dbh->prepare(" > SELECT * > FROM reserves >- WHERE borrowernumber = ? >- AND biblionumber = ? >+ WHERE reservenumber = ? > "); >- $sth->execute( $borrowernumber, $biblionumber ); >+ $sth->execute( $reservenumber ); > my $reserve = $sth->fetchrow_hashref; > my $branch_details = GetBranchDetail( $reserve->{'branchcode'} ); > >@@ -1688,6 +1955,7 @@ sub _koha_notify_reserve { > C4::Letters::parseletter( $letter, 'borrowers', $borrowernumber ); > C4::Letters::parseletter( $letter, 'biblio', $biblionumber ); > C4::Letters::parseletter( $letter, 'reserves', $borrowernumber, $biblionumber ); >+ C4::Letters::parseletter( $letter, 'items', $itemnumber ); > > if ( $reserve->{'itemnumber'} ) { > C4::Letters::parseletter( $letter, 'items', $reserve->{'itemnumber'} ); >diff --git a/admin/branch_transfer_limits.pl b/admin/branch_transfer_limits.pl >index 64d2a70..4f8c080 100755 >--- a/admin/branch_transfer_limits.pl >+++ b/admin/branch_transfer_limits.pl >@@ -91,13 +91,13 @@ while ( my $row = $sth->fetchrow_hashref ) { > > ## If Form Data Passed, Update the Database > if ( $input->param('updateLimits') ) { >- DeleteBranchTransferLimits(); >+ DeleteBranchTransferLimits($branchcode); > > foreach my $code ( @codes ) { >- foreach my $toBranch ( @branchcodes ) { >- my $isSet = not $input->param( $code . "_" . $toBranch); >+ foreach my $fromBranch ( @branchcodes ) { >+ my $isSet = not $input->param( $code . "_" . $fromBranch); > if ( $isSet ) { >- CreateBranchTransferLimit( $toBranch, $branchcode, $code ); >+ CreateBranchTransferLimit( $branchcode, $fromBranch, $code ); > } > } > } >@@ -115,18 +115,18 @@ my $branchcount = scalar(@branchcode_loop); > ## Build the default data > my @codes_loop; > foreach my $code ( @codes ) { >- my @to_branch_loop; >+ my @from_branch_loop; > my %row_data; > $row_data{ code } = $code; >- $row_data{ to_branch_loop } = \@to_branch_loop; >- foreach my $toBranch ( @branchcodes ) { >+ $row_data{ from_branch_loop } = \@from_branch_loop; >+ foreach my $fromBranch ( @branchcodes ) { > my %row_data; >- my $isChecked = IsBranchTransferAllowed( $toBranch, $branchcode, $code ); >+ my $isChecked = IsBranchTransferAllowed( $branchcode, $fromBranch, $code ); > $row_data{ code } = $code; >- $row_data{ toBranch } = $toBranch; >+ $row_data{ fromBranch } = $fromBranch; > $row_data{ isChecked } = $isChecked; >- $row_data{ toBranchname } = GetBranchName($toBranch); >- push( @to_branch_loop, \%row_data ); >+ $row_data{ fromBranchname } = GetBranchName($fromBranch); >+ push( @from_branch_loop, \%row_data ); > } > > push( @codes_loop, \%row_data ); >diff --git a/admin/smart-rules.pl b/admin/smart-rules.pl >index d015ec2..1388104 100755 >--- a/admin/smart-rules.pl >+++ b/admin/smart-rules.pl >@@ -25,317 +25,32 @@ use C4::Output; > use C4::Auth; > use C4::Koha; > use C4::Debug; >-use C4::Branch; # GetBranches >+use C4::Branch; >+use C4::IssuingRules; >+use C4::Circulation; > > my $input = new CGI; > my $dbh = C4::Context->dbh; > >-# my $flagsrequired; >-# $flagsrequired->{circulation}=1; >-my ($template, $loggedinuser, $cookie) >- = get_template_and_user({template_name => "admin/smart-rules.tmpl", >- query => $input, >- type => "intranet", >- authnotrequired => 0, >- flagsrequired => {parameters => 1}, >- debug => 1, >- }); >- >-my $type=$input->param('type'); >-my $branch = $input->param('branch') || ( C4::Branch::onlymine() ? ( C4::Branch::mybranch() || '*' ) : '*' ); >-my $op = $input->param('op'); >- >-if ($op eq 'delete') { >- my $itemtype = $input->param('itemtype'); >- my $categorycode = $input->param('categorycode'); >- $debug and warn "deleting $1 $2 $branch"; >- >- my $sth_Idelete = $dbh->prepare("delete from issuingrules where branchcode=? and categorycode=? and itemtype=?"); >- $sth_Idelete->execute($branch, $categorycode, $itemtype); >-} >-elsif ($op eq 'delete-branch-cat') { >- my $categorycode = $input->param('categorycode'); >- if ($branch eq "*") { >- if ($categorycode eq "*") { >- my $sth_delete = $dbh->prepare("DELETE FROM default_circ_rules"); >- $sth_delete->execute(); >- } else { >- my $sth_delete = $dbh->prepare("DELETE FROM default_borrower_circ_rules >- WHERE categorycode = ?"); >- $sth_delete->execute($categorycode); >- } >- } elsif ($categorycode eq "*") { >- my $sth_delete = $dbh->prepare("DELETE FROM default_branch_circ_rules >- WHERE branchcode = ?"); >- $sth_delete->execute($branch); >- } else { >- my $sth_delete = $dbh->prepare("DELETE FROM branch_borrower_circ_rules >- WHERE branchcode = ? >- AND categorycode = ?"); >- $sth_delete->execute($branch, $categorycode); >- } >-} >-elsif ($op eq 'delete-branch-item') { >- my $itemtype = $input->param('itemtype'); >- if ($branch eq "*") { >- if ($itemtype eq "*") { >- my $sth_delete = $dbh->prepare("DELETE FROM default_circ_rules"); >- $sth_delete->execute(); >- } else { >- my $sth_delete = $dbh->prepare("DELETE FROM default_branch_item_rules >- WHERE itemtype = ?"); >- $sth_delete->execute($itemtype); >- } >- } elsif ($itemtype eq "*") { >- my $sth_delete = $dbh->prepare("DELETE FROM default_branch_circ_rules >- WHERE branchcode = ?"); >- $sth_delete->execute($branch); >- } else { >- my $sth_delete = $dbh->prepare("DELETE FROM branch_item_rules >- WHERE branchcode = ? >- AND itemtype = ?"); >- $sth_delete->execute($branch, $itemtype); >- } >-} >-# 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, fine, finedays, firstremind, chargeperiod,rentaldiscount) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)"); >- my $sth_update=$dbh->prepare("UPDATE issuingrules SET fine=?, finedays=?, firstremind=?, chargeperiod=?, maxissueqty=?, renewalsallowed=?, reservesallowed=?, issuelength=?, rentaldiscount=? WHERE branchcode=? AND categorycode=? AND itemtype=?"); >- >- my $br = $branch; # branch >- my $bor = $input->param('categorycode'); # borrower category >- my $cat = $input->param('itemtype'); # item type >- my $fine = $input->param('fine'); >- my $finedays = $input->param('finedays'); >- my $firstremind = $input->param('firstremind'); >- my $chargeperiod = $input->param('chargeperiod'); >- my $maxissueqty = $input->param('maxissueqty'); >- my $renewalsallowed = $input->param('renewalsallowed'); >- my $reservesallowed = $input->param('reservesallowed'); >- $maxissueqty =~ s/\s//g; >- $maxissueqty = undef if $maxissueqty !~ /^\d+/; >- my $issuelength = $input->param('issuelength'); >- my $rentaldiscount = $input->param('rentaldiscount'); >- $debug and warn "Adding $br, $bor, $cat, $fine, $maxissueqty"; >- >- $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,$rentaldiscount, $br,$bor,$cat); >- } else { >- $sth_insert->execute($br,$bor,$cat,$maxissueqty,$renewalsallowed,$reservesallowed,$issuelength,$fine,$finedays,$firstremind,$chargeperiod,$rentaldiscount); >- } >-} >-elsif ($op eq "set-branch-defaults") { >- my $categorycode = $input->param('categorycode'); >- my $maxissueqty = $input->param('maxissueqty'); >- my $holdallowed = $input->param('holdallowed'); >- $maxissueqty =~ s/\s//g; >- $maxissueqty = undef if $maxissueqty !~ /^\d+/; >- $holdallowed =~ s/\s//g; >- $holdallowed = undef if $holdallowed !~ /^\d+/; >- >- if ($branch eq "*") { >- my $sth_search = $dbh->prepare("SELECT count(*) AS total >- FROM default_circ_rules"); >- my $sth_insert = $dbh->prepare("INSERT INTO default_circ_rules >- (maxissueqty, holdallowed) >- VALUES (?, ?)"); >- my $sth_update = $dbh->prepare("UPDATE default_circ_rules >- SET maxissueqty = ?, holdallowed = ?"); >- >- $sth_search->execute(); >- my $res = $sth_search->fetchrow_hashref(); >- if ($res->{total}) { >- $sth_update->execute($maxissueqty, $holdallowed); >- } else { >- $sth_insert->execute($maxissueqty, $holdallowed); >- } >- } else { >- my $sth_search = $dbh->prepare("SELECT count(*) AS total >- FROM default_branch_circ_rules >- WHERE branchcode = ?"); >- my $sth_insert = $dbh->prepare("INSERT INTO default_branch_circ_rules >- (branchcode, maxissueqty, holdallowed) >- VALUES (?, ?, ?)"); >- my $sth_update = $dbh->prepare("UPDATE default_branch_circ_rules >- SET maxissueqty = ?, holdallowed = ? >- WHERE branchcode = ?"); >- $sth_search->execute($branch); >- my $res = $sth_search->fetchrow_hashref(); >- if ($res->{total}) { >- $sth_update->execute($maxissueqty, $holdallowed, $branch); >- } else { >- $sth_insert->execute($branch, $maxissueqty, $holdallowed); >- } >- } >-} >-elsif ($op eq "add-branch-cat") { >- my $categorycode = $input->param('categorycode'); >- my $maxissueqty = $input->param('maxissueqty'); >- $maxissueqty =~ s/\s//g; >- $maxissueqty = undef if $maxissueqty !~ /^\d+/; >- >- if ($branch eq "*") { >- if ($categorycode eq "*") { >- my $sth_search = $dbh->prepare("SELECT count(*) AS total >- FROM default_circ_rules"); >- my $sth_insert = $dbh->prepare("INSERT INTO default_circ_rules >- (maxissueqty) >- VALUES (?)"); >- my $sth_update = $dbh->prepare("UPDATE default_circ_rules >- SET maxissueqty = ?"); >- >- $sth_search->execute(); >- my $res = $sth_search->fetchrow_hashref(); >- if ($res->{total}) { >- $sth_update->execute($maxissueqty); >- } else { >- $sth_insert->execute($maxissueqty); >- } >- } else { >- my $sth_search = $dbh->prepare("SELECT count(*) AS total >- FROM default_borrower_circ_rules >- WHERE categorycode = ?"); >- my $sth_insert = $dbh->prepare("INSERT INTO default_borrower_circ_rules >- (categorycode, maxissueqty) >- VALUES (?, ?)"); >- my $sth_update = $dbh->prepare("UPDATE default_borrower_circ_rules >- SET maxissueqty = ? >- WHERE categorycode = ?"); >- $sth_search->execute($branch); >- my $res = $sth_search->fetchrow_hashref(); >- if ($res->{total}) { >- $sth_update->execute($maxissueqty, $categorycode); >- } else { >- $sth_insert->execute($categorycode, $maxissueqty); >- } >- } >- } elsif ($categorycode eq "*") { >- my $sth_search = $dbh->prepare("SELECT count(*) AS total >- FROM default_branch_circ_rules >- WHERE branchcode = ?"); >- my $sth_insert = $dbh->prepare("INSERT INTO default_branch_circ_rules >- (branchcode, maxissueqty) >- VALUES (?, ?)"); >- my $sth_update = $dbh->prepare("UPDATE default_branch_circ_rules >- SET maxissueqty = ? >- WHERE branchcode = ?"); >- $sth_search->execute($branch); >- my $res = $sth_search->fetchrow_hashref(); >- if ($res->{total}) { >- $sth_update->execute($maxissueqty, $branch); >- } else { >- $sth_insert->execute($branch, $maxissueqty); >- } >- } else { >- my $sth_search = $dbh->prepare("SELECT count(*) AS total >- FROM branch_borrower_circ_rules >- WHERE branchcode = ? >- AND categorycode = ?"); >- my $sth_insert = $dbh->prepare("INSERT INTO branch_borrower_circ_rules >- (branchcode, categorycode, maxissueqty) >- VALUES (?, ?, ?)"); >- my $sth_update = $dbh->prepare("UPDATE branch_borrower_circ_rules >- SET maxissueqty = ? >- WHERE branchcode = ? >- AND categorycode = ?"); >- >- $sth_search->execute($branch, $categorycode); >- my $res = $sth_search->fetchrow_hashref(); >- if ($res->{total}) { >- $sth_update->execute($maxissueqty, $branch, $categorycode); >- } else { >- $sth_insert->execute($branch, $categorycode, $maxissueqty); >- } >- } >-} >-elsif ($op eq "add-branch-item") { >- my $itemtype = $input->param('itemtype'); >- my $holdallowed = $input->param('holdallowed'); >- $holdallowed =~ s/\s//g; >- $holdallowed = undef if $holdallowed !~ /^\d+/; >- >- if ($branch eq "*") { >- if ($itemtype eq "*") { >- my $sth_search = $dbh->prepare("SELECT count(*) AS total >- FROM default_circ_rules"); >- my $sth_insert = $dbh->prepare("INSERT INTO default_circ_rules >- (holdallowed) >- VALUES (?)"); >- my $sth_update = $dbh->prepare("UPDATE default_circ_rules >- SET holdallowed = ?"); >- >- $sth_search->execute(); >- my $res = $sth_search->fetchrow_hashref(); >- if ($res->{total}) { >- $sth_update->execute($holdallowed); >- } else { >- $sth_insert->execute($holdallowed); >- } >- } else { >- my $sth_search = $dbh->prepare("SELECT count(*) AS total >- FROM default_branch_item_rules >- WHERE itemtype = ?"); >- my $sth_insert = $dbh->prepare("INSERT INTO default_branch_item_rules >- (itemtype, holdallowed) >- VALUES (?, ?)"); >- my $sth_update = $dbh->prepare("UPDATE default_branch_item_rules >- SET holdallowed = ? >- WHERE itemtype = ?"); >- $sth_search->execute($itemtype); >- my $res = $sth_search->fetchrow_hashref(); >- if ($res->{total}) { >- $sth_update->execute($holdallowed, $itemtype); >- } else { >- $sth_insert->execute($itemtype, $holdallowed); >- } >- } >- } elsif ($itemtype eq "*") { >- my $sth_search = $dbh->prepare("SELECT count(*) AS total >- FROM default_branch_circ_rules >- WHERE branchcode = ?"); >- my $sth_insert = $dbh->prepare("INSERT INTO default_branch_circ_rules >- (branchcode, holdallowed) >- VALUES (?, ?)"); >- my $sth_update = $dbh->prepare("UPDATE default_branch_circ_rules >- SET holdallowed = ? >- WHERE branchcode = ?"); >- $sth_search->execute($branch); >- my $res = $sth_search->fetchrow_hashref(); >- if ($res->{total}) { >- $sth_update->execute($holdallowed, $branch); >- } else { >- $sth_insert->execute($branch, $holdallowed); >- } >- } else { >- my $sth_search = $dbh->prepare("SELECT count(*) AS total >- FROM branch_item_rules >- WHERE branchcode = ? >- AND itemtype = ?"); >- my $sth_insert = $dbh->prepare("INSERT INTO branch_item_rules >- (branchcode, itemtype, holdallowed) >- VALUES (?, ?, ?)"); >- my $sth_update = $dbh->prepare("UPDATE branch_item_rules >- SET holdallowed = ? >- WHERE branchcode = ? >- AND itemtype = ?"); >- >- $sth_search->execute($branch, $itemtype); >- my $res = $sth_search->fetchrow_hashref(); >- if ($res->{total}) { >- $sth_update->execute($holdallowed, $branch, $itemtype); >- } else { >- $sth_insert->execute($branch, $itemtype, $holdallowed); >- } >- } >-} >- >+my ($template, $loggedinuser, $cookie) = get_template_and_user({ >+ template_name => "admin/smart-rules.tmpl", >+ query => $input, >+ type => "intranet", >+ authnotrequired => 0, >+ flagsrequired => {parameters => 1}, >+ debug => 1, >+}); >+ >+my $type = $input->param('type'); >+my $branchcode = $input->param('branchcode') || ( C4::Branch::onlymine() ? ( C4::Branch::mybranch() || '*' ) : '*' ); >+my $op = $input->param('op'); >+my $confirm = $input->param('confirm'); >+ >+# This block builds the branch list > my $branches = GetBranches(); > my @branchloop; >-for my $thisbranch (sort { $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname} } keys %$branches) { >- my $selected = 1 if $thisbranch eq $branch; >+for my $thisbranch (sort { $branches->{$a}->{'branchname'} cmp $branches->{$b}->{'branchname'} } keys %$branches) { >+ my $selected = 1 if $thisbranch eq $branchcode; > my %row =(value => $thisbranch, > selected => $selected, > branchname => $branches->{$thisbranch}->{'branchname'}, >@@ -343,177 +58,115 @@ for my $thisbranch (sort { $branches->{$a}->{branchname} cmp $branches->{$b}->{b > push @branchloop, \%row; > } > >-my $sth=$dbh->prepare("SELECT description,categorycode FROM categories ORDER BY description"); >-$sth->execute; >-my @category_loop; >-while (my $data=$sth->fetchrow_hashref){ >- push @category_loop,$data; >-} >- >-$sth->finish; >-$sth=$dbh->prepare("SELECT description,itemtype FROM itemtypes ORDER BY description"); >-$sth->execute; >-# $i=0; >-my @row_loop; >-my @itemtypes; >-while (my $row=$sth->fetchrow_hashref){ >- push @itemtypes,$row; >-} >+# Get the patron category list >+my @category_loop = C4::Category->all; > >-my $sth2 = $dbh->prepare(" >- SELECT issuingrules.*, itemtypes.description AS humanitemtype, categories.description AS humancategorycode >- FROM issuingrules >- LEFT JOIN itemtypes >- ON (itemtypes.itemtype = issuingrules.itemtype) >- LEFT JOIN categories >- ON (categories.categorycode = issuingrules.categorycode) >- WHERE issuingrules.branchcode = ? >-"); >-$sth2->execute($branch); >+# Get the item types list >+my @itemtypes = C4::ItemType->all; > >-while (my $row = $sth2->fetchrow_hashref) { >- $row->{'humanitemtype'} ||= $row->{'itemtype'}; >- $row->{'default_humanitemtype'} = 1 if $row->{'humanitemtype'} eq '*'; >- $row->{'humancategorycode'} ||= $row->{'categorycode'}; >- $row->{'default_humancategorycode'} = 1 if $row->{'humancategorycode'} eq '*'; >- $row->{'fine'} = sprintf('%.2f', $row->{'fine'}); >- push @row_loop, $row; >+if ( $op eq 'delete' ) { >+ DelIssuingRule({ >+ branchcode => $branchcode, >+ categorycode => $input->param('categorycode'), >+ itemtype => $input->param('itemtype'), >+ }); > } >-$sth->finish; >- >-my @sorted_row_loop = sort by_category_and_itemtype @row_loop; >+# save the values entered >+elsif ( $op eq 'add' ) { > >-my $sth_branch_cat; >-if ($branch eq "*") { >- $sth_branch_cat = $dbh->prepare(" >- SELECT default_borrower_circ_rules.*, categories.description AS humancategorycode >- FROM default_borrower_circ_rules >- JOIN categories USING (categorycode) >- >- "); >- $sth_branch_cat->execute(); >-} else { >- $sth_branch_cat = $dbh->prepare(" >- SELECT branch_borrower_circ_rules.*, categories.description AS humancategorycode >- FROM branch_borrower_circ_rules >- JOIN categories USING (categorycode) >- WHERE branch_borrower_circ_rules.branchcode = ? >- "); >- $sth_branch_cat->execute($branch); >-} >+ # Converts '' to undef, so we can have NULL in database fields >+ my $issuingrule; >+ for ( $input->param ) { >+ my $v = $input->param($_); >+ $issuingrule->{$_} = length $v ? $v : undef; >+ } > >-my @branch_cat_rules = (); >-while (my $row = $sth_branch_cat->fetchrow_hashref) { >- push @branch_cat_rules, $row; >+ # We don't want op to be passed to the API >+ delete $issuingrule->{'op'}; >+ >+ # If the (branchcode,categorycode,itemtype) combination already exists... >+ my @issuingrules = GetIssuingRules({ >+ branchcode => $issuingrule->{'branchcode'}, >+ categorycode => $issuingrule->{'categorycode'}, >+ itemtype => $issuingrule->{'itemtype'}, >+ }); >+ >+ # ...we modify the existing rule... >+ if ( @issuingrules ) { >+ ModIssuingRule( $issuingrule ); >+# } elsif (@issuingrules){ >+# $template->param(confirm=>1); >+# $template->param(%$issuingrule); >+# foreach (@category_loop) { >+# $_->{selected}="selected" if ($_->{categorycode} eq $issuingrule->{categorycode}); >+# } >+# foreach (@itemtypes) { >+# $_->{selected}="selected" if ($_->{itemtype} eq $issuingrule->{itemtype}); >+# } >+ # ...else we add a new rule. >+ } else { >+ AddIssuingRule( $issuingrule ); >+ } > } >-my @sorted_branch_cat_rules = sort { $a->{'humancategorycode'} cmp $b->{'humancategorycode'} } @branch_cat_rules; > >-# note undef maxissueqty so that template can deal with them >-foreach my $entry (@sorted_branch_cat_rules, @sorted_row_loop) { >- $entry->{unlimited_maxissueqty} = 1 unless defined($entry->{maxissueqty}); >-} >+# Get the issuing rules list... >+my @issuingrules = GetIssuingRulesByBranchCode($branchcode); > >-my @sorted_row_loop = sort by_category_and_itemtype @row_loop; >+# ...and refine its data, row by row. >+for my $rule ( @issuingrules ) { >+ $rule->{'humanitemtype'} ||= $rule->{'itemtype'}; >+ $rule->{'default_humanitemtype'} = $rule->{'humanitemtype'} eq '*'; >+ $rule->{'humancategorycode'} ||= $rule->{'categorycode'}; >+ $rule->{'default_humancategorycode'} = $rule->{'humancategorycode'} eq '*'; > >-my $sth_branch_item; >-if ($branch eq "*") { >- $sth_branch_item = $dbh->prepare(" >- SELECT default_branch_item_rules.*, itemtypes.description AS humanitemtype >- FROM default_branch_item_rules >- JOIN itemtypes USING (itemtype) >- "); >- $sth_branch_item->execute(); >-} else { >- $sth_branch_item = $dbh->prepare(" >- SELECT branch_item_rules.*, itemtypes.description AS humanitemtype >- FROM branch_item_rules >- JOIN itemtypes USING (itemtype) >- WHERE branch_item_rules.branchcode = ? >- "); >- $sth_branch_item->execute($branch); >+ # This block is to show herited values in grey. >+ # We juste compare keys from our raw rule, with keys from the computed rule. >+ my $computedrule = GetIssuingRule($rule->{'categorycode'}, $rule->{'itemtype'}, $rule->{'branchcode'}); >+ for ( keys %$rule ) { >+ if ( not defined $rule->{$_} ) { >+ $rule->{$_} = $computedrule->{$_}; >+ $rule->{"herited_$_"} = 1; >+ } >+ } > } > >-my @branch_item_rules = (); >-while (my $row = $sth_branch_item->fetchrow_hashref) { >- push @branch_item_rules, $row; >-} >-my @sorted_branch_item_rules = sort { $a->{'humanitemtype'} cmp $b->{'humanitemtype'} } @branch_item_rules; >+# Get the issuing rules list... >+my @issuingrules = GetIssuingRulesByBranchCode($branchcode); > >-# note undef holdallowed so that template can deal with them >-foreach my $entry (@sorted_branch_item_rules) { >- $entry->{holdallowed_any} = 1 if($entry->{holdallowed} == 2); >- $entry->{holdallowed_same} = 1 if($entry->{holdallowed} == 1); >-} >+# ...and refine its data, row by row. >+for my $rule ( @issuingrules ) { >+ $rule->{'humanitemtype'} ||= $rule->{'itemtype'}; >+ $rule->{'default_humanitemtype'} = $rule->{'humanitemtype'} eq '*'; >+ $rule->{'humancategorycode'} ||= $rule->{'categorycode'}; >+ $rule->{'default_humancategorycode'} = $rule->{'humancategorycode'} eq '*'; > >-$template->param(show_branch_cat_rule_form => 1); >-$template->param(branch_item_rule_loop => \@sorted_branch_item_rules); >-$template->param(branch_cat_rule_loop => \@sorted_branch_cat_rules); >+ # This block is to show herited values in grey. >+ # We juste compare keys from our raw rule, with keys from the computed rule. >+ my $computedrule = GetIssuingRule($rule->{'categorycode'}, $rule->{'itemtype'}, $rule->{'branchcode'}); >+ for ( keys %$rule ) { >+ if ( not defined $rule->{$_} ) { >+ $rule->{$_} = $computedrule->{$_}; >+ $rule->{"herited_$_"} = 1; >+ } >+ } > >-my $sth_defaults; >-if ($branch eq "*") { >- $sth_defaults = $dbh->prepare(" >- SELECT * >- FROM default_circ_rules >- "); >- $sth_defaults->execute(); >-} else { >- $sth_defaults = $dbh->prepare(" >- SELECT * >- FROM default_branch_circ_rules >- WHERE branchcode = ? >- "); >- $sth_defaults->execute($branch); >+ $rule->{'fine'} = sprintf('%.2f', $rule->{'fine'}); > } > >-my $defaults = $sth_defaults->fetchrow_hashref; >- >-if ($defaults) { >- $template->param(default_holdallowed_none => 1) if($defaults->{holdallowed} == 0); >- $template->param(default_holdallowed_same => 1) if($defaults->{holdallowed} == 1); >- $template->param(default_holdallowed_any => 1) if($defaults->{holdallowed} == 2); >- $template->param(default_maxissueqty => $defaults->{maxissueqty}); >-} > > $template->param(default_rules => ($defaults ? 1 : 0)); > >-$template->param(categoryloop => \@category_loop, >- itemtypeloop => \@itemtypes, >- rules => \@sorted_row_loop, >- branchloop => \@branchloop, >- humanbranch => ($branch ne '*' ? $branches->{$branch}->{branchname} : ''), >- current_branch => $branch, >- definedbranch => scalar(@sorted_row_loop)>0 >- ); >+$template->param( >+ categoryloop => \@category_loop, >+ itemtypeloop => \@itemtypes, >+ rules => \@issuingrules, >+ branchloop => \@branchloop, >+ humanbranch => ($branchcode ne '*' ? $branches->{$branchcode}->{branchname} : ''), >+ branchcode => $branchcode, >+ definedbranch => scalar(@issuingrules) > 0, >+); >+ > output_html_with_http_headers $input, $cookie, $template->output; > > exit 0; > >-# sort by patron category, then item type, putting >-# default entries at the bottom >-sub by_category_and_itemtype { >- unless (by_category($a, $b)) { >- return by_itemtype($a, $b); >- } >-} >- >-sub by_category { >- my ($a, $b) = @_; >- if ($a->{'default_humancategorycode'}) { >- return ($b->{'default_humancategorycode'} ? 0 : 1); >- } elsif ($b->{'default_humancategorycode'}) { >- return -1; >- } else { >- return $a->{'humancategorycode'} cmp $b->{'humancategorycode'}; >- } >-} >- >-sub by_itemtype { >- my ($a, $b) = @_; >- if ($a->{'default_humanitemtype'}) { >- return ($b->{'default_humanitemtype'} ? 0 : 1); >- } elsif ($b->{'default_humanitemtype'}) { >- return -1; >- } else { >- return $a->{'humanitemtype'} cmp $b->{'humanitemtype'}; >- } >-} >diff --git a/circ/branchtransfers.pl b/circ/branchtransfers.pl >index ab38749..6374f71 100755 >--- a/circ/branchtransfers.pl >+++ b/circ/branchtransfers.pl >@@ -87,7 +87,9 @@ if ( $request eq "KillWaiting" ) { > } > elsif ( $request eq "SetWaiting" ) { > my $item = $query->param('itemnumber'); >- ModReserveAffect( $item, $borrowernumber ); >+ my $itemhash=C4::Items::GetItem($item); >+ my ( $reservetype, $reserve ) = C4::Reserves::CheckReserves( undef, $itemhash->{barcode} ); >+ ModReserveAffect( $item, $borrowernumber,$tobranchcd ne C4::Context->userenv->{'branch'}, $reserve->{reservenumber}); > $ignoreRs = 1; > $setwaiting = 1; > $reqmessage = 1; >diff --git a/circ/circulation.pl b/circ/circulation.pl >index f145f5c..40f3a70 100755 >--- a/circ/circulation.pl >+++ b/circ/circulation.pl >@@ -30,27 +30,33 @@ use C4::Dates qw/format_date/; > use C4::Branch; # GetBranches > use C4::Koha; # GetPrinter > use C4::Circulation; >+use C4::Overdues qw/CheckBorrowerDebarred/; > use C4::Members; > use C4::Biblio; > use C4::Reserves; > use C4::Context; >+use C4::Debug; > use CGI::Session; >- >+use C4::Items; >+use JSON; >+use YAML; > use Date::Calc qw( > Today > Add_Delta_YM > Add_Delta_Days > Date_to_Days > ); >+use List::MoreUtils qw/uniq/; > > > # > # PARAMETERS READING > # > my $query = new CGI; >- >-my $sessionID = $query->cookie("CGISESSID") ; >-my $session = get_session($sessionID); >+my $dbh = C4::Context->dbh; >+my $remotehost = $query->remote_host(); >+my $sessionID = $query->cookie("CGISESSID"); >+my $session = get_session($sessionID); > > # branch and printer are now defined by the userenv > # but first we have to check if someone has tried to change them >@@ -88,9 +94,14 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user ( > > my $branches = GetBranches(); > >-my @failedrenews = $query->param('failedrenew'); # expected to be itemnumbers >+my @failedrenews = $query->param('failedrenew'); # expected to be itemnumbers >+my @failedreturns = $query->param('failedreturn'); # expected to be barcodes >+my @renewerrors = $query->param('renewerror'); # expected to be json >+my @returnerrors = $query->param('returnerror'); # expected to be json > my %renew_failed; >-for (@failedrenews) { $renew_failed{$_} = 1; } >+my %return_failed; >+for (@failedrenews) { $renew_failed{$_} = decode_json(shift @renewerrors); } >+for (@failedreturns) { $return_failed{GetItemnumberFromBarcode($_)} = decode_json(shift @returnerrors); } > > my $findborrower = $query->param('findborrower'); > $findborrower =~ s|,| |g; >@@ -125,14 +136,13 @@ my $organisation = $query->param('organisations'); > my $print = $query->param('print'); > my $newexpiry = $query->param('dateexpiry'); > my $debt_confirmed = $query->param('debt_confirmed') || 0; # Don't show the debt error dialog twice >- >+$debug && warn $newexpiry; > # Check if stickyduedate is turned off > if ( $barcode ) { > # was stickyduedate loaded from session? > if ( $stickyduedate && ! $query->param("stickyduedate") ) { > $session->clear( 'stickyduedate' ); > $stickyduedate = $query->param('stickyduedate'); >- $duedatespec = $query->param('duedatespec'); > } > } > >@@ -169,7 +179,7 @@ if($duedatespec_allow){ > $datedue = $globalduedate if ($globalduedate); > } > >-my $todaysdate = C4::Dates->new->output('iso'); >+my $todaysdate = C4::Dates->new->output( 'iso' ); > > # check and see if we should print > if ( $barcode eq '' && $print eq 'maybe' ) { >@@ -231,8 +241,8 @@ if ($borrowernumber) { > > # Warningdate is the date that the warning starts appearing > my ( $today_year, $today_month, $today_day) = Today(); >- my ($warning_year, $warning_month, $warning_day) = split /-/, $borrower->{'dateexpiry'}; >- my ( $enrol_year, $enrol_month, $enrol_day) = split /-/, $borrower->{'dateenrolled'}; >+ my ($warning_year, $warning_month, $warning_day) = split (/-/, $borrower->{'dateexpiry'}); >+ my ( $enrol_year, $enrol_month, $enrol_day) = split (/-/, $borrower->{'dateenrolled'}); > # Renew day is calculated by adding the enrolment period to today > my ( $renew_year, $renew_month, $renew_day); > if ($enrol_year*$enrol_month*$enrol_day>0) { >@@ -250,6 +260,7 @@ if ($borrowernumber) { > flagged => "1", > noissues => "1", > expired => format_date($borrower->{dateexpiry}), >+ warning => 1, > renewaldate => format_date("$renew_year-$renew_month-$renew_day") > ); > } >@@ -260,9 +271,9 @@ if ($borrowernumber) { > { > # borrower card soon to expire warn librarian > $template->param("warndeparture" => format_date($borrower->{dateexpiry}), >- flagged => "1",); >+ flagged => "1", "warning" => 1); > if (C4::Context->preference('ReturnBeforeExpiry')){ >- $template->param("returnbeforeexpiry" => 1); >+ $template->param("returnbeforeexpiry" => 1, "warning => 1"); > } > } > $template->param( >@@ -270,12 +281,22 @@ if ($borrowernumber) { > issuecount => $issue, > finetotal => $fines > ); >+ >+ my $debar = CheckBorrowerDebarred($borrowernumber); >+ if($debar){ >+ $template->param(userdebarred => 1); >+ $template->param(debarredcomment => $borrower->{debarredcomment}); >+ if( $debar ne "9999-12-31"){ >+ $template->param(userdebarreddate => C4::Dates::format_date($debar)); >+ } >+ } > } > > # > # STEP 3 : ISSUING > # > # >+my $confirm_required = 0; > if ($barcode) { > # always check for blockers on issuing > my ( $error, $question ) = >@@ -321,8 +342,33 @@ if ($barcode) { > # FIXME If the issue is confirmed, we launch another time GetMemberIssuesAndFines, now display the issue count after issue > my ( $od, $issue, $fines ) = GetMemberIssuesAndFines( $borrowernumber ); > $template->param( issuecount => $issue ); >+ >+ # Is there a circulation note? >+ my $itemnumber = GetItemnumberFromBarcode($barcode); >+ my $biblionumber = GetBiblionumberFromItemnumber($itemnumber); >+ my $record = GetMarcBiblio($biblionumber); >+ my $frameworkcode = GetFrameworkCode($biblionumber); >+ my $circnotefield = GetRecordValue('circnote', $record, $frameworkcode); >+ if (defined @$circnotefield[0]) { >+ $template->param(circnote => @$circnotefield[0]->{'subfield'}); >+ } > } > >+ >+# Setting the right status if an hold has been confirmed >+#This should never be used in fact >+my $resbarcode = $query->param("resbarcode"); >+if ($resbarcode) { >+ if ( my ( $reservetype, $reserve ) = C4::Reserves::CheckReserves( undef, $resbarcode ) ) { >+ if ( $reservetype eq "Waiting" || $reservetype eq "Reserved" ) { >+ my $transfer = C4::Context->userenv->{branch} ne $reserve->{branchcode}; >+ ModReserveAffect( $reserve->{itemnumber}, $reserve->{borrowernumber}, $transfer, $reserve->{"reservenumber"} ); >+ } >+ } >+} >+ >+ >+ > # reload the borrower info for the sake of reseting the flags..... > if ($borrowernumber) { > $borrower = GetMemberDetails( $borrowernumber, 0 ); >@@ -360,11 +406,18 @@ if ($borrowernumber) { > $getreserv{itemcallnumber} = $getiteminfo->{'itemcallnumber'}; > $getreserv{biblionumber} = $getiteminfo->{'biblionumber'}; > $getreserv{waitingat} = GetBranchName( $num_res->{'branchcode'} ); >+ my $materials = $getiteminfo->{'materials'}; >+ $template->param(materials => $materials); > # check if we have a waiting status for reservations > if ( $num_res->{'found'} eq 'W' ) { > $getreserv{color} = 'reserved'; > $getreserv{waiting} = 1; > # genarate information displaying only waiting reserves >+ my @maxpickupdate = $num_res->{'waitingdate'} ? GetMaxPickupDate( $num_res->{'waitingdate'}, $borrowernumber, $num_res ) : ''; >+ $getreserv{'maxpickupdate'} = sprintf( "%d-%02d-%02d", @maxpickupdate ); >+ $getWaitingReserveInfo{'formattedwaitingdate'} = format_date( $getreserv{'maxpickupdate'} ); >+ $getreserv{'formattedwaitingdate'} = format_date( $getreserv{'maxpickupdate'} ); >+ > $getWaitingReserveInfo{title} = $getiteminfo->{'title'}; > $getWaitingReserveInfo{biblionumber} = $getiteminfo->{'biblionumber'}; > $getWaitingReserveInfo{itemtype} = $itemtypeinfo->{'description'}; >@@ -420,51 +473,97 @@ my $previssues = ''; > my @todaysissues; > my @previousissues; > >+my @borrowers_with_issues; >+my @relissues; >+my @relprevissues; >+my $displayrelissues; >+## ADDED BY JF: new itemtype issuingrules counter stuff >+my $issued_itemtypes_count; >+my @issued_itemtypes_count_loop; >+ > my $totalprice = 0; > >-if ($borrower) { >-# get each issue of the borrower & separate them in todayissues & previous issues >- my ($issueslist) = GetPendingIssues($borrower->{'borrowernumber'}); >- # split in 2 arrays for today & previous >- foreach my $it ( @$issueslist ) { >- my $itemtypeinfo = getitemtypeinfo( (C4::Context->preference('item-level_itypes')) ? $it->{'itype'} : $it->{'itemtype'} ); >- # set itemtype per item-level_itype syspref - FIXME this is an ugly hack >- $it->{'itemtype'} = ( C4::Context->preference( 'item-level_itypes' ) ) ? $it->{'itype'} : $it->{'itemtype'}; >+sub build_issue_data { >+ my $issueslist = shift; >+ my $relatives = shift; > >- ($it->{'charge'}, $it->{'itemtype_charge'}) = GetIssuingCharges( >- $it->{'itemnumber'}, $borrower->{'borrowernumber'} >- ); >- $it->{'charge'} = sprintf("%.2f", $it->{'charge'}); >- my ($can_renew, $can_renew_error) = CanBookBeRenewed( >- $borrower->{'borrowernumber'},$it->{'itemnumber'} >- ); >- $it->{"renew_error_${can_renew_error}"} = 1 if defined $can_renew_error; >+ # split in 2 arrays for today & previous >+ foreach my $it (@$issueslist) { >+ my $itemtypeinfo = getitemtypeinfo( ( C4::Context->preference('item-level_itypes') ) ? $it->{'itype'} : $it->{'itemtype'} ); >+ >+ # Getting borrower details >+ my $memberdetails = GetMemberDetails($it->{'borrowernumber'}); >+ $it->{'borrowername'} = $memberdetails->{'firstname'} . " " . $memberdetails->{'surname'}; >+ >+ # set itemtype per item-level_itype syspref - FIXME this is an ugly hack >+ $it->{'itemtype'} = ( C4::Context->preference('item-level_itypes') ) ? $it->{'itype'} : $it->{'itemtype'}; >+ >+ ( $it->{'charge'}, $it->{'itemtype_charge'} ) = GetIssuingCharges( $it->{'itemnumber'}, $borrower->{'borrowernumber'} ); >+ $it->{'charge'} = sprintf( "%.2f", $it->{'charge'} ); >+ my ( $can_renew, $can_renew_error ) = CanBookBeRenewed( $borrower->{'borrowernumber'}, $it->{'itemnumber'} ); >+ if ( defined $can_renew_error->{message} ) { >+ $it->{ "renew_error_" . $can_renew_error->{message} } = 1; >+ $it->{'renew_error'} = 1; >+ } >+ $it->{renewals} ||= 0; >+ $it->{$_} = $can_renew_error->{$_} for (qw(renewalsallowed reserves)); > my ( $restype, $reserves ) = CheckReserves( $it->{'itemnumber'} ); >- $it->{'can_renew'} = $can_renew; >- $it->{'can_confirm'} = !$can_renew && !$restype; >- $it->{'renew_error'} = $restype; >- $it->{'checkoutdate'} = C4::Dates->new($it->{'issuedate'},'iso')->output('syspref'); >+ if ($restype) { >+ $it->{'reserved'} = 1; >+ $it->{$restype} = 1; >+ } >+ $it->{'can_renew'} = $can_renew; >+ $it->{'can_confirm'} = !$can_renew && !$restype; >+ $it->{'renew_error'} = $restype; >+ $it->{'checkoutdate'} = $it->{'issuedate'}; > > $totalprice += $it->{'replacementprice'}; >- $it->{'itemtype'} = $itemtypeinfo->{'description'}; >+ $it->{'itemtype'} = $itemtypeinfo->{'description'}; > $it->{'itemtype_image'} = $itemtypeinfo->{'imageurl'}; >- $it->{'dd'} = format_date($it->{'date_due'}); >- $it->{'displaydate'} = format_date($it->{'issuedate'}); >- $it->{'od'} = ( $it->{'date_due'} lt $todaysdate ) ? 1 : 0 ; >- ($it->{'author'} eq '') and $it->{'author'} = ' '; >- $it->{'renew_failed'} = $renew_failed{$it->{'itemnumber'}}; >- >- if ( $todaysdate eq $it->{'issuedate'} or $todaysdate eq $it->{'lastreneweddate'} ) { >- push @todaysissues, $it; >- } else { >- push @previousissues, $it; >+ $it->{'dd'} = format_date( $it->{'date_due'} ); >+ $it->{'displaydate'} = format_date( $it->{'issuedate'} ); >+ ( $it->{'author'} eq '' ) and $it->{'author'} = ' '; >+ if ( defined( $return_failed{ $it->{'itemnumber'} } ) ) { >+ $it->{ 'return_error_' . $return_failed{ $it->{'itemnumber'} }->{message} } = 1; >+ delete $return_failed{ $it->{'itemnumber'} }; > } >+ if ( defined( $renew_failed{ $it->{'itemnumber'} } ) ) { >+ $it->{ 'renew_error_' . $renew_failed{ $it->{'itemnumber'} }->{message} } = 1; >+ } >+ $it->{'return_failed'} = defined( $return_failed{ $it->{'itemnumber'} } ); >+ $it->{'branchdisplay'} = GetBranchName( ( C4::Context->preference('HomeOrHoldingBranch') eq 'holdingbranch' ) ? $it->{'holdingbranch'} : $it->{'homebranch'} ); >+ >+ # ADDED BY JF: NEW ITEMTYPE COUNT DISPLAY >+ $issued_itemtypes_count->{ $it->{'itemtype'} }++; >+ if ( $todaysdate eq $it->{'checkoutdate'} or $todaysdate eq $it->{'lastreneweddate'} ) { >+ (!$relatives) ? push @todaysissues, $it : push @relissues, $it; >+ } else { >+ (!$relatives) ? push @previousissues, $it : push @relprevissues, $it; >+ } >+ > } >- if ( C4::Context->preference( "todaysIssuesDefaultSortOrder" ) eq 'asc' ) { >- @todaysissues = sort { $a->{'timestamp'} cmp $b->{'timestamp'} } @todaysissues; >- } >- else { >- @todaysissues = sort { $b->{'timestamp'} cmp $a->{'timestamp'} } @todaysissues; >+ >+} >+ >+if ($borrower) { >+ >+ # Getting borrower relatives >+ my @relborrowernumbers = GetMemberRelatives($borrower->{'borrowernumber'}); >+ #push @borrowernumbers, $borrower->{'borrowernumber'}; >+ >+ # get each issue of the borrower & separate them in todayissues & previous issues >+ my ($issueslist) = GetPendingIssues($borrower->{'borrowernumber'}); >+ my ($relissueslist) = GetPendingIssues(@relborrowernumbers); >+ >+ build_issue_data($issueslist, 0); >+ build_issue_data($relissueslist, 1); >+ >+ $displayrelissues = scalar($relissueslist); >+ >+ if ( C4::Context->preference("todaysIssuesDefaultSortOrder") eq 'asc' ) { >+ @todaysissues = sort { $a->{'timestamp'} cmp $b->{'timestamp'} } @todaysissues; >+ } else { >+ @todaysissues = sort { $b->{'timestamp'} cmp $a->{'timestamp'} } @todaysissues; > } > if ( C4::Context->preference( "previousIssuesDefaultSortOrder" ) eq 'asc' ){ > @previousissues = sort { $a->{'date_due'} cmp $b->{'date_due'} } @previousissues; >@@ -473,7 +572,48 @@ if ($borrower) { > @previousissues = sort { $b->{'date_due'} cmp $a->{'date_due'} } @previousissues; > } > } >+my @reserveswaiting; >+foreach my $itemnumber (keys %return_failed){ >+ next unless $return_failed{$itemnumber}->{'reservesdata'}; >+ my $hashdata=$return_failed{$itemnumber}->{'reservesdata'}; >+ $hashdata->{circborrowernumber}=$borrowernumber; >+ $hashdata->{script_name}=$query->script_name(); >+ push @reserveswaiting, $hashdata if (%$hashdata); >+} >+ >+$template->param(reserves_waiting=>\@reserveswaiting); >+ >+#### ADDED BY JF FOR COUNTS BY ITEMTYPE RULES >+# FIXME: This should utilize all the issuingrules options rather than just the defaults >+# and it should be moved to a module >+ >+# how many of each is allowed? >+my $issueqty_sth = $dbh->prepare( >+ 'SELECT itemtypes.description AS description,issuingrules.itemtype,maxissueqty ' . >+ 'FROM issuingrules LEFT JOIN itemtypes ON (itemtypes.itemtype=issuingrules.itemtype) ' . >+ 'WHERE categorycode=?' >+); >+$issueqty_sth->execute(q{*}); # This is a literal asterisk, not a wildcard. >+ >+while ( my $data = $issueqty_sth->fetchrow_hashref() ) { >+ >+ # subtract how many of each this borrower has >+ $data->{'count'} = $issued_itemtypes_count->{ $data->{'description'} }; >+ $data->{'left'} = >+ ( $data->{'maxissueqty'} - >+ $issued_itemtypes_count->{ $data->{'description'} } ); >+ >+ # can't have a negative number of remaining >+ if ( $data->{'left'} < 0 ) { $data->{'left'} = '0' } >+ if ( $data->{maxissueqty} <= $data->{count} ) { >+ $data->{flag} = 1; >+ } >+ if ( $data->{maxissueqty} > 0 && $data->{itemtype} !~m/^(\*|CIRC)$/ ) { >+ push @issued_itemtypes_count_loop, $data; >+ } >+} > >+#### / JF > > my @values; > my %labels; >@@ -503,6 +643,7 @@ if ($borrowerslist) { > > #title > my $flags = $borrower->{'flags'}; >+ $debug && warn Dump($flags); > foreach my $flag ( sort keys %$flags ) { > $template->param( flagged=> 1); > $flags->{$flag}->{'message'} =~ s#\n#<br />#g; >@@ -512,20 +653,19 @@ foreach my $flag ( sort keys %$flags ) { > noissues => 'true', > ); > if ( $flag eq 'GNA' ) { >- $template->param( gna => 'true' ); >+ $template->param( gna => 'true', gonenoaddresscomment => $borrower->{'gonenoaddresscomment'}, warning => 1 ); > } > elsif ( $flag eq 'LOST' ) { >- $template->param( lost => 'true' ); >- } >- elsif ( $flag eq 'DBARRED' ) { >- $template->param( dbarred => 'true' ); >- } >- elsif ( $flag eq 'CHARGES' ) { >+ $template->param( lost => 'true', lostcomment => $borrower->{'lostcomment'}, warning => 1 ); >+ } elsif ( $flag eq 'DEBARRED' ) { >+ $template->param( userdebarred => 'true', warning => 1, userdebarreddate=> format_date($flags->{DEBARRED}->{dateend}),debardebarredcomment=>$borrower->{'debarredcomment'}); >+ } elsif ( $flag eq 'CHARGES' ) { > $template->param( > charges => 'true', > chargesmsg => $flags->{'CHARGES'}->{'message'}, > chargesamount => $flags->{'CHARGES'}->{'amount'}, >- charges_is_blocker => 1 >+ charges_is_blocker => 1, >+ warning => 1 > ); > } > elsif ( $flag eq 'CREDITS' ) { >@@ -533,6 +673,7 @@ foreach my $flag ( sort keys %$flags ) { > credits => 'true', > creditsmsg => $flags->{'CREDITS'}->{'message'}, > creditsamount => sprintf("%.02f", -($flags->{'CREDITS'}->{'amount'})), # from patron's pov >+ warning => 1 > ); > } > } >@@ -543,6 +684,7 @@ foreach my $flag ( sort keys %$flags ) { > flagged => 1, > chargesmsg => $flags->{'CHARGES'}->{'message'}, > chargesamount => $flags->{'CHARGES'}->{'amount'}, >+ warning => 1 > ); > } > elsif ( $flag eq 'CREDITS' ) { >@@ -550,13 +692,15 @@ foreach my $flag ( sort keys %$flags ) { > credits => 'true', > creditsmsg => $flags->{'CREDITS'}->{'message'}, > creditsamount => sprintf("%.02f", -($flags->{'CREDITS'}->{'amount'})), # from patron's pov >+ warning => 1 > ); > } > elsif ( $flag eq 'ODUES' ) { > $template->param( > odues => 'true', > flagged => 1, >- oduesmsg => $flags->{'ODUES'}->{'message'} >+ oduesmsg => $flags->{'ODUES'}->{'message'}, >+ warning => 1 > ); > > my $items = $flags->{$flag}->{'itemlist'}; >@@ -611,9 +755,16 @@ if($lib_messages_loop){ $template->param(flagged => 1 ); } > my $bor_messages_loop = GetMessages( $borrowernumber, 'B', $branch ); > if($bor_messages_loop){ $template->param(flagged => 1 ); } > >+ > # Computes full borrower address > my (undef, $roadttype_hashref) = &GetRoadTypes(); >-my $address = $borrower->{'streetnumber'}.' '.$roadttype_hashref->{$borrower->{'streettype'}}.' '.$borrower->{'address'}; >+my $address = $borrower->{'streetnumber'}.' ' if ($borrower->{'streetnumber'}); >+$address .= $roadttype_hashref->{$borrower->{'streettype'}}.' ' if ( $roadttype_hashref->{$borrower->{'streettype'}}); >+$address .= $borrower->{'address'}; >+ >+ >+$duedatespec = "" if not ($stickyduedate or scalar $confirm_required); >+my @categories = C4::Category->all; > > my $fast_cataloging = 0; > if (defined getframeworkinfo('FA')) { >@@ -633,9 +784,9 @@ $template->param( > printername => $printer, > firstname => $borrower->{'firstname'}, > surname => $borrower->{'surname'}, >- dateexpiry => format_date($newexpiry), >+ printer => $printer, >+ printername => $printer, > expiry => format_date($borrower->{'dateexpiry'}), >- categorycode => $borrower->{'categorycode'}, > categoryname => $borrower->{description}, > address => $address, > address2 => $borrower->{'address2'}, >@@ -646,7 +797,6 @@ $template->param( > zipcode => $borrower->{'zipcode'}, > country => $borrower->{'country'}, > phone => $borrower->{'phone'} || $borrower->{'mobile'}, >- cardnumber => $borrower->{'cardnumber'}, > amountold => $amountold, > barcode => $barcode, > stickyduedate => $stickyduedate, >@@ -657,6 +807,9 @@ $template->param( > totaldue => sprintf('%.2f', $total), > todayissues => \@todaysissues, > previssues => \@previousissues, >+ relissues => \@relissues, >+ relprevissues => \@relprevissues, >+ displayrelissues => $displayrelissues, > inprocess => $inprocess, > memberofinstution => $member_of_institution, > CGIorganisations => $CGIorganisations, >@@ -664,8 +817,13 @@ $template->param( > circview => 1, > soundon => C4::Context->preference("SoundOn"), > fast_cataloging => $fast_cataloging, >+ categoryloop => \@categories, > ); > >+$template->param(newexpiry => format_date($newexpiry)) if (defined $newexpiry); >+ >+SetMemberInfosInTemplate($borrowernumber, $template); >+ > # save stickyduedate to session > if ($stickyduedate) { > $session->param( 'stickyduedate', $duedatespec ); >diff --git a/circ/returns.pl b/circ/returns.pl >index 40706a2..b014ca3 100755 >--- a/circ/returns.pl >+++ b/circ/returns.pl >@@ -36,16 +36,20 @@ use C4::Circulation; > use C4::Dates qw/format_date/; > use Date::Calc qw/Add_Delta_Days/; > use C4::Calendar; >+use C4::Budgets qw/GetCurrency/; > use C4::Print; > use C4::Reserves; > use C4::Biblio; > use C4::Items; > use C4::Members; >+use C4::Overdues qw/CheckBorrowerDebarred/; > use C4::Branch; # GetBranches GetBranchName > use C4::Koha; # FIXME : is it still useful ? > use C4::RotatingCollections; >+use C4::Debug; > > my $query = new CGI; >+my $remotehost = $query->remote_host(); > > if (!C4::Context->userenv){ > my $sessionID = $query->cookie("CGISESSID"); >@@ -133,6 +137,7 @@ if ( $query->param('resbarcode') ) { > my $item = $query->param('itemnumber'); > my $borrowernumber = $query->param('borrowernumber'); > my $resbarcode = $query->param('resbarcode'); >+ my $reservenumber = $query->param('reservenumber'); > my $diffBranchReturned = $query->param('diffBranch'); > my $iteminfo = GetBiblioFromItemNumber($item); > # fix up item type for display >@@ -140,18 +145,19 @@ if ( $query->param('resbarcode') ) { > my $diffBranchSend = ($userenv_branch ne $diffBranchReturned) ? $diffBranchReturned : undef; > # diffBranchSend tells ModReserveAffect whether document is expected in this library or not, > # i.e., whether to apply waiting status >- ModReserveAffect( $item, $borrowernumber, $diffBranchSend); >+ ModReserveAffect( $item, $borrowernumber, $diffBranchSend, $reservenumber ); >+ > # check if we have other reserves for this document, if we have a return send the message of transfer >- my ( $messages, $nextreservinfo ) = GetOtherReserves($item); >+ my ( $reservemessages, $nextreservinfo ) = GetOtherReserves($item); > > my ($borr) = GetMemberDetails( $nextreservinfo, 0 ); > my $name = $borr->{'surname'} . ", " . $borr->{'title'} . " " . $borr->{'firstname'}; >- if ( $messages->{'transfert'} ) { >+ if ( $reservemessages->{'transfert'} ) { > $template->param( > itemtitle => $iteminfo->{'title'}, > itembiblionumber => $iteminfo->{'biblionumber'}, > iteminfo => $iteminfo->{'author'}, >- tobranchname => GetBranchName($messages->{'transfert'}), >+ tobranchname => GetBranchName($reservemessages->{'transfert'}), > name => $name, > borrowernumber => $borrowernumber, > borcnum => $borr->{'cardnumber'}, >@@ -167,10 +173,12 @@ my $returned = 0; > my $messages; > my $issueinformation; > my $itemnumber; >+my $biblio; > my $barcode = $query->param('barcode'); > my $exemptfine = $query->param('exemptfine'); > my $dropboxmode = $query->param('dropboxmode'); > my $dotransfer = $query->param('dotransfer'); >+my $override = $query->param('override'); > my $calendar = C4::Calendar->new( branchcode => $userenv_branch ); > #dropbox: get last open day (today - 1) > my $today = C4::Dates->new(); >@@ -184,7 +192,7 @@ if ($dotransfer){ > } > > # actually return book and prepare item table..... >-if ($barcode) { >+if ($barcode and not $query->param('cancel')) { > $barcode =~ s/^\s*|\s*$//g; # remove leading/trailing whitespace > $barcode = barcodedecode($barcode) if C4::Context->preference('itemBarcodeInputFilter'); > $itemnumber = GetItemnumberFromBarcode($barcode); >@@ -207,11 +215,19 @@ if ($barcode) { > # save the return > # > ( $returned, $messages, $issueinformation, $borrower ) = >- AddReturn( $barcode, $userenv_branch, $exemptfine, $dropboxmode); # do the return >+ AddReturn( $barcode, $userenv_branch, $exemptfine, $dropboxmode,$override); # do the return > my $homeorholdingbranchreturn = C4::Context->preference('HomeOrHoldingBranchReturn') or 'homebranch'; > >+ my @ips=split /,|\|/, C4::Context->preference("CI-3M:AuthorizedIPs"); >+ #my $pid=fork(); >+ #unless($pid && $remotehost=~qr(^$ips$)){ >+ #if (!$pid && any{ $remotehost eq $_ }@ips ){ >+ if (any{ $remotehost eq $_ }@ips ){ >+ system("../services/magnetise.pl $remotehost in"); >+ #die 0; >+ } > # get biblio description >- my $biblio = GetBiblioFromItemNumber($itemnumber); >+ $biblio = GetBiblioFromItemNumber($itemnumber); > # fix up item type for display > $biblio->{'itemtype'} = C4::Context->preference('item-level_itypes') ? $biblio->{'itype'} : $biblio->{'itemtype'}; > >@@ -249,7 +265,7 @@ if ($barcode) { > } > > } >- elsif ( !$messages->{'BadBarcode'} ) { >+ elsif ( !$messages->{'BadBarcode'} and ! $messages->{'Wrongbranch'} ) { > $input{duedate} = 0; > $returneditems{0} = $barcode; > $riduedate{0} = 0; >@@ -267,6 +283,18 @@ if ($barcode) { > } > $template->param( inputloop => \@inputloop ); > >+ >+# Is there a circulation note? >+my $itemnumber = GetItemnumberFromBarcode($barcode); >+my $biblionumber = GetBiblionumberFromItemnumber($itemnumber); >+my $record = GetMarcBiblio($biblionumber); >+my $frameworkcode = GetFrameworkCode($biblionumber); >+my $circnotefield = GetRecordValue('circnote', $record, $frameworkcode); >+if (defined @$circnotefield[0]) { >+ $template->param(circnote => @$circnotefield[0]->{'subfield'}); >+} >+ >+ > my $found = 0; > my $waiting = 0; > my $reserved = 0; >@@ -290,9 +318,13 @@ if ( $messages->{'NeedsTransfer'} ){ > } > > if ( $messages->{'Wrongbranch'} ){ >- $template->param( >- wrongbranch => 1, >- ); >+ $template->param( >+ wrongbranch => $branches->{$messages->{'Wrongbranch'}->{'Wrongbranch'}}->{'branchname'}, >+ rightbranch => $branches->{$messages->{'Wrongbranch'}->{'Rightbranch'}}->{'branchname'}, >+ barcode => $barcode, >+ exemptfine => $exemptfine, >+ dropboxmode => $dropboxmode, >+ ); > } > > # case of wrong transfert, if the document wasn't transfered to the right library (according to branchtransfer (tobranch) BDD) >@@ -347,7 +379,7 @@ if ( $messages->{'ResFound'}) { > reserved => 1, > ); > } >- >+ my $debarred = CheckBorrowerDebarred($reserve->{borrowernumber}); > # same params for Waiting or Reserved > $template->param( > found => 1, >@@ -364,17 +396,18 @@ if ( $messages->{'ResFound'}) { > borcity => $borr->{'city'}, > borzip => $borr->{'zipcode'}, > borcnum => $borr->{'cardnumber'}, >- debarred => $borr->{'debarred'}, >+ debarred => $debarred, > gonenoaddress => $borr->{'gonenoaddress'}, > barcode => $barcode, >- destbranch => $reserve->{'branchcode'}, >+ reservenumber => $reserve->{'reservenumber'}, >+ destbranch => $reserve->{'branchcode'}, > borrowernumber => $reserve->{'borrowernumber'}, > itemnumber => $reserve->{'itemnumber'}, > reservenotes => $reserve->{'reservenotes'}, > ); > } # else { ; } # error? > } >- >+$borrower->{'flags'}= C4::Members::patronflags($borrower); > # Error Messages > my @errmsgloop; > foreach my $code ( keys %$messages ) { >@@ -400,6 +433,35 @@ foreach my $code ( keys %$messages ) { > elsif ( $code eq 'WasTransfered' ) { > ; # FIXME... anything to do here? > } >+ elsif ( $code eq 'NotForLoan' ) { >+ my $fw = GetFrameworkCode($biblio->{'biblionumber'}); >+ my $category = GetAuthValCode('items.notforloan',$fw); >+ my $authorizedvalues = GetAuthorisedValues($category, $messages->{$code}); >+ >+ foreach my $authvalue (@$authorizedvalues){ >+ $err{notforloan} = $authvalue->{lib} if $authvalue->{'authorised_value'} eq $messages->{$code}; >+ } >+ } >+ elsif ( $code eq 'Damaged' ) { >+ my $fw = GetFrameworkCode($biblio->{'biblionumber'}); >+ my $category = GetAuthValCode('items.damaged',$fw); >+ my $authorizedvalues = GetAuthorisedValues($category, $messages->{$code}); >+ >+ foreach my $authvalue (@$authorizedvalues){ >+ $err{damaged} = $authvalue->{lib} if $authvalue->{'authorised_value'} eq $messages->{$code}; >+ } >+ } >+ elsif( $code eq 'Debarred' ){ >+ $err{debarred} = format_date($messages->{'Debarred'}); >+ $err{debarcardnumber} = $borrower->{cardnumber}; >+ $err{debarborrowernumber} = $borrower->{borrowernumber}; >+ $err{debarname} = "$borrower->{firstname} $borrower->{surname}"; >+ } >+ elsif( $code eq 'HaveFines' ){ >+ $err{havefines} = $borrower->{'flags'}->{'CHARGES'}->{'amount'} . %{GetCurrency()}->{symbol}; >+ $err{finecardnumber} = $borrower->{cardnumber}; >+ $err{finename} = "$borrower->{firstname} $borrower->{surname}"; >+ } > elsif ( $code eq 'wthdrawn' ) { > $err{withdrawn} = 1; > $exit_required_p = 1; >@@ -421,7 +483,6 @@ foreach my $code ( keys %$messages ) { > } > elsif ( $code eq 'Wrongbranch' ) { > } >- > else { > die "Unknown error code $code"; # note we need all the (empty) elsif's above, or we die. > # This forces the issue of staying in sync w/ Circulation.pm >@@ -435,14 +496,10 @@ $template->param( errmsgloop => \@errmsgloop ); > > # patrontable .... > if ($borrower) { >- my $flags = $borrower->{'flags'}; > my @flagloop; >- my $flagset; >+ my $flags=$borrower->{flags}; > foreach my $flag ( sort keys %$flags ) { > my %flaginfo; >- unless ($flagset) { $flagset = 1; } >- $flaginfo{redfont} = ( $flags->{$flag}->{'noissues'} ); >- $flaginfo{flag} = $flag; > if ( $flag eq 'CHARGES' ) { > $flaginfo{msg} = $flag; > $flaginfo{charges} = 1; >@@ -457,14 +514,29 @@ if ($borrower) { > foreach my $item (@$items) { > my $biblio = GetBiblioFromItemNumber( $item->{'itemnumber'}); > push @waitingitemloop, { >- biblionum => $biblio->{'biblionumber'}, >- barcode => $biblio->{'barcode'}, >- title => $biblio->{'title'}, >- brname => $branches->{ $biblio->{'holdingbranch'} }->{'branchname'}, >+ biblionumber=> $biblio->{'biblionumber'}, >+ author => $biblio->{'author'}, >+ itemtype => $item->{'ccode'}, >+ reservedate => format_date($item->{'reservedate'}), >+ waitingdate => format_date($item->{'waitingdate'}), >+ barcode => $item->{'barcode'}, >+ maxpickupdate=> format_date( sprintf("%d-%02d-%02d",GetMaxPickupDate($item->{'waitingdate'}, $borrower->{borrowernumber},$item ))), >+ title => $biblio->{'title'}, >+ brname => $branches->{ $item->{'branchcode'} }->{'branchname'}, >+ waitinghere => ($item->{'branchcode'} eq $userenv_branch) > }; > } > $flaginfo{itemloop} = \@waitingitemloop; > } >+ elsif ( $flag =~ /DEBARRED|LOST|GNA/ ) { >+ if ($flag ne "GNA"){ >+ $flag=lc($flag); >+ } >+ else{ >+ $flag="gonenoaddress"; >+ } >+ %flaginfo=( $flag =>1, $flag."comment"=>$borrower->{$flag."comment"},dateend=>$flags->{uc($flag)}->{dateend}); >+ } > elsif ( $flag eq 'ODUES' ) { > my $items = $flags->{$flag}->{'itemlist'}; > my @itemloop; >@@ -490,7 +562,6 @@ if ($borrower) { > push( @flagloop, \%flaginfo ); > } > $template->param( >- flagset => $flagset, > flagloop => \@flagloop, > riborrowernumber => $borrower->{'borrowernumber'}, > riborcnum => $borrower->{'cardnumber'}, >@@ -501,7 +572,7 @@ if ($borrower) { > } > > #set up so only the last 8 returned items display (make for faster loading pages) >-my $returned_counter = ( C4::Context->preference('numReturnedItemsToShow') ) ? C4::Context->preference('numReturnedItemsToShow') : 8; >+my $returned_counter = ( C4::Context->preference('numReturnedItemsToShow') ) ? C4::Context->preference('numReturnedItemsToShow') : 10; > my $count = 0; > my @riloop; > foreach ( sort { $a <=> $b } keys %returneditems ) { >@@ -528,19 +599,25 @@ foreach ( sort { $a <=> $b } keys %returneditems ) { > else { > $ri{borrowernumber} = $riborrowernumber{$_}; > } >- > # my %ri; > my $biblio = GetBiblioFromItemNumber(GetItemnumberFromBarcode($bar_code)); >+ my $item = GetItem(GetItemnumberFromBarcode($bar_code)); > # fix up item type for display > $biblio->{'itemtype'} = C4::Context->preference('item-level_itypes') ? $biblio->{'itype'} : $biblio->{'itemtype'}; > $ri{itembiblionumber} = $biblio->{'biblionumber'}; > $ri{itemtitle} = $biblio->{'title'}; > $ri{itemauthor} = $biblio->{'author'}; >- $ri{itemtype} = $biblio->{'itemtype'}; > $ri{itemnote} = $biblio->{'itemnotes'}; >- $ri{ccode} = $biblio->{'ccode'}; > $ri{itemnumber} = $biblio->{'itemnumber'}; >+ $ri{itemtype} = $item->{'itype'}; >+ $ri{ccode} = $item->{'ccode'}; >+ $ri{itemcallnumber} = $item->{'itemcallnumber'}; >+ $ri{homebranch} = $item->{'homebranch'}; >+ $ri{holdingbranch} = $item->{'holdingbranch'}; > $ri{barcode} = $bar_code; >+ my $shelflocations = GetKohaAuthorisedValues('items.location',''); >+ $ri{itemlocation} = $shelflocations->{$biblio->{'location'}}; >+ > } > else { > last; >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branch_transfer_limits.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branch_transfer_limits.tmpl >index ce4ccaf..be1b325 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branch_transfer_limits.tmpl >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branch_transfer_limits.tmpl >@@ -50,6 +50,7 @@ > return false; > }); > >+ $('#selectlibrary input[type=submit]').hide(); > }); > </script> > <style type="text/css">td { text-align: center; }</style> >@@ -70,13 +71,18 @@ > <form method="get" action="/cgi-bin/koha/admin/branch_transfer_limits.pl" id="selectlibrary"> > <label for="branchselect">Select a library :</label> > <select name="branchcode" id="branchselect"> >+ <option value="">Choose one</option> > <!-- TMPL_LOOP NAME="branch_loop" --> >+ <!-- TMPL_IF EXPR="value eq branchcode" --> >+ <option value="<!-- TMPL_VAR NAME="value" -->" selected="selected"><!-- TMPL_VAR NAME="branchname" --></option> >+ <!-- TMPL_ELSE --> > <option value="<!-- TMPL_VAR NAME="value" -->"><!-- TMPL_VAR NAME="branchname" --></option> >+ <!-- /TMPL_IF --> > <!-- /TMPL_LOOP --> > </select> > <input type="submit" value="Choose" /> > </form> >- >+<!-- TMPL_IF NAME="branchcode" --> > <p class="help">Check the boxes for the libraries you accept to checkin items from.</p> > <fieldset>For <strong>all</strong> <!--TMPL_VAR NAME="limit_phrase" -->s: <a id="CheckAll" href="#">Check All</a> | <a id="UncheckAll" href="#">Uncheck All</a></fieldset> > >@@ -126,11 +132,11 @@ > </thead> > > <tbody> >- <!-- TMPL_LOOP NAME="to_branch_loop" --> >+ <!-- TMPL_LOOP NAME="from_branch_loop" --> > <!-- TMPL_UNLESS NAME="__odd__" --><tr class="highlight"><!-- TMPL_ELSE > --><tr><!-- /TMPL_UNLESS --> >- <td><label style="min-width:400px;" for="<!-- TMPL_VAR NAME="code" --><!-- TMPL_VAR NAME="toBranch" -->row"><!-- TMPL_VAR NAME="toBranch" --> - <!-- TMPL_VAR NAME="toBranchname" --></label></td> >- <td><input type="checkbox" id="<!-- TMPL_VAR NAME="code" --><!-- TMPL_VAR NAME="toBranch" -->row" name="<!-- TMPL_VAR NAME="code" -->_<!-- TMPL_VAR NAME="toBranch" -->" <!-- TMPL_IF NAME="isChecked" -->checked="checked" <!-- /TMPL_IF --> /></td> >+ <td><label style="min-width:400px;" for="<!-- TMPL_VAR NAME="code" --><!-- TMPL_VAR NAME="fromBranch" -->row"><!-- TMPL_VAR NAME="fromBranch" --> - <!-- TMPL_VAR NAME="fromBranchname" --></label></td> >+ <td><input type="checkbox" id="<!-- TMPL_VAR NAME="code" --><!-- TMPL_VAR NAME="fromBranch" -->row" name="<!-- TMPL_VAR NAME="code" -->_<!-- TMPL_VAR NAME="fromBranch" -->" <!-- TMPL_IF NAME="isChecked" -->checked="checked" <!-- /TMPL_IF --> /></td> > </tr> > <!-- /TMPL_LOOP --> > </tbody> >@@ -148,6 +154,7 @@ > </div> > </div> > </div> >+<!-- /TMPL_IF --> > <div class="yui-b"> > <!-- TMPL_INCLUDE NAME="admin-menu.inc" --> > </div> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/clone-rules.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/clone-rules.tmpl >index ad675d1..dcb57a2 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/clone-rules.tmpl >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/clone-rules.tmpl >@@ -24,7 +24,8 @@ > <!-- TMPL_IF NAME="error" --> > <div class="dialog alert">Cloning of issuing rules failed!</div> > <!-- TMPL_ELSE --> >- <div class="dialog message"><p>The rules have been cloned.</p></div> >+ <div class="message"><p>The rules have <a href="/cgi-bin/koha/admin/smart-rules.pl?branch=<!-- TMPL_VAR NAME="tobranch" -->">been cloned</a>.</p></div> >+ <script language="javascript">document.location.href = "/cgi-bin/koha/admin/smart-rules.pl?branch=<!-- TMPL_VAR NAME="tobranch" -->";</script> > <!-- /TMPL_IF --> > <a href="/cgi-bin/koha/admin/smart-rules.pl">Return to Issuing rules</a> > <!-- TMPL_ELSE --> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tmpl >index 92a44ce..f7f76fe 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tmpl >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tmpl >@@ -6,9 +6,145 @@ > //<![CDATA[ > $(document).ready(function() { > $('#selectlibrary').find("input:submit").hide(); >- $('#branch').change(function() { >+ $('#branchcode').change(function() { > $('#selectlibrary').submit(); > }); >+ $('#filter').keyup(function() { >+ $.uiTableFilter( $('#smartrules'), this.value ); >+ }); >+ $('#nofilter').click(function() { >+ $('.issues').show(); >+ $('.fines').show(); >+ $('.reserves').show(); >+ $('.issues :input').removeAttr('disabled',true); >+ $('.fines :input').removeAttr('disabled',true); >+ $('.reserves :input').removeAttr('disabled',true); >+ $(this).parent().attr('class','ui-tabs-selected'); >+ $('#issuesfilter').parent().attr('class',null); >+ $('#finesfilter').parent().attr('class',null); >+ $('#reservesfilter').parent().attr('class',null); >+ }); >+ $('#issuesfilter').click(function() { >+ $('.issues').show(); >+ $('.fines').hide(); >+ $('.reserves').hide(); >+ $('.issues :input').removeAttr('disabled',true); >+ $('.fines :input').attr('disabled',true); >+ $('.reserves :input').attr('disabled',true); >+ $(this).parent().attr('class','ui-tabs-selected'); >+ $('#nofilter').parent().attr('class',null); >+ $('#finesfilter').parent().attr('class',null); >+ $('#reservesfilter').parent().attr('class',null); >+ }); >+ $('#finesfilter').click(function() { >+ $('.issues').hide(); >+ $('.fines').show(); >+ $('.reserves').hide(); >+ $('.issues :input').attr('disabled',true); >+ $('.fines :input').removeAttr('disabled',true); >+ $('.reserves :input').attr('disabled',true); >+ $(this).parent().attr('class','ui-tabs-selected'); >+ $('#issuesfilter').parent().attr('class',null); >+ $('#nofilter').parent().attr('class',null); >+ $('#reservesfilter').parent().attr('class',null); >+ }); >+ $('#reservesfilter').click(function() { >+ $('.issues').hide(); >+ $('.fines').hide(); >+ $('.reserves').show(); >+ $('.issues :input').attr('disabled',true); >+ $('.fines :input').attr('disabled',true); >+ $('.reserves :input').removeAttr('disabled',true); >+ $(this).parent().attr('class','ui-tabs-selected'); >+ $('#issuesfilter').parent().attr('class',null); >+ $('#finesfilter').parent().attr('class',null); >+ $('#nofilter').parent().attr('class',null); >+ }); >+ >+ // Inline editor >+ var editor = false; >+ $('#smartrules>tbody>tr>td.editable').click(function() { >+ if ( ! editor ) { >+ var td = $(this); >+ var tdvalue = td.text().trim(); >+ td.text(''); >+ >+ var type; >+ if ( $.inArray('boolean', td.attr('class').split(' ')) != -1 ) { // If the td is boolean, we display a checkbox >+ editor = $('<input id="inlineeditor" type="checkbox" /\>'); >+ editor.attr('checked', tdvalue == 'Yes' ? 'checked' : ''); >+ type = 'boolean'; >+ } else if ( $.inArray('triple', td.attr('class').split(' ')) != -1 ) { // else if it is a triple, we display a listbox >+ var selectedn = tdvalue == '' ? 'selected="selected"' : ''; >+ var selected1 = tdvalue == 'Yes' ? 'selected="selected"' : ''; >+ var selected0 = tdvalue == 'No' ? 'selected="selected"' : ''; >+ var str = '<select id="inlineeditor">'; >+ str += '<option value="" ' + selectedn + '></option>'; >+ str += '<option value="1" ' + selected1 + '>Yes</option>'; >+ str += '<option value="0" ' + selected0 + '>No</option>'; >+ str += '</select>'; >+ editor = $(str); >+ type = 'triple'; >+ } else { // else we display a textbox >+ editor = $('<input id="inlineeditor" type="text" size="4" /\>'); >+ editor.attr('value', tdvalue); >+ } >+ >+ editor.focus(); >+ >+ editor.keyup(function(e) { // on press >+ if ( e.keyCode == 13 ) { // enter >+ >+ // let's build the atomic rule >+ var branchcode = $('#branchcode').val(); >+ var categorycode = td.parent().children('td.categorycode').children('span').text(); >+ var itemtype = td.parent().children('td.itemtype').children('span').text(); >+ var varname = td.attr('class').split(' ')[0]; >+ var inputvalue; >+ switch ( type ) { >+ case 'boolean': >+ inputvalue = editor.attr('checked') ? 1 : 0; >+ break; >+ default: >+ inputvalue = editor.val(); >+ break; >+ } >+ >+ // post it to the server >+ $.ajax({ >+ url: '/cgi-bin/koha/admin/smart-rules-service.pl', >+ type: "POST", >+ async: false, >+ data: "branchcode="+branchcode+"&categorycode="+categorycode+"&itemtype="+itemtype+"&varname="+varname+"&inputvalue="+inputvalue, >+ success: function(result) { >+ >+ // repopulate the td with data >+ switch ( type ) { >+ case 'boolean': >+ td.text(result == '1' ? 'Yes' : 'No'); >+ break; >+ case 'triple': >+ switch ( result ) { >+ case '' : td.text(''); break; >+ case '1': td.text('Yes'); break; >+ case '0': td.text('No'); break; >+ } >+ break; >+ default: >+ td.text(result); >+ break; >+ } >+ >+ editor.remove(); >+ editor = false; >+ } >+ }); >+ } >+ }); >+ >+ td.append(editor); >+ } >+ }); > }); > //]]> > </script> >@@ -32,25 +168,11 @@ $(document).ready(function() { > Defining circulation and fine rules for all libraries > <!-- /TMPL_IF --> > </h1> >- <div class="help"> >- <p>The rules are applied from most specific to less specific, using the first found in this order:</p> >- <ul> >- <li>same library, same patron type, same item type</li> >- <li>same library, same patron type, all item types</li> >- <li>same library, all patron types, same item type</li> >- <li>same library, all patron types, all item types</li> >- <li>all libraries, same patron type, same item type</li> >- <li>all libraries, same patron type, all item types</li> >- <li>all libraries, all patron types, same item type</li> >- <li>all libraries, all patron types, all item types</li> >- </ul> >- <p>To modify a rule, create a new one with the same patron type and item type.</p> >- </div> >- <div> >+ <div id="bloc100"> > <form method="get" action="/cgi-bin/koha/admin/smart-rules.pl" id="selectlibrary"> > Select a library : >- <select name="branch" id="branch" style="width:20em;"> >- <option value="*">All libraries</option> >+ <select name="branchcode" id="branchcode" style="width:20em;"> >+ <option value="*">Default</option> > <!-- TMPL_LOOP NAME="branchloop" --> > <!-- TMPL_IF NAME="selected" --><option value="<!-- TMPL_VAR NAME="value" -->" selected="selected"><!-- TMPL_VAR NAME="branchname" --></option><!-- TMPL_ELSE --><option value="<!-- TMPL_VAR NAME="value" -->"><!-- TMPL_VAR NAME="branchname" --></option><!-- /TMPL_IF --> > <!-- /TMPL_LOOP --> >@@ -60,272 +182,223 @@ $(document).ready(function() { > for="tobranch"><strong>Clone these rules to:</strong></label> <input type="hidden" name="frombranch" value="<!-- TMPL_VAR NAME="current_branch" -->" /> > <select name="tobranch" id="tobranch"><!-- TMPL_LOOP NAME="branchloop" --><option value="<!-- TMPL_VAR NAME="value" -->"><!-- TMPL_VAR NAME="branchname" --></option><!-- /TMPL_LOOP --></select> <input type="submit" value="Clone" /></form><!-- /TMPL_IF --></fieldset> > >- <form method="post" action="/cgi-bin/koha/admin/smart-rules.pl"> >- <input type="hidden" name="op" value="add" /> >- <table> >- <tr> >- <th>Patron Category</th> >- <th>Item Type</th> >- <th>Current Checkouts Allowed</th> >- <th>Loan Period (day)</th> >- <th>Fine Amount</th> >- <th>Fine Charging Interval</th> >- <th>Fine Grace period (day)</th> >- <th>Suspension in Days (day)</th> >- <th>Renewals Allowed (count)</th> >- <th>Holds Allowed (count)</th> >- <th>Rental Discount (%)</th> >- <th> </th> >- </tr> >- <!-- TMPL_LOOP NAME="rules" --> >- <!-- TMPL_UNLESS NAME="__odd__" --> >- <tr class="highlight"> >- <!-- TMPL_ELSE --> >- <tr> >- <!-- /TMPL_UNLESS --> >- <td><!-- TMPL_IF NAME="default_humancategorycode" --> >- <em>All</em> >- <!-- TMPL_ELSE --> >- <!-- TMPL_VAR NAME="humancategorycode" --> >- <!-- /TMPL_IF --> >- </td> >- <td><!-- TMPL_IF NAME="default_humanitemtype" --> >- <em>All</em> >- <!-- TMPL_ELSE --> >- <!-- TMPL_VAR NAME="humanitemtype" --> >- <!-- /TMPL_IF --> >- </td> >- <td><!-- TMPL_IF NAME="unlimited_maxissueqty" --> >- Unlimited >- <!-- TMPL_ELSE --> >- <!-- TMPL_VAR NAME="maxissueqty" --> >- <!-- /TMPL_IF --> >- </td> >- <td><!-- TMPL_VAR NAME="issuelength" --></td> >- <td><!-- TMPL_VAR NAME="fine" --></td> >- <td><!-- TMPL_VAR NAME="chargeperiod" --></td> >- <td><!-- TMPL_VAR NAME="firstremind" --></td> >- <td><!-- TMPL_VAR NAME="finedays" --></td> >- <td><!-- TMPL_VAR NAME="renewalsallowed" --></td> >- <td><!-- TMPL_VAR NAME="reservesallowed" --></td> >- <td><!-- TMPL_VAR NAME="rentaldiscount" --></td> >- <td> >- <a class="button" href="/cgi-bin/koha/admin/smart-rules.pl?op=delete&itemtype=<!-- TMPL_VAR NAME="itemtype" -->&categorycode=<!-- TMPL_VAR NAME="categorycode" -->&branch=<!-- TMPL_VAR NAME="current_branch" -->">Delete</a> >- </td> >- </tr> >- <!-- /TMPL_LOOP --> >- <tr> >- <td> >- <select name="categorycode"> >- <option value="*">All</option> >- <!-- TMPL_LOOP NAME="categoryloop" --> >- <option value="<!-- TMPL_VAR NAME="categorycode" -->"><!-- TMPL_VAR NAME="description" --></option> >- <!-- /TMPL_LOOP --> >- </select> >- </td> >- <td> >- <select name="itemtype" style="width:13em;"> >- <option value="*">All</option> >- <!-- TMPL_LOOP NAME="itemtypeloop" --> >- <option value="<!-- TMPL_VAR NAME="itemtype" -->"><!-- TMPL_VAR NAME="description" --></option> >- <!-- /TMPL_LOOP --> >- </select> >- </td> >- <td><input name="maxissueqty" size="3" /></td> >- <td><input name="issuelength" size="3" /> </td> >- <td><input name="fine" size="4" /></td> >- <td><input name="chargeperiod" size="2" /></td> >- <td><input name="firstremind" size="2" /> </td> >- <td><input name="finedays" size="3" /> </td> >- <td><input name="renewalsallowed" size="2" /></td> >- <td><input name="reservesallowed" size="2" /></td> >- <td><input name="rentaldiscount" size="2" /></td> >- <td><input type="hidden" name="branch" value="<!-- TMPL_VAR NAME="current_branch" -->"/><input type="submit" value="Add" class="submit" /></td> >- </tr> >- </table> >- </form> >- </div> >- <div id="defaults-for-this-library" class="container"> >- <h3>Default checkout and hold policy for <!-- TMPL_IF NAME="humanbranch" --><!-- TMPL_VAR NAME="humanbranch" --><!-- TMPL_ELSE -->all libraries<!-- /TMPL_IF --></h3> >- <p>You can set a default maximum number of checkouts and hold policy that will be used if none is defined below for a particular item type or category.</p> >- <form method="post" action="/cgi-bin/koha/admin/smart-rules.pl"> >- <input type="hidden" name="op" value="set-branch-defaults" /> >- <input type="hidden" name="branch" value="<!-- TMPL_VAR NAME="current_branch" -->"/> >- <table> >- <tr> >- <th> </th> >- <th>Total Current Checkouts Allowed</th> >- <th>Hold Policy</th> >- <th> </th> >- <th> </th> >- </tr> >- <tr> >- <td><em>Defaults<!-- TMPL_UNLESS NAME="default_rules" --> (not set)<!-- /TMPL_IF --></em></td> >- <td><input type="text" name="maxissueqty" size="3" value="<!-- TMPL_VAR NAME="default_maxissueqty" -->"/></td> >- <td> >- <select name="holdallowed"> >- <!-- TMPL_IF NAME="default_holdallowed_any" --> >- <option value="2" selected="selected"> >- <!-- TMPL_ELSE --> >- <option value="2"> >- <!-- /TMPL_IF --> >- From Any Library >- </option> >- <!-- TMPL_IF NAME="default_holdallowed_same" --> >- <option value="1" selected="selected"> >- <!-- TMPL_ELSE --> >- <option value="1"> >- <!-- /TMPL_IF --> >- From Home Library >- </option> >- <!-- TMPL_IF NAME="default_holdallowed_none" --> >- <option value="0" selected="selected"> >- <!-- TMPL_ELSE --> >- <option value="0"> >- <!-- /TMPL_IF --> >- No Holds Allowed >- </option> >- </select> >- </td> >- <td><input type="submit" value="Save" class="submit" /></td> >- <td> >- <a class="button" href="/cgi-bin/koha/admin/smart-rules.pl?op=delete-branch-cat&categorycode=*&branch=<!-- TMPL_VAR NAME="current_branch" -->">Unset</a> >- </td> >- </tr> >- </table> >- </form> >- </div> >- <!-- TMPL_IF NAME="show_branch_cat_rule_form" --> >- <div id="holds-policy-by-patron-category" class="container"> >- <h3>Checkout limit by patron category for <!-- TMPL_IF NAME="humanbranch" --><!-- TMPL_VAR NAME="humanbranch" --><!-- TMPL_ELSE -->all libraries<!-- /TMPL_IF --></h3> >- <p>For this library, you can specify the maximum number of loans that >- a patron of a given category can make, regardless of the item type. >- </p> >- <p>If the total amount loanable for a given patron category is left blank, >- no limit applies, except possibly for a limit you define for a specific item type. >- </p> >- <form method="post" action="/cgi-bin/koha/admin/smart-rules.pl"> >- <input type="hidden" name="op" value="add-branch-cat" /> >- <input type="hidden" name="branch" value="<!-- TMPL_VAR NAME="current_branch" -->"/> >- <table> >- <tr> >- <th>Patron Category</th> >- <th>Total Current Checkouts Allowed</th> >- <th> </th> >- </tr> >- <!-- TMPL_LOOP NAME="branch_cat_rule_loop" --> >- <!-- TMPL_UNLESS NAME="__odd__" --> >- <tr class="highlight"> >- <!-- TMPL_ELSE --> >- <tr> >- <!-- /TMPL_UNLESS --> >- <td><!-- TMPL_IF NAME="default_humancategorycode" --> >- <em>Default</em> >+ <div class="toptabs"> >+ <ul class="ui-tabs-nav"> >+ <li class="ui-tabs-selected"><a id="nofilter">All</a></li> >+ <li><a id="issuesfilter">Issues</a></li> >+ <li><a id="finesfilter">Fines</a></li> >+ <li><a id="reservesfilter">Reserves</a></li> >+ <div style="text-align:right;"> >+ <label for="filter" style="float:none;">Filter: </label> >+ <input type="text" name="filter" id="filter" /> >+ </div> >+ </ul> >+ <div class="tabs-container"> >+ <table id="smartrules" width="100%"> >+ <thead> >+ <tr> >+ <th>Patron category</th> >+ <th>Item type</th> >+ <th class="issues">Current checkouts allowed</th> >+ <th class="issues">Loan period (day)</th> >+ <th class="fines">Fine amount</th> >+ <th class="fines">Fine charging interval</th> >+ <th class="fines">Grace period (day)</th> >+ <th class="fines">Suspension duration (day)</th> >+ <th class="issues">Renewals allowed (count)</th> >+ <th class="issues">Renewals period (days)</th> >+ <th class="reserves">Holds allowed (count)</th> >+ <th class="reserves">Holds pickup delay (day)</th> >+ <th class="reserves">Allow on shelf holds</th> >+ <th class="reserves">Holds restricted to library</th> >+ <th class="issues">Rental Discount (%)</th> >+ <th> </th> >+ </tr> >+ </thead> >+ <tbody> >+ <!-- TMPL_LOOP NAME="rules" --> >+ <!-- TMPL_UNLESS NAME="__odd__" --> >+ <tr class="highlight"> > <!-- TMPL_ELSE --> >- <!-- TMPL_VAR NAME="humancategorycode" --> >- <!-- /TMPL_IF --> >- </td> >- <td><!-- TMPL_IF NAME="unlimited_maxissueqty" --> >- Unlimited >- <!-- TMPL_ELSE --> >- <!-- TMPL_VAR NAME="maxissueqty" --> >- <!-- /TMPL_IF --> >- </td> >- <td> >- <a class="button" href="/cgi-bin/koha/admin/smart-rules.pl?op=delete-branch-cat&categorycode=<!-- TMPL_VAR NAME="categorycode" -->&branch=<!-- TMPL_VAR NAME="current_branch" -->">Delete</a> >- </td> >- </tr> >- <!-- /TMPL_LOOP --> >- <tr> >- <td> >- <select name="categorycode"> >- <!-- TMPL_LOOP NAME="categoryloop" --> >- <option value="<!-- TMPL_VAR NAME="categorycode" -->"><!-- TMPL_VAR NAME="description" --></option> >- <!-- /TMPL_LOOP --> >- </select> >- </td> >- <td><input name="maxissueqty" size="3" /></td> >- <td><input type="submit" value="Add" class="submit" /></td> >- </tr> >- </table> >- </form> >- </div> >- <!-- /TMPL_IF --> >- <div id="holds-policy-by-item-type" class="container"> >- <h3>Holds policy by item type for <!-- TMPL_IF NAME="humanbranch" --><!-- TMPL_VAR NAME="humanbranch" --><!-- TMPL_ELSE -->all libraries<!-- /TMPL_IF --></h3> >- <p> >- For this library, you can edit rules for given itemtypes, regardless >- of the patron's category. >- </p> >- <p> >- Currently, this means hold policies. >- The various policies have the following effects: >- </p> >- <ul> >- <li><strong>From Any Library:</strong> Patrons from any library may put this item on hold. <cite>(default if none is defined)</cite></li> >- <li><strong>From Home Library:</strong> Only patrons from the item's home library may put this book on hold.</li> >- <li><strong>No Holds Allowed:</strong> No patron may put this book on hold.</li> >- </ul> >- <p> >- Note that if the system preference >- <code>AllowHoldPolicyOverride</code> is enabled, these policies can >- be overridden by your circulation staff. Also, these policies are >- based on the patron's home library, <em>not</em> the library where the hold is being placed.. >- </p> >- >- <form method="post" action="/cgi-bin/koha/admin/smart-rules.pl"> >- <input type="hidden" name="op" value="add-branch-item" /> >- <input type="hidden" name="branch" value="<!-- TMPL_VAR NAME="current_branch" -->"/> >- <table> >- <tr> >- <th>Item Type</th> >- <th>Hold Policy</th> >- <th> </th> >- </tr> >- <!-- TMPL_LOOP NAME="branch_item_rule_loop" --> >- <!-- TMPL_UNLESS NAME="__odd__" --> >- <tr class="highlight"> >- <!-- TMPL_ELSE --> >- <tr> >- <!-- /TMPL_UNLESS --> >- <td><!-- TMPL_IF NAME="default_humanitemtype" --> >- <em>Default</em> >- <!-- TMPL_ELSE --> >- <!-- TMPL_VAR NAME="humanitemtype" --> >- <!-- /TMPL_IF --> >- </td> >- <td><!-- TMPL_IF NAME="holdallowed_any" --> >- From Any Library >- <!-- TMPL_ELSIF NAME="holdallowed_same" --> >- From Home Library >- <!-- TMPL_ELSE --> >- No Holds Allowed >- <!-- /TMPL_IF --> >- </td> >- <td> >- <a class="button" href="/cgi-bin/koha/admin/smart-rules.pl?op=delete-branch-item&itemtype=<!-- TMPL_VAR NAME="itemtype" -->&branch=<!-- TMPL_VAR NAME="current_branch" -->">Delete</a> >- </td> >- </tr> >- <!-- /TMPL_LOOP --> >- <tr> >- <td> >- <select name="itemtype"> >- <!-- TMPL_LOOP NAME="itemtypeloop" --> >- <option value="<!-- TMPL_VAR NAME="itemtype" -->"><!-- TMPL_VAR NAME="description" --></option> >- <!-- /TMPL_LOOP --> >- </select> >- </td> >- <td> >- <select name="holdallowed"> >- <option value="2">From Any Library</option> >- <option value="1">From Home Library</option> >- <option value="0">No Holds Allowed</option> >- </select> >- </td> >- <td><input type="submit" value="Add" class="submit" /></td> >- </tr> >- </table> >- </form> >+ <tr> >+ <!-- /TMPL_UNLESS --> >+ <td class="categorycode"> >+ <span style="display:none;"><!-- TMPL_VAR NAME="categorycode" --></span> >+ <!-- TMPL_IF NAME="default_humancategorycode" --> >+ <em>Default</em> >+ <!-- TMPL_ELSE --> >+ <!-- TMPL_VAR NAME="humancategorycode" --> >+ <!-- /TMPL_IF --> >+ </td> >+ <td class="itemtype"> >+ <span style="display:none;"><!-- TMPL_VAR NAME="itemtype" --></span> >+ <!-- TMPL_IF NAME="default_humanitemtype" --> >+ <em>Default</em> >+ <!-- TMPL_ELSE --> >+ <!-- TMPL_VAR NAME="humanitemtype" --> >+ <!-- /TMPL_IF --> >+ </td> >+ <!-- TMPL_IF NAME="herited_maxissueqty" --> >+ <td class="maxissueqty editable issues herited"> >+ <!-- TMPL_ELSE --> >+ <td class="maxissueqty editable issues"> >+ <!-- /TMPL_IF --> >+ <!-- TMPL_IF NAME="unlimited_maxissueqty" --> >+ Unlimited >+ <!-- TMPL_ELSE --> >+ <!-- TMPL_VAR NAME="maxissueqty" --> >+ <!-- /TMPL_IF --> >+ </td> >+ <!-- TMPL_IF NAME="herited_issuelength" --> >+ <td class="issuelength editable issues herited"> >+ <!-- TMPL_ELSE --> >+ <td class="issuelength editable issues"> >+ <!-- /TMPL_IF --> >+ <!-- TMPL_VAR NAME="issuelength" --> >+ </td> >+ <!-- TMPL_IF NAME="herited_fine" --> >+ <td class="fine editable fines herited"> >+ <!-- TMPL_ELSE --> >+ <td class="fine editable fines"> >+ <!-- /TMPL_IF --> >+ <!-- TMPL_VAR NAME="fine" --> >+ </td> >+ <!-- TMPL_IF NAME="herited_chargeperiod" --> >+ <td class="chargeperiod editable fines herited"> >+ <!-- TMPL_ELSE --> >+ <td class="chargeperiod editable fines"> >+ <!-- /TMPL_IF --> >+ <!-- TMPL_VAR NAME="chargeperiod" --> >+ </td> >+ <!-- TMPL_IF NAME="herited_firstremind" --> >+ <td class="firstremind editable fines herited"> >+ <!-- TMPL_ELSE --> >+ <td class="firstremind editable fines"> >+ <!-- /TMPL_IF --> >+ <!-- TMPL_VAR NAME="firstremind" --> >+ </td> >+ <!-- TMPL_IF NAME="herited_finedays" --> >+ <td class="finedays editable fines herited"> >+ <!-- TMPL_ELSE --> >+ <td class="finedays editable fines"> >+ <!-- /TMPL_IF --> >+ <!-- TMPL_VAR NAME="finedays" --> >+ </td> >+ <!-- TMPL_IF NAME="herited_renewalsallowed" --> >+ <td class="renewalsallowed editable issues herited"> >+ <!-- TMPL_ELSE --> >+ <td class="renewalsallowed editable issues"> >+ <!-- /TMPL_IF --> >+ <!-- TMPL_VAR NAME="renewalsallowed" --> >+ </td> >+ <!-- TMPL_IF NAME="herited_renewalperiod" --> >+ <td class="renewalperiod editable issues herited"> >+ <!-- TMPL_ELSE --> >+ <td class="renewalperiod editable issues"> >+ <!-- /TMPL_IF --> >+ <!-- TMPL_VAR NAME="renewalperiod" --> >+ </td> >+ <!-- TMPL_IF NAME="herited_reservesallowed" --> >+ <td class="reservesallowed editable reserves herited"> >+ <!-- TMPL_ELSE --> >+ <td class="reservesallowed editable reserves"> >+ <!-- /TMPL_IF --> >+ <!-- TMPL_VAR NAME="reservesallowed" --> >+ </td> >+ <!-- TMPL_IF NAME="herited_holdspickupdelay" --> >+ <td class="holdspickupdelay editable reserves herited"> >+ <!--TMPL_ELSE--> >+ <td class="holdspickupdelay editable reserves"> >+ <!--/TMPL_IF--> >+ <!-- TMPL_VAR NAME="holdspickupdelay" --> >+ </td> >+ <!-- TMPL_IF NAME="herited_allowonshelfholds" --> >+ <td class="allowonshelfholds editable reserves triple herited"> >+ <!--TMPL_ELSE--> >+ <td class="allowonshelfholds editable reserves triple"> >+ <!--/TMPL_IF--> >+ <!-- TMPL_IF NAME="allowonshelfholds" --> >+ Yes >+ <!--TMPL_ELSE--> >+ No >+ <!--/TMPL_IF--> >+ </td> >+ <!-- TMPL_IF NAME="herited_holdrestricted" --> >+ <td class="holdrestricted editable reserves boolean herited"> >+ <!--TMPL_ELSE--> >+ <td class="holdrestricted editable reserves boolean"> >+ <!--/TMPL_IF--> >+ <!-- TMPL_IF NAME="holdrestricted" --> >+ Yes >+ <!--TMPL_ELSE--> >+ No >+ <!--/TMPL_IF--> >+ </td> >+ <!-- TMPL_IF NAME="herited_rentaldiscount" --> >+ <td class="rentaldiscount editable issues herited"> >+ <!-- TMPL_ELSE --> >+ <td class="rentaldiscount editable issues"> >+ <!-- /TMPL_IF --> >+ <!-- TMPL_VAR NAME="rentaldiscount" --> >+ </td> >+ <td> >+ <a class="button" href="/cgi-bin/koha/admin/smart-rules.pl?op=delete&itemtype=<!-- TMPL_VAR NAME="itemtype" -->&categorycode=<!-- TMPL_VAR NAME="categorycode" -->&branchcode=<!-- TMPL_VAR NAME="branchcode" -->">Delete</a> >+ </td> >+ </tr> >+ <!-- /TMPL_LOOP --> >+ </tbody> >+ <form method="post" name="inputrules" action="/cgi-bin/koha/admin/smart-rules.pl"> >+ <input type="hidden" name="op" value="add" /> >+ <tfoot> >+ <tr> >+ <td> >+ <select name="categorycode" id="categorycode" style="width:12em;"> >+ <option value="*">Default</option> >+ <!-- TMPL_LOOP NAME="categoryloop" --> >+ <!-- TMPL_IF Name="selected"--> >+ <option value="<!-- TMPL_VAR NAME="categorycode" -->" selected="selected"><!-- TMPL_VAR NAME="description" --></option> >+ <!--TMPL_ELSE --> <option value="<!-- TMPL_VAR NAME="categorycode" -->" ><!-- TMPL_VAR NAME="description" --></option> >+ <!-- /TMPL_IF --> >+ <!-- /TMPL_LOOP --> >+ </select> >+ </td> >+ <td> >+ <select name="itemtype" style="width:12em;"> >+ <option value="*">Default</option> >+ <!-- TMPL_LOOP NAME="itemtypeloop" --> >+ <!-- TMPL_IF Name="selected"--> >+ <option value="<!-- TMPL_VAR NAME="itemtype" -->" selected="selected"><!-- TMPL_VAR NAME="description" --></option> >+ <!--TMPL_ELSE --> <option value="<!-- TMPL_VAR NAME="itemtype" -->"><!-- TMPL_VAR NAME="description" --></option> >+ <!-- /TMPL_IF --> >+ <!-- /TMPL_LOOP --> >+ </select> >+ </td> >+ <td class="issues"><input name="maxissueqty" size="3" value="<!-- TMPL_VAR NAME="maxissueqty" -->"/></td> >+ <td class="issues"><input name="issuelength" size="3" value="<!-- TMPL_VAR NAME="issuelength" -->"/> </td> >+ <td class="fines"><input name="fine" size="4" value="<!-- TMPL_VAR NAME="fine" -->"/></td> >+ <td class="fines"><input name="chargeperiod" size="2" value="<!-- TMPL_VAR NAME="chargeperiod" -->"/></td> >+ <td class="fines"><input name="firstremind" size="2" value="<!-- TMPL_VAR NAME="firstremind" -->"/> </td> >+ <td class="fines"><input name="finedays" size="3" value="<!-- TMPL_VAR NAME="finedays" -->"/> </td> >+ <td class="issues"><input name="renewalsallowed" size="2" value="<!-- TMPL_VAR NAME="renewalsallowed" -->"/></td> >+ <td class="issues"><input name="renewalperiod" size="2" value="<!-- TMPL_VAR NAME="renewalperiod" -->"/></td> >+ <td class="reserves"><input name="reservesallowed" size="2" value="<!-- TMPL_VAR NAME="reservesallowed" -->"/></td> >+ <td class="reserves"><input name="holdspickupdelay" size="2" value="<!-- TMPL_VAR NAME="holdspickupdelay" -->"/></td> >+ <td class="reserves"> >+ <select name="allowonshelfholds"> >+ <option value=""></option> >+ <option value="1">Yes</option> >+ <option value="0">No</option> >+ </select> >+ </td> >+ <td class="reserves"><!-- TMPL_IF NAME="holdrestricted"--><input type="checkbox" name="holdrestricted" checked="checked" value="1"/> <!--TMPL_ELSE--><input type="checkbox" name="holdrestricted" value="1"/> <!-- /TMPL_IF --></td> >+ <td class="issues"><input name="rentaldiscount" size="2" /></td> >+ <td><input type="hidden" name="branchcode" value="<!-- TMPL_VAR NAME="branchcode" -->"/><input type="submit" value="Add" class="submit" /></td> >+ </tr> >+ </tfoot> >+ </form> >+ </table> >+ </div><!-- tabs-container --> >+ </div><!-- toptabs --> > </div> > </div> > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tmpl >index dc7ed5f..dbb43d0 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tmpl >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tmpl >@@ -10,6 +10,12 @@ > <script type="text/javascript"> > //<![CDATA[ > if($.cookie("holdfor") != <!-- TMPL_VAR NAME="borrowernumber" -->){ $.cookie("holdfor",null, { path: "/", expires: 0 }); } >+ >+function Dopop(link) { >+ var newin=window.open(link,'popup','width=600,height=400,resizable=1,toolbar=0,scrollbars=1,top'); >+} >+ >+ > <!-- TMPL_IF NAME="UseTablesortForCirc" -->$.tablesorter.addParser({ > id: 'articles', > is: function(s) {return false; }, >@@ -24,9 +30,20 @@ if($.cookie("holdfor") != <!-- TMPL_VAR NAME="borrowernumber" -->){ $.cookie("ho > dateFormat: 'uk',<!-- /TMPL_IF --> > headers: { 1: { sorter: 'articles' },5: { sorter: false },6:{sorter:false},7:{sorter:false},8:{sorter:false}} > }); >+ $("#relissuest").tablesorter({<!-- TMPL_IF NAME="dateformat_metric" --> >+ dateFormat: 'uk',<!-- /TMPL_IF --> >+ headers: { 1: { sorter: 'articles' },5: { sorter: false },6:{sorter:false},7:{sorter:false},8:{sorter:false}} >+ }); >+ >+ //FIXME: Sorting does not work when there are previous checkouts only >+ // (It works fine when there are only checkouts of the day, or both previous and today checkouts) > $("#issuest").bind("sortEnd",function() { > $("#previous").parents("tr").remove(); // 'previous checkouts' header chokes table sorter > }); >+ $("#relissuest").bind("sortEnd",function() { >+ $("#relprevious").parents("tr").remove(); // 'previous checkouts' header chokes table sorter >+ }); >+ > $("#holdst").tablesorter({<!-- TMPL_IF NAME="dateformat_metric" --> > dateFormat: 'uk',<!-- /TMPL_IF --> > sortList: [[0,0]], >@@ -43,14 +60,15 @@ if($.cookie("holdfor") != <!-- TMPL_VAR NAME="borrowernumber" -->){ $.cookie("ho > <!-- /TMPL_IF --> > > var allcheckboxes = $(".checkboxed"); >- $("#renew_all").click(function(){ >- $(allcheckboxes).checkCheckboxes(":input[name*=items]"); >- $(allcheckboxes).unCheckCheckboxes(":input[name*=barcodes]"); >- }); > $("#CheckAllitems").click(function(){ > $(allcheckboxes).checkCheckboxes(":input[name*=items]"); > $(allcheckboxes).unCheckCheckboxes(":input[name*=barcodes]"); return false; > }); >+// $(":input[name*]=items").click(function(){ >+// var itemnumber=getitemnumber($(this).attr(âidâ)); >+// alert(getitemnumber($(this).attr(âidâ))); >+// $("#return_"+itemnumber).attr('checked', !$(this).attr('checked')); >+// }); > $("#CheckNoitems").click(function(){ > $(allcheckboxes).unCheckCheckboxes(":input[name*=items]"); return false; > }); >@@ -65,12 +83,9 @@ var allcheckboxes = $(".checkboxed"); > <!-- TMPL_IF NAME="CAN_user_circulate_override_renewals" --> > <!-- TMPL_IF NAME="AllowRenewalLimitOverride" --> > $( '#override_limit' ).click( function () { >- if ( this.checked ) { >- $( '.renewals-allowed' ).show(); $( '.renewals-disabled' ).hide(); >- } else { >- $( '.renewals-allowed' ).hide(); $( '.renewals-disabled' ).show(); >- } >+ $( '.renewals-allowed' ).toggle(); > } ).attr( 'checked', false ); >+ $( '.renewals-allowed' ).hide(); > <!-- /TMPL_IF --> > <!-- /TMPL_IF --> > // Clicking the table cell checks the checkbox inside it >@@ -109,13 +124,38 @@ var allcheckboxes = $(".checkboxed"); > radioCheckBox($(this)); > }); > }); >- >+ index = id.IndexOf("_"); >+ return id.substr(index+1); >+} >+function uncheck_sibling(me){ >+nodename=me.getAttribute("name"); >+if (nodename =="barcodes[]"){ >+ var Node=me.parentNode.previousSibling; >+ while (Node.nodeName!="TD"){Node=Node.previousSibling} >+ var Nodes=Node.childNodes; >+ for (var i=0;i<Nodes.length;i++){ >+ if (Nodes[i].nodeName=="INPUT" && Nodes[i].getAttribute("type")=="checkbox"){ >+ Nodes[i].checked=false; >+ } >+ } >+ >+}else { >+ var Node=me.parentNode.nextSibling; >+ while (Node.nodeName!="TD"){Node=Node.nextSibling} >+ var Nodes=Node.childNodes; >+ for (var i=0;i<Nodes.length;i++){ >+ if (Nodes[i].nodeName=="INPUT" && Nodes[i].getAttribute("type")=="checkbox"){ >+ Nodes[i].checked=false; >+ } >+ } >+} >+} > function validate1(date) { > var today = new Date(); >- if ( date < today ) { >- return true; >- } else { >+ if ( today < date || date.toDateString() == today.toDateString() ) { > return false; >+ } else { >+ return true; > } > }; > function refocus(calendar) { >@@ -191,10 +231,17 @@ function refocus(calendar) { > </form> > </div> > >-<!-- TMPL_IF NAME="dateexpiry" --><div class="dialog message">Patron's account has been renewed until <!-- TMPL_VAR NAME="dateexpiry" --></div><!-- /TMPL_IF --> >+<!-- TMPL_INCLUDE NAME="reserves_waiting.inc" --> >+ >+<!-- TMPL_IF name="circnote" --> >+ <div id="circnote" class="dialog alert"> >+ <h3>Circulation note:</h2> >+ <!-- TMPL_VAR name="circnote" --> >+ </div> >+<!-- /TMPL_IF --> >+<!-- TMPL_IF NAME="newexpiry" --><div class="dialog message">Patron's account has been renewed until <!-- TMPL_VAR NAME="newexpiry" --></div><!-- /TMPL_IF --> > <!-- TMPL_IF NAME="NEEDSCONFIRMATION" --> > <div class="yui-g"> >- > <div id="circ_needsconfirmation" class="dialog alert"> > <h3>Please Confirm Checkout</h3> > >@@ -220,23 +267,44 @@ function refocus(calendar) { > <!-- /TMPL_IF --> > > <!-- TMPL_IF NAME="TOO_MANY" --> >- <li>Too many checked out. <!-- TMPL_VAR NAME="current_loan_count" --> checked out, only <!-- TMPL_VAR NAME="max_loans_allowed" --> are allowed.</li> >+ <li>Check out limit reached (already checked out / max : <!-- TMPL_VAR name="TOO_MANY" -->)</li> > <!-- /TMPL_IF --> > > <!-- TMPL_IF NAME="BORRNOTSAMEBRANCH" --> > <li>This patrons is from a different library (<!-- TMPL_VAR NAME="BORRNOTSAMEBRANCH" -->)</li> > <!-- /TMPL_IF --> > >+<!-- TMPL_IF NAME="BRANCH_TRANSFER_NOT_ALLOWED" --> >+ <li>Item should be at <!--TMPL_VAR Name="BRANCH_TRANSFER_NOT_ALLOWED"-->.<br /> It should not be checked out in this library.</li> >+<!-- /TMPL_IF --> >+ > <!-- TMPL_IF NAME="PATRON_CANT" --> >- <li>This patron can't check out this item per library circulation policy</i> >+ <li>This patron can't check out this item per library circulation policy</li> >+<!-- /TMPL_IF --> >+ >+<!-- TMPL_IF NAME="USERBLOCKEDOVERDUE" --> >+ <li>This patron can't check out this item. Debarred until : <!--TMPL_VAR Name="USERBLOCKEDOVERDUE"--> </li> > <!-- /TMPL_IF --> > > <!-- TMPL_IF NAME="NOT_FOR_LOAN_FORCING" --> > <li>Item is normally not for loan. Check out anyway?</li> > <!-- /TMPL_IF --> >-<!-- TMPL_IF NAME="USERBLOCKEDOVERDUE" --> >- <li>Patron has <!-- TMPL_VAR NAME="USERBLOCKEDOVERDUE" --> overdue item(s). Check out anyway?</li> >+<!-- TMPL_IF NAME="DAMAGED" --> >+ <li>Item is considered damaged (<!-- TMPL_VAR NAME="DAMAGED" -->). Check out anyway?</li> >+<!-- /TMPL_IF --> >+ >+<!-- TMPL_IF NAME="ISSUED_TO_ANOTHER" --> >+ <li>Item ( <!-- TMPL_VAR NAME="getTitleMessageIteminfo" --> ) checked out to <!-- TMPL_VAR NAME="ISSUED_TO_ANOTHER" -->. Check in and check out?</li> > <!-- /TMPL_IF --> >+ >+<!-- TMPL_IF NAME="RENEW_ISSUE" --> >+ <li>Item is currently checked out to this patron. Renew?</li> >+<!-- /TMPL_IF --> >+ >+<!-- TMPL_IF NAME="USERBLOCKEDREMAINING" --> >+ <li>Patron cannot check-out this item : has overdue items.</li> >+<!-- /TMPL_IF --> >+ > </ul> > > <form method="post" action="/cgi-bin/koha/circ/circulation.pl"> >@@ -309,6 +377,10 @@ function refocus(calendar) { > <!-- /TMPL_IF --> > <!-- /TMPL_IF --> > >+ <!-- TMPL_IF NAME="LOAN_LENGTH_UNDEFINED" --> >+ <li>No circulation rule defined for <!-- TMPL_VAR Name="LOAN_LENGTH_UNDEFINED"--> </li> >+ <!-- /TMPL_IF --> >+ > <!-- TMPL_IF NAME="NOT_FOR_LOAN" --> > <li>Item not for loan</li> > <!-- /TMPL_IF --> >@@ -322,15 +394,11 @@ function refocus(calendar) { > <!-- /TMPL_IF --> > > <!-- TMPL_IF NAME="GNA" --> >- <li>Patron's address is in doubt</li> >+ <li>Patron's address is in doubt<!-- TMPL_IF NAME="gonenoaddresscomment" -->: <!-- TMPL_VAR NAME="gonenoaddresscomment" --><!-- /TMPL_IF --></li> > <!-- /TMPL_IF --> > > <!-- TMPL_IF NAME="CARD_LOST" --> >- <li>Patron's card is lost</li> >- <!-- /TMPL_IF --> >- >- <!-- TMPL_IF NAME="DEBARRED" --> >- <li>Patron is restricted</li> >+ <li>Patron's card is lost<!-- TMPL_IF NAME="lostcomment" -->: <!-- TMPL_VAR NAME="lostcomment" --><!-- /TMPL_IF --></li> > <!-- /TMPL_IF --> > > <!-- TMPL_IF NAME="NO_MORE_RENEWALS" --> >@@ -359,7 +427,6 @@ function refocus(calendar) { > <!-- /TMPL_IF --> > > </div></div> >-<!-- TMPL_ELSE --> > <!-- TMPL_IF NAME="soundon" --> > <audio src="/intranet-tmpl/prog/sound/beep.ogg" autoplay="autoplay" autobuffer="autobuffer"></audio> > <!-- /TMPL_IF --> >@@ -435,40 +502,29 @@ No patron matched <span class="ex"><!-- TMPL_VAR name="message" --></span> > <img src="<!-- TMPL_VAR Name="themelang" -->/lib/calendar/cal.gif" alt="Show Calendar" border="0" id="CalendarDueDate" style="cursor: pointer;" /> > <script language="JavaScript" type="text/javascript"> > //<![CDATA[ >- function validate1(date) { >- var today = new Date(); >- if ( date < today ) { >- return true; >- } else { >- return false; >- } >- }; >- function refocus(calendar) { >- $('#barcode').focus(); >- calendar.hide(); >- }; > //#TODO - ADD syspref (AllowPostDatedCheckouts). > Calendar.setup( > { > inputField : "duedatespec", > ifFormat : "<!-- TMPL_VAR NAME="DHTMLcalendar_dateformat" -->", > button : "CalendarDueDate", >-// disableFunc : validate1, >-// dateStatusFunc : validate1, >+ dateStatusFunc : validate1, > onClose : refocus > } > ); > //]]> > </script> >- >- <label for="stickyduedate"> Remember for Session:</label> >-<!-- TMPL_IF NAME="stickyduedate" --> >-<input type="checkbox" id="stickyduedate" onclick="this.form.barcode.focus();" name="stickyduedate" checked="checked" /> >-<!-- TMPL_ELSE --> >-<input type="checkbox" id="stickyduedate" onclick="this.form.barcode.focus();" name="stickyduedate" /> >+ </p><p> >+ <label for="stickyduedate"> Remember for Session:</label> >+ <!-- TMPL_IF NAME="stickyduedate" --> >+ <input type="checkbox" id="stickyduedate" onclick="this.form.barcode.focus();" name="stickyduedate" checked="checked" /> >+ <!-- TMPL_ELSE --> >+ <input type="checkbox" id="stickyduedate" onclick="this.form.barcode.focus();" name="stickyduedate" /> >+ <!-- /TMPL_IF --> >+ <input type="button" class="action" id="cleardate" value="Clear" name="cleardate" onclick="this.checked = false; this.form.duedatespec.value = ''; this.form.stickyduedate.checked = false; this.form.barcode.focus(); return false;" /> >+ </p> >+ </div> > <!-- /TMPL_IF --> >- <input type="button" class="action" id="cleardate" value="Clear" name="cleardate" onclick="this.checked = false; this.form.duedatespec.value = ''; this.form.stickyduedate.checked = false; this.form.barcode.focus(); return false;" /> >-</div><!-- /TMPL_IF --> > <input type="hidden" name="borrowernumber" id="borrowernumber" value="<!-- TMPL_VAR NAME="borrowernumber" -->" /> > <input type="hidden" name="branch" value="<!-- TMPL_VAR NAME="branch" -->" /> > <input type="hidden" name="printer" value="<!-- TMPL_VAR NAME="printer" -->" /> >@@ -491,9 +547,8 @@ No patron matched <span class="ex"><!-- TMPL_VAR name="message" --></span> > <div id="circmessages" class="circmessage attention"> > <!-- /TMPL_IF --> > >- <h3><!-- TMPL_IF NAME="noissues" --> >- Cannot check out! >- <!-- TMPL_ELSE -->Attention:<!-- /TMPL_IF --></h3> >+ <h3><!-- TMPL_IF NAME="noissues" -->Cannot Check Out!<!-- TMPL_ELSE --> >+ <!-- TMPL_IF NAME="warning" -->Attention:<!-- /TMPL_IF --><!-- /TMPL_IF --></h3> > <ul> > > <!-- TMPL_IF NAME = "warndeparture" --> >@@ -517,16 +572,21 @@ No patron matched <span class="ex"><!-- TMPL_VAR name="message" --></span> > <!-- /TMPL_IF --> > > <!-- TMPL_IF NAME="gna" --> >- <li class="blocker"><span class="circ-hlt">Address:</span> Patron's address in doubt</li> >+ <li class="blocker"><span class="circ-hlt">Address: </span>Patron's address is in doubt<!-- TMPL_IF NAME="gonenoaddresscomment" --> (<!-- TMPL_VAR NAME="gonenoaddresscomment" -->)<!-- /TMPL_IF --></li> > <!-- /TMPL_IF --> > > <!-- TMPL_IF NAME="lost" --> >- <li class="blocker"><span class="circ-hlt">Lost: </span>Patron's card is lost</li> >+ <li class="blocker"><span class="circ-hlt">Lost: </span>Patron's card is lost<!-- TMPL_IF NAME="lostcomment" --> (<!-- TMPL_VAR NAME="lostcomment" -->)<!-- /TMPL_IF --></li> > <!-- /TMPL_IF --> > >- <!-- TMPL_IF NAME="dbarred" --><li class="blocker"> >- <span class="circ-hlt"> Restricted:</span> Patron's account is restricted <a href="/cgi-bin/koha/members/setstatus.pl?borrowernumber=<!-- TMPL_VAR NAME="borrowernumber" -->&cardnumber=<!-- TMPL_VAR NAME="cardnumber" -->&destination=circ&status=0">Lift restriction</a> >-</li><!-- /TMPL_IF --> >+ <!-- TMPL_IF NAME="userdebarred" --><li class="blocker"> >+ <span class="circ-hlt"> Restricted:</span> Patron's account is restricted<!-- TMPL_IF NAME="userdebarreddate" --> until <!-- TMPL_VAR NAME="userdebarreddate" --> <!--/TMPL_IF--> <!-- TMPL_IF NAME="debarredcomment"-->(<!-- TMPL_VAR NAME="debarredcomment" -->)<!-- /TMPL_IF --> >+ <form class="inline compact" action="/cgi-bin/koha/members/setstatus.pl" method="post"> >+ <input type="hidden" name="borrowernumber" value="<!-- TMPL_VAR NAME="borrowernumber" -->" /> >+ <input type="hidden" name="destination" value="circ" /> >+ <input type="submit" value="Lift Debarment" /> >+ </form> >+ </li><!-- /TMPL_IF --> > > <!-- TMPL_IF name="odues" --><li><!-- TMPL_IF name="nonreturns" --><span class="circ-hlt">Overdues:</span> Patron has <span class="circ-hlt">ITEMS OVERDUE</span>. See highlighted items <a href="#checkouts">below</a><!-- /TMPL_IF --></li> > <!-- /TMPL_IF --> >@@ -556,7 +616,7 @@ No patron matched <span class="ex"><!-- TMPL_VAR name="message" --></span> > <h4>Holds waiting:</h4> > <!-- TMPL_LOOP NAME="WaitingReserveLoop" --> > <ul> >- <li> <a href="/cgi-bin/koha/reserve/request.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->"><!-- TMPL_VAR NAME="title" escape="html" --></a> (<!-- TMPL_VAR NAME="itemtype"-->), <!-- TMPL_IF NAME="author" -->by <!-- TMPL_VAR NAME="author"--><!-- /TMPL_IF --> Hold placed on <!-- TMPL_VAR NAME="reservedate"-->. >+ <li> <a href="/cgi-bin/koha/reserve/request.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->"><!-- TMPL_VAR NAME="title" escape="html" --></a> (<!-- TMPL_VAR NAME="itemtype"-->), <!-- TMPL_IF NAME="author" -->by <!-- TMPL_VAR NAME="author"--><!-- /TMPL_IF --> Hold placed on <!-- TMPL_VAR NAME="reservedate"--> waiting until <!-- TMPL_VAR NAME="formattedwaitingdate" --> > <!-- TMPL_IF NAME="waitingat" --> > <br /><!-- TMPL_IF NAME="waitinghere" --><strong class="waitinghere"><!-- TMPL_ELSE --><strong><!-- /TMPL_IF -->Waiting at <!-- TMPL_VAR NAME="waitingat" --></strong> > <!-- /TMPL_IF --> >@@ -632,20 +692,58 @@ No patron matched <span class="ex"><!-- TMPL_VAR name="message" --></span> > <input type="hidden" name="borrowernumber" value="<!-- TMPL_VAR NAME="borrowernumber" -->" /> > <input type="hidden" name="branch" value="<!-- TMPL_VAR NAME="branch" -->" /> > <table id="issuest"> >- <thead><tr> >+ <thead> >+ <tr> > <th scope="col">Due date</th> > <th scope="col">Title</th> > <th scope="col">Item Type</th> >+ <th scope="col">Branch</th> > <th scope="col">Checked out on</th> >- <th scope="col">Call no</th> >+ <!-- TMPL_IF NAME="multiple_borrowers" --><th scope="col">Borrower</th><!-- /TMPL_IF --> > <th scope="col">Charge</th> >- <th scope="col">Price</th> >+ <th scope="col">Material</th> > <th scope="col">Renew <p class="column-tool"><a href="#" id="CheckAllitems">select all</a> | <a href="#" id="CheckNoitems">none</a></p></th> > <th scope="col">Check in <p class="column-tool"><a href="#" id="CheckAllreturns">select all</a> | <a href="#" id="CheckNoreturns">none</a></p></th> > </tr> >-<!-- TMPL_IF NAME="todayissues" --></thead> >-<!-- TMPL_INCLUDE NAME="checkouts-table-footer.inc" --> >- <tbody> >+</thead> >+<tfoot> >+ <tr> >+ <td colspan="<!-- TMPL_IF NAME="multiple_borrowers" -->6<!-- TMPL_ELSE -->5<!-- /TMPL_IF -->" style="text-align: right; font-weight:bold;">Totals:</td> >+ <td><!-- TMPL_VAR NAME="totaldue" --></td> >+ <td><!-- TMPL_VAR NAME="totalprice" --></td> >+ <td colspan="2"> >+ <p> >+ Renewal due date: <input type="text" size="8" id="newduedate" name="newduedate" value="<!-- TMPL_VAR Name="newduedate" -->" /> >+ <img src="<!-- TMPL_VAR Name="themelang" -->/lib/calendar/cal.gif" id="newduedate_button" alt="Show Calendar" /> >+ <script type="text/javascript"> //<![CDATA[ >+ //#TODO - ADD syspref (AllowPostDatedCheckouts). >+ Calendar.setup( >+ { >+ inputField : "newduedate", >+ ifFormat : "<!-- TMPL_VAR NAME="DHTMLcalendar_dateformat" -->", >+ button : "newduedate_button", >+ dateStatusFunc : validate1, >+ onClose : refocus >+ } >+ ); >+ //]]> >+ </script> >+ </p> >+ <p> >+ <label for="exemptfine">Forgive fines on return: </label><input type="checkbox" name="exemptfine" value="1" /> >+ </p> >+ <!-- TMPL_IF NAME="CAN_user_circulate_override_renewals" --> >+ <!-- TMPL_IF NAME="AllowRenewalLimitOverride" --> >+ <p> >+ <label for="override_limit">Override Renewal Limit:</label> >+ <input type="checkbox" name="override_limit" id="override_limit" value="1" /> >+ </p> >+ <!-- /TMPL_IF --> >+ <!-- /TMPL_IF --> >+ </td> >+ </tr> >+ </tfoot> >+<!-- TMPL_IF NAME="todayissues" --> <tbody> > > <!-- TMPL_LOOP NAME="todayissues" --> > <!-- TMPL_IF NAME="__odd__" --> >@@ -653,121 +751,95 @@ No patron matched <span class="ex"><!-- TMPL_VAR name="message" --></span> > <!-- TMPL_ELSE --> > <tr class="highlight"> > <!-- /TMPL_IF --> >- <!-- TMPL_IF NAME="od" --><td class="od"><!-- TMPL_ELSE --><td><!-- /TMPL_IF --> >- <!-- TMPL_VAR NAME="dd" --> >- </td> >+ <!-- TMPL_IF NAME="overdue" --><td class="od"><!-- TMPL_ELSE --><td><!-- /TMPL_IF --> >+ <!-- TMPL_VAR NAME="dd" --></td> > <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->&type=intra"><strong><!-- TMPL_VAR NAME="title" escape="html" --></strong></a><!-- TMPL_IF NAME="author" -->, by <!-- TMPL_VAR NAME="author" --><!-- /TMPL_IF --><!-- TMPL_IF NAME="itemnotes" -->- <span class="circ-hlt"><!-- TMPL_VAR name="itemnotes" --></span><!-- /TMPL_IF --> <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->&itemnumber=<!-- TMPL_VAR NAME="itemnumber" -->#item<!-- TMPL_VAR NAME="itemnumber" -->"><!-- TMPL_VAR NAME="barcode" --></a></td> > <td><!-- TMPL_UNLESS NAME="noItemTypeImages" --> <!-- TMPL_IF NAME="itemtype_image" --><img src="<!-- TMPL_VAR NAME="itemtype_image" -->" alt="" /><!-- /TMPL_IF --><!-- /TMPL_UNLESS --><!-- TMPL_VAR NAME="itemtype" --></td> >- <td><!-- TMPL_VAR NAME="checkoutdate" --></td> >- <td><!-- TMPL_VAR NAME="itemcallnumber" --></td> >+ <td><!-- TMPL_VAR NAME="branchdisplay" --> >+ <!--TMPL_IF Name="itemcallnumber"-->(<!-- TMPL_VAR NAME="itemcallnumber" -->)<!--/TMPL_IF--></td> >+ <td><!-- TMPL_VAR NAME="displaydate" --></td> >+ <!-- TMPL_IF NAME="multiple_borrowers" --><td><!-- TMPL_VAR NAME="borrowername" --></td><!-- /TMPL_IF --> > <td><!-- TMPL_VAR NAME="charge" --></td> >- <td><!-- TMPL_VAR NAME="replacementprice" --></td> >- <!-- TMPL_IF NAME="renew_failed" --> >- <td class="problem">Renewal Failed</td> >- <!-- TMPL_ELSE --> >- <td><span style="padding: 0 1em;"><!-- TMPL_IF NAME="renewals" --><!-- TMPL_VAR NAME="renewals" --><!-- TMPL_ELSE -->0<!-- /TMPL_IF --></span> >- <!-- TMPL_IF NAME="can_renew" --> >- <input type="checkbox" name="all_items[]" value="<!-- TMPL_VAR NAME="itemnumber" -->" checked="checked" style="display: none;" /> >- <!-- TMPL_IF NAME="od" --> >- <input type="checkbox" class="radio" name="items[]" value="<!-- TMPL_VAR NAME="itemnumber" -->" checked="checked" /> >- <!-- TMPL_ELSE --> >- <input type="checkbox" class="radio" name="items[]" value="<!-- TMPL_VAR NAME="itemnumber" -->" /> >- <!-- /TMPL_IF --> >- <!-- TMPL_ELSE --> >- <!-- TMPL_IF NAME="can_confirm" --><span class="renewals-allowed" style="display: none"> >- <input type="checkbox" name="all_items[]" value="<!-- TMPL_VAR NAME="itemnumber" -->" checked="checked" style="display: none;" /> >- <!-- TMPL_IF NAME="od" --> >- <input type="checkbox" class="radio" name="items[]" value="<!-- TMPL_VAR NAME="itemnumber" -->" checked="checked" /> >- <!-- TMPL_ELSE --> >- <input type="checkbox" class="radio" name="items[]" value="<!-- TMPL_VAR NAME="itemnumber" -->" /> >- <!-- /TMPL_IF --> >- </span> >- <span class="renewals-disabled"> >- <!-- /TMPL_IF --> >- <!-- TMPL_IF NAME="renew_error_on_reserve" --> >- On Hold >- <!-- /TMPL_IF --> >- <!-- TMPL_IF NAME="renew_error_too_many" --> >- Not Renewable >- <!-- /TMPL_IF --> >- <!-- TMPL_IF NAME="can_confirm" --> >+ <td><!-- TMPL_VAR NAME="materials" --></td> >+ <td><span style="padding: 0 1em;"> >+ <!-- TMPL_IF Name="renew_error_too_many"--><span class="problem"><!-- /TMPL_IF --> >+ <!-- TMPL_VAR NAME="renewals" -->/<!-- TMPL_VAR NAME="renewalsallowed" --> >+ <!-- TMPL_IF NAME="renew_error_too_many"--></span><!-- /TMPL_IF --> > </span> >+ <!-- TMPL_UNLESS NAME="can_renew" --> >+ <span class="renewals-allowed" style="display: none"> >+ <!-- /TMPL_UNLESS --> >+ <input type="checkbox" id="renew_<!--TMPL_VAR NAME="itemnumber"-->" name="items[]" value="<!-- TMPL_VAR NAME="itemnumber" -->" /> >+ <!-- TMPL_UNLESS NAME="can_renew" --> >+ </span> >+ <!-- /TMPL_UNLESS --> >+ >+ <!-- TMPL_IF NAME="renew_error"--> >+ <br/> >+ <span class="renewals-disabled problem"> >+ <!-- TMPL_IF NAME="renew_error_on_reserve" --> On Hold <!-- /TMPL_IF --> >+ <!-- TMPL_IF NAME="renew_error_overdue" --> Overdue <!-- /TMPL_IF --> >+ <!-- TMPL_IF NAME="renew_error_too_many" --> Not Renewable <!-- /TMPL_IF --> >+ </span> > <!-- /TMPL_IF --> >- <!-- /TMPL_IF --> > </td> >- <!-- /TMPL_IF --> > <!-- TMPL_IF NAME="return_failed" --> > <td class="problem">Checkin Failed</td> > <!--TMPL_ELSE--> >- <td><input type="checkbox" class="radio" name="barcodes[]" value="<!-- TMPL_VAR NAME="barcode" -->" /> >- <input type="checkbox" name="all_barcodes[]" value="<!-- TMPL_VAR NAME="barcode" -->" checked="checked" style="display: none;" /> >+ <td style="text-align:center;"><input type="checkbox" id="return_<!--TMPL_VAR NAME="itemnumber"-->" name="barcodes[]" value="<!-- TMPL_VAR NAME="barcode" -->" /> >+ <!-- TMPL_IF Name="reserved"--><br/><a href="javascript:void(0);" onclick="window.open('/cgi-bin/koha/reserve/request.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->')">On Hold</a><!-- /TMPL_IF --> > </td> > <!-- /TMPL_IF --> > </tr> > <!-- /TMPL_LOOP --> <!-- /loop todayissues --> > <!-- /if todayissues --><!-- /TMPL_IF --> > <!-- TMPL_IF NAME="previssues" --> >-<!-- TMPL_IF NAME="todayissues" --><tr><th colspan="10"><a name="previous" id="previous"></a>Previous checkouts</th></tr><!-- TMPL_ELSE --> >-<tr><th class="{sorter: false}" colspan="10"><a name="previous" id="previous"></a>Previous checkouts</th></tr></thead> >-<!-- TMPL_INCLUDE NAME="checkouts-table-footer.inc" --> >- <tbody> >-<!-- /TMPL_IF --> >+<tr><th class="{sorter: false}" colspan="<!-- TMPL_IF NAME="multiple_borrowers"-->10<!-- TMPL_ELSE -->9<!-- /TMPL_IF -->"><a name="previous" id="previous"></a>Previous checkouts</th></tr> > <!-- TMPL_LOOP NAME="previssues" --> > <!-- TMPL_IF NAME="__odd__" --> > <tr> > <!-- TMPL_ELSE --> > <tr class="highlight"> > <!-- /TMPL_IF --> >- <!-- TMPL_IF NAME="od" --><td class="od"><!-- TMPL_ELSE --><td><!-- /TMPL_IF --> >+ <!-- TMPL_IF NAME="overdue" --><td class="od"><!-- TMPL_ELSE --><td><!-- /TMPL_IF --> > <!-- TMPL_VAR NAME="dd" --> > </td> > <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->&type=intra"><strong><!-- TMPL_VAR NAME="title" escape="html" --></strong></a><!-- TMPL_IF NAME="author" -->, by <!-- TMPL_VAR NAME="author" --><!-- /TMPL_IF --> <!-- TMPL_IF NAME="itemnotes" -->- <!-- TMPL_VAR name="itemnotes" --><!-- /TMPL_IF --> <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->&itemnumber=<!-- TMPL_VAR NAME="itemnumber" -->#item<!-- TMPL_VAR NAME="itemnumber" -->"><!-- TMPL_VAR NAME="barcode" --></a></td> > <td> > <!-- TMPL_VAR NAME="itemtype" --> > </td> >+ <td><!-- TMPL_VAR NAME="branchdisplay" --> >+ <!--TMPL_IF NAME="itemcallnumber"-->(<!-- TMPL_VAR NAME="itemcallnumber" -->)<!--/TMPL_IF--></td> > <td><!-- TMPL_VAR NAME="displaydate" --></td> >- <td><!-- TMPL_VAR NAME="itemcallnumber" --></td> >+ <!-- TMPL_IF NAME="multiple_borrowers" --><td><!-- TMPL_VAR NAME="borrowername" --></td><!-- /TMPL_IF --> > <td><!-- TMPL_VAR NAME="charge" --></td> >- <td><!-- TMPL_VAR NAME="replacementprice" --></td> >- <!-- TMPL_IF NAME="renew_failed" --> >- <td class="problem">Renewal Failed</td> >- <!-- TMPL_ELSE --> >- <td><span style="padding: 0 1em;"><!-- TMPL_IF NAME="renewals" --><!-- TMPL_VAR NAME="renewals" --><!-- TMPL_ELSE -->0<!-- /TMPL_IF --></span> >- <!-- TMPL_IF NAME="can_renew" --> >- <input type="checkbox" name="all_items[]" value="<!-- TMPL_VAR NAME="itemnumber" -->" checked="checked" style="display: none;" /> >- <!-- TMPL_IF NAME="od" --> >- <input type="checkbox" class="radio" name="items[]" value="<!-- TMPL_VAR NAME="itemnumber" -->" checked="checked" /> >- <!-- TMPL_ELSE --> >- <input type="checkbox" class="radio" name="items[]" value="<!-- TMPL_VAR NAME="itemnumber" -->" /> >- <!-- /TMPL_IF --> >- <!-- TMPL_ELSE --> >- <!-- TMPL_IF NAME="can_confirm" --><span class="renewals-allowed" style="display: none"> >- <input type="checkbox" name="all_items[]" value="<!-- TMPL_VAR NAME="itemnumber" -->" checked="checked" style="display: none;" /> >- <!-- TMPL_IF NAME="od" --> >- <input type="checkbox" class="radio" name="items[]" value="<!-- TMPL_VAR NAME="itemnumber" -->" checked="checked" /> >- <!-- TMPL_ELSE --> >- <input type="checkbox" class="radio" name="items[]" value="<!-- TMPL_VAR NAME="itemnumber" -->" /> >- <!-- /TMPL_IF --> >- </span> >- <span class="renewals-disabled"> >- <!-- /TMPL_IF --> >- <!-- TMPL_IF NAME="renew_error_on_reserve" --> >- On Hold >- <!-- /TMPL_IF --> >- <!-- TMPL_IF NAME="renew_error_too_many" --> >- Not Renewable >- <!-- /TMPL_IF --> >- <!-- TMPL_IF NAME="can_confirm" --> >- </span> >+ <td><!-- TMPL_VAR NAME="materials" --></td> >+ <td style="text-align : center;"><span style="padding: 0 1em;"> >+ <!-- TMPL_IF Name="renew_error_too_many"--><span class="problem"><!-- /TMPL_IF --> >+ <!-- TMPL_VAR NAME="renewals" -->/<!-- TMPL_VAR NAME="renewalsallowed" --> >+ <!-- TMPL_IF Name="renew_error_too_many"--></span><!-- /TMPL_IF --> >+ </span> >+ <!-- TMPL_UNLESS NAME="can_renew" --> >+ <span class="renewals-allowed" style="display: none"> >+ <!-- /TMPL_UNLESS --> >+ <input type="checkbox" id="renew_<!--TMPL_VAR NAME="itemnumber"-->" name="items[]" value="<!-- TMPL_VAR NAME="itemnumber" -->" /> >+ <!-- TMPL_UNLESS NAME="can_renew" --> >+ </span> >+ <!-- /TMPL_UNLESS --> >+ <!-- TMPL_IF NAME="renew_error"--> >+ <br/> >+ <span class="renewals-disabled problem"> >+ <!-- TMPL_IF NAME="renew_error_on_reserve" --> On Hold <!-- /TMPL_IF --> >+ <!-- TMPL_IF NAME="renew_error_overdue" --> Overdue <!-- /TMPL_IF --> >+ <!-- TMPL_IF NAME="renew_error_too_many" --> Not Renewable <!-- /TMPL_IF --> >+ </span> > <!-- /TMPL_IF --> >- <!-- /TMPL_IF --> > </td> >- <!-- /TMPL_IF --> > <!-- TMPL_IF NAME="return_failed" --> > <td class="problem">Checkin Failed</td> >- <!--TMPL_ELSE--> >- <td><input type="checkbox" class="radio" name="barcodes[]" value="<!-- TMPL_VAR NAME="barcode" -->" /> >- <input type="checkbox" name="all_barcodes[]" value="<!-- TMPL_VAR NAME="barcode" -->" checked="checked" style="display: none;" /> >+ <!--TMPL_ELSE--> >+ <td style="text-align : center;"><input type="checkbox" id="return_<!--TMPL_VAR NAME="itemnumber"-->" name="barcodes[]" value="<!-- TMPL_VAR NAME="barcode" -->" onclick="uncheck_sibling(this);" /> >+ <!-- TMPL_IF Name="reserved"--><br/><a href="javascript:void(0);" onclick="window.open('/cgi-bin/koha/reserve/request.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->')">On Hold</a><!-- /TMPL_IF --> > </td> > <!-- /TMPL_IF --> > </tr> >@@ -777,20 +849,81 @@ No patron matched <span class="ex"><!-- TMPL_VAR name="message" --></span> > </table> > <!--TMPL_IF NAME="issuecount"--> > <fieldset class="action"> >- <!-- TMPL_IF NAME="CAN_user_circulate_override_renewals" --> >- <!-- TMPL_IF NAME="AllowRenewalLimitOverride" --> >- <label for="override_limit">Override Renewal Limit:</label> >- <input type="checkbox" name="override_limit" id="override_limit" value="1" /> >- <!-- /TMPL_IF --> >- <!-- /TMPL_IF --> > <input type="submit" name="renew_checked" value="Renew or Return checked items" /> >- <input type="submit" id="renew_all" name="renew_all" value="Renew all" /> > </fieldset> > <!-- /TMPL_IF --> > </form> > <!-- TMPL_ELSE --> > <p>Patron has nothing checked out.</p> > <!-- /TMPL_IF --> >+ >+ >+<!-- TMPL_IF NAME="displayrelissues" --> >+<h2>Relatives issues</h2> >+ <table id="relissuest"> >+ <thead> >+ <tr> >+ <th scope="col">Due date</th> >+ <th scope="col">Title</th> >+ <th scope="col">Item Type</th> >+ <th scope="col">Branch</th> >+ <th scope="col">Checked out on</th> >+ <th scope="col">Charge</th> >+ <th scope="col">Borrower</th> >+ <th scope="col">Material</th> >+ </tr> >+ </thead> >+<!-- TMPL_IF NAME="relissues" --> <tbody> >+ >+ <!-- TMPL_LOOP NAME="relissues" --> >+ <!-- TMPL_IF NAME="__odd__" --> >+ <tr> >+ <!-- TMPL_ELSE --> >+ <tr class="highlight"> >+ <!-- /TMPL_IF --> >+ <!-- TMPL_IF NAME="overdue" --><td class="od"><!-- TMPL_ELSE --><td><!-- /TMPL_IF --> >+ <!-- TMPL_VAR NAME="dd" --></td> >+ <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->&type=intra"><strong><!-- TMPL_VAR NAME="title" escape="html" --></strong></a><!-- TMPL_IF NAME="author" -->, by <!-- TMPL_VAR NAME="author" --><!-- /TMPL_IF --><!-- TMPL_IF NAME="itemnotes" -->- <span class="circ-hlt"><!-- TMPL_VAR name="itemnotes" --></span><!-- /TMPL_IF --> <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->&itemnumber=<!-- TMPL_VAR NAME="itemnumber" -->#item<!-- TMPL_VAR NAME="itemnumber" -->"><!-- TMPL_VAR NAME="barcode" --></a></td> >+ <td><!-- TMPL_UNLESS NAME="noItemTypeImages" --> <!-- TMPL_IF NAME="itemtype_image" --><img src="<!-- TMPL_VAR NAME="itemtype_image" -->" alt="" /><!-- /TMPL_IF --><!-- /TMPL_UNLESS --><!-- TMPL_VAR NAME="itemtype" --></td> >+ <td><!-- TMPL_VAR NAME="branchdisplay" --> >+ <!--TMPL_IF Name="itemcallnumber"-->(<!-- TMPL_VAR NAME="itemcallnumber" -->)<!--/TMPL_IF--></td> >+ <td><!-- TMPL_VAR NAME="displaydate" --></td> >+ <td><!-- TMPL_VAR NAME="charge" --></td> >+ <td><a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=<!-- TMPL_VAR NAME="borrowernumber" -->"><!-- TMPL_VAR NAME="borrowername" --></a></td> >+ <td><!-- TMPL_VAR NAME="materials" --></td> >+ </tr> >+ <!-- /TMPL_LOOP --> <!-- /loop todayissues --> >+ <!-- /if todayissues --><!-- /TMPL_IF --> >+<!-- TMPL_IF NAME="relprevissues" --> >+<tr><th class="{sorter: false}" colspan="10"><a name="relprevious" id="relprevious"></a>Previous checkouts</th></tr> >+ <!-- TMPL_LOOP NAME="relprevissues" --> >+ <!-- TMPL_IF NAME="__odd__" --> >+ <tr> >+ <!-- TMPL_ELSE --> >+ <tr class="highlight"> >+ <!-- /TMPL_IF --> >+ <!-- TMPL_IF NAME="overdue" --><td class="od"><!-- TMPL_ELSE --><td><!-- /TMPL_IF --> >+ <!-- TMPL_VAR NAME="dd" --> >+ </td> >+ <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->&type=intra"><strong><!-- TMPL_VAR NAME="title" escape="html" --></strong></a><!-- TMPL_IF NAME="author" -->, by <!-- TMPL_VAR NAME="author" --><!-- /TMPL_IF --> <!-- TMPL_IF NAME="itemnotes" -->- <!-- TMPL_VAR name="itemnotes" --><!-- /TMPL_IF --> <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->&itemnumber=<!-- TMPL_VAR NAME="itemnumber" -->#item<!-- TMPL_VAR NAME="itemnumber" -->"><!-- TMPL_VAR NAME="barcode" --></a></td> >+ <td> >+ <!-- TMPL_VAR NAME="itemtype" --> >+ </td> >+ <td><!-- TMPL_VAR NAME="branchdisplay" --> >+ <!--TMPL_IF NAME="itemcallnumber"-->(<!-- TMPL_VAR NAME="itemcallnumber" -->)<!--/TMPL_IF--></td> >+ <td><!-- TMPL_VAR NAME="displaydate" --></td> >+ <!-- TMPL_IF NAME="multiple_borrowers" --><td><!-- TMPL_VAR NAME="borrowername" --></td><!-- /TMPL_IF --> >+ <td><!-- TMPL_VAR NAME="charge" --></td> >+ <td><a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=<!-- TMPL_VAR NAME="borrowernumber" -->"><!-- TMPL_VAR NAME="borrowername" --></a></td> >+ <td><!-- TMPL_VAR NAME="materials" --></td> >+ </tr> >+ <!-- /loop previssues --><!-- /TMPL_LOOP --> >+<!--/if previssues --><!-- /TMPL_IF --> >+ </tbody> >+ </table> >+</form> >+<!-- /TMPL_IF --><!-- end displayrelissues --> >+ > </div> > > >@@ -814,7 +947,7 @@ No patron matched <span class="ex"><!-- TMPL_VAR name="message" --></span> > <td><a href="/cgi-bin/koha/reserve/request.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->"><strong><!-- TMPL_VAR NAME="title" escape="html" --></strong></a><!-- TMPL_IF NAME="author" -->, by <!-- TMPL_VAR NAME="author" --><!-- /TMPL_IF --></td> > <td><!-- TMPL_VAR NAME="itemcallnumber" --></td> > <td><em><!-- TMPL_IF name="barcodereserv" -->Item <!-- TMPL_VAR NAME="barcodereserv" --> >- <!-- /TMPL_IF --><!-- TMPL_IF name="waiting" --> <strong>waiting at <!-- TMPL_VAR NAME="waitingat" --></strong> >+ <!-- /TMPL_IF --><!-- TMPL_IF name="waiting" --> <strong>waiting at <!-- TMPL_VAR NAME="waitingat" --> <!-- TMPL_IF name="formattedwaitingdate" --> until <!-- TMPL_VAR NAME="formattedwaitingdate" --><!--/TMPL_IF--></strong> > <!-- /TMPL_IF --> > <!-- TMPL_IF name="transfered" --> <strong>in transit</strong> from > <!-- TMPL_VAR NAME="frombranch" --> since <!-- TMPL_VAR NAME="datesent" --> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tmpl >index 724a3e9..d39f4a5 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tmpl >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tmpl >@@ -1,6 +1,9 @@ > <!-- TMPL_INCLUDE NAME="doc-head-open.inc" --> > <title>Koha › Circulation › Check In <!-- TMPL_VAR Name="title" escape="html" --></title> > <!-- TMPL_INCLUDE NAME="doc-head-close.inc" --> >+<style type="text/css"> >+ background-color: red; >+</style> > <script type="text/javascript"> > //<![CDATA[ > function Dopop(link) { >@@ -46,7 +49,6 @@ function Dopop(link) { > <!-- TMPL_INCLUDE NAME="checkin-search.inc" --> > > <div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/circ/circulation-home.pl">Circulation</a> › Check In</div> >- > <div id="doc" class="yui-t7"> > > <div id="bd"> >@@ -54,8 +56,11 @@ function Dopop(link) { > > <div class="yui-g"> > >-<!-- TMPL_IF Name="collectionItemNeedsTransferred" --> >- <div class="dialog message">This item is part of a Rotating Collection and needs to be Transferred to <!-- TMPL_VAR NAME="collectionBranch" --></div> >+<!-- TMPL_IF name="circnote" --> >+ <div id="circnote" class="dialog alert"> >+ <h3>Circulation note:</h2> >+ <!-- TMPL_VAR name="circnote" --> >+ </div> > <!-- /TMPL_IF --> > > <!-- Patron has fines --> >@@ -68,9 +73,18 @@ function Dopop(link) { > > > <!-- TMPL_IF NAME="wrongbranch" --> >-<div class="dialog alert"><h3>Cannot Check In</h3><p>This item must be checked in at its home library. <strong>NOT CHECKED IN</strong></p> >+<div class="dialog alert"><h3>Cannot Check In</h3><p>This item must be checked in at its home library: <!-- TMPL_VAR Name="rightbranch" -->. <strong>NOT CHECKED IN</strong></p> >+ <form method="post" action="returns.pl" class="confirm"> >+ >+ <input type="hidden" name="barcode" value="<!-- TMPL_VAR Name="barcode" -->" /> >+ <input type="hidden" name="exemptfine" value="<!-- TMPL_VAR Name="exemptfine" -->" /> >+ <input type="hidden" name="dropboxmode" value="<!-- TMPL_VAR Name="dropboxmode" -->" /> >+ <input type="submit" name="override" value="Check-In" class="submit" /> >+ <input type="submit" name="cancel" value="Cancel" class="submit" /> >+ </form> > </div> > <!-- /TMPL_IF --> >+ > <!-- case of a mistake in transfer loop --> > <!-- TMPL_IF Name="WrongTransfer" --><div class="dialog message"><!-- WrongTransfer --><h3>Please return <a href="/cgi-bin/koha/catalogue/detail.pl?type=intra&biblionumber=<!-- TMPL_VAR NAME="itembiblionumber" -->"><!-- TMPL_VAR Name="title" escape="html" --></a> to <!-- TMPL_VAR Name="TransferWaitingAt" --></h3> > <!-- TMPL_IF Name="wborcnum"--><h5>Hold for:</h5> >@@ -98,11 +112,6 @@ function Dopop(link) { > <!-- case of a reservation found, and display info --> > <!-- TMPL_IF Name="waiting" --> > <!-- waiting --> >- >-<!-- TMPL_IF NAME="soundon" --> >-<audio src="/intranet-tmpl/prog/sound/ending.ogg" autoplay="autoplay" autobuffer="autobuffer"></audio> >-<!-- /TMPL_IF --> >- > <div class="dialog message"> > <h3>Hold Found (item is already waiting): <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=<!-- TMPL_VAR NAME="itembiblionumber" -->"><!-- TMPL_VAR Name="title" escape="html" --></a></h3> > <!-- TMPL_IF NAME="reservenotes" --><h4>Notes: <!-- TMPL_VAR Name="reservenotes" --></h4><!-- /TMPL_IF --> >@@ -114,8 +123,9 @@ function Dopop(link) { > <!-- TMPL_VAR Name="borcity" --> <!-- TMPL_VAR NAME="borzip" --></li> > <!-- TMPL_IF NAME="borphone" --><li> <!-- TMPL_VAR Name="borphone" --></li><!-- /TMPL_IF --> > <!-- TMPL_IF NAME="boremail" --><li><a id="boremail" href="mailto:<!-- TMPL_VAR NAME="boremail" -->"><!-- TMPL_VAR NAME="boremail" --></a></li><!-- /TMPL_IF --> >-<!-- TMPL_IF NAME="debarred" --><li class="error">Patron is RESTRICTED</li><!-- /TMPL_IF --> >-<!-- TMPL_IF NAME="gonenoaddress" --><li class="error">Patron's address is in doubt</li><!-- /TMPL_IF --></ul> >+<!-- TMPL_IF NAME="lost" --><li class="error">Patron's card is lost <!-- TMPL_IF Name="lostcomment" -->(<!-- TMPL_VAR NAME="lostcomment" -->)<!-- /TMPL_IF --></li><!-- /TMPL_IF --> >+<!-- TMPL_IF NAME="debarred" --><li class="error">Patron is RESTRICTED <!-- TMPL_IF Name="debarredcomment" -->(<!-- TMPL_VAR NAME="debarredcomment" -->)<!-- /TMPL_IF --></li><!-- /TMPL_IF --> >+<!-- TMPL_IF NAME="gonenoaddress" --><li class="error">Patron's address is in doubt<!-- TMPL_IF Name="gonenoaddresscomment" -->(<!-- TMPL_VAR NAME="gonenoaddresscomment" -->)<!-- /TMPL_IF --></li><!-- /TMPL_IF --></ul> > <!-- TMPL_IF name="transfertodo" --> > <h4><strong>Transfer to:</strong> <!-- TMPL_VAR Name="destbranchname" --></h4> > <!-- TMPL_ELSE --> >@@ -136,8 +146,10 @@ function Dopop(link) { > <input type="hidden" name="diffBranch" value="<!-- TMPL_VAR Name="destbranch" -->" /> > <input type="hidden" name="exemptfine" value="<!-- TMPL_VAR Name="exemptfine" -->" /> > <input type="hidden" name="dropboxmode" value="<!-- TMPL_VAR Name="dropboxmode" -->" /> >+ <input type="hidden" name="reservenumber" value="<!-- TMPL_VAR Name="reservenumber" -->" /> > </form> > </div> >+ <!-- /waiting --> > <!-- /TMPL_IF --> > > <!-- TMPL_IF Name="diffbranch" --> >@@ -152,8 +164,9 @@ function Dopop(link) { > <!-- TMPL_VAR Name="borcity" --> <!-- TMPL_VAR NAME="borzip" --></li> > <!-- TMPL_IF NAME="borphone" --><li><!-- TMPL_VAR Name="borphone" --></li><!-- /TMPL_IF --> > <!-- TMPL_IF NAME="boremail" --><li><!-- TMPL_IF name="transfertodo" --><!-- TMPL_VAR NAME="boremail" --><!-- TMPL_ELSE --><a id="boremail" href="mailto:<!-- TMPL_VAR NAME="boremail" -->"><!-- TMPL_VAR NAME="boremail" --></a><!-- /TMPL_IF --></li><!-- /TMPL_IF --> >-<!-- TMPL_IF NAME="debarred" --><li class="error">Patron is RESTRICTED</li><!-- /TMPL_IF --> >-<!-- TMPL_IF NAME="gonenoaddress" --><li class="error">Patron's address is in doubt</li><!-- /TMPL_IF --> >+<!-- TMPL_IF NAME="lost" --><li class="error">Patron's card is lost <!-- TMPL_IF Name="lostcomment" -->(<!-- TMPL_VAR NAME="lostcomment" -->)<!-- /TMPL_IF --></li><!-- /TMPL_IF --> >+<!-- TMPL_IF NAME="debarred" --><li class="error">Patron is RESTRICTED <!-- TMPL_IF Name="debarredcomment" -->(<!-- TMPL_VAR NAME="debarredcomment" -->)<!-- /TMPL_IF --></li><!-- /TMPL_IF --> >+<!-- TMPL_IF NAME="gonenoaddress" --><li class="error">Patron's address is in doubt<!-- TMPL_IF Name="gonenoaddresscomment" -->(<!-- TMPL_VAR NAME="gonenoaddresscomment" -->)<!-- /TMPL_IF --></li><!-- /TMPL_IF --></ul> > </ul> > <!-- TMPL_IF name="transfertodo" --> > <h4><strong>Transfer to:</strong> <!-- TMPL_VAR Name="destbranchname" --></h4> >@@ -180,7 +193,7 @@ function Dopop(link) { > <!-- TMPL_IF Name="transfer" --> > <!-- transfer: item with no reservation, must be returned to its homebranch --> > <div class="dialog message"> >- <h3>Please return <a href="/cgi-bin/koha/catalogue/detail.pl?type=intra&biblionumber=<!-- TMPL_VAR NAME="itembiblionumber" -->"><!-- TMPL_VAR NAME="title" escape="html" DEFAULT="item" --></a> to <!-- TMPL_VAR NAME="homebranchname" --></h3></div><!-- /TMPL_IF --> >+ <h3>Please return <a href="/cgi-bin/koha/catalogue/detail.pl?type=intra&biblionumber=<!-- TMPL_VAR NAME="itembiblionumber" -->"><!-- TMPL_VAR NAME="title" escape="html" DEFAULT="item" --></a> to <!-- TMPL_VAR NAME="homebranch" DEFAULT="homebranch" --></h3></div><!-- /TMPL_IF --> > > <!-- TMPL_IF Name="needstransfer" --> > <!-- needstransfer --> >@@ -228,11 +241,6 @@ function Dopop(link) { > <!-- case of simple return no issue or transfer but with a reservation --> > <!-- TMPL_IF Name="reserved" --> > <!-- reserved --> >- >-<!-- TMPL_IF NAME="soundon" --> >-<audio src="/intranet-tmpl/prog/sound/opening.ogg" autoplay="autoplay" autobuffer="autobuffer"></audio> >-<!-- /TMPL_IF --> >- > <div class="dialog message"> > <h3>Hold Found: <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=<!-- TMPL_VAR NAME="itembiblionumber" -->"><!-- TMPL_VAR Name="title" escape="html" --></a></h3> > <!-- TMPL_IF NAME="reservenotes" --><h4>Notes: <!-- TMPL_VAR Name="reservenotes" --></h4><!-- /TMPL_IF --> >@@ -246,8 +254,9 @@ function Dopop(link) { > <!-- TMPL_VAR Name="borcity" --> <!-- TMPL_VAR NAME="borzip" --></li> > <!-- TMPL_IF NAME="borphone" --><li><!-- TMPL_VAR Name="borphone" --></li><!-- /TMPL_IF --> > <!-- TMPL_IF NAME="boremail" --><li><!-- TMPL_IF name="transfertodo" --><!-- TMPL_VAR NAME="boremail" --><!-- TMPL_ELSE --><a id="boremail" href="mailto:<!-- TMPL_VAR NAME="boremail" -->"><!-- TMPL_VAR NAME="boremail" --></a><!-- /TMPL_IF --></li><!-- /TMPL_IF --> >-<!-- TMPL_IF NAME="debarred" --><li class="error">Patron is RESTRICTED</li><!-- /TMPL_IF --> >-<!-- TMPL_IF NAME="gonenoaddress" --><li class="error">Patron's address is in doubt</li><!-- /TMPL_IF --> >+<!-- TMPL_IF NAME="lost" --><li class="error">Patron's card is lost <!-- TMPL_IF Name="lostcomment" -->(<!-- TMPL_VAR NAME="lostcomment" -->)<!-- /TMPL_IF --></li><!-- /TMPL_IF --> >+<!-- TMPL_IF NAME="debarred" --><li class="error">Patron is RESTRICTED <!-- TMPL_IF Name="debarredcomment" -->(<!-- TMPL_VAR NAME="debarredcomment" -->)<!-- /TMPL_IF --></li><!-- /TMPL_IF --> >+<!-- TMPL_IF NAME="gonenoaddress" --><li class="error">Patron's address is in doubt<!-- TMPL_IF Name="gonenoaddresscomment" -->(<!-- TMPL_VAR NAME="gonenoaddresscomment" -->)<!-- /TMPL_IF --></li><!-- /TMPL_IF --></ul> > </ul> > <!-- TMPL_IF name="transfertodo" --> > <h4><strong>Transfer to:</strong> <!-- TMPL_VAR Name="destbranchname" --></h4> >@@ -273,13 +282,16 @@ function Dopop(link) { > <input type="hidden" name="diffBranch" value="<!-- TMPL_VAR Name="destbranch" -->" /> > <input type="hidden" name="exemptfine" value="<!-- TMPL_VAR Name="exemptfine" -->" /> > <input type="hidden" name="dropboxmode" value="<!-- TMPL_VAR Name="dropboxmode" -->" /> >+ <input type="hidden" name="reservenumber" value="<!-- TMPL_VAR Name="reservenumber" -->" /> > </form> > </div> >+ <!-- /reserved --> > <!-- /TMPL_IF --> >-<!-- TMPL_ELSE --> >+<!--/found--> >+<!-- /TMPL_IF --> > > <!-- TMPL_IF NAME="errmsgloop" --> >- <div class="dialog alert"> >+ <div class="dialog message"> > <!-- TMPL_LOOP Name="errmsgloop" --> > <!-- TMPL_IF Name="badbarcode" --> > <p class="problem">No Item with barcode: <!-- TMPL_VAR Name="msg" --></p> >@@ -293,18 +305,22 @@ function Dopop(link) { > <!-- TMPL_IF Name="waslost" --> > <p class="problem">Item was lost, now found.</p> > <!-- /TMPL_IF --> >+ <!-- TMPL_IF Name="havefines" --> >+ <p class="problem"><!-- TMPL_VAR NAME="finename" --> (<!-- TMPL_VAR NAME="finecardnumber" -->) has an outstanding fine of <!-- TMPL_VAR NAME="havefines" --> for books returned late.</p> >+ <!-- /TMPL_IF --> > <!-- TMPL_IF Name="withdrawn" --> > <p class="problem">Item is withdrawn.</p> > <!-- /TMPL_IF --> >+ <!-- TMPL_IF Name="notforloan" --> >+ <p class="problem">Item was not for loan: <!-- TMPL_VAR NAME="notforloan" -->.</p> >+ <!-- /TMPL_IF --> >+ <!-- TMPL_IF Name="damaged" --> >+ <p class="problem">Item is considered damaged (<!-- TMPL_VAR NAME="damaged" -->).</p> >+ <!-- /TMPL_IF --> >+ <!-- TMPL_IF Name="debarred" --> >+ <p class="problem"><a href="/cgi-bin/koha/circ/circulation.pl?borrowernumber=<!-- TMPL_VAR NAME="debarborrowernumber" -->"><!-- TMPL_VAR NAME="debarname" -->(<!-- TMPL_VAR NAME="debarcardnumber" -->)</a> is now debarred until <!-- TMPL_VAR NAME="debarred" --> <!-- TMPL_IF Name="debarredcomment"-->(<!-- TMPL_VAR NAME="debarredcomment" -->)<!-- /TMPL_IF -->.</p> >+ <!-- /TMPL_IF --> > <!-- /TMPL_LOOP --> >-<!-- TMPL_IF NAME="soundon" --> >-<audio src="/intranet-tmpl/prog/sound/critical.ogg" autoplay="autoplay" autobuffer="autobuffer"></audio> >-<!-- /TMPL_IF --> >- <!-- TMPL_ELSE --> >-<!-- TMPL_IF NAME="soundon" --> >-<audio src="/intranet-tmpl/prog/sound/beep.ogg" autoplay="autoplay" autobuffer="autobuffer"></audio> >-<!-- /TMPL_IF --> >- <!-- /TMPL_IF --> > </div> > <!-- /TMPL_IF --> > >@@ -366,30 +382,53 @@ function Dopop(link) { > </div> > </form> > </div> >+<!-- TMPL_IF Name="flagloop" --> >+<div class="yui-g dialog message"> >+ >+ <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=<!-- TMPL_VAR Name="riborrowernumber" -->"><!-- TMPL_VAR Name="riborsurname" -->, <!-- TMPL_VAR Name="ribortitle" --> <!-- TMPL_VAR Name="riborfirstname" --></a> (<!-- TMPL_VAR Name="riborcnum" -->) >+ <!-- TMPL_IF NAME="flagloop"--> >+ <ul> >+ <!-- TMPL_LOOP Name="flagloop" --> >+ <!-- TMPL_IF NAME="gonenoaddress" --> >+ <li>Patron's address is in doubt<!-- TMPL_IF NAME="gonenoaddresscomment" -->: <!-- TMPL_VAR NAME="gonenoaddresscomment" --><!-- /TMPL_IF --></li> >+ <!-- /TMPL_IF --> > >-<!-- TMPL_IF Name="returned" --> >-<div class="yui-g"> <table> >- <tr><th>Item Information</th><th>Patron Information</th></tr> >- <tr> >- <td><!-- TMPL_VAR Name="title" escape="html" --></td> >- <td> >+ <!-- TMPL_IF NAME="lost" --> >+ <li>Patron's card is lost<!-- TMPL_IF NAME="lostcomment" -->: <!-- TMPL_VAR NAME="lostcomment" --><!-- /TMPL_IF --></li> >+ <!-- /TMPL_IF --> > >- <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=<!-- TMPL_VAR Name="riborrowernumber" -->"><!-- TMPL_VAR Name="riborsurname" -->, <!-- TMPL_VAR Name="ribortitle" --> <!-- TMPL_VAR Name="riborfirstname" --></a> (<!-- TMPL_VAR Name="riborcnum" -->) >- <!-- TMPL_IF Name="flagset" --> >- (<!-- TMPL_LOOP Name="flagloop" --> >- <!-- TMPL_VAR Name="flag" --> >- <!-- TMPL_IF NAME="charges" --> of <!-- TMPL_VAR NAME="chargeamount" --> <!-- /TMPL_IF --> >- , >- <!-- /TMPL_LOOP -->)<!-- /TMPL_IF --> >- </td> >- </tr> >- </table> >+ <!-- TMPL_IF NAME="debarred" --> >+ <li>Patron is restricted <!--TMPL_IF NAME="dateend"-->until <!--TMPL_VAR Name="dateend"--><!--/TMPL_IF--><!-- TMPL_IF NAME="debarredcomment" -->: <!-- TMPL_VAR NAME="debarredcomment" --><!-- /TMPL_IF --></li> >+ <!-- /TMPL_IF --> >+ >+ <!-- TMPL_IF Name="waiting"--> >+ <li><div id="holdswaiting" class="circmessage"> >+ <h4>Holds waiting:</h4> >+ <!-- TMPL_LOOP NAME="itemloop" --> >+ <ul> >+ <li> <a href="/cgi-bin/koha/reserve/request.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->"><!-- TMPL_VAR NAME="title" escape="html" --></a> (<!-- TMPL_VAR NAME="itemtype"-->), <!-- TMPL_IF NAME="author" -->by <!-- TMPL_VAR NAME="author"--><!-- /TMPL_IF --> Hold placed on <!-- TMPL_VAR NAME="reservedate"--> available since <!-- TMPL_VAR NAME="waitingdate" --> until <!-- TMPL_VAR NAME="maxpickupdate" -->. >+ <!-- TMPL_IF NAME="brname" --> >+ <br /><!-- TMPL_IF NAME="waitinghere" --><strong class="waitinghere"><!-- TMPL_ELSE --><strong><!-- /TMPL_IF -->Waiting at <!-- TMPL_VAR NAME="brname" --></strong> >+ <!-- /TMPL_IF --> >+ </li> >+ </ul> >+ <!-- /TMPL_LOOP --> >+ </div></li> >+ <!-- /If waiting --><!-- /TMPL_IF --> >+ >+ <!-- TMPL_IF Name="flag"--> >+ <li><!-- TMPL_VAR Name="flag" --> <!-- TMPL_IF NAME="charges" --> of <!-- TMPL_VAR NAME="chargeamount" --> <!-- /TMPL_IF --> </li> >+ <!-- /TMPL_IF --> >+ <!-- /TMPL_LOOP --> >+ </ul> >+ <!-- /TMPL_IF --> >+</div> > <!-- /TMPL_IF --> > <!-- TMPL_IF Name="riloop" --> > <h2>Checked-In items</h2> > <table> >- <tr><th>Due Date</th><th>Title</th> <th>Author</th> <th>Barcode</th><th>Type</th> <th>Patron</th><th>Note</th></tr> >- >+ <tr><th>Due Date</th><th>Title and Author</th> <th>Barcode (Type)</th><th>Home Branch</th><th>Holding Branch</th><th>Location</th><th>Callnumber</th><th>Patron</th><th>Note</th></tr> >+ > <!-- TMPL_LOOP Name="riloop" --> > <tr> > <td><!-- TMPL_IF Name="duedate" --> >@@ -401,12 +440,16 @@ function Dopop(link) { > <!-- /TMPL_IF --> > </td> > <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=<!-- TMPL_VAR Name="itembiblionumber" -->"> >- <!-- TMPL_VAR Name="itemtitle" escape="html" --></a></td> >- <td><!-- TMPL_VAR Name="itemauthor" --></td> >- <td><a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=<!-- TMPL_VAR NAME="itembiblionumber" -->&itemnumber=<!-- TMPL_VAR NAME="itemnumber" -->#item<!-- TMPL_VAR NAME="itemnumber" -->"><!-- TMPL_VAR Name="barcode" --></a></td> >- <td><!-- TMPL_VAR Name="itemtype" --> <!-- TMPL_VAR Name="ccode" --></td> >+ <!-- TMPL_VAR Name="itemtitle" escape="html" --></a> >+ <!-- TMPL_VAR Name="itemauthor" --></td> >+ <td><a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=<!-- TMPL_VAR NAME="itembiblionumber" -->&itemnumber=<!-- TMPL_VAR NAME="itemnumber" -->#item<!-- TMPL_VAR NAME="itemnumber" -->"><!-- TMPL_VAR Name="barcode" --></a> >+ <!-- TMPL_IF name="itemtype"-->(<!-- TMPL_VAR Name="itemtype" -->) <!-- /TMPL_IF --><!-- TMPL_IF Name="ccode"-->(<!-- TMPL_VAR Name="ccode" -->)<!-- /TMPL_IF --></td> >+ <td><!-- TMPL_VAR NAME="homebranch" --></td> >+ <td><!-- TMPL_VAR NAME="holdingbranch" --></td> >+ <td><!-- TMPL_VAR NAME="itemlocation" --></td> >+ <td><!-- TMPL_VAR NAME="itemcallnumber" --></td> > <td><!-- TMPL_IF Name="duedate" --> >- <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=<!-- TMPL_VAR Name="borrowernumber" -->"> >+ <a href="/cgi-bin/koha/circ/circulation.pl?borrowernumber=<!-- TMPL_VAR Name="borrowernumber" -->"> > <!-- TMPL_VAR Name="borsurname" -->, <!-- TMPL_VAR Name="borfirstname" --> (<!-- TMPL_VAR name="borcategorycode" -->) > </a> > <!-- TMPL_ELSE -->Not checked out<!-- /TMPL_IF --></td> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tmpl >index 53ff7b7..09e1038 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tmpl >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tmpl >@@ -22,11 +22,14 @@ function check() { > var msg = ""; > var count_reserv = 0; > var alreadyreserved = 0; >- >+ var hold_type=""; > // check if we have checkitem form > if (document.form.checkitem){ > for (i=0;i<document.form.checkitem.length;i++){ > if (document.form.checkitem[i].checked == true) { >+ if (hold_type=="" || hold_type=="single"){ >+ hold_type=document.form.hold_type[i].value; >+ } > count_reserv++ ; > } > } >@@ -49,11 +52,11 @@ function check() { > if (count_reserv == "0"){ > msg += (_("- Please select an item to place a hold") + "\n"); > } >- if (count_reserv >= "2"){ >+ if (count_reserv >= "2" && hold_type != "multiple"){ > msg += (_("- You may only place a hold on one item at a time") + "\n"); > } > >- if (alreadyreserved > "0"){ >+ if (alreadyreserved > "0" && hold_type != "multiple"){ > msg += (_("- This patron had already placed a hold on this item") + "\n" + _("Please cancel the previous hold first") + "\n"); > } > >@@ -393,7 +396,21 @@ function checkMultiHold() { > <!-- TMPL_LOOP Name="itemloop" --> > <tr class="<!-- TMPL_VAR NAME="backgroundcolor" -->"> > <td> >- <!-- TMPL_IF NAME="available" --> >+ >+ <!-- TMPL_IF NAME="canholdmultiple" --> >+ <input type="hidden" name="hold_type" value="multiple" /> >+ <!-- TMPL_ELSIF NAME="available" --> >+ <input type="hidden" name="hold_type" value="single" /> >+ <!-- TMPL_ELSIF NAME="override" --> >+ <input type="hidden" name="hold_type" value="single" /> >+ <!-- /TMPL_IF --> >+ <!-- TMPL_IF NAME="cannothold" --> >+ <input disabled="disabled" type="radio" name="checkitem" value="<!-- TMPL_VAR NAME="itemnumber" -->" /> >+ <img src="/intranet-tmpl/<!-- TMPL_VAR NAME="theme" -->/img/famfamfam/silk/cross.png" alt="Cannot be put on hold" /> >+ <!-- TMPL_ELSE --> >+ <!-- TMPL_IF NAME="canholdmultiple" --> >+ <input type="checkbox" name="checkitem" value="<!-- TMPL_VAR NAME="itemnumber" -->" /> >+ <!-- TMPL_ELSIF NAME="available" --> > <input type="radio" name="checkitem" value="<!-- TMPL_VAR NAME="itemnumber" -->" /> > <!-- TMPL_ELSIF NAME="override" --> > <input type="radio" name="checkitem" class="needsoverride" value="<!-- TMPL_VAR NAME="itemnumber" -->" /> >@@ -402,6 +419,10 @@ function checkMultiHold() { > <input disabled="disabled" type="radio" name="checkitem" value="<!-- TMPL_VAR NAME="itemnumber" -->" /> > <img src="/intranet-tmpl/<!-- TMPL_VAR NAME="theme" -->/img/famfamfam/silk/cross.png" alt="Cannot be put on hold" /> > <!-- /TMPL_IF --> >+ <!-- TMPL_ELSE --> >+ <input disabled="disabled" type="radio" name="checkitem" value="<!-- TMPL_VAR NAME="itemnumber" -->" /> >+ <img src="/intranet-tmpl/<!-- TMPL_VAR NAME="theme" -->/img/famfamfam/silk/cross.png" alt="Cannot be put on hold" /> >+ <!-- /TMPL_IF --> > </td> > <!-- TMPL_IF NAME="item_level_itypes" --> > <td> >@@ -584,6 +605,7 @@ function checkMultiHold() { > <!-- TMPL_LOOP Name="reserveloop" --> > <!-- TMPL_UNLESS Name="__odd__" --><tr class="highlight"><!-- TMPL_ELSE --><tr><!-- /TMPL_UNLESS --> > <td> >+ <input type="hidden" name="reservenumber" value="<!-- TMPL_VAR NAME="reservenumber" -->" /> > <input type="hidden" name="borrowernumber" value="<!-- TMPL_VAR NAME="borrowernumber" -->" /> > <input type="hidden" name="biblionumber" value="<!-- TMPL_VAR NAME="biblionumber" -->" /> > <select name="rank-request"> >diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tmpl b/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tmpl >index 56cc345..a8f7717 100644 >--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tmpl >+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tmpl >@@ -113,28 +113,33 @@ > var badBib = null; > $(".confirmjs:checked").each(function() { > var biblioNum = $(this).val(); >- biblionumbers += biblioNum + "/"; >- selections += biblioNum + "/"; >+ var separator="/"; >+ biblionumbers += biblioNum + separator; >+ >+ // Add the pickup location >+ var branchSel = $("#branch_" + biblioNum); >+ var branch = ""; >+ if (branchSel.size() > 0) { >+ branch = $(branchSel).val(); >+ } > > // If the 'specific copy' radio button is checked > if ($("#reqspecific_" + biblioNum + ":checked").size() > 0) { > // Find the selected copy >- var item = $(".checkitem_" + biblioNum + ":checked"); >- if ($(item).size() == 0) { >+ var items = $(".checkitem_" + biblioNum + ":checked"); >+ if ($(items).size() == 0) { > badBib = biblioNum; > return false; > } else { >- selections += $(item).val(); >+ $(items).each( function(idx,item){ >+ selections+=biblioNum+separator+item.value+separator+branch+separator; >+ }); > } > } >- selections += "/"; >- >- // Add the pickup location >- var branchSel = $("#branch_" + biblioNum); >- if (branchSel.size() > 0) { >- selections += $(branchSel).val(); >+ else { >+ selections=biblioNum+separator+separator+branch+separator; > } >- selections += "/"; >+ > return true; > }); > >@@ -259,10 +264,17 @@ > <input class="single_bib" name="single_bib" type="hidden" value="<!-- TMPL_VAR NAME="biblionumber" -->"/> > <span class="confirmjs_hold" title="<!-- TMPL_VAR NAME="biblionumber" -->"></span> > <span class="confirm_nonjs"> >+ <!-- TMPL_IF Name="multi"--> >+ <input type="checkbox" class="confirmbox checkitem <!-- TMPL_VAR NAME="checkitem_bib" -->" >+ name="<!-- TMPL_VAR NAME="checkitem_bib" -->" checked="checked" >+ id="<!-- TMPL_VAR NAME="checkitem_bib" -->" >+ value="any" /> >+ <!--TMPL_ELSE--> > <input type="radio" class="confirmbox checkitem <!-- TMPL_VAR NAME="checkitem_bib" -->" > name="<!-- TMPL_VAR NAME="checkitem_bib" -->" checked="checked" > id="<!-- TMPL_VAR NAME="checkitem_bib" -->" > value="any" /> >+ <!-- /TMPL_IF --> > <label class="confirm_label" for="<!-- TMPL_VAR NAME="checkitem_bib" -->">Next available copy</label> > </span> > </td> >@@ -298,8 +310,18 @@ > <!-- TMPL_IF NAME="holdable" --> > <!-- TMPL_IF NAME="showpriority" --> > <td> >- <!-- TMPL_VAR name="rank" --> out of <!-- TMPL_VAR NAME="reservecount" --> >- </td><!-- /TMPL_IF --><!-- /TMPL_IF --> >+ <a href="/cgi-bin/koha/opac-detail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->"><!-- TMPL_VAR NAME="title" escape="html" --><!-- TMPL_IF NAME="subtitle" --> <!-- TMPL_LOOP NAME="subtitle" --><!--TMPL VAR Name="subfield"--><!--/TMPL_LOOP--><!-- /TMPL_IF --></a> >+ <!-- TMPL_IF NAME="author" -->, by <!-- TMPL_VAR NAME="author" --><!-- /TMPL_IF --> >+ </td> >+ <!-- TMPL_UNLESS NAME="item-level_itypes" --> >+ <td> >+ <!-- TMPL_UNLESS NAME="noItemTypeImages" --> >+ <!-- TMPL_IF NAME="imageurl" --><img src="<!-- TMPL_VAR NAME="imageurl" -->" alt="" /><!-- /TMPL_IF --> >+ <!-- /TMPL_UNLESS --> >+ <!-- TMPL_VAR NAME="description" --> >+ </td> >+ <!-- /TMPL_UNLESS --> >+ <!-- TMPL_IF NAME="showpriority" --><td>You are number <!-- TMPL_VAR name="rank" --> in line</td><!-- /TMPL_IF --> > <!-- TMPL_IF NAME="reserve_in_future" --> > <!-- TMPL_IF NAME="holdable" --><td> > <input name="reserve_date_<!-- TMPL_VAR NAME="biblionumber" -->" id="reserve_date_<!-- TMPL_VAR NAME="biblionumber" -->" size="10"> >@@ -418,22 +440,22 @@ > <!-- /TMPL_IF --><!-- /TMPL_IF --> > > <!-- TMPL_UNLESS NAME="singleBranchMode" --> >- <!-- TMPL_IF NAME="holdable" --> >- <!-- TMPL_IF NAME="choose_branch" --> >- <td> >- <select name="branch" id="branch_<!-- TMPL_VAR NAME="biblionumber" -->" >- <!-- TMPL_UNLESS NAME="holdable" -->disabled="disabled"<!-- /TMPL_UNLESS --> > >- <!-- TMPL_LOOP NAME="branchChoicesLoop" --> >- <!-- TMPL_IF name="selected" --> >- <option value="<!-- TMPL_VAR NAME="value" -->" selected="selected"><!-- TMPL_VAR NAME="branchname" --></option> >- <!-- TMPL_ELSE --> >- <option value="<!-- TMPL_VAR NAME="value" -->"><!-- TMPL_VAR NAME="branchname" --></option> >- <!-- /TMPL_IF --> >- <!-- /TMPL_LOOP --> >- </select> >- </td> >- <!-- /TMPL_IF --> >- <!-- /TMPL_IF --> >+ <td> >+ <!-- TMPL_IF NAME="OPACPickupLocation" --> >+ <select name="branch" id="branch_<!-- TMPL_VAR NAME="biblionumber" -->" >+ <!-- TMPL_UNLESS NAME="holdable" -->disabled="disabled"<!-- /TMPL_UNLESS --> > >+ <!-- TMPL_LOOP NAME="branchChoicesLoop" --> >+ <!-- TMPL_IF name="selected" --> >+ <option value="<!-- TMPL_VAR NAME="value" -->" selected="selected"><!-- TMPL_VAR NAME="branchname" --></option> >+ <!-- TMPL_ELSE --> >+ <option value="<!-- TMPL_VAR NAME="value" -->"><!-- TMPL_VAR NAME="branchname" --></option> >+ <!-- /TMPL_IF --> >+ <!-- /TMPL_LOOP --> >+ </select> >+ <!-- TMPL_ELSE --> >+ <input type="hidden" name="branch" id="branch_<!-- TMPL_VAR NAME="biblionumber" -->" value="<!--TMPL_VAR Name="branch"-->" /> <!-- TMPL_VAR NAME="branchname" --> >+ <!-- /TMPL_IF --> >+ </td> > <!-- /TMPL_UNLESS --> > </tr> > >@@ -466,8 +488,15 @@ > <tr class="<!-- TMPL_VAR NAME="backgroundcolor" -->"> > <td> > <!-- TMPL_IF NAME="available" --> >- <input type="radio" class="checkitem checkitem_<!-- TMPL_VAR NAME="biblionumber" -->" name="checkitem_<!-- TMPL_VAR NAME="biblionumber" -->" >- value="<!-- TMPL_VAR NAME="itemnumber" -->" /> >+ <!-- TMPL_UNLESS NAME="ReservedForThisBorrower" --> >+ <!-- TMPL_IF Name="canholdmultiple"--> >+ <input type="checkbox" class="checkitem checkitem_<!-- TMPL_VAR NAME="biblionumber" -->" name="checkitem_<!-- TMPL_VAR NAME="biblionumber" -->" >+ value="<!-- TMPL_VAR NAME="itemnumber" -->" /> >+ <!--TMPL_ELSE--> >+ <input type="radio" class="checkitem checkitem_<!-- TMPL_VAR NAME="biblionumber" -->" name="checkitem_<!-- TMPL_VAR NAME="biblionumber" -->" >+ value="<!-- TMPL_VAR NAME="itemnumber" -->" /> >+ <!-- /TMPL_IF --> >+ <!-- /TMPL_UNLESS --> > <!-- TMPL_ELSE --> > <input disabled="disabled" type="radio" class="checkitem" name="checkitem" value="<!-- TMPL_VAR NAME="itemnumber" -->" /> > <img src="/opac-tmpl/<!-- TMPL_VAR NAME="theme" -->/famfamfam/silk/cross.png" alt="Cannot be put on hold" title="Cannot be put on hold" /> >diff --git a/members/member.pl b/members/member.pl >index df688d1..a2a79fa 100755 >--- a/members/member.pl >+++ b/members/member.pl >@@ -99,14 +99,20 @@ my ($count,$results); > > my @searchpatron; > push @searchpatron, $member if ($member); >-push @searchpatron, $patron if (keys %$patron); >-my $from= ($startfrom-1)*$resultsperpage; >-my $to=$from+$resultsperpage; >- #($results)=Search(\@searchpatron,{surname=>1,firstname=>1},[$from,$to],undef,["firstname","surname","email","othernames"] ) if (@searchpatron); >- my $search_scope=($quicksearch?"field_start_with":"contain"); >- ($results)=Search(\@searchpatron,\@orderby,undef,undef,["firstname","surname","email","othernames","cardnumber","userid"],$search_scope ) if (@searchpatron); >-if ($results){ >- $count =scalar(@$results); >+push @searchpatron, $patron if ( keys %$patron ); >+my $from = ( $startfrom - 1 ) * $resultsperpage; >+my $to = $from + $resultsperpage; >+ >+#($results)=Search(\@searchpatron,{surname=>1,firstname=>1},[$from,$to],undef,["firstname","surname","email","othernames"] ) if (@searchpatron); >+my $search_scope = ( $quicksearch ? "field_start_with" : "start_with" ); >+($results) = Search( \@searchpatron, \@orderby, undef, undef, [ "firstname", "surname", "othernames", "cardnumber", "userid" ], $search_scope ) if (@searchpatron); >+ >+if ($results) { >+ for my $field ('categorycode','branchcode'){ >+ next unless ($patron->{$field}); >+ @$results = grep { $_->{$field} eq $patron->{$field} } @$results; >+ } >+ $count = scalar(@$results); > } > my @resultsdata; > $to=($count>$to?$to:$count); >diff --git a/opac/opac-modrequest.pl b/opac/opac-modrequest.pl >index 7e2f2e5..0003079 100755 >--- a/opac/opac-modrequest.pl >+++ b/opac/opac-modrequest.pl >@@ -42,7 +42,9 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( > ); > > my $biblionumber = $query->param('biblionumber'); >+my $reservenumber = $query->param('reservenumber'); >+ > if ($biblionumber and $borrowernumber) { >- CancelReserve($biblionumber, '', $borrowernumber); >+ CancelReserve( $reservenumber, $biblionumber ); > } > print $query->redirect("/cgi-bin/koha/opac-user.pl#opac-user-holds"); >diff --git a/opac/opac-reserve.pl b/opac/opac-reserve.pl >index d50480a..0c099f7 100755 >--- a/opac/opac-reserve.pl >+++ b/opac/opac-reserve.pl >@@ -1,5 +1,7 @@ > #!/usr/bin/perl > >+# Parts Copyright Biblibre 2010 >+ > # This file is part of Koha. > # > # Koha is free software; you can redistribute it and/or modify it under the >@@ -28,11 +30,12 @@ use C4::Output; > use C4::Dates qw/format_date/; > use C4::Context; > use C4::Members; >+use C4::Overdues; > use C4::Branch; # GetBranches > use C4::Debug; >+use C4::Items; > # use Data::Dumper; > >-my $MAXIMUM_NUMBER_OF_RESERVES = C4::Context->preference("maxreserves"); > > my $query = new CGI; > my ( $template, $borrowernumber, $cookie ) = get_template_and_user( >@@ -77,7 +80,9 @@ if ((! $biblionumbers) && (! $query->param('place_reserve'))) { > > # Pass the numbers to the page so they can be fed back > # when the hold is confirmed. TODO: Not necessary? >-$template->param( biblionumbers => $biblionumbers ); >+$template->param( biblionumbers => $biblionumbers, >+ OPACPickupLocation => "" . C4::Context->preference("OPACPickupLocation"), >+ ); > > # Each biblio number is suffixed with '/', e.g. "1/2/3/" > my @biblionumbers = split /\//, $biblionumbers; >@@ -91,6 +96,7 @@ if (($#biblionumbers < 0) && (! $query->param('place_reserve'))) { > my $branch = $query->param('branch') || $borr->{'branchcode'} || C4::Context->userenv->{branch} || '' ; > ($branches->{$branch}) or $branch = ""; # Confirm branch is real > $template->param( branch => $branch ); >+$template->param( branchname => $branches->{$branch}->{branchname} ); > > # make branch selection options... > my $CGIbranchloop = GetBranchesLoop($branch); >@@ -252,7 +258,7 @@ if ( $borr->{lost} && ($borr->{lost} eq 1) ) { > lost => 1 > ); > } >-if ( $borr->{debarred} && ($borr->{debarred} eq 1) ) { >+if ( CheckBorrowerDebarred($borrowernumber) ) { > $noreserves = 1; > $template->param( > message => 1, >@@ -262,11 +268,6 @@ if ( $borr->{debarred} && ($borr->{debarred} eq 1) ) { > > my @reserves = GetReservesFromBorrowernumber( $borrowernumber ); > $template->param( RESERVES => \@reserves ); >-if ( $MAXIMUM_NUMBER_OF_RESERVES && (scalar(@reserves) >= $MAXIMUM_NUMBER_OF_RESERVES) ) { >- $template->param( message => 1 ); >- $noreserves = 1; >- $template->param( too_many_reserves => scalar(@reserves)); >-} > foreach my $res (@reserves) { > foreach my $biblionumber (@biblionumbers) { > if ( $res->{'biblionumber'} == $biblionumber && $res->{'borrowernumber'} == $borrowernumber) { >@@ -342,10 +343,20 @@ foreach my $biblioNum (@biblionumbers) { > } > } > >+ $biblioLoopIter{itemtype} = $biblioData->{itemtype}; >+ $biblioLoopIter{itemTypeDescription} = $itemTypes->{ $biblioData->{itemtype} }{description}; > $biblioLoopIter{itemLoop} = []; > my $numCopiesAvailable = 0; >- foreach my $itemInfo (@{$biblioData->{itemInfos}}) { >- my $itemNum = $itemInfo->{itemnumber}; >+ >+ # $canReserveMultiple is set to "yes" ( >0 ) if multiple items can be reserved >+ # it is set to 0 otherwise. depends on item-level_itypes syspref >+ # and the list of itypes that can be multiple reserved >+ my $canReserveMultiple = 0; >+ unless ( C4::Context->preference("item-level_itypes") ) { >+ $canReserveMultiple = CanHoldMultipleItems( $biblioLoopIter{itemtype} ); >+ } >+ foreach my $itemInfo ( @{ $biblioData->{itemInfos} } ) { >+ my $itemNum = $itemInfo->{itemnumber}; > my $itemLoopIter = {}; > > $itemLoopIter->{itemnumber} = $itemNum; >@@ -359,6 +370,16 @@ foreach my $biblioNum (@biblionumbers) { > $itemLoopIter->{imageurl} = $itemInfo->{imageurl}; > } > >+ # check if the itype is one that can be multiple reserved >+ if ( C4::Context->preference("item-level_itypes") ) { >+ >+ # sum canReserveMultiple : if at least one item can be multiple reserved, then the flag will be >0 >+ # FIXME : there can be complex & strange cases, where some items can be multiple reserved, and some can't >+ # this case is not managed. Note it may be only theoric, and have no real case >+ $itemLoopIter->{canholdmultiple} = CanHoldMultipleItems( $itemInfo->{itype} ); >+ $canReserveMultiple = $canReserveMultiple + CanHoldMultipleItems( $itemInfo->{itype} ); >+ } >+ > # If the holdingbranch is different than the homebranch, we show the > # holdingbranch of the document too. > if ( $itemInfo->{homebranch} ne $itemInfo->{holdingbranch} ) { >@@ -375,9 +396,8 @@ foreach my $biblioNum (@biblionumbers) { > } > > # checking reserve >- my ($reservedate,$reservedfor,$expectedAt) = GetReservesFromItemnumber($itemNum); >- my $ItemBorrowerReserveInfo = GetMemberDetails( $reservedfor, 0); >- >+ my ( $reservedate, $reservedfor, $expectedAt ) = GetReservesFromItemnumber($itemNum); >+ my $ItemBorrowerReserveInfo = GetMemberDetails( $reservedfor, 0 ); > if ( defined $reservedate ) { > $itemLoopIter->{backgroundcolor} = 'reserved'; > $itemLoopIter->{reservedate} = format_date($reservedate); >@@ -385,6 +405,8 @@ foreach my $biblioNum (@biblionumbers) { > $itemLoopIter->{ReservedForSurname} = $ItemBorrowerReserveInfo->{'surname'}; > $itemLoopIter->{ReservedForFirstname} = $ItemBorrowerReserveInfo->{'firstname'}; > $itemLoopIter->{ExpectedAtLibrary} = $expectedAt; >+ $itemLoopIter->{ReservedForThisBorrower} = ( $reservedfor eq $borrowernumber ); >+ warn "ReservedForThisBorrower: " . $itemLoopIter->{ReservedForThisBorrower}; > } > > $itemLoopIter->{notforloan} = $itemInfo->{notforloan}; >@@ -422,17 +444,7 @@ foreach my $biblioNum (@biblionumbers) { > # If there is no loan, return and transfer, we show a checkbox. > $itemLoopIter->{notforloan} = $itemLoopIter->{notforloan} || 0; > >- my $branch = C4::Circulation::_GetCircControlBranch($itemLoopIter, $borr); >- >- my $branchitemrule = GetBranchItemRule( $branch, $itemInfo->{'itype'} ); >- my $policy_holdallowed = 1; >- >- if ( $branchitemrule->{'holdallowed'} == 0 || >- ( $branchitemrule->{'holdallowed'} == 1 && $borr->{'branchcode'} ne $itemInfo->{'homebranch'} ) ) { >- $policy_holdallowed = 0; >- } >- >- if (IsAvailableForItemLevelRequest($itemNum) and $policy_holdallowed and CanItemBeReserved($borrowernumber,$itemNum)) { >+ if (IsAvailableForItemLevelRequest($itemNum) and CanItemBeReserved($borrowernumber,$itemNum)) { > $itemLoopIter->{available} = 1; > $numCopiesAvailable++; > } >@@ -461,7 +473,8 @@ foreach my $biblioNum (@biblionumbers) { > $biblioLoopIter{holdable} = 1; > $anyholdable = 1; > } >- if ($biblioLoopIter{already_reserved}) { >+# $biblioLoopIter{multi} = $canReserveMultiple; >+ if ( $biblioLoopIter{already_reserved} && !$canReserveMultiple ) { > $biblioLoopIter{holdable} = undef; > $anyholdable = undef; > } >diff --git a/reserve/modrequest.pl b/reserve/modrequest.pl >index eecd86b..d65cdc3 100755 >--- a/reserve/modrequest.pl >+++ b/reserve/modrequest.pl >@@ -41,12 +41,13 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( > } > ); > >-my @rank=$query->param('rank-request'); >-my @biblionumber=$query->param('biblionumber'); >-my @borrower=$query->param('borrowernumber'); >-my @branch=$query->param('pickup'); >-my @itemnumber=$query->param('itemnumber'); >-my $multi_hold = $query->param('multi_hold'); >+my @rank = $query->param('rank-request'); >+my @reservenumber = $query->param('reservenumber'); >+my @biblionumber = $query->param('biblionumber'); >+my @borrower = $query->param('borrowernumber'); >+my @branch = $query->param('pickup'); >+my @itemnumber = $query->param('itemnumber'); >+my $multi_hold = $query->param('multi_hold'); > my $biblionumbers = $query->param('biblionumbers'); > my $count=@rank; > >@@ -54,9 +55,9 @@ my $CancelBiblioNumber=$query->param('CancelBiblioNumber'); > my $CancelBorrowerNumber=$query->param('CancelBorrowerNumber'); > my $CancelItemnumber=$query->param('CancelItemnumber'); > >-# 2 possibilitys : cancel an item reservation, or modify or cancel the queded list >+# 2 possibilitys : cancel an item reservation, or modify or cancel the queued list > >-# 1) cancel an item reservation by fonction ModReserveCancelAll (in reserves.pm) >+# 1) cancel an item reservation by function ModReserveCancelAll (in reserves.pm) > if ($CancelBorrowerNumber) { > ModReserveCancelAll($CancelItemnumber, $CancelBorrowerNumber); > $biblionumber[0] = $CancelBiblioNumber, >@@ -66,7 +67,7 @@ if ($CancelBorrowerNumber) { > else { > for (my $i=0;$i<$count;$i++){ > undef $itemnumber[$i] unless $itemnumber[$i] ne ''; >- ModReserve($rank[$i],$biblionumber[$i],$borrower[$i],$branch[$i],$itemnumber[$i]); #from C4::Reserves >+ ModReserve($rank[$i],$biblionumber[$i],$borrower[$i],$branch[$i],$itemnumber[$i],$reservenumber[$i]); #from C4::Reserves > } > } > my $from=$query->param('from'); >diff --git a/reserve/placerequest.pl b/reserve/placerequest.pl >index bc3fc74..5920e79 100755 >--- a/reserve/placerequest.pl >+++ b/reserve/placerequest.pl >@@ -3,7 +3,6 @@ > #script to place reserves/requests > #writen 2/1/00 by chris@katipo.oc.nz > >- > # Copyright 2000-2002 Katipo Communications > # > # This file is part of Koha. >@@ -37,34 +36,34 @@ my $input = CGI->new(); > > my ($user, $cookie, $sesion_id, $flags) = checkauth($input, 0, { reserveforothers => 'place_holds' }, 'intranet'); > >-my @bibitems=$input->param('biblioitem'); >+my @bibitems = $input->param('biblioitem'); > # FIXME I think reqbib does not exist anymore, it's used in line 82, to AddReserve of contraint type 'o' > # I bet it's a 2.x feature, reserving a given biblioitem, that is useless in Koha 3.0 > # we can remove this line, the AddReserve of constrainttype 'o', > # and probably remove the reserveconstraint table as well, I never could fill anything in this table. >-my @reqbib=$input->param('reqbib'); >-my $biblionumber=$input->param('biblionumber'); >-my $borrower=$input->param('member'); >-my $notes=$input->param('notes'); >-my $branch=$input->param('pickup'); >-my $startdate=$input->param('reserve_date') || ''; >-my @rank=$input->param('rank-request'); >-my $type=$input->param('type'); >-my $title=$input->param('title'); >-my $borrowernumber=GetMember('cardnumber'=>$borrower); >-my $checkitem=$input->param('checkitem'); >+#my @reqbib = $input->param('reqbib'); >+my $biblionumber = $input->param('biblionumber'); >+my $borrower = $input->param('member'); >+my $notes = $input->param('notes'); >+my $branch = $input->param('pickup'); >+my $startdate = $input->param('reserve_date') || ''; >+my @rank = $input->param('rank-request'); >+my $type = $input->param('type'); >+my $title = $input->param('title'); >+my $borrowernumber = GetMember( 'cardnumber' => $borrower ); >+my @checkitems = $input->param('checkitem'); > my $expirationdate = $input->param('expiration_date'); > >-my $multi_hold = $input->param('multi_hold'); >-my $biblionumbers = $multi_hold ? $input->param('biblionumbers') : ($biblionumber . '/'); >-my $bad_bibs = $input->param('bad_bibs'); >+my $multi_hold = $input->param('multi_hold'); >+my $biblionumbers = $multi_hold ? $input->param('biblionumbers') : ( $biblionumber . '/' ); >+my $bad_bibs = $input->param('bad_bibs'); > > my %bibinfos = (); > my @biblionumbers = split '/', $biblionumbers; > foreach my $bibnum (@biblionumbers) { > my %bibinfo = (); >- $bibinfo{title} = $input->param("title_$bibnum"); >- $bibinfo{rank} = $input->param("rank_$bibnum"); >+ $bibinfo{title} = $input->param("title_$bibnum"); >+ $bibinfo{rank} = $input->param("rank_$bibnum"); > $bibinfos{$bibnum} = \%bibinfo; > } > >@@ -72,27 +71,28 @@ my $found; > > # if we have an item selectionned, and the pickup branch is the same as the holdingbranch > # of the document, we force the value $rank and $found . >-if ($checkitem ne ''){ >- $rank[0] = '0' unless C4::Context->preference('ReservesNeedReturns'); >- my $item = $checkitem; >- $item = GetItem($item); >- if ( $item->{'holdingbranch'} eq $branch ){ >- $found = 'W' unless C4::Context->preference('ReservesNeedReturns'); >+for my $item (@checkitems){ >+ if ( $item ne '' ) { >+ $rank[0] = '0' unless C4::Context->preference('ReservesNeedReturns'); >+ my $itemdata = GetItem($item); >+ if ( $itemdata->{'holdingbranch'} eq $branch ) { >+ $found = 'W' unless C4::Context->preference('ReservesNeedReturns'); >+ } > } > } > >-if ($type eq 'str8' && $borrowernumber ne ''){ >+if ( $type eq 'str8' && $borrowernumber ne '' ) { > >- foreach my $biblionumber (keys %bibinfos) { >- my $count=@bibitems; >- @bibitems=sort @bibitems; >- my $i2=1; >+ 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]; >+ $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++; > } > } >@@ -101,17 +101,17 @@ if ($type eq 'str8' && $borrowernumber ne ''){ > if ($multi_hold) { > my $bibinfo = $bibinfos{$biblionumber}; > AddReserve($branch,$borrowernumber->{'borrowernumber'},$biblionumber,'a',[$biblionumber], >- $bibinfo->{rank},$startdate,$expirationdate,$notes,$bibinfo->{title},$checkitem,$found); >+ $bibinfo->{rank},$startdate,$expirationdate,$notes,$bibinfo->{title},$checkitems[0],$found); > } else { >- if ($input->param('request') eq 'any'){ >+ if ( lc($input->param('request')) eq 'any' ) { > # place a request on 1st available >- AddReserve($branch,$borrowernumber->{'borrowernumber'},$biblionumber,'a',\@realbi,$rank[0],$startdate,$expirationdate,$notes,$title,$checkitem,$found); >- } elsif ($reqbib[0] ne ''){ >- # FIXME : elsif probably never reached, (see top of the script) >- # place a request on a given item >- AddReserve($branch,$borrowernumber->{'borrowernumber'},$biblionumber,'o',\@reqbib,$rank[0],$startdate,$expirationdate,$notes,$title,$checkitem, $found); >+ AddReserve($branch,$borrowernumber->{'borrowernumber'},$biblionumber,'a',\@realbi,$rank[0],$startdate,$expirationdate,$notes,$title,undef,$found); > } else { >- AddReserve($branch,$borrowernumber->{'borrowernumber'},$biblionumber,'a',\@realbi,$rank[0],$startdate,$expirationdate,$notes,$title,$checkitem, $found); >+ for my $item (@checkitems){ >+ AddReserve( $branch, $borrowernumber->{'borrowernumber'}, >+ $biblionumber, 'a', \@realbi, $rank[0], $startdate, $expirationdate, $notes, $title, $item, $found ); >+ $rank[0]++; >+ } > } > } > } >@@ -124,8 +124,8 @@ if ($type eq 'str8' && $borrowernumber ne ''){ > } else { > print $input->redirect("request.pl?biblionumber=$biblionumber"); > } >-} elsif ($borrowernumber eq ''){ >- print $input->header(); >- print "Invalid card number please try again"; >- print $input->Dump; >+} elsif ( $borrowernumber eq '' ) { >+ print $input->header(); >+ print "Invalid card number please try again"; >+ print $input->Dump; > } >diff --git a/reserve/renewscript.pl b/reserve/renewscript.pl >index f4c7fb4..a0304b8 100755 >--- a/reserve/renewscript.pl >+++ b/reserve/renewscript.pl >@@ -28,6 +28,13 @@ use C4::Circulation; > use C4::Auth; > use URI::Escape; > use C4::Dates qw/format_date_in_iso/; >+use C4::Context; >+use C4::Overdues; #CheckBorrowerDebarred >+use C4::Members; #GetMemberDetail >+use C4::Items; >+use C4::Branch; >+use JSON; >+use C4::Reserves; > my $input = new CGI; > > #Set Up User_env >@@ -48,6 +55,7 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( > # find items to renew, all items or a selection of items > # > >+my $branches = GetBranches(); > my @data; > if ($input->param('renew_all')) { > @data = $input->param('all_items[]'); >@@ -80,12 +88,12 @@ my $override_limit = $input->param("override_limit") || 0; > my $failedrenews = q{}; > foreach my $itemno (@data) { > # check status before renewing issue >- my ($renewokay,$error) = CanBookBeRenewed($borrowernumber,$itemno,$override_limit); >- if ($renewokay){ >+ my ($renewokay,$error) = CanBookBeRenewed($borrowernumber,$itemno); >+ if ($renewokay||$override_limit){ > AddRenewal($borrowernumber,$itemno,$branch,$datedue); > } > else { >- $failedrenews.="&failedrenew=$itemno"; >+ $failedrenews.="&failedrenew=$itemno&renewerror=".encode_json($error); > } > } > my $failedreturn = q{}; >@@ -93,7 +101,48 @@ foreach my $barcode (@barcodes) { > # check status before renewing issue > my ( $returned, $messages, $issueinformation, $borrower ) = > AddReturn($barcode, $branch, $exemptfine); >- $failedreturn.="&failedreturn=$barcode" unless ($returned); >+ my $itemnumber=GetItemnumberFromBarcode($barcode); >+ if ($returned){ >+ if (my ($reservetype,$reserve)=C4::Reserves::CheckReserves(undef,$barcode)){ >+ if ($reservetype eq "Waiting" || $reservetype eq "Reserved"){ >+ my $transfer=C4::Context->userenv->{branch} ne $reserve->{branchcode}; >+ ModReserveAffect( $itemnumber, $reserve->{borrowernumber}, $transfer, $reserve->{"reservenumber"} ); >+ my ( $message_reserve, $nextreservinfo ) = GetOtherReserves($itemnumber); >+ >+ my ($borr) = GetMemberDetails( $nextreservinfo, 0 ); >+ $messages->{reservesdata}={ >+ found => 1, >+ currentbranch => $branches->{C4::Context->userenv->{branch}}->{'branchname'}, >+ destbranchname => $branches->{ $reserve->{'branchcode'} }->{'branchname'}, >+ name => $borr->{'surname'} . ", " . $borr->{'title'} . " " . $borr->{'firstname'}, >+ borfirstname => $borr->{'firstname'}, >+ borsurname => $borr->{'surname'}, >+ bortitle => $borr->{'title'}, >+ borphone => $borr->{'phone'}, >+ boremail => $borr->{'email'}, >+ boraddress => $borr->{'address'}, >+ boraddress2 => $borr->{'address2'}, >+ borcity => $borr->{'city'}, >+ borzip => $borr->{'zipcode'}, >+ borcnum => $borr->{'cardnumber'}, >+ debarred => CheckBorrowerDebarred($borr->{borrowernumber}), >+ gonenoaddress => $borr->{'gonenoaddress'}, >+ barcode => $barcode, >+ transfertodo => $transfer, >+ destbranch => $reserve->{'branchcode'}, >+ reservenumber => $reserve->{'reservenumber'}, >+ borrowernumber => $reserve->{'borrowernumber'}, >+ itemnumber => $reserve->{'itemnumber'}, >+ biblionumber => $reserve->{'biblionumber'}, >+ reservenotes => $reserve->{'reservenotes'}, >+ }; >+ >+ } >+ } >+ } >+ if (!$returned ||$messages){ >+ $failedreturn.="&failedreturn=$barcode&returnerror=".encode_json($messages); >+ } > } > > # >diff --git a/reserve/request.pl b/reserve/request.pl >index 7e51364..fb60098 100755 >--- a/reserve/request.pl >+++ b/reserve/request.pl >@@ -38,6 +38,7 @@ use C4::Biblio; > use C4::Items; > use C4::Koha; > use C4::Circulation; >+use C4::IssuingRules; > use C4::Dates qw/format_date/; > use C4::Members; > use C4::Search; # enabled_staff_search_views >@@ -142,8 +143,8 @@ if ($cardnumber) { > my $number_reserves = > GetReserveCount( $borrowerinfo->{'borrowernumber'} ); > >- if ( $number_reserves > C4::Context->preference('maxreserves') ) { >- $warnings = 1; >+ if ( not CanBookBeReserved( $borrowerinfo->{borrowernumber}, $input->param('biblionumber') ) ) { >+ $warnings = 1; > $maxreserves = 1; > } > >@@ -151,7 +152,7 @@ if ($cardnumber) { > my $expiry_date = $borrowerinfo->{dateexpiry}; > my $expiry = 0; # flag set if patron account has expired > if ($expiry_date and $expiry_date ne '0000-00-00' and >- Date_to_Days(split /-/,$date) > Date_to_Days(split /-/,$expiry_date)) { >+ Date_to_Days(split (/-/,$date)) > Date_to_Days(split (/-/,$expiry_date))) { > $messages = $expiry = 1; > } > >@@ -224,7 +225,7 @@ my $borrowerinfo = GetMemberDetails( 0, $cardnumber ); > my @biblionumbers = (); > my $biblionumbers = $input->param('biblionumbers'); > if ($multihold) { >- @biblionumbers = split '/', $biblionumbers; >+ @biblionumbers = split ('/', $biblionumbers); > } else { > push @biblionumbers, $input->param('biblionumber'); > } >@@ -250,8 +251,11 @@ foreach my $biblionumber (@biblionumbers) { > if ( defined $res->{found} && $res->{found} eq 'W' ) { > $count--; > } >- >- if ( defined $borrowerinfo && ($borrowerinfo->{borrowernumber} eq $res->{borrowernumber}) ) { >+ if ($res->{itemnumber} && not $res->{itemtype}){ >+ $res->{itemtype}=GetItem($res->{itemnumber},$res->{biblionumber})->{itype}; >+ } >+ next if CanHoldMultipleItems($res->{itemtype}); >+ if ( defined $borrowerinfo && ($borrowerinfo->{borrowernumber} eq $res->{borrowernumber}) && !CanHoldMultipleItems($res->{itemtype}) ) { > $warnings = 1; > $alreadyreserved = 1; > $biblioloopiter{warn} = 1; >@@ -414,24 +418,16 @@ foreach my $biblionumber (@biblionumbers) { > } > } > } >- >- my $branch = C4::Circulation::_GetCircControlBranch($item, $borrowerinfo); > >- my $branchitemrule = GetBranchItemRule( $branch, $item->{'itype'} ); >- my $policy_holdallowed = 1; >- >- $item->{'holdallowed'} = $branchitemrule->{'holdallowed'}; >- >- if ( $branchitemrule->{'holdallowed'} == 0 || >- ( $branchitemrule->{'holdallowed'} == 1 && $borrowerinfo->{'branchcode'} ne $item->{'homebranch'} ) ) { >- $policy_holdallowed = 0; >- } >+ my $branchitemrule = GetIssuingRule( $borrowerinfo->{categorycode}, $item->{'itype'}, GetReservesControlBranch( $borrowerinfo, $item ) ); >+ my $policy_holdrestricted = $branchitemrule->{'reservesallowed'}; >+ $item->{'holdrestricted'} = $branchitemrule->{'holdrestricted'}; > > if (IsAvailableForItemLevelRequest($itemnumber) and not $item->{cantreserve} and CanItemBeReserved($borrowerinfo->{borrowernumber}, $itemnumber) ) { >- if ( not $policy_holdallowed and C4::Context->preference( 'AllowHoldPolicyOverride' ) ) { >+ if ( not $policy_holdrestricted and C4::Context->preference( 'AllowHoldPolicyOverride' ) ) { > $item->{override} = 1; > $num_override++; >- } elsif ( $policy_holdallowed ) { >+ } elsif ( $policy_holdrestricted ) { > $item->{available} = 1; > $num_available++; > } >@@ -447,10 +443,17 @@ foreach my $biblionumber (@biblionumbers) { > while (my $wait_hashref = $sth2->fetchrow_hashref) { > $item->{waitingdate} = format_date($wait_hashref->{waitingdate}); > } >+ >+ if ( BorrowerHasReserve( $borrowerinfo->{'borrowernumber'}, '', $itemnumber ) ) { >+ $item->{available} = 0; >+ $item->{override} = 0; >+ } >+ $item->{canholdmultiple}=CanHoldMultipleItems($item->{itype}) && $item->{available}; >+ $item->{cannothold}=!CanHoldMultipleItems($item->{itype}); >+ > push @{ $biblioitem->{itemloop} }, $item; > } >- >- if ( $num_override == scalar( @{ $biblioitem->{itemloop} } ) ) { # That is, if all items require an override >+ if ( $num_override > 0) { > $template->param( override_required => 1 ); > } elsif ( $num_available == 0 ) { > $template->param( none_available => 1 ); >@@ -471,6 +474,9 @@ foreach my $biblionumber (@biblionumbers) { > $a_found cmp $b_found; > } @$reserves ) { > my %reserve; >+ >+ $reserve{'reservenumber'} = $res->{'reservenumber'}; >+ > my @optionloop; > for ( my $i = 1 ; $i <= $totalcount ; $i++ ) { > push( >diff --git a/t/db_dependent/lib/KohaTest/Circulation.pm b/t/db_dependent/lib/KohaTest/Circulation.pm >index 7d5e69d..8236bcb 100644 >--- a/t/db_dependent/lib/KohaTest/Circulation.pm >+++ b/t/db_dependent/lib/KohaTest/Circulation.pm >@@ -20,8 +20,6 @@ sub methods : Test( 1 ) { > CanBookBeIssued > AddIssue > GetLoanLength >- GetIssuingRule >- GetBranchBorrowerCircRule > AddReturn > MarkIssueReturned > _FixOverduesOnReturn >diff --git a/t/db_dependent/lib/KohaTest/Members/GetMemberDetails.pm b/t/db_dependent/lib/KohaTest/Members/GetMemberDetails.pm >index e93742b..d75c60e 100644 >--- a/t/db_dependent/lib/KohaTest/Members/GetMemberDetails.pm >+++ b/t/db_dependent/lib/KohaTest/Members/GetMemberDetails.pm >@@ -50,12 +50,10 @@ sub startup_create_detailed_borrower : Test( startup => 2 ) { > $description = 'Test account'; > $type = 'M'; > $amount = 5.00; >- $user = ''; >+ $note = ''; > > my $acct_added = >- C4::Accounts::manualinvoice( $borrowernumber, undef, $description, $type, $amount, >- $user ); >- >+ C4::Accounts::manualinvoice( $borrowernumber, undef, $description, $type, $amount, $note ); > ok( $acct_added == 0, 'added account for borrower' ); > > $self->{amountoutstanding} = $amount; >diff --git a/t/db_dependent/lib/KohaTest/Overdues.pm b/t/db_dependent/lib/KohaTest/Overdues.pm >index 949c670..02b907e 100644 >--- a/t/db_dependent/lib/KohaTest/Overdues.pm >+++ b/t/db_dependent/lib/KohaTest/Overdues.pm >@@ -23,7 +23,6 @@ sub methods : Test( 1 ) { > BorType > ReplacementCost > GetFine >- GetIssuingRules > ReplacementCost2 > GetNextIdNotify > NumberNotifyId >-- >1.7.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 5872
:
3310
|
3329
|
3394
|
3432
|
4741
|
4795
|
4811
|
4854