[Koha-patches] [PATCH 34/54] Circulation rules management : everything (issues, holds, fines) now at granular level
Mike Hafen
mdhafen at tech.washk12.org
Thu Dec 16 18:21:22 CET 2010
Looks like the remains of a merge conflict. Better fix that.
in C4/Reserves.pm
+>>>>>>> [MT2355] Ergonomy improvement in smart rule management
On Thu, Dec 16, 2010 at 3:54 AM, <paul.poulain at biblibre.com> wrote:
> From: Paul Poulain <paul.poulain at biblibre.com>
>
> All scripts = there are some (a few) reindenting changes.
>
> * C4/IssuintRules.pm
> script created : contains all circ rules related functions
>
> * C4/Circulation.pm
> - rewrite issuing rules according to new behaviour : default values applies
> as default, not as total. There is also an inheritance, meaning you don't
> have to define all rules
> - debarment management : debarred patrons now can have a limit date of
> debarment (for fine in days, but also for a limited debarrment)
> - lot of lines removes (now in IssuinRules.pm)
> - modifys the offline circ : works in conjunction with the Firefox plugin.
> All offline circ code is in another patch
>
> * C4/Overdues.pm
> - use IssuingRules.pm functions
> - deal with debarment up to a givendate
>
> * C4/Reserves.pm
> - deal with HoldRules at granular level. The library can now define rules
> for hold at ccode(itype) / branch / patron category level
> - added a pickupDelay
>
> * admin/smart-rules.pl
> - script rewritten
> - added ajax (smart-rules-service) to modify a cell directly
>
> * admin/branch_transfer_limits.pl
> - some variable renamed for more readability
>
> * circ/branchtransfers.pl
> - ModReserveAffect now deals with branches to check hold rules
>
> * circ/circulation.pl and circ/returns.pl
> - deals with debardate where applicable
> - deals with possible holds on a given item adapted to fit new hold rules
> - display borrower relatives issues (on circulation.pl only)
>
> * reserve/modrequest.pl, placerequest.pl, renewscript.pl and request.pl
> - deals with new granular-level hold rules
>
> * unit tests for Circulation.pm, GetMemberDetails.pm and Overdues.pm
> - deals with IssuingRules.pm package & API changes
>
> * opac-reserve.pl and opac-modrequest:
> - deals with holds at granular level
> ---
> C4/Circulation.pm | 918
> +++++++++-----------
> C4/IssuingRules.pm | 261 ++++++
> C4/Overdues.pm | 81 +--
> C4/Reserves.pm | 631 ++++++++++----
> admin/branch_transfer_limits.pl | 22 +-
> admin/smart-rules-service.pl | 59 ++
> admin/smart-rules.pl | 567 +++----------
> 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 | 589 +++++++------
> .../prog/en/modules/circ/circulation.tmpl | 441 ++++++----
> .../prog/en/modules/circ/returns.tmpl | 151 ++--
> .../prog/en/modules/reserve/request.tmpl | 30 +-
> .../opac-tmpl/prog/en/modules/opac-reserve.tmpl | 53 +-
> opac/opac-modrequest.pl | 4 +-
> opac/opac-reserve.pl | 68 +-
> reserve/modrequest.pl | 19 +-
> reserve/placerequest.pl | 92 +-
> reserve/renewscript.pl | 57 ++-
> reserve/request.pl | 48 +-
> t/lib/KohaTest/Circulation.pm | 2 -
> t/lib/KohaTest/Members/GetMemberDetails.pm | 6 +-
> t/lib/KohaTest/Overdues.pm | 1 -
> 26 files changed, 2608 insertions(+), 1933 deletions(-)
> create mode 100644 C4/IssuingRules.pm
> create mode 100755 admin/smart-rules-service.pl
>
> diff --git a/C4/Circulation.pm b/C4/Circulation.pm
> index 0131e90..08b2a0b 100644
> --- a/C4/Circulation.pm
> +++ b/C4/Circulation.pm
> @@ -27,12 +27,15 @@ 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::Message;
> use C4::Debug;
> +use YAML;
> use Date::Calc qw(
> Today
> Today_and_Now
> @@ -41,6 +44,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
> @@ -72,9 +78,6 @@ BEGIN {
> &GetItemIssues
> &GetBorrowerIssues
> &GetIssuingCharges
> - &GetIssuingRule
> - &GetBranchBorrowerCircRule
> - &GetBranchItemRule
> &GetBiblioIssues
> &GetOpenIssue
> &AnonymiseIssueHistory
> @@ -97,6 +100,15 @@ BEGIN {
> &CreateBranchTransferLimit
> &DeleteBranchTransferLimits
> );
> +
> + # subs to deal with offline circulation
> + push @EXPORT, qw(
> + &GetOfflineOperations
> + &GetOfflineOperation
> + &AddOfflineOperation
> + &DeleteOfflineOperation
> + &ProcessOfflineOperation
> + );
> }
>
> =head1 NAME
> @@ -345,116 +357,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
> @@ -683,7 +676,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.
> @@ -711,15 +707,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;
> }
> }
> #
> @@ -761,14 +764,15 @@ sub CanBookBeIssued {
> #
> # JB34 CHECKS IF BORROWERS DONT HAVE ISSUE TOO MANY BOOKS
> #
> - my $toomany = TooMany( $borrower, $item->{biblionumber}, $item );
> - # if TooMany return / 0, then the user has no permission to check out
> this book
> - if ($toomany =~ /\/ 0/) {
> + my @toomany = TooMany( $borrower, $item->{biblionumber}, $item );
> +
> + if ( $toomany[0] == 1 && scalar(@toomany)<3) {
> $needsconfirmation{PATRON_CANT} = 1;
> - } else {
> - $needsconfirmation{TOO_MANY} = $toomany if $toomany;
> + } elsif (scalar(@toomany)==3) {
> + $needsconfirmation{TOO_MANY} = "$toomany[1] / $toomany[2]";
> }
>
> +
> #
> # ITEM CHECKING
> #
> @@ -805,8 +809,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'}
> @@ -814,15 +828,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
> @@ -860,20 +882,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} =
> -"$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'})";
> + 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
> @@ -954,7 +977,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
> );
> }
>
> @@ -987,7 +1013,9 @@ sub AddIssue {
> ModReserve(1,
> $res->{'biblionumber'},
> $res->{'borrowernumber'},
> - $res->{'branchcode'}
> + $res->{'branchcode'},
> + undef,
> + $res->{'reservenumber'}
> );
> }
> }
> @@ -1077,10 +1105,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!
> }
> @@ -1095,254 +1124,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
> @@ -1420,8 +1203,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;
> }
> @@ -1465,9 +1248,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,
> @@ -1478,7 +1269,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
> @@ -1489,12 +1279,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) {
> @@ -1502,15 +1291,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
> @@ -1537,11 +1326,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.....
> @@ -1577,20 +1381,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;
> @@ -1652,6 +1456,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('-', at newdate);
> + my ($deby, $debm, $debd) = split(/-/,$borrower->{debarred});
> + if(check_date($deby, $debm, $debd)){
> + my @olddate = split(/-/, $borrower->{debarred});
> +
> + if(Delta_Days(@olddate, at 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);
> @@ -1826,7 +1685,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};
> @@ -1863,7 +1722,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=?");
> @@ -1934,7 +1793,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;
> }
> @@ -2040,69 +1899,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
> @@ -2157,22 +1989,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=?"
> );
> @@ -2180,8 +2018,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
> );
> @@ -2547,15 +2385,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} ) {
> @@ -2765,18 +2596,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/IssuingRules.pm b/C4/IssuingRules.pm
> new file mode 100644
> index 0000000..b64b817
> --- /dev/null
> +++ b/C4/IssuingRules.pm
> @@ -0,0 +1,261 @@
> +package C4::IssuingRules;
> +
> +# Copyright 2009 BibLibre SARL
> +#
> +# This file is part of Koha.
> +#
> +# Koha is free software; you can redistribute it and/or modify it under
> the
> +# terms of the GNU General Public License as published by the Free
> Software
> +# Foundation; either version 2 of the License, or (at your option) any
> later
> +# version.
> +#
> +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
> +# WARRANTY; without even the implied warranty of MERCHANTABILITY or
> FITNESS FOR
> +# A PARTICULAR PURPOSE. See the GNU General Public License for more
> details.
> +#
> +# You should have received a copy of the GNU General Public License along
> with
> +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple
> Place,
> +# Suite 330, Boston, MA 02111-1307 USA
> +
> +use strict;
> +use warnings;
> +use C4::Context;
> +use C4::Koha;
> +use C4::SQLHelper qw( SearchInTable InsertInTable UpdateInTable
> DeleteInTable );
> +use Memoize;
> +
> +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
> +
> +BEGIN {
> + # set the version for version checking
> + $VERSION = 3.0.5;
> + @ISA = qw(Exporter);
> + @EXPORT = qw(
> + &GetIssuingRule
> + &GetIssuingRulesByBranchCode
> + &GetIssuingRules
> + &AddIssuingRule
> + &ModIssuingRule
> + &DelIssuingRule
> + );
> +}
> +
> +=head1 NAME
> +
> +C4::IssuingRules - Koha issuing rules module
> +
> +=head1 SYNOPSIS
> +
> +use C4::IssuingRules;
> +
> +=head1 DESCRIPTION
> +
> +The functions in this module deal with issuing rules.
> +
> +=head1 FUNCTIONS
> +
> +=head2 GetIssuingRule
> +
> +Compute the issuing rule for an itemtype, a borrower category and a
> branch.
> +Returns a hashref from the issuingrules table.
> +
> +my $rule = &GetIssuingRule($categorycode, $itemtype, $branchcode);
> +
> +The rules are applied from most specific to less specific, using the first
> found in this order:
> + * same library, same patron type, same item type
> + * same library, same patron type, default item type
> + * same library, default patron type, same item type
> + * same library, default patron type, default item type
> + * default library, same patron type, same item type
> + * default library, same patron type, default item type
> + * default library, default patron type, same item type
> + * default library, default patron type, default item type
> +
> +The values in the returned hashref are inherited from a more generic rules
> if undef.
> +
> +=cut
> +#Caching GetIssuingRule
> +memoize('GetIssuingRule');
> +
> +sub GetIssuingRule {
> + my ( $categorycode, $itemtype, $branchcode ) = @_;
> + $categorycode||="*";
> + $itemtype||="*";
> + $branchcode||="*";
> +
> + # This configuration table defines the order of inheritance. We'll
> loop over it.
> + my @attempts = (
> + [ "*" , "*" , "*" ],
> + [ "*" , $itemtype, "*" ],
> + [ $categorycode, "*" , "*" ],
> + [ $categorycode, $itemtype, "*" ],
> + [ "*" , "*" , $branchcode ],
> + [ "*" , $itemtype, $branchcode ],
> + [ $categorycode, "*" , $branchcode ],
> + [ $categorycode, $itemtype, $branchcode ],
> + );
> +
> + # This complex query returns a nested hashref, so we can access a rule
> using :
> + # my $rule = $$rules{$categorycode}{$itemtype}{$branchcode};
> + # this will be usefull in the inheritance computation code
> + my $dbh = C4::Context->dbh;
> + my $rules = $dbh->selectall_hashref(
> + "SELECT * FROM issuingrules where branchcode IN ('*',?) and
> itemtype IN ('*', ?) and categorycode IN ('*',?)",
> + ["branchcode", "itemtype", "categorycode"],
> + undef,
> + ( $branchcode, $itemtype, $categorycode )
> + );
> +
> + # This block is for inheritance. It loops over rules returned by the
> + # previous query. If a value is found in a more specific rule, it
> replaces
> + # the old value from the more generic rule.
> + my $oldrule;
> + for my $attempt ( @attempts ) {
> + if ( my $rule = $$rules{@$attempt[2]}{@$attempt[1]}{@$attempt[0]}
> ) {
> + if ( $oldrule ) {
> + for ( keys %$oldrule ) {
> + if ( defined $rule->{$_} ) {
> + $oldrule->{$_} = $rule->{$_};
> + }
> + }
> + } else {
> + $oldrule = $rule;
> + }
> + }
> + }
> + if($oldrule){
> + return $oldrule;
> + }else{
> + return {
> + 'itemtype' => $itemtype,
> + 'categorycode' => $categorycode,
> + 'branchcode' => $branchcode,
> + 'holdspickupdelay' => 0,
> + # 'maxissueqty' => 0,
> + 'renewalsallowed' => 0,
> + 'firstremind' => 0,
> + 'accountsent' => 0,
> + 'reservecharge' => 0,
> + 'fine' => 0,
> + 'restrictedtype' => 0,
> + 'rentaldiscount' => 0,
> + 'chargename' => 0,
> + 'finedays' => 0,
> + 'holdrestricted' => 0,
> + 'allowonshelfholds' => 0,
> + 'reservesallowed' => 0,
> + 'chargeperiod' => 0,
> + # 'issuelength' => 0,
> + 'renewalperiod' => 0,
> + };
> + }
> +}
> +
> +=head2 GetIssuingRulesByBranchCode
> +
> + my @issuingrules = &GetIssuingRulesByBranchCode($branchcode);
> +
> + Retruns a list of hashref from the issuingrules Koha table for a given
> + branchcode.
> + Each hashref will contain data from issuingrules plus human readable
> names of
> + patron and item categories.
> +
> +=cut
> +
> +sub GetIssuingRulesByBranchCode {
> + my $dbh = C4::Context->dbh;
> + my $sth = $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 = ?
> + ORDER BY humancategorycode, humanitemtype
> + ");
> + $sth->execute(shift);
> +
> + my $res = $sth->fetchall_arrayref({});
> +
> + return @$res;
> +}
> +
> +=head2 GetIssuingRules
> +
> + my @issuingrules = &GetIssuingRules({
> + branchcode => $branch,
> + categorycode => $input->param('categorycode'),
> + itemtype => $input->param('itemtype'),
> + });
> +
> + Get an issuing rule from Koha database.
> + An alias for SearchInTable, see C4::SQLHelper for more help.
> +
> +=cut
> +
> +sub GetIssuingRules {
> + my $res = SearchInTable('issuingrules', shift);
> + return @$res;
> +}
> +
> +=head2 AddIssuingRule
> +
> + my $issuingrule = {
> + branchcode => $branch,
> + categorycode => $input->param('categorycode'),
> + itemtype => $input->param('itemtype'),
> + maxissueqty => $maxissueqty,
> + renewalsallowed => $input->param('renewalsallowed'),
> + reservesallowed => $input->param('reservesallowed'),
> + issuelength => $input->param('issuelength'),
> + fine => $input->param('fine'),
> + finedays => $input->param('finedays'),
> + firstremind => $input->param('firstremind'),
> + chargeperiod => $input->param('chargeperiod'),
> + };
> +
> + &AddIssuingRule( $issuingrule );
> +
> + Adds an issuing rule to Koha database.
> + An alias for InsertInTable, see C4::SQLHelper for more help.
> +
> +=cut
> +
> +sub AddIssuingRule { InsertInTable('issuingrules',shift); }
> +
> +=head2 ModIssuingRule
> +
> + &ModIssuingRule( $issuingrule );
> +
> + Update an issuing rule of the Koha database.
> + An alias for UpdateInTable, see C4::SQLHelper for more help.
> +
> +=cut
> +
> +sub ModIssuingRule { UpdateInTable('issuingrules',shift); }
> +
> +=head2 DelIssuingRule
> +
> + DelIssuingRule({
> + branchcode => $branch,
> + categorycode => $input->param('categorycode'),
> + itemtype => $input->param('itemtype'),
> + });
> +
> + Delete an issuing rule from Koha database.
> + An alias for DeleteInTable, see C4::SQLHelper for more help.
> +
> +=cut
> +
> +sub DelIssuingRule { DeleteInTable('issuingrules',shift); }
> +
> +1;
> +
> +=head1 AUTHOR
> +
> +Koha Developement team <info at koha.org>
> +
> +Jean-André Santoni <jeanandre.santoni at biblibre.com>
> +
> +=cut
> diff --git a/C4/Overdues.pm b/C4/Overdues.pm
> index 032ca93..03b3d22 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 fcf9209..dd60a61 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 );
> @@ -248,24 +262,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;
> @@ -371,9 +388,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
>
> @@ -397,7 +445,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;
>
> @@ -405,7 +453,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
> @@ -436,22 +484,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 = ?";
> @@ -477,6 +534,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
>
> @@ -516,21 +673,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'},
> ),
> ;
> }
> @@ -541,7 +699,8 @@ sub GetOtherReserves {
> ModReserveMinusPriority(
> $itemnumber,
> $checkreserves->{'borrowernumber'},
> - $iteminfo->{'biblionumber'}
> + $iteminfo->{'biblionumber'},
> + $checkreserves->{'reservenumber'}
> );
> ModReserveStatus($itemnumber,'W');
> }
> @@ -655,6 +814,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 );
> @@ -838,23 +1017,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.
> @@ -862,9 +1036,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 = "
> @@ -872,27 +1051,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....
> @@ -900,52 +1098,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])
>
> @@ -978,52 +1196,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);
>
> @@ -1042,16 +1256,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;
>
> @@ -1059,35 +1274,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} );
> }
> }
>
> @@ -1104,7 +1319,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;
> @@ -1138,9 +1352,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=?");
> @@ -1158,27 +1371,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 );
> @@ -1218,23 +1456,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);
>
> @@ -1319,7 +1555,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
> @@ -1354,10 +1590,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"));
> }
> }
>
> @@ -1385,15 +1621,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} )
>
> }
> }
> @@ -1416,18 +1652,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 #
> @@ -1439,7 +1707,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 );
> @@ -1450,12 +1718,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;
> @@ -1466,7 +1733,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)
> @@ -1501,16 +1768,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;
> @@ -1550,15 +1816,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
> @@ -1580,15 +1847,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
> @@ -1609,15 +1877,16 @@ sub _Findgroupreserve {
> return @results if @results;
>
> my $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,
> reserveconstraints.biblioitemnumber AS biblioitemnumber,
> reserves.itemnumber AS itemnumber
> FROM reserves
> @@ -1649,30 +1918,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'} );
>
> @@ -1685,6 +1953,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 1b89efb..7028a90 100755
> --- a/admin/branch_transfer_limits.pl
> +++ b/admin/branch_transfer_limits.pl
> @@ -83,13 +83,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 );
> }
> }
> }
> @@ -107,18 +107,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-service.pl b/admin/smart-rules-service.pl
> new file mode 100755
> index 0000000..3fca0ee
> --- /dev/null
> +++ b/admin/smart-rules-service.pl
> @@ -0,0 +1,59 @@
> +#!/usr/bin/perl
> +
> +# 2009 BibLibre <jeanandre.santoni at biblibre.com>
> +
> +# This file is part of Koha.
> +#
> +# Koha is free software; you can redistribute it and/or modify it under
> the
> +# terms of the GNU General Public License as published by the Free
> Software
> +# Foundation; either version 2 of the License, or (at your option) any
> later
> +# version.
> +#
> +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
> +# WARRANTY; without even the implied warranty of MERCHANTABILITY or
> FITNESS FOR
> +# A PARTICULAR PURPOSE. See the GNU General Public License for more
> details.
> +#
> +# You should have received a copy of the GNU General Public License along
> with
> +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple
> Place,
> +# Suite 330, Boston, MA 02111-1307 USA
> +#
> +
> +use CGI;
> +use C4::Auth;
> +use C4::IssuingRules;
> +
> +my $cgi = CGI->new;
> +
> +# get the status of the user, this will check his credentials and rights
> +my ($status, $cookie, $sessionId) = C4::Auth::check_api_auth($cgi, undef);
> +
> +my $result;
> +
> +if ($status eq 'ok') { # if authentication is ok
> +
> + # Get the POST data
> + my $branchcode = $cgi->param('branchcode');
> + my $categorycode = $cgi->param('categorycode');
> + my $itemtype = $cgi->param('itemtype');
> + my $varname = $cgi->param('varname');
> + my $inputvalue = $cgi->param('inputvalue') eq '' ? undef :
> $cgi->param('inputvalue');
> +
> + # Modify the existing rule
> + ModIssuingRule({
> + branchcode => $branchcode,
> + categorycode => $categorycode,
> + itemtype => $itemtype,
> + $varname => $inputvalue,
> + });
> +
> + # Compute inheritance, and return the new value;
> + my $rule = GetIssuingRule($categorycode, $itemtype, $branchcode);
> +
> + $result = $rule->{$varname};
> +} else {
> + $result = 'Fail';
> +}
> +
> +print CGI::header('-type'=>'text/plain', '-charset'=>'utf-8');
> +print $result;
> +
> diff --git a/admin/smart-rules.pl b/admin/smart-rules.pl
> index fdd9b91..72535b9 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,111 @@ 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;
> -}
> -
> -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);
> -
> -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;
> -}
> -$sth->finish;
> +# Get the patron category list
> +my @category_loop = C4::Category->all;
>
> -my @sorted_row_loop = sort by_category_and_itemtype @row_loop;
> +# Get the item types list
> +my @itemtypes = C4::ItemType->all;
>
> -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);
> +if ( $op eq 'delete' ) {
> + DelIssuingRule({
> + branchcode => $branchcode,
> + categorycode => $input->param('categorycode'),
> + itemtype => $input->param('itemtype'),
> + });
> }
> +# save the values entered
> +elsif ( $op eq 'add' ) {
>
> -my @branch_cat_rules = ();
> -while (my $row = $sth_branch_cat->fetchrow_hashref) {
> - push @branch_cat_rules, $row;
> -}
> -my @sorted_branch_cat_rules = sort { $a->{'humancategorycode'} cmp
> $b->{'humancategorycode'} } @branch_cat_rules;
> + # 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;
> + }
>
> -# 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});
> + # 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_row_loop = sort by_category_and_itemtype @row_loop;
> -
> -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);
> -}
> +# Get the issuing rules list...
> +my @issuingrules = GetIssuingRulesByBranchCode($branchcode);
>
> -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;
> +# ...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 '*';
>
> -# 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);
> + # 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;
> + }
> + }
> }
>
> -$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);
> +# Get the issuing rules list...
> +my @issuingrules = GetIssuingRulesByBranchCode($branchcode);
>
> -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);
> -}
> +# ...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 $defaults = $sth_defaults->fetchrow_hashref;
> + # 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;
> + }
> + }
>
> -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});
> + $rule->{'fine'} = sprintf('%.2f',
> $rule->{'fine'});
> }
>
> -$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} : ''),
> - 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 c4421ed..a7c8716 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 ) =
> @@ -320,8 +341,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 );
> @@ -359,11 +405,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'};
> @@ -419,51 +472,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;
> @@ -472,7 +571,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;
> @@ -502,6 +642,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;
> @@ -511,20 +652,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' ) {
> @@ -532,6 +672,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
> );
> }
> }
> @@ -542,6 +683,7 @@ foreach my $flag ( sort keys %$flags ) {
> flagged => 1,
> chargesmsg => $flags->{'CHARGES'}->{'message'},
> chargesamount => $flags->{'CHARGES'}->{'amount'},
> + warning => 1
> );
> }
> elsif ( $flag eq 'CREDITS' ) {
> @@ -549,13 +691,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'};
> @@ -610,9 +754,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;
>
> $template->param(
> lib_messages_loop => $lib_messages_loop,
> @@ -627,9 +778,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'},
> @@ -640,7 +791,6 @@ $template->param(
> zipcode => $borrower->{'zipcode'},
> country => $borrower->{'country'},
> phone => $borrower->{'phone'} || $borrower->{'mobile'},
> - cardnumber => $borrower->{'cardnumber'},
> amountold => $amountold,
> barcode => $barcode,
> stickyduedate => $stickyduedate,
> @@ -651,14 +801,22 @@ $template->param(
> totaldue => sprintf('%.2f', $total),
> todayissues => \@todaysissues,
> previssues => \@previousissues,
> + relissues => \@relissues,
> + relprevissues => \@relprevissues,
> + displayrelissues => $displayrelissues,
> inprocess => $inprocess,
> memberofinstution => $member_of_institution,
> CGIorganisations => $CGIorganisations,
> is_child => ($borrower->{'category_type'} eq 'C'),
> circview => 1,
> soundon => C4::Context->preference("SoundOn"),
> + 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 2aac76a..13c3283 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'};
>
> @@ -242,7 +258,7 @@ if ($barcode) {
> $input{return_overdue} = 1 if ($duedate and $duedate lt
> $today->output('iso'));
> push( @inputloop, \%input );
> }
> - elsif ( !$messages->{'BadBarcode'} ) {
> + elsif ( !$messages->{'BadBarcode'} and ! $messages->{'Wrongbranch'} )
> {
> $input{duedate} = 0;
> $returneditems{0} = $barcode;
> $riduedate{0} = 0;
> @@ -260,6 +276,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;
> @@ -283,9 +311,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)
> @@ -340,7 +372,7 @@ if ( $messages->{'ResFound'}) {
> reserved => 1,
> );
> }
> -
> + my $debarred = CheckBorrowerDebarred($reserve->{borrowernumber});
> # same params for Waiting or Reserved
> $template->param(
> found => 1,
> @@ -357,17 +389,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 ) {
> @@ -393,6 +426,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;
> @@ -414,7 +476,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
> @@ -428,14 +489,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;
> @@ -450,14 +507,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;
> @@ -483,7 +555,6 @@ if ($borrower) {
> push( @flagloop, \%flaginfo );
> }
> $template->param(
> - flagset => $flagset,
> flagloop => \@flagloop,
> riborrowernumber => $borrower->{'borrowernumber'},
> riborcnum => $borrower->{'cardnumber'},
> @@ -494,7 +565,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 ) {
> @@ -521,19 +592,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 fc7e41f..ad7001c 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
> @@ -48,6 +48,7 @@
> return false;
> });
>
> + $('#selectlibrary input[type=submit]').hide();
> });
> </script>
> <style type="text/css">td { text-align: center; }</style>
> @@ -68,13 +69,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>
>
> @@ -99,11 +105,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>
> @@ -121,6 +127,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 895ceb9..03a6de9 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
> @@ -9,7 +9,7 @@
> //<![CDATA[
> $(document).ready(function() {
> $('#selectlibrary').find("input:submit").hide();
> - $('#branch').change(function() {
> + $('#branchcode').change(function() {
> $('#selectlibrary').submit();
> });
> $('#filter').keyup(function() {
> @@ -19,6 +19,9 @@ $(document).ready(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);
> @@ -28,6 +31,9 @@ $(document).ready(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);
> @@ -37,6 +43,9 @@ $(document).ready(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);
> @@ -46,11 +55,99 @@ $(document).ready(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>
> @@ -74,24 +171,10 @@ $(document).ready(function() {
> Defining default circulation and fine rules
> <!-- /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, default item type</li>
> - <li>same library, default patron type, same item type</li>
> - <li>same library, default patron type, default item type</li>
> - <li>default library, same patron type, same item type</li>
> - <li>default library, same patron type, default item type</li>
> - <li>default library, default patron type, same item type</li>
> - <li>default library, default patron type, default item
> type</li>
> - </ul>
> - <p>To modify a rule, create a new one with the same patron type
> and item type.</p>
> - </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;">
> + <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
> -->
> @@ -107,288 +190,218 @@ $(document).ready(function() {
> <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">Filter:
> </label><input type="text" name="filter" id="filter" /></div>
> + <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">
> - <form method="post" action="/cgi-bin/koha/admin/
> smart-rules.pl">
> - <input type="hidden" name="op" value="add" />
> - <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">Fine Grace period (day)</th>
> - <th class="fines">Suspension in Days (day)</th>
> - <th class="issues">Renewals Allowed (count)</th>
> - <th class="reserves">Holds Allowed (count)</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 -->
> - <tr>
> - <!-- /TMPL_UNLESS -->
> - <td><!-- TMPL_IF
> NAME="default_humancategorycode" -->
> -
> <em>Default</em>
> - <!--
> TMPL_ELSE -->
> -
> <!-- TMPL_VAR NAME="humancategorycode" -->
> - <!--
> /TMPL_IF -->
> - </td>
> - <td><!-- TMPL_IF
> NAME="default_humanitemtype" -->
> -
> <em>Default</em>
> - <!--
> TMPL_ELSE -->
> -
> <!-- TMPL_VAR NAME="humanitemtype" -->
> - <!--
> /TMPL_IF -->
> - </td>
> - <td
> class="issues"><!-- TMPL_IF NAME="unlimited_maxissueqty" -->
> + <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 -->
> + <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>
> - <td class="issues"><!-- TMPL_IF
> NAME="issuelength" --><!-- TMPL_VAR NAME="issuelength" --> <!-- /TMPL_IF
> --></td>
> - <td class="fines"><!-- TMPL_VAR
> NAME="fine" --></td>
> - <td class="fines"><!-- TMPL_IF
> NAME="chargeperiod" --><!-- TMPL_VAR NAME="chargeperiod" --> <!-- /TMPL_IF
> --></td>
> - <td class="fines"><!-- TMPL_IF
> NAME="firstremind" --><!-- TMPL_VAR NAME="firstremind" --> <!-- /TMPL_IF
> --></td>
> - <td class="fines"><!-- TMPL_IF
> NAME="finedays" --> <!-- TMPL_VAR NAME="finedays" --> <!-- /TMPL_IF --></td>
> - <td class="issues"><!-- TMPL_IF
> NAME="renewalsallowed" --><!-- TMPL_VAR NAME="renewalsallowed" --> <!--
> /TMPL_IF --></td>
> - <td class="reserves"><!-- TMPL_IF
> NAME="reservesallowed" --><!-- TMPL_VAR NAME="reservesallowed" --> <!--
> /TMPL_IF --></td>
> - <td
> class="issues"><!-- 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="branch" -->">Delete</a>
> - </td>
> - </tr>
> - <!-- /TMPL_LOOP -->
> - </tbody>
> - <tfoot>
> - <tr>
> - <td>
> - <select name="categorycode">
> - <option value="*">Default</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="*">Default</option>
> - <!-- TMPL_LOOP NAME="itemtypeloop" -->
> - <option value="<!-- TMPL_VAR NAME="itemtype"
> -->"><!-- TMPL_VAR NAME="description" --></option>
> - <!-- /TMPL_LOOP -->
> - </select>
> - </td>
> - <td class="issues"><input name="maxissueqty"
> size="3" /></td>
> - <td class="issues"><input
> name="issuelength" size="3" /> </td>
> - <td class="fines"><input name="fine"
> size="4" /></td>
> - <td class="fines"><input
> name="chargeperiod" size="2" /></td>
> - <td class="fines"><input
> name="firstremind" size="2" /> </td>
> - <td class="fines"><input name="finedays"
> size="3" /> </td>
> - <td class="issues"><input
> name="renewalsallowed" size="2" /></td>
> - <td class="reserves"><input
> name="reservesallowed" size="2" /></td>
> - <td><input class="issues" name="rentaldiscount"
> size="2" /></td>
> - <td><input type="hidden" name="branch" value="<!--
> TMPL_VAR NAME="branch" -->"/><input type="submit" value="Add" class="submit"
> /></td>
> - </tr>
> - </tfoot>
> - </table>
> - </form>
> + <!-- 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 class="help">
> - <h4>Defaults for this library</h4>
> - <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>
> - </div>
> - <div>
> - <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="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="branch" -->">Unset</a>
> - </td>
> - </tr>
> - </table>
> - </form>
> - </div>
> - <!-- TMPL_IF NAME="show_branch_cat_rule_form" -->
> - <div class="help">
> - <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>
> - </div>
> - <div>
> - <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="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>
> - <!-- 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="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 class="help">
> - <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 branch, <em>not</em> the branch
> that
> - the reserving staff member is from.
> - </p>
> - </div>
> - <div>
> - <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="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="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>
> - </div>
> </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 20b3650..6194a99 100644
> --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tmpl
> +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tmpl
> @@ -9,6 +9,10 @@
> <script type="text/javascript" src="<!-- TMPL_VAR name="themelang"
> -->/lib/jquery/plugins/jquery.checkboxes.min.js"></script>
> <script type="text/javascript">
> //<![CDATA[
> +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; },
> @@ -23,9 +27,20 @@
> 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]],
> @@ -42,14 +57,15 @@
> <!-- /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;
> });
> @@ -64,12 +80,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
> @@ -108,13 +121,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) {
> @@ -190,10 +228,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>
>
> @@ -202,10 +247,6 @@ function refocus(calendar) {
> <li>The patron has a debt of <!-- TMPL_VAR name="DEBT" --></li>
> <!-- /TMPL_IF -->
>
> -<!-- TMPL_IF NAME="RENEW_ISSUE" -->
> - <li>Item is currently checked out to this patron. Renew?</li>
> -<!-- /TMPL_IF -->
> -
> <!-- TMPL_IF NAME="RESERVE_WAITING" -->
> <li>Item is consigned for <!-- TMPL_VAR NAME="RESERVE_WAITING" --></li>
> <!-- /TMPL_IF -->
> @@ -214,28 +255,45 @@ function refocus(calendar) {
> <li>Item is on hold for <!-- TMPL_VAR NAME="RESERVED" --></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="TOO_MANY" -->
> - <li>Too many checked out (already checked out / max : <!-- TMPL_VAR
> name="TOO_MANY" -->)</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">
> @@ -303,6 +361,10 @@ function refocus(calendar) {
> <li>The barcode was not found <!-- TMPL_VAR NAME="barcode"
> --></li>
> <!-- /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 -->
> @@ -316,15 +378,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" -->
> @@ -353,7 +411,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 -->
> @@ -429,40 +486,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" -->" />
> @@ -485,7 +531,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" -->
> @@ -509,16 +556,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 -->
> @@ -552,7 +604,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 -->
> @@ -628,20 +680,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__" -->
> @@ -649,119 +739,95 @@ No patron matched <span class="ex"><!-- TMPL_VAR
> name="message" --></span>
> <!-- TMPL_ELSE -->
> <tr class="highlight">
> <!-- /TMPL_IF -->
> - <td><!-- 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 -->
> + <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>
> - <span class="renewals-disabled">
> + <!-- 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 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>
> - <!-- /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>
> @@ -771,20 +837,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>
>
>
> @@ -808,7 +935,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 ba8d117..e1896a5 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,14 +56,26 @@ 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 -->
>
> <!-- 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>
> @@ -89,11 +103,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 -->
> @@ -105,8 +114,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 -->
> @@ -127,8 +137,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" -->
> @@ -143,8 +155,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>
> @@ -171,7 +184,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 -->
> @@ -219,11 +232,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 -->
> @@ -237,8 +245,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>
> @@ -264,13 +273,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>
> @@ -284,18 +296,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 -->
>
> @@ -357,30 +373,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" -->
> @@ -392,12 +431,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 53f9138..004866a 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>
> @@ -581,6 +602,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 52ff4cd..3646009 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;
> });
>
> @@ -261,10 +266,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>
> @@ -302,7 +314,7 @@
> <!-- TMPL_VAR
> NAME="description" -->
> </td>
> <!-- /TMPL_UNLESS -->
> - <!-- TMPL_IF NAME="showpriority" --><td><!-- TMPL_VAR
> name="rank" --> out of <!-- TMPL_VAR NAME="reservecount" --></td><!--
> /TMPL_IF -->
> + <!-- TMPL_IF NAME="showpriority" --><td>You are number
> <!-- TMPL_VAR name="rank" --> in line</td><!-- /TMPL_IF -->
> <!-- TMPL_IF NAME="reserve_in_future" -->
> <td>
> <input name="reserve_date_<!-- TMPL_VAR
> NAME="biblionumber" -->" id="reserve_date_<!-- TMPL_VAR NAME="biblionumber"
> -->" size="10">
> @@ -422,6 +434,7 @@
>
> <!-- TMPL_UNLESS NAME="singleBranchMode" -->
> <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" -->
> @@ -432,6 +445,9 @@
> <!-- /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>
> @@ -465,8 +481,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/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 699179b..62dc49f 100755
> --- a/opac/opac-reserve.pl
> +++ b/opac/opac-reserve.pl
> @@ -28,11 +28,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 +78,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 +94,7 @@ if (($#biblionumbers < 0) && (!
> $query->param('place_reserve'))) {
> my $branch = $query->param('branch') || 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);
> @@ -247,7 +251,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,
> @@ -257,11 +261,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) {
> @@ -336,12 +335,21 @@ foreach my $biblioNum (@biblionumbers) {
> }
> }
>
> - $biblioLoopIter{itemTypeDescription} =
> $itemTypes->{$biblioData->{itemtype}}{description};
> + $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;
> @@ -355,6 +363,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} ) {
> @@ -371,9 +389,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);
> @@ -381,6 +398,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};
> @@ -418,17 +437,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++;
> }
> @@ -456,11 +465,16 @@ foreach my $biblioNum (@biblionumbers) {
> $biblioLoopIter{bib_available} = 1;
> $biblioLoopIter{holdable} = 1;
> }
> - if ($biblioLoopIter{already_reserved}) {
> +# $biblioLoopIter{multi} = $canReserveMultiple;
> + if ( $biblioLoopIter{already_reserved} && !$canReserveMultiple ) {
> $biblioLoopIter{holdable} = undef;
> + #warn "Already_Reserved";
> }
> if(not CanBookBeReserved($borrowernumber,$biblioNum)){
> - $biblioLoopIter{holdable} = undef;
> + $template->param( message => 1 );
> + $noreserves = 1;
> + $template->param( too_many_reserves => scalar(@reserves));
> + $biblioLoopIter{holdable} = undef;
> }
>
> push @$biblioLoop, \%biblioLoopIter;
> 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 at 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 ad746c9..7e65440 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/lib/KohaTest/Circulation.pm b/t/lib/KohaTest/Circulation.pm
> index 7d5e69d..8236bcb 100644
> --- a/t/lib/KohaTest/Circulation.pm
> +++ b/t/lib/KohaTest/Circulation.pm
> @@ -20,8 +20,6 @@ sub methods : Test( 1 ) {
> CanBookBeIssued
> AddIssue
> GetLoanLength
> - GetIssuingRule
> - GetBranchBorrowerCircRule
> AddReturn
> MarkIssueReturned
> _FixOverduesOnReturn
> diff --git a/t/lib/KohaTest/Members/GetMemberDetails.pm
> b/t/lib/KohaTest/Members/GetMemberDetails.pm
> index e93742b..d75c60e 100644
> --- a/t/lib/KohaTest/Members/GetMemberDetails.pm
> +++ b/t/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/lib/KohaTest/Overdues.pm b/t/lib/KohaTest/Overdues.pm
> index 949c670..02b907e 100644
> --- a/t/lib/KohaTest/Overdues.pm
> +++ b/t/lib/KohaTest/Overdues.pm
> @@ -23,7 +23,6 @@ sub methods : Test( 1 ) {
> BorType
> ReplacementCost
> GetFine
> - GetIssuingRules
> ReplacementCost2
> GetNextIdNotify
> NumberNotifyId
> --
> 1.7.1
>
>
> _______________________________________________
> Koha-patches mailing list
> Koha-patches at lists.koha-community.org
> http://lists.koha-community.org/cgi-bin/mailman/listinfo/koha-patches
> website : http://www.koha-community.org/
> git : http://git.koha-community.org/
> bugs : http://bugs.koha-community.org/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/koha-patches/attachments/20101216/01fd89c9/attachment-0001.htm>
More information about the Koha-patches
mailing list