@@ -, +, @@ 1) Apply patch 2) Run updatedatabase.pl 3) Pick a patron, note the patron's category 5) Issue an item to this patron 4) Edit that category, set "Block expired patrons" to "Block" 5) Verify the patron cannot renew or place holds in the opac 6) Edit the category again, set "Block expired patrons" to "Don't block" 7) Verify the patron *can* renew and place holds in the opac 8) Edit the category again, set "Block expired patrons" to "Follow system preference BlockExpiredPatronOpacActions" 9) Set the system preference BlockExpiredPatronOpacActions to "Block" --- C4/Members.pm | 24 ++- admin/categorie.pl | 323 +++++++++++++------- installer/data/mysql/kohastructure.sql | 1 + installer/data/mysql/sysprefs.sql | 1 + installer/data/mysql/updatedatabase.pl | 17 + .../prog/en/modules/admin/categorie.tt | 8 + .../prog/en/modules/admin/preferences/opac.pref | 7 + .../prog/en/modules/admin/preferences/patrons.pref | 2 +- .../opac-tmpl/prog/en/modules/opac-reserve.tt | 3 + koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt | 11 + opac/opac-renew.pl | 78 +++--- opac/opac-reserve.pl | 11 + opac/opac-user.pl | 149 +++++----- 13 files changed, 406 insertions(+), 229 deletions(-) --- a/C4/Members.pm +++ a/C4/Members.pm @@ -325,11 +325,31 @@ sub GetMemberDetails { my $query; my $sth; if ($borrowernumber) { - $sth = $dbh->prepare("SELECT borrowers.*,category_type,categories.description,reservefee,enrolmentperiod FROM borrowers LEFT JOIN categories ON borrowers.categorycode=categories.categorycode WHERE borrowernumber=?"); + $sth = $dbh->prepare(" + SELECT borrowers.*, + category_type, + categories.description, + categories.BlockExpiredPatronOpacActions, + reservefee, + enrolmentperiod + FROM borrowers + LEFT JOIN categories ON borrowers.categorycode=categories.categorycode + WHERE borrowernumber = ? + "); $sth->execute($borrowernumber); } elsif ($cardnumber) { - $sth = $dbh->prepare("SELECT borrowers.*,category_type,categories.description,reservefee,enrolmentperiod FROM borrowers LEFT JOIN categories ON borrowers.categorycode=categories.categorycode WHERE cardnumber=?"); + $sth = $dbh->prepare(" + SELECT borrowers.*, + category_type, + categories.description, + categories.BlockExpiredPatronOpacActions, + reservefee, + enrolmentperiod + FROM borrowers + LEFT JOIN categories ON borrowers.categorycode = categories.categorycode + WHERE cardnumber = ? + "); $sth->execute($cardnumber); } else { --- a/admin/categorie.pl +++ a/admin/categorie.pl @@ -46,42 +46,47 @@ use C4::Output; use C4::Dates; use C4::Form::MessagingPreferences; -sub StringSearch { - my ($searchstring,$type)=@_; - my $dbh = C4::Context->dbh; - $searchstring=~ s/\'/\\\'/g; - my @data=split(' ',$searchstring); - my $count=@data; - my $sth=$dbh->prepare("Select * from categories where (description like ?) order by category_type,description,categorycode"); - $sth->execute("$data[0]%"); - my @results; - while (my $data=$sth->fetchrow_hashref){ - push(@results,$data); - } - # $sth->execute; - $sth->finish; - return (scalar(@results),\@results); -} +sub StringSearch { + my ( $searchstring, $type ) = @_; + my $dbh = C4::Context->dbh; + $searchstring =~ s/\'/\\\'/g; + my @data = split( ' ', $searchstring ); + my $count = @data; + my $sth = $dbh->prepare("SELECT * FROM categories WHERE (description LIKE ?) ORDER BY category_type, description, categorycode"); + $sth->execute("$data[0]%"); + my @results; -my $input = new CGI; -my $searchfield=$input->param('description'); -my $script_name="/cgi-bin/koha/admin/categorie.pl"; -my $categorycode=$input->param('categorycode'); -my $op = $input->param('op'); + while ( my $data = $sth->fetchrow_hashref ) { + push( @results, $data ); + } -my ($template, $loggedinuser, $cookie) - = get_template_and_user({template_name => "admin/categorie.tmpl", - query => $input, - type => "intranet", - authnotrequired => 0, - flagsrequired => {parameters => 'parameters_remaining_permissions'}, - debug => 1, - }); + # $sth->execute; + $sth->finish; + return ( scalar(@results), \@results ); +} +my $input = new CGI; +my $searchfield = $input->param('description'); +my $script_name = "/cgi-bin/koha/admin/categorie.pl"; +my $categorycode = $input->param('categorycode'); +my $op = $input->param('op'); +my $block_expired = $input->param("block_expired"); -$template->param(script_name => $script_name, - categorycode => $categorycode, - searchfield => $searchfield); +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { template_name => "admin/categorie.tmpl", + query => $input, + type => "intranet", + authnotrequired => 0, + flagsrequired => { parameters => 'parameters_remaining_permissions' }, + debug => 1, + } +); + +$template->param( + script_name => $script_name, + categorycode => $categorycode, + searchfield => $searchfield +); ################## ADD_FORM ################################## @@ -94,10 +99,13 @@ if ($op eq 'add_form') { my @selected_branches; if ($categorycode) { my $dbh = C4::Context->dbh; - my $sth=$dbh->prepare("select categorycode,description,enrolmentperiod,enrolmentperioddate,upperagelimit,dateofbirthrequired,enrolmentfee,issuelimit,reservefee,hidelostitems,overduenoticerequired,category_type from categories where categorycode=?"); + my $sth=$dbh->prepare(" + SELECT * + FROM categories + WHERE categorycode = ? + "); $sth->execute($categorycode); - $data=$sth->fetchrow_hashref; - + $data = $sth->fetchrow_hashref; $sth = $dbh->prepare("SELECT b.branchcode, b.branchname FROM categories_branches AS cb, branches AS b WHERE cb.branchcode = b.branchcode AND cb.categorycode = ?"); $sth->execute( $categorycode ); while ( my $branch = $sth->fetchrow_hashref ) { @@ -119,22 +127,26 @@ if ($op eq 'add_form') { }; } - $template->param(description => $data->{'description'}, - enrolmentperiod => $data->{'enrolmentperiod'}, - enrolmentperioddate => C4::Dates::format_date($data->{'enrolmentperioddate'}), - upperagelimit => $data->{'upperagelimit'}, - dateofbirthrequired => $data->{'dateofbirthrequired'}, - enrolmentfee => sprintf("%.2f",$data->{'enrolmentfee'}), - overduenoticerequired => $data->{'overduenoticerequired'}, - issuelimit => $data->{'issuelimit'}, - reservefee => sprintf("%.2f",$data->{'reservefee'}), - hidelostitems => $data->{'hidelostitems'}, - category_type => $data->{'category_type'}, - SMSSendDriver => C4::Context->preference("SMSSendDriver"), - TalkingTechItivaPhone => C4::Context->preference("TalkingTechItivaPhoneNotification"), - "type_".$data->{'category_type'} => 1, - branches_loop => \@branches_loop, - ); + $template->param( + description => $data->{'description'}, + enrolmentperiod => $data->{'enrolmentperiod'}, + enrolmentperioddate => C4::Dates::format_date( $data->{'enrolmentperioddate'} ), + upperagelimit => $data->{'upperagelimit'}, + dateofbirthrequired => $data->{'dateofbirthrequired'}, + enrolmentfee => sprintf( "%.2f", $data->{'enrolmentfee'} ), + overduenoticerequired => $data->{'overduenoticerequired'}, + issuelimit => $data->{'issuelimit'}, + reservefee => sprintf( "%.2f", $data->{'reservefee'} ), + hidelostitems => $data->{'hidelostitems'}, + category_type => $data->{'category_type'}, + SMSSendDriver => C4::Context->preference("SMSSendDriver"), + TalkingTechItivaPhone => C4::Context->preference("TalkingTechItivaPhoneNotification"), + branches_loop => \@branches_loop, + SMSSendDriver => C4::Context->preference("SMSSendDriver"), + BlockExpiredPatronOpacActions => $data->{'BlockExpiredPatronOpacActions'}, + "type_" . $data->{'category_type'} => 1, + ); + if (C4::Context->preference('EnhancedMessagingPreferences')) { C4::Form::MessagingPreferences::set_form_values({ categorycode => $categorycode } , $template); } @@ -148,19 +160,47 @@ if ($op eq 'add_form') { if($input->param('enrolmentperioddate')){ $input->param('enrolmentperioddate' => C4::Dates::format_date_in_iso($input->param('enrolmentperioddate')) ); } - + if ($is_a_modif) { - my $sth=$dbh->prepare("UPDATE categories SET description=?,enrolmentperiod=?, enrolmentperioddate=?,upperagelimit=?,dateofbirthrequired=?,enrolmentfee=?,reservefee=?,hidelostitems=?,overduenoticerequired=?,category_type=? WHERE categorycode=?"); - $sth->execute(map { $input->param($_) } ('description','enrolmentperiod','enrolmentperioddate','upperagelimit','dateofbirthrequired','enrolmentfee','reservefee','hidelostitems','overduenoticerequired','category_type','categorycode')); + my $sth=$dbh->prepare(" + UPDATE categories + SET description=?, + enrolmentperiod=?, + enrolmentperioddate=?, + upperagelimit=?, + dateofbirthrequired=?, + enrolmentfee=?, + reservefee=?, + hidelostitems=?, + overduenoticerequired=?, + category_type=?, + BlockExpiredPatronOpacActions=? + WHERE categorycode=?" + ); + $sth->execute( + map { $input->param($_) } ( + 'description', + 'enrolmentperiod', + 'enrolmentperioddate', + 'upperagelimit', + 'dateofbirthrequired', + 'enrolmentfee', + 'reservefee', + 'hidelostitems', + 'overduenoticerequired', + 'category_type', + 'block_expired', + 'categorycode' + ) + ); my @branches = $input->param("branches"); if ( @branches ) { $sth = $dbh->prepare("DELETE FROM categories_branches WHERE categorycode = ?"); $sth->execute( $input->param( "categorycode" ) ); - $sth = $dbh->prepare( - "INSERT INTO categories_branches - ( categorycode, branchcode ) - VALUES ( ?, ? )" - ); + $sth = $dbh->prepare(" + INSERT INTO categories_branches ( categorycode, branchcode ) + VALUES ( ?, ? ) + "); for my $branchcode ( @branches ) { next if not $branchcode; $sth->bind_param( 1, $input->param( "categorycode" ) ); @@ -169,32 +209,65 @@ if ($op eq 'add_form') { } } $sth->finish; - } else { - my $sth=$dbh->prepare("INSERT INTO categories (categorycode,description,enrolmentperiod,enrolmentperioddate,upperagelimit,dateofbirthrequired,enrolmentfee,reservefee,hidelostitems,overduenoticerequired,category_type) values (?,?,?,?,?,?,?,?,?,?,?)"); - $sth->execute(map { $input->param($_) } ('categorycode','description','enrolmentperiod','enrolmentperioddate','upperagelimit','dateofbirthrequired','enrolmentfee','reservefee','hidelostitems','overduenoticerequired','category_type')); - $sth->finish; - } - if (C4::Context->preference('EnhancedMessagingPreferences')) { - C4::Form::MessagingPreferences::handle_form_action($input, - { categorycode => $input->param('categorycode') }, $template); + } else { + my $sth=$dbh->prepare(" + INSERT INTO categories ( + categorycode, + description, + enrolmentperiod, + enrolmentperioddate, + upperagelimit, + dateofbirthrequired, + enrolmentfee, + reservefee, + hidelostitems, + overduenoticerequired, + category_type, + BlockExpiredPatronOpacActions + ) + VALUES (?,?,?,?,?,?,?,?,?,?,?,?)"); + $sth->execute( + map { $input->param($_) } ( + 'categorycode', + 'description', + 'enrolmentperiod', + 'enrolmentperioddate', + 'upperagelimit', + 'dateofbirthrequired', + 'enrolmentfee', + 'reservefee', + 'hidelostitems', + 'overduenoticerequired', + 'category_type', + 'block_expired' + ) + ); + $sth->finish; + } + if ( C4::Context->preference('EnhancedMessagingPreferences') ) { + C4::Form::MessagingPreferences::handle_form_action( $input, { categorycode => $input->param('categorycode') }, $template ); } print "Content-Type: text/html\n\n"; exit; - # END $OP eq ADD_VALIDATE +# END $OP eq ADD_VALIDATE ################## DELETE_CONFIRM ################################## # called by default form, used to confirm deletion of data in DB } elsif ($op eq 'delete_confirm') { $template->param(delete_confirm => 1); my $dbh = C4::Context->dbh; - my $sth=$dbh->prepare("select count(*) as total from borrowers where categorycode=?"); + my $sth=$dbh->prepare("SELECT count(*) AS total FROM borrowers WHERE categorycode = ?"); $sth->execute($categorycode); my $total = $sth->fetchrow_hashref; $sth->finish; $template->param(total => $total->{'total'}); - - my $sth2=$dbh->prepare("select categorycode,description,enrolmentperiod,enrolmentperioddate,upperagelimit,dateofbirthrequired,enrolmentfee,issuelimit,reservefee,hidelostitems,overduenoticerequired,category_type from categories where categorycode=?"); + + my $sth2 = $dbh->prepare(" + SELECT * + FROM categories + WHERE categorycode = ? + "); $sth2->execute($categorycode); my $data=$sth2->fetchrow_hashref; $sth2->finish; @@ -202,18 +275,20 @@ if ($op eq 'add_form') { $template->param(totalgtzero => 1); } - $template->param( description => $data->{'description'}, - enrolmentperiod => $data->{'enrolmentperiod'}, - enrolmentperioddate => C4::Dates::format_date($data->{'enrolmentperioddate'}), - upperagelimit => $data->{'upperagelimit'}, - dateofbirthrequired => $data->{'dateofbirthrequired'}, - enrolmentfee => sprintf("%.2f",$data->{'enrolmentfee'}), - overduenoticerequired => $data->{'overduenoticerequired'}, - issuelimit => $data->{'issuelimit'}, - reservefee => sprintf("%.2f",$data->{'reservefee'}), - hidelostitems => $data->{'hidelostitems'}, - category_type => $data->{'category_type'}, - ); + $template->param( + description => $data->{'description'}, + enrolmentperiod => $data->{'enrolmentperiod'}, + enrolmentperioddate => C4::Dates::format_date( $data->{'enrolmentperioddate'} ), + upperagelimit => $data->{'upperagelimit'}, + dateofbirthrequired => $data->{'dateofbirthrequired'}, + enrolmentfee => sprintf( "%.2f", $data->{'enrolmentfee'} ), + overduenoticerequired => $data->{'overduenoticerequired'}, + issuelimit => $data->{'issuelimit'}, + reservefee => sprintf( "%.2f", $data->{'reservefee'} ), + hidelostitems => $data->{'hidelostitems'}, + category_type => $data->{'category_type'}, + BlockExpiredPatronOpacActions => $data->{'BlockExpiredPatronOpacActions'}, + ); # END $OP eq DELETE_CONFIRM ################## DELETE_CONFIRMED ################################## # called by delete_confirm, used to effectively confirm deletion of data in DB @@ -229,51 +304,67 @@ if ($op eq 'add_form') { # END $OP eq DELETE_CONFIRMED } else { # DEFAULT - $template->param(else => 1); - my @loop; - my ($count,$results)=StringSearch($searchfield,'web'); + $template->param(else => 1); + my @loop; + my ($count,$results) = StringSearch($searchfield,'web'); + my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare("SELECT b.branchcode, b.branchname FROM categories_branches AS cb, branches AS b WHERE cb.branchcode = b.branchcode AND cb.categorycode = ?"); - for (my $i=0; $i < $count; $i++){ + my $sth = $dbh->prepare(" + SELECT b.branchcode, + b.branchname + FROM categories_branches AS cb, + branches AS b + WHERE cb.branchcode = b.branchcode + AND cb.categorycode = ? + "); + + for (my $i=0; $i < $count; $i++){ $sth->execute( $results->[$i]{'categorycode'} ); + my @selected_branches; while ( my $branch = $sth->fetchrow_hashref ) { push @selected_branches, $branch; } - my %row = ( - categorycode => $results->[$i]{'categorycode'}, - description => $results->[$i]{'description'}, - enrolmentperiod => $results->[$i]{'enrolmentperiod'}, - enrolmentperioddate => C4::Dates::format_date($results->[$i]{'enrolmentperioddate'}), - upperagelimit => $results->[$i]{'upperagelimit'}, - dateofbirthrequired => $results->[$i]{'dateofbirthrequired'}, - enrolmentfee => sprintf("%.2f",$results->[$i]{'enrolmentfee'}), - overduenoticerequired => $results->[$i]{'overduenoticerequired'}, - issuelimit => $results->[$i]{'issuelimit'}, - reservefee => sprintf("%.2f",$results->[$i]{'reservefee'}), - hidelostitems => $results->[$i]{'hidelostitems'}, - category_type => $results->[$i]{'category_type'}, - "type_".$results->[$i]{'category_type'} => 1, - branches => \@selected_branches, + + my %row = ( + categorycode => $results->[$i]{'categorycode'}, + description => $results->[$i]{'description'}, + enrolmentperiod => $results->[$i]{'enrolmentperiod'}, + enrolmentperioddate => C4::Dates::format_date($results->[$i]{'enrolmentperioddate'}), + upperagelimit => $results->[$i]{'upperagelimit'}, + dateofbirthrequired => $results->[$i]{'dateofbirthrequired'}, + enrolmentfee => sprintf("%.2f",$results->[$i]{'enrolmentfee'}), + overduenoticerequired => $results->[$i]{'overduenoticerequired'}, + issuelimit => $results->[$i]{'issuelimit'}, + reservefee => sprintf("%.2f",$results->[$i]{'reservefee'}), + hidelostitems => $results->[$i]{'hidelostitems'}, + category_type => $results->[$i]{'category_type'}, + block_syspref => 1, + branches => \@selected_branches, + "type_".$results->[$i]{'category_type'} => 1, ); + if (C4::Context->preference('EnhancedMessagingPreferences')) { my $brief_prefs = _get_brief_messaging_prefs($results->[$i]{'categorycode'}); $row{messaging_prefs} = $brief_prefs if @$brief_prefs; } - push @loop, \%row; - } - $template->param(loop => \@loop); - # check that I (institution) and C (child) exists. otherwise => warning to the user - $sth=$dbh->prepare("select category_type from categories where category_type='C'"); - $sth->execute; - my ($categoryChild) = $sth->fetchrow; - $template->param(categoryChild => $categoryChild); - $sth=$dbh->prepare("select category_type from categories where category_type='I'"); - $sth->execute; - my ($categoryInstitution) = $sth->fetchrow; - $template->param(categoryInstitution => $categoryInstitution); - $sth->finish; + + push @loop, \%row; + } + + $template->param(loop => \@loop); + # check that I (institution) and C (child) exists. otherwise => warning to the user + + $sth = $dbh->prepare("select category_type from categories where category_type='C'"); + $sth->execute; + my ($categoryChild) = $sth->fetchrow; + $template->param(categoryChild => $categoryChild); + $sth = $dbh->prepare("select category_type from categories where category_type='I'"); + $sth->execute; + my ($categoryInstitution) = $sth->fetchrow; + $template->param(categoryInstitution => $categoryInstitution); + $sth->finish; } #---- END $OP eq DEFAULT output_html_with_http_headers $input, $cookie, $template->output; --- a/installer/data/mysql/kohastructure.sql +++ a/installer/data/mysql/kohastructure.sql @@ -438,6 +438,7 @@ CREATE TABLE `categories` ( -- this table shows information related to Koha patr `reservefee` decimal(28,6) default NULL, -- cost to place holds `hidelostitems` tinyint(1) NOT NULL default '0', -- are lost items shown to this category (1 for yes, 0 for no) `category_type` varchar(1) NOT NULL default 'A', -- type of Koha patron (Adult, Child, Professional, Organizational, Statistical, Staff) + `BlockExpiredPatronOpacActions` tinyint(1) NOT NULL default '-1', -- wheither or not a patron of this categori can renew books or place holds once their card has expired. 0 means they can, 1 means they cannot, -1 means use syspref BLockExpiredPAtronOpacACtions PRIMARY KEY (`categorycode`), UNIQUE KEY `categorycode` (`categorycode`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; --- a/installer/data/mysql/sysprefs.sql +++ a/installer/data/mysql/sysprefs.sql @@ -418,3 +418,4 @@ INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES(' INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('Persona',0,'Use Mozilla Persona for login','','YesNo'); INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacItemLocation','callnum','Show the shelving location of items in the opac','callnum|ccode|location','Choice'); INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('TrackClicks','0','Track links clicked',NULL,'Integer'); +INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('BlockExpiredPatronOpacActions', 'yes', 'Set whether an expired patron can perform opac actions such as placing a hold or reserve, can be overridden on a per patron-type basis',NULL,'YesNo'); --- a/installer/data/mysql/updatedatabase.pl +++ a/installer/data/mysql/updatedatabase.pl @@ -6476,6 +6476,23 @@ if ( CheckVersion($DBversion) ) { SetVersion($DBversion); } +$DBversion = "3.11.00.XXX"; +if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { + $dbh->do(" + INSERT INTO systempreferences (variable,value,explanation,options,type) + VALUES ( + 'BlockExpiredPatronOpacActions', + 'yes', + 'Set whether an expired patron can perform opac actions such as placing a hold or reserve, can be overridden on a per patron-type basis', + NULL, + 'YesNo' + ) + "); + $dbh->do("ALTER TABLE `categories` ADD COLUMN `BlockExpiredPatronOpacActions` TINYINT(1) DEFAULT 0 NOT NULL"); + print "Upgraded to $DBversion done (Bug 6739 - expired patrons not blocked from opac actions)\n"; + SetVersion ($DBversion); +} +=head1 FUNCTIONS =head1 FUNCTIONS --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categorie.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categorie.tt @@ -198,6 +198,14 @@ Select All if this category type must to be displayed all the time. Otherwise select librairies you want to associate with this value. +
  • + + Should patrons of this category be blocked from opac actions such as renew and reserve when their cards have expired. +
  • --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref @@ -493,6 +493,13 @@ OPAC: yes: Allow - opac users to share private lists with other patrons. This feature is not active yet but will be released soon + - + - pref: BlockExpiredPatronOpacActions + choices: + yes: "Block" + no: "Don't Block" + - expired patrons from opac actions such as placing a hold or renew, the setting for a patron category takes priority over this + Privacy: - - pref: AnonSuggestions --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref @@ -91,7 +91,7 @@ Patrons: class: integer - characters long. - - - Show a notice that a patron is about to expire + - Show a notice if the patron is about to expire or has expired - pref: NotifyBorrowerDeparture class: integer - days beforehand. --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt +++ a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt @@ -210,6 +210,9 @@ [% IF ( bad_data ) %]
    ERROR: Internal error: incomplete hold request.
    [% END %] + [% IF ( expired_patron ) %] +

    Sorry, you cannot place holds because your library card has expired.

    Please contact your librarian if you wish to renew your card

    + [% END %] [% ELSE %] [% IF ( none_available ) %]
    Sorry, none of these items can be placed on hold. --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt +++ a/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt @@ -96,8 +96,19 @@ $.tablesorter.addParser({
    Please note: Your card has expired. Please contact the library for more information.
    + [% ELSIF ( BORROWER_INF.warnexpired ) %] +
    + Please note: You card has expired as of [% BORROWER_INF.warnexpired %]. Please contact the library if you wish to renew your subscription. +
    [% END %] + [% IF ( RENEW_ERROR ) %] +
    + Please note: You're renew failed with the following error: [% RENEW_ERROR %] +
    + [% END %] + + [% IF ( patron_flagged ) %]