Bugzilla – Attachment 16063 Details for
Bug 6739
expired patrons not blocked from opac actions
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 6739 - expired patrons not blocked from opac actions
bug-6739--added-the-ability-to-configure-whether-a.patch (text/plain), 45.18 KB, created by
Kyle M Hall (khall)
on 2013-03-12 13:47:10 UTC
(
hide
)
Description:
Bug 6739 - expired patrons not blocked from opac actions
Filename:
MIME Type:
Creator:
Kyle M Hall (khall)
Created:
2013-03-12 13:47:10 UTC
Size:
45.18 KB
patch
obsolete
>From 414d3e292fc7779eab5c71f1c9a5ba58e2e1aa53 Mon Sep 17 00:00:00 2001 >From: Chris Hall <chrish@catalyst.net.nz> >Date: Mon, 20 Feb 2012 10:07:13 +1300 >Subject: [PATCH] bug 6739 : added the ability to configure whether an expired patron can perform opac actions such as renew and reserve on both a syspref and patron-category level > >Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com> >--- > C4/Members.pm | 4 +- > 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 | 156 +++++----- > 13 files changed, 393 insertions(+), 229 deletions(-) > >diff --git a/C4/Members.pm b/C4/Members.pm >index 8042840..05ea848 100644 >--- a/C4/Members.pm >+++ b/C4/Members.pm >@@ -325,11 +325,11 @@ 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 { >diff --git a/admin/categorie.pl b/admin/categorie.pl >index 952ef7a..2a006b3 100755 >--- a/admin/categorie.pl >+++ b/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<META HTTP-EQUIV=Refresh CONTENT=\"0; URL=categorie.pl\"></html>"; > 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; >diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql >index d004fe1..3ed7066 100644 >--- a/installer/data/mysql/kohastructure.sql >+++ b/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; >diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql >index cad409c..2825d8b 100644 >--- a/installer/data/mysql/sysprefs.sql >+++ b/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'); >diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl >index 041040a..39f321b 100755 >--- a/installer/data/mysql/updatedatabase.pl >+++ b/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 > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categorie.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categorie.tt >index e7e00d4..176b68b 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categorie.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categorie.tt >@@ -198,6 +198,14 @@ > <span>Select All if this category type must to be displayed all the time. Otherwise select librairies you want to associate with this value. > </span> > </li> >+ <li><label for="block_expired">Block expired patrons</label> >+ <select name="block_expired" id="block_expired"> >+ <option value="-1" [% IF ( BlockExpiredPatronOpacActions == -1 ) %] selected="selected" [% END %]> Use syspref </option> >+ <option value="1" [% IF ( BlockExpiredPatronOpacActions == 1 ) %] selected="selected" [% END %]> Block </option> >+ <option value="0" [% IF ( BlockExpiredPatronOpacActions == 0 ) %] selected="selected" [% END %]> Don't block </option> >+ </select> >+ Should patrons of this category be blocked from opac actions such as renew and reserve when their cards have expired. >+ </li> > </ol> > </fieldset> > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref >index 57df512..dc5c4a6 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref >+++ b/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 >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref >index 74d14af..fbd801a 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref >+++ b/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. >diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt >index 5788b38..55abab1 100644 >--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt >+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt >@@ -210,6 +210,9 @@ > [% IF ( bad_data ) %] > <div id="bad_data" class="dialog alert">ERROR: Internal error: incomplete hold request.</div> > [% END %] >+ [% IF ( expired_patron ) %] >+ <div id="expired_patron" class="dialog alert"><p><strong>Sorry</strong>, you cannot place holds because your library card has expired.<p><p>Please contact your librarian if you wish to renew your card</p></div> >+ [% END %] > [% ELSE %] > [% IF ( none_available ) %] > <div id="none_available" class="dialog alert"><strong>Sorry</strong>, none of these items can be placed on hold. >diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt >index 96f6e8d..7d0f003 100644 >--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt >+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt >@@ -96,8 +96,19 @@ $.tablesorter.addParser({ > <div class="dialog alert" id="warnexpired"> > <strong>Please note:</strong><span> Your card has expired. Please contact the library for more information.</span> > </div> >+ [% ELSIF ( BORROWER_INF.warnexpired ) %] >+ <div class="dialog alert"> >+ <string>Please note:</string><span> You card has expired as of [% BORROWER_INF.warnexpired %]. Please contact the library if you wish to renew your subscription.</span> >+ </div> > [% END %] > >+ [% IF ( RENEW_ERROR ) %] >+ <div class="dialog alert"> >+ <string>Please note:</string><span> You're renew failed with the following error: [% RENEW_ERROR %]</span> >+ </div> >+ [% END %] >+ >+ > [% IF ( patron_flagged ) %] > <div class="dialog alert"> > <ul> >diff --git a/opac/opac-renew.pl b/opac/opac-renew.pl >index c699b35..39d7c03 100755 >--- a/opac/opac-renew.pl >+++ b/opac/opac-renew.pl >@@ -29,50 +29,58 @@ use C4::Circulation; > use C4::Auth; > use C4::Items; > use C4::Members; >+use Date::Calc qw( Today Date_to_Days ); > my $query = new CGI; > > my ( $template, $borrowernumber, $cookie ) = get_template_and_user( >- { >- template_name => "opac-user.tmpl", >- query => $query, >- type => "opac", >- authnotrequired => 0, >- flagsrequired => { borrow => 1 }, >- debug => 1, >- } >+ { >+ template_name => "opac-user.tmpl", >+ query => $query, >+ type => "opac", >+ authnotrequired => 0, >+ flagsrequired => { borrow => 1 }, >+ debug => 1, >+ } > ); > my @items = $query->param('item'); > > my $opacrenew = C4::Context->preference("OpacRenewalAllowed"); > > my $errorstring=''; >-for my $itemnumber ( @items ) { >- my ($status,$error) = CanBookBeRenewed( $borrowernumber, $itemnumber ); >- if ( $status == 1 && $opacrenew == 1 ) { >- my $renewalbranch = C4::Context->preference('OpacRenewalBranch'); >- my $branchcode; >- if ($renewalbranch eq 'itemhomebranch'){ >- my $item = GetItem($itemnumber); >- $branchcode=$item->{'homebranch'}; >- } >- elsif ($renewalbranch eq 'patronhomebranch'){ >- my $borrower = GetMemberDetails($borrowernumber); >- $branchcode = $borrower->{'branchcode'}; >- } >- elsif ($renewalbranch eq 'checkoutbranch'){ >- my $issue = GetOpenIssue($itemnumber); >- $branchcode = $issue->{'branchcode'}; >- } >- elsif ($renewalbranch eq 'NULL'){ >- $branchcode=''; >- } >- else { >- $branchcode='OPACRenew' >- } >- AddRenewal( $borrowernumber, $itemnumber, $branchcode); >- } >- else { >- $errorstring .= $error ."|"; >+my $member_details = GetMemberDetails($borrowernumber); >+# BlockExpiredPatronOpacActions syspref 0 is false, 1 is true. BlockExpiredPatronOpacActions for categories (from GetMemberDetails) -1 means use syspref, 0 is false, 1 is true (where false means dont block, true means block) >+if( ($member_details->{'BlockExpiredPatronOpacActions'} == -1 ? C4::Conext->preference('BlockExpiredPatronOpacActions') : $member_details->{'BlockExpiredPatronOpacActions'}) >+ && Date_to_Days( Today() ) > Date_to_Days( split /-/, $member_details->{'dateexpiry'} ) ){ >+ $errorstring='unable to renew as your card has expired'; >+} else { >+ for my $itemnumber ( @items ) { >+ my ($status,$error) = CanBookBeRenewed( $borrowernumber, $itemnumber ); >+ if ( $status == 1 && $opacrenew == 1 ) { >+ my $renewalbranch = C4::Context->preference('OpacRenewalBranch'); >+ my $branchcode; >+ if ($renewalbranch eq 'itemhomebranch'){ >+ my $item = GetItem($itemnumber); >+ $branchcode=$item->{'homebranch'}; >+ } >+ elsif ($renewalbranch eq 'patronhomebranch'){ >+ my $borrower = GetMemberDetails($borrowernumber); >+ $branchcode = $borrower->{'branchcode'}; >+ } >+ elsif ($renewalbranch eq 'checkoutbranch'){ >+ my $issue = GetOpenIssue($itemnumber); >+ $branchcode = $issue->{'branchcode'}; >+ } >+ elsif ($renewalbranch eq 'NULL'){ >+ $branchcode=''; >+ } >+ else { >+ $branchcode='OPACRenew' >+ } >+ AddRenewal( $borrowernumber, $itemnumber, $branchcode); >+ } >+ else { >+ $errorstring .= $error ."|"; >+ } > } > } > >diff --git a/opac/opac-reserve.pl b/opac/opac-reserve.pl >index 07b4f76..5296f3c 100755 >--- a/opac/opac-reserve.pl >+++ b/opac/opac-reserve.pl >@@ -35,6 +35,7 @@ use C4::Branch; # GetBranches > use C4::Overdues; > use C4::Debug; > use Koha::DateUtils; >+use Date::Calc qw/Today Date_to_Days/; > # use Data::Dumper; > > my $MAXIMUM_NUMBER_OF_RESERVES = C4::Context->preference("maxreserves"); >@@ -65,6 +66,16 @@ sub get_out { > # get borrower information .... > my ( $borr ) = GetMemberDetails( $borrowernumber ); > >+# check if this user can place a reserve, -1 means use sys pref, 0 means dont block, 1 means block >+if( $borr->{'BlockExpiredPatronOpacActions'} == -1 ? C4::Context->preference("BlockExpiredPatronOpacActions") : $borr->{'BlockExpiredPatronOpacActions'} ) { >+ >+ if( Date_to_Days( Today() ) > Date_to_Days( split /-/, $borr->{'dateexpiry'} ) ){ >+ # cannot reserve, their card has expired and the rules set mean this is not allowed >+ $template->param( message=>1, expired_patron=>1 ); >+ get_out($query, $cookie, $template->output); >+ } >+} >+ > # Pass through any reserve charge > if ($borr->{reservefee} > 0){ > $template->param( RESERVE_CHARGE => sprintf("%.2f",$borr->{reservefee})); >diff --git a/opac/opac-user.pl b/opac/opac-user.pl >index f4273cb..d2ad90d 100755 >--- a/opac/opac-user.pl >+++ b/opac/opac-user.pl >@@ -12,9 +12,9 @@ > # 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., >-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+# 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; >@@ -65,10 +65,7 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( > } > ); > >-my $show_priority; >-for ( C4::Context->preference("OPACShowHoldQueueDetails") ) { >- m/priority/ and $show_priority = 1; >-} >+my $OPACDisplayRequestPriority = (C4::Context->preference("OPACDisplayRequestPriority")) ? 1 : 0; > my $patronupdate = $query->param('patronupdate'); > my $canrenew = 1; > >@@ -110,7 +107,6 @@ if ( $borr->{amountoutstanding} > $no_renewal_amt ) { > $canrenew = 0; > $template->param( > renewal_blocked_fines => sprintf( '%.02f', $no_renewal_amt ), >- renewal_blocked_fines_amountoutstanding => sprintf( '%.02f', $borr->{amountoutstanding} ), > ); > } > >@@ -125,19 +121,24 @@ my @bordat; > $bordat[0] = $borr; > > # Warningdate is the date that the warning starts appearing >-if ( $borr->{dateexpiry} && Date_to_Days( $today_year, $today_month, $today_day ) > Date_to_Days( $warning_year, $warning_month, $warning_day ) ) { >- $borr->{'warnexpired'} = 1; >-} >-elsif ( $borr->{dateexpiry} && C4::Context->preference('NotifyBorrowerDeparture') && >- Date_to_Days(Add_Delta_Days($warning_year, $warning_month, $warning_day,- C4::Context->preference('NotifyBorrowerDeparture'))) < >- Date_to_Days( $today_year, $today_month, $today_day ) ) { >+if ( $borr->{'dateexpiry'} && C4::Context->preference('NotifyBorrowerDeparture') ) { >+ my $days_to_expiry = Date_to_Days( $warning_year, $warning_month, $warning_day ) - Date_to_Days( $today_year, $today_month, $today_day ); >+ if ( $days_to_expiry < 0 ) { >+ >+ #borrower card has expired, warn the borrower >+ $borr->{'warnexpired'} = $borr->{'dateexpiry'}; >+ } elsif ( $days_to_expiry < C4::Context->preference('NotifyBorrowerDeparture') ) { >+ > # borrower card soon to expire, warn the borrower > $borr->{'warndeparture'} = $borr->{dateexpiry}; >- if (C4::Context->preference('ReturnBeforeExpiry')){ >+ if ( C4::Context->preference('ReturnBeforeExpiry') ) { > $borr->{'returnbeforeexpiry'} = 1; > } >+ } > } > >+# pass on any renew errors to the template for displaying >+$template->param( RENEW_ERROR => $query->param('renew_error') ) if $query->param('renew_error'); > > $template->param( BORROWER_INFO => \@bordat, > borrowernumber => $borrowernumber, >@@ -145,6 +146,7 @@ $template->param( BORROWER_INFO => \@bordat, > OPACMySummaryHTML => (C4::Context->preference("OPACMySummaryHTML")) ? 1 : 0, > surname => $borr->{surname}, > showname => $borr->{showname}, >+ > ); > > #get issued items .... >@@ -156,55 +158,58 @@ my @issuedat; > my $itemtypes = GetItemTypes(); > my $issues = GetPendingIssues($borrowernumber); > if ($issues){ >- foreach my $issue ( sort { $b->{date_due}->datetime() cmp $a->{date_due}->datetime() } @{$issues} ) { >- # check for reserves >- my ( $restype, $res, undef ) = CheckReserves( $issue->{'itemnumber'} ); >- if ( $restype ) { >- $issue->{'reserved'} = 1; >- } >- >- my ( $total , $accts, $numaccts) = GetMemberAccountRecords( $borrowernumber ); >- my $charges = 0; >- foreach my $ac (@$accts) { >- if ( $ac->{'itemnumber'} == $issue->{'itemnumber'} ) { >- $charges += $ac->{'amountoutstanding'} >- if $ac->{'accounttype'} eq 'F'; >- $charges += $ac->{'amountoutstanding'} >- if $ac->{'accounttype'} eq 'FU'; >- $charges += $ac->{'amountoutstanding'} >- if $ac->{'accounttype'} eq 'L'; >- } >- } >- $issue->{'charges'} = $charges; >- >- # check if item is renewable >- my ($status,$renewerror) = CanBookBeRenewed( $borrowernumber, $issue->{'itemnumber'} ); >- ($issue->{'renewcount'},$issue->{'renewsallowed'},$issue->{'renewsleft'}) = GetRenewCount($borrowernumber, $issue->{'itemnumber'}); >+ foreach my $issue ( sort { $b->{date_due}->datetime() cmp $a->{date_due}->datetime() } @{$issues} ) { >+ # check for reserves >+ my ( $restype, $res, undef ) = CheckReserves( $issue->{'itemnumber'} ); >+ if ( $restype ) { >+ $issue->{'reserved'} = 1; >+ } >+ >+ my ( $total , $accts, $numaccts) = GetMemberAccountRecords( $borrowernumber ); >+ my $charges = 0; >+ foreach my $ac (@$accts) { >+ if ( $ac->{'itemnumber'} == $issue->{'itemnumber'} ) { >+ $charges += $ac->{'amountoutstanding'} >+ if $ac->{'accounttype'} eq 'F'; >+ $charges += $ac->{'amountoutstanding'} >+ if $ac->{'accounttype'} eq 'L'; >+ } >+ } >+ $issue->{'charges'} = $charges; >+ >+ # get publictype for icon >+ >+ my $publictype = $issue->{'publictype'}; >+ $issue->{$publictype} = 1; >+ >+ # check if item is renewable >+ my ($status,$renewerror) = CanBookBeRenewed( $borrowernumber, $issue->{'itemnumber'} ); >+ ($issue->{'renewcount'},$issue->{'renewsallowed'},$issue->{'renewsleft'}) = GetRenewCount($borrowernumber, $issue->{'itemnumber'}); > if($status && C4::Context->preference("OpacRenewalAllowed")){ > $issue->{'status'} = $status; > } >- $issue->{'too_many'} = 1 if $renewerror and $renewerror eq 'too_many'; >- $issue->{'on_reserve'} = 1 if $renewerror and $renewerror eq 'on_reserve'; >- >- if ( $issue->{'overdue'} ) { >- push @overdues, $issue; >- $overdues_count++; >- $issue->{'overdue'} = 1; >- } >- else { >- $issue->{'issued'} = 1; >- } >- # imageurl: >- my $itemtype = $issue->{'itemtype'}; >- if ( $itemtype ) { >- $issue->{'imageurl'} = getitemtypeimagelocation( 'opac', $itemtypes->{$itemtype}->{'imageurl'} ); >- $issue->{'description'} = $itemtypes->{$itemtype}->{'description'}; >- } >- push @issuedat, $issue; >- $count++; >- >- my $isbn = GetNormalizedISBN($issue->{'isbn'}); >- $issue->{normalized_isbn} = $isbn; >+ $issue->{'too_many'} = 1 if $renewerror and $renewerror eq 'too_many'; >+ $issue->{'on_reserve'} = 1 if $renewerror and $renewerror eq 'on_reserve'; >+ >+ if ( $issue->{'overdue'} ) { >+ push @overdues, $issue; >+ $overdues_count++; >+ $issue->{'overdue'} = 1; >+ } >+ else { >+ $issue->{'issued'} = 1; >+ } >+ # imageurl: >+ my $itemtype = $issue->{'itemtype'}; >+ if ( $itemtype ) { >+ $issue->{'imageurl'} = getitemtypeimagelocation( 'opac', $itemtypes->{$itemtype}->{'imageurl'} ); >+ $issue->{'description'} = $itemtypes->{$itemtype}->{'description'}; >+ } >+ push @issuedat, $issue; >+ $count++; >+ >+ my $isbn = GetNormalizedISBN($issue->{'isbn'}); >+ $issue->{normalized_isbn} = $isbn; > > # My Summary HTML > if (my $my_summary_html = C4::Context->preference('OPACMySummaryHTML')){ >@@ -216,7 +221,7 @@ if ($issues){ > $issue->{biblionumber} ? $my_summary_html =~ s/{BIBLIONUMBER}/$issue->{biblionumber}/g : $my_summary_html =~ s/{BIBLIONUMBER}//g; > $issue->{MySummaryHTML} = $my_summary_html; > } >- } >+ } > } > $template->param( ISSUES => \@issuedat ); > $template->param( issues_count => $count ); >@@ -256,13 +261,15 @@ foreach my $res (@reserves) { > if ( $res->{'expirationdate'} eq '0000-00-00' ) { > $res->{'expirationdate'} = ''; > } >- >+ >+ my $publictype = $res->{'publictype'}; >+ $res->{$publictype} = 1; > $res->{'waiting'} = 1 if $res->{'found'} eq 'W'; > $res->{'branch'} = $branches->{ $res->{'branchcode'} }->{'branchname'}; > my $biblioData = GetBiblioData($res->{'biblionumber'}); > $res->{'reserves_title'} = $biblioData->{'title'}; >- if ($show_priority) { >- $res->{'priority'} ||= ''; >+ if ($OPACDisplayRequestPriority) { >+ $res->{'priority'} = '' if $res->{'priority'} eq '0'; > } > $res->{'suspend_until'} = C4::Dates->new( $res->{'suspend_until'}, "iso")->output("syspref") if ( $res->{'suspend_until'} ); > } >@@ -272,7 +279,7 @@ foreach my $res (@reserves) { > > $template->param( RESERVES => \@reserves ); > $template->param( reserves_count => $#reserves+1 ); >-$template->param( showpriority=>$show_priority ); >+$template->param( showpriority=>1 ) if $OPACDisplayRequestPriority; > > my @waiting; > my $wcount = 0; >@@ -288,7 +295,7 @@ foreach my $res (@reserves) { > if ( ( $res->{'found'} eq 'W' ) ) { > my $item = $res->{'itemnumber'}; > $item = GetBiblioFromItemNumber($item,undef); >- $res->{'wait'}= 1; >+ $res->{'wait'}= 1; > $res->{'holdingbranch'}=$item->{'holdingbranch'}; > $res->{'biblionumber'}=$item->{'biblionumber'}; > $res->{'barcode'} = $item->{'barcode'}; >@@ -314,7 +321,7 @@ foreach my $res (@reserves) { > # can be cancelled > #$res->{'cancelable'} = 1 if ($res->{'wait'} && $res->{'atdestination'} && $res->{'found'} ne "1"); > $res->{'cancelable'} = 1 if ($res->{wait} and not $res->{found}) or (not $res->{wait} and not $res->{intransit}); >- >+ > } > > $template->param( WAITING => \@waiting ); >@@ -338,12 +345,12 @@ if (C4::Context->preference('BakerTaylorEnabled')) { > if (C4::Context->preference("OPACAmazonCoverImages") or > C4::Context->preference("GoogleJackets") or > C4::Context->preference("BakerTaylorEnabled") or >- C4::Context->preference("SyndeticsCoverImages")) { >+ C4::Context->preference("SyndeticsCoverImages")) { > $template->param(JacketImages=>1); > } > > if ( GetMessagesCount( $borrowernumber, 'B' ) ) { >- $template->param( bor_messages => 1 ); >+ $template->param( bor_messages => 1 ); > } > > if ( $borr->{'opacnote'} ) { >@@ -354,17 +361,16 @@ if ( $borr->{'opacnote'} ) { > } > > $template->param( >- bor_messages_loop => GetMessages( $borrowernumber, 'B', 'NONE' ), >+ bor_messages_loop => GetMessages( $borrowernumber, 'B', 'NONE' ), > waiting_count => $wcount, > patronupdate => $patronupdate, > OpacRenewalAllowed => C4::Context->preference("OpacRenewalAllowed"), > userview => 1, >+ dateformat => C4::Context->preference("dateformat"), > ); > >-$template->param( >- SuspendHoldsOpac => C4::Context->preference('SuspendHoldsOpac'), >- AutoResumeSuspendedHolds => C4::Context->preference('AutoResumeSuspendedHolds'), >-); >+$template->param( DHTMLcalendar_dateformat => C4::Dates->DHTMLcalendar() ); >+$template->param( AutoResumeSuspendedHolds => C4::Context->preference('AutoResumeSuspendedHolds') ); > > output_html_with_http_headers $query, $cookie, $template->output; > >-- >1.7.2.5
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 6739
:
7814
|
9108
|
16061
|
16063
|
16064
|
16065
|
16069
|
16071
|
16072
|
17356
|
17357
|
17463
|
17464
|
17466
|
17517
|
17518
|
17907
|
17908
|
17909
|
18041
|
18042
|
18043
|
19553
|
19554
|
19555
|
19558
|
19559
|
19560
|
19678
|
19679
|
19993
|
19994
|
19995
|
19996
|
19997
|
20641
|
20642
|
20643
|
20644
|
20645
|
21312
|
21313
|
21314
|
21315
|
21316
|
21317
|
24385
|
24386
|
24387
|
24388
|
24389
|
24390
|
24391
|
24392
|
25158
|
25159
|
25160
|
25161
|
25162
|
25163
|
25164
|
25165
|
25231
|
25232
|
25233
|
26546
|
26547
|
26548
|
26549
|
26550
|
26551
|
26552
|
26553
|
26836
|
26837
|
26838
|
26839
|
26840
|
26841
|
26842
|
26843