Commit 92782d38 authored by Kyle M Hall's avatar Kyle M Hall Committed by Jared Camins-Esakov

Bug 7067 - OPAC Borrower Self Registration

This development will add the ability for a new patron to register
himself or herself. The self-registration will attempt to match this
newly inputted data to any existing patrons and if any possible matches
are found, ask if the patron is sure he or she doesn't already have an
account at the library. A system preference may be set to prevent patron
self-registration if the system detects the possibility that the person
may already have an account.

Once the patron has registered, passing a captcha (or similar
bot-stopper), the patron will then be optionally verified a second time
via email. At this point, the patron will be able to print a temporary
library card (optional by system preference), and will be provided any
details necessary to access electronic resources (this body of text
would be a template in the slips and notices system). At the library's
choice, this new patron would either be set to a temporary patron status
(patron type set via system preference), or a fully-fledged patron
(allow patron type to be determined by age and/or other attributes).
Assuming the library uses temporary patron types for OPAC registrations,
this patron will next enter a queue and would need to physically enter
the library to verify himself and become a fully-fledged patron (most
likely by bringing in physical proof of address, etc.). The librarian
would look up the patron record and modify the patron type. If a
temporary patron has not been verified within a certain time frame
(defined by a system preference), the patron record will be deleted
from the system via a cron job.

For registered patrons, the system will allow each person to also
update his or her personal data via the OPAC. When a patron updates his
or her information, the changes will be entered into a queue to be
verified by a librarian (preventing a patron from inputting obviously
bogus data). The staff client home page will display the number of
patron records with changes awaiting approval. A librarian would then be
able to click through a list of modification requests, and approve or
deny each (with approval and denial alerts being sent to the patron via
the standard messaging system).

NEW SYSTEM PREFERENCES
* PatronSelfRegistration
* PatronSelfRegistrationDetectDuplicates
* PatronSelfRegistrationVerifyByEmail
* PatronSelfRegistrationPrintTemporaryCard
* PatronSelfRegistrationUseTemporaryStatus
* PatronSelfRegistrationExpireTemporaryAccountsDelay

NEW NOTICE
* Verify by email notice

NEW SLIP
* Temporary card slip

NEW CRON JOB
* delete_expired_opac_registrations.pl
  - Deletes patrons that have not been upgraded from the temporary
    status within the specified delay
* delete_unverified_opac_registrations.pl
  - Deletes the unverified patrons based on the length of time specified
    in the PatronSelfRegistrationExpireTemporaryAccountsDelay

The patron will register from self_registration.pl, linked off opac-main.pl if enabled. The registration page will be translatable to other languages in the same way that existing templates are.

Test Plan:
1) Enable PatronSelfRegistration
2) Set PatronSelfRegistrationExpireTemporaryAccountsDelay to a number
   of days
3) Create a self-registered borrower category
4) Set PatronSelfRegistrationUseTemporaryStatus
5) Set PatronSelfRegistrationVerifyByEmail to "Don't require"
6) Go to OPAC, log out if logged in.
7) You should see the "Register here" link below the login box
8) Attempt to register yourself
9) Verify you can log in with your temporary password.
10) Set PatronSelfRegistrationVerifyByEmail to "Require"
11) Attempt another self-registration
12) Check the messages table, you should see a new message with a
    verification link.
13) Copy and paste the link into a web browser to verify the registration
14) Log in with the given credentials to verify the account was created.

Test Plan - Part 2 - Borrower Modifications

1) Log in to OPAC, go to "my personal details" tab.
2) Make some modifications to your details.
3) Repeat steps 1 and 2 for two more borrowers.
4) Log in to Koha intranet with a user that can modify borrowers.
5) At the bottom of mainpage.pl, you should see:
  Patrons requesting modifications: 3
6) Click the link
7) Approve one change, deny a different one, and ignore the third, then
   submit.
8) Check the records, you should see the changes take affect on the
   approved one, and no changes to the other two. You should also see
   "Patrons requesting modifications: 1" at the bottom of mainpage.pl
   now.
Signed-off-by: joubu's avatarJonathan Druart <jonathan.druart@biblibre.com>
Signed-off-by: default avatarOwen Leonard <oleonard@myacpl.org>

Bug 7067 - OPAC Borrower Self Registration - Followup

* Rename PatronSelfRegistrationUseTemporaryStatus to PatronSelfRegistrationDefaultCategory
* Hide register link unless PatronSelfRegistrationDefaultCategory is set.
* Add invalid token page
* Add documentation and switches to cron scripts
* Add required fields check for editing exiting patrons
* Don't force require email address for existing patrons when
  PatronSelfRegistrationVerifyByEmail is enabled.
Signed-off-by: default avatarOwen Leonard <oleonard@myacpl.org>
Passed-QA-by: joubu's avatarJonathan Druart <jonathan.druart@biblibre.com>
Signed-off-by: Jared Camins-Esakov's avatarJared Camins-Esakov <jcamins@cpbibliography.com>
parent 9b9f289f
......@@ -462,6 +462,8 @@ sub get_template_and_user {
SyndeticsSeries => C4::Context->preference("SyndeticsSeries"),
SyndeticsCoverImageSize => C4::Context->preference("SyndeticsCoverImageSize"),
OPACLocalCoverImages => C4::Context->preference("OPACLocalCoverImages"),
PatronSelfRegistration => C4::Context->preference("PatronSelfRegistration"),
PatronSelfRegistrationDefaultCategory => C4::Context->preference("PatronSelfRegistrationDefaultCategory"),
);
$template->param(OpacPublic => '1') if ($user || C4::Context->preference("OpacPublic"));
......@@ -967,10 +969,9 @@ sub checkauth {
OpacAuthorities => C4::Context->preference("OpacAuthorities"),
OpacBrowser => C4::Context->preference("OpacBrowser"),
opacheader => C4::Context->preference("opacheader"),
TagsEnabled => C4::Context->preference("TagsEnabled"),
TagsEnabled => C4::Context->preference("TagsEnabled"),
OPACUserCSS => C4::Context->preference("OPACUserCSS"),
intranetcolorstylesheet =>
C4::Context->preference("intranetcolorstylesheet"),
intranetcolorstylesheet => C4::Context->preference("intranetcolorstylesheet"),
intranetstylesheet => C4::Context->preference("intranetstylesheet"),
intranetbookbag => C4::Context->preference("intranetbookbag"),
IntranetNav => C4::Context->preference("IntranetNav"),
......@@ -978,7 +979,9 @@ sub checkauth {
intranetuserjs => C4::Context->preference("intranetuserjs"),
IndependantBranches=> C4::Context->preference("IndependantBranches"),
AutoLocation => C4::Context->preference("AutoLocation"),
wrongip => $info{'wrongip'},
wrongip => $info{'wrongip'},
PatronSelfRegistration => C4::Context->preference("PatronSelfRegistration"),
PatronSelfRegistrationDefaultCategory => C4::Context->preference("PatronSelfRegistrationDefaultCategory"),
);
$template->param( OpacPublic => C4::Context->preference("OpacPublic"));
......
......@@ -629,6 +629,11 @@ our $PERL_DEPS = {
'required' => '0',
'min_ver' => '1.09',
},
'String::Random' => {
'usage' => 'OpacSelfRegistration',
'required' => '0',
'min_ver' => '1.4',
},
};
1;
......
......@@ -540,6 +540,9 @@ sub GetProcessedLetter {
}
}
my $OPACBaseURL = C4::Context->preference('OPACBaseURL');
$letter->{content} =~ s/<<OPACBaseURL>>/$OPACBaseURL/go;
if ($want_librarian) {
# parsing librarian name
my $userenv = C4::Context->userenv;
......@@ -638,18 +641,19 @@ sub _parseletter_sth {
# check cache first
(defined $handles{$table}) and return $handles{$table};
my $query =
($table eq 'biblio' ) ? "SELECT * FROM $table WHERE biblionumber = ?" :
($table eq 'biblioitems' ) ? "SELECT * FROM $table WHERE biblionumber = ?" :
($table eq 'items' ) ? "SELECT * FROM $table WHERE itemnumber = ?" :
($table eq 'issues' ) ? "SELECT * FROM $table WHERE itemnumber = ?" :
($table eq 'old_issues' ) ? "SELECT * FROM $table WHERE itemnumber = ? ORDER BY timestamp DESC LIMIT 1" :
($table eq 'reserves' ) ? "SELECT * FROM $table WHERE borrowernumber = ? and biblionumber = ?" :
($table eq 'borrowers' ) ? "SELECT * FROM $table WHERE borrowernumber = ?" :
($table eq 'branches' ) ? "SELECT * FROM $table WHERE branchcode = ?" :
($table eq 'suggestions' ) ? "SELECT * FROM $table WHERE suggestionid = ?" :
($table eq 'aqbooksellers') ? "SELECT * FROM $table WHERE id = ?" :
($table eq 'aqorders' ) ? "SELECT * FROM $table WHERE ordernumber = ?" :
($table eq 'opac_news' ) ? "SELECT * FROM $table WHERE idnew = ?" :
($table eq 'biblio' ) ? "SELECT * FROM $table WHERE biblionumber = ?" :
($table eq 'biblioitems' ) ? "SELECT * FROM $table WHERE biblionumber = ?" :
($table eq 'items' ) ? "SELECT * FROM $table WHERE itemnumber = ?" :
($table eq 'issues' ) ? "SELECT * FROM $table WHERE itemnumber = ?" :
($table eq 'old_issues' ) ? "SELECT * FROM $table WHERE itemnumber = ? ORDER BY timestamp DESC LIMIT 1" :
($table eq 'reserves' ) ? "SELECT * FROM $table WHERE borrowernumber = ? and biblionumber = ?" :
($table eq 'borrowers' ) ? "SELECT * FROM $table WHERE borrowernumber = ?" :
($table eq 'branches' ) ? "SELECT * FROM $table WHERE branchcode = ?" :
($table eq 'suggestions' ) ? "SELECT * FROM $table WHERE suggestionid = ?" :
($table eq 'aqbooksellers') ? "SELECT * FROM $table WHERE id = ?" :
($table eq 'aqorders' ) ? "SELECT * FROM $table WHERE ordernumber = ?" :
($table eq 'opac_news' ) ? "SELECT * FROM $table WHERE idnew = ?" :
($table eq 'borrower_modifications') ? "SELECT * FROM $table WHERE borrowernumber = ? OR verification_token =?":
undef ;
unless ($query) {
warn "ERROR: No _parseletter_sth query for table '$table'";
......@@ -756,7 +760,7 @@ sub EnqueueLetter {
my $params = shift or return;
return unless exists $params->{'letter'};
return unless exists $params->{'borrowernumber'};
# return unless exists $params->{'borrowernumber'};
return unless exists $params->{'message_transport_type'};
my $content = $params->{letter}->{content};
......
......@@ -73,6 +73,7 @@ sub logaction {
# the scalar '0'.
my $userenv = C4::Context->userenv();
my $usernumber = (ref($userenv) eq 'HASH') ? $userenv->{'number'} : 0;
$usernumber ||= 0;
my $dbh = C4::Context->dbh;
my $sth=$dbh->prepare("Insert into action_logs (timestamp,user,module,action,object,info) values (now(),?,?,?,?,?)");
......
......@@ -25,6 +25,7 @@ use strict;
use C4::Context;
use C4::Dates qw(format_date_in_iso format_date);
use Digest::MD5 qw(md5_base64);
use String::Random qw( random_string );
use Date::Calc qw/Today Add_Delta_YM check_date Date_to_Days/;
use C4::Log; # logaction
use C4::Overdues;
......@@ -118,6 +119,7 @@ BEGIN {
#Insert data
push @EXPORT, qw(
&AddMember
&AddMember_Opac
&add_member_orgs
&MoveMemberToDeleted
&ExtendMemberSubscriptionTo
......@@ -751,11 +753,25 @@ Returns as undef upon any db error without further processing
sub AddMember {
my (%data) = @_;
my $dbh = C4::Context->dbh;
# generate a proper login if none provided
$data{'userid'} = Generate_Userid($data{'borrowernumber'}, $data{'firstname'}, $data{'surname'}) if $data{'userid'} eq '';
# create a disabled account if no password provided
$data{'password'} = ($data{'password'})? md5_base64($data{'password'}) : '!';
$data{'borrowernumber'}=InsertInTable("borrowers",\%data);
# generate a proper login if none provided
$data{'userid'} = Generate_Userid($data{'borrowernumber'}, $data{'firstname'}, $data{'surname'}) if $data{'userid'} eq '';
# add expiration date if it isn't already there
unless ( $data{'dateexpiry'} ) {
$data{'dateexpiry'} = GetExpiryDate( $data{'categorycode'}, C4::Dates->new()->output("iso") );
}
# add enrollment date if it isn't already there
unless ( $data{'dateenrolled'} ) {
$data{'dateenrolled'} = C4::Dates->new()->output("iso");
}
# create a disabled account if no password provided
$data{'password'} = ($data{'password'})? md5_base64($data{'password'}) : '!';
$data{'borrowernumber'}=InsertInTable("borrowers",\%data);
# mysql_insertid is probably bad. not necessarily accurate and mysql-specific at best.
logaction("MEMBERS", "CREATE", $data{'borrowernumber'}, "") if C4::Context->preference("BorrowersLog");
......@@ -2379,6 +2395,22 @@ sub GetBorrowersWithEmail {
return @result;
}
sub AddMember_Opac {
my ( %borrower ) = @_;
$borrower{'categorycode'} = C4::Context->preference('PatronSelfRegistrationDefaultCategory');
my $sr = new String::Random;
$sr->{'A'} = [ 'A'..'Z', 'a'..'z' ];
my $password = $sr->randpattern("AAAAAAAAAA");
$borrower{'password'} = $password;
$borrower{'cardnumber'} = fixup_cardnumber();
my $borrowernumber = AddMember(%borrower);
return ( $borrowernumber, $password );
}
END { } # module clean-up code here (global destructor)
......
package Koha::Borrower::Modifications;
# Copyright 2012 ByWater Solutions
# 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.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
=head1 NAME
C4::Borrowers::Modifications
=cut
use Modern::Perl;
use C4::Context;
use C4::Debug;
use C4::SQLHelper qw(InsertInTable UpdateInTable);
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
BEGIN {
# set the version for version checking
$VERSION = 0.01;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(
);
my $debug = C4::Context->preference("DebugLevel");
}
sub new {
my ( $class, %args ) = @_;
my $self = bless( {}, $class );
$self->{'verification_token'} = $args{'verification_token'};
$self->{'borrowernumber'} = $args{'borrowernumber'};
return $self;
}
=head AddModifications
Koha::Borrower::Modifications->AddModifications( %data );
Adds or updates modifications for a borrower.
Requires either the key borrowernumber, or verification_token
to be part of the passed in hash.
=cut
sub AddModifications {
my ( $self, %data ) = @_;
if ( $self->{'borrowernumber'} ) {
delete $data{'borrowernumber'};
if ( keys %data ) {
$data{'borrowernumber'} = $self->{'borrowernumber'};
my $dbh = C4::Context->dbh;
my $query = "
SELECT COUNT(*) AS count
FROM borrower_modifications
WHERE borrowernumber = ?
";
my $sth = $dbh->prepare($query);
$sth->execute( $self->{'borrowernumber'} );
my $result = $sth->fetchrow_hashref();
if ( $result->{'count'} ) {
$data{'verification_token'} = q{};
return UpdateInTable( "borrower_modifications", \%data );
}
else {
return InsertInTable( "borrower_modifications", \%data );
}
}
}
elsif ( $self->{'verification_token'} ) {
delete $data{'borrowernumber'};
$data{'verification_token'} = $self->{'verification_token'};
return InsertInTable( "borrower_modifications", \%data );
}
else {
return;
}
}
=head Verify
$verified = Koha::Borrower::Modifications->Verify( $verification_token );
Returns true if the passed in token is valid.
=cut
sub Verify {
my ( $self, $verification_token ) = @_;
if ( ref($self) ) {
$verification_token =
($verification_token)
? $verification_token
: $self->{'verification_token'};
}
my $dbh = C4::Context->dbh;
my $query = "
SELECT COUNT(*) AS count
FROM borrower_modifications
WHERE verification_token = ?
";
my $sth = $dbh->prepare($query);
$sth->execute($verification_token);
my $result = $sth->fetchrow_hashref();
return $result->{'count'};
}
=head GetPendingModificationsCount
$count = Koha::Borrower::Modifications->GetPendingModificationsCount();
Returns the number of pending modifications for existing borrowers.
=cut
sub GetPendingModificationsCount {
my ( $self, $branchcode ) = @_;
my $dbh = C4::Context->dbh;
my $query = "
SELECT COUNT(*) AS count
FROM borrower_modifications, borrowers
WHERE borrower_modifications.borrowernumber > 0
AND borrower_modifications.borrowernumber = borrowers.borrowernumber
";
my @params;
if ($branchcode) {
$query .= " AND borrowers.branchcode = ? ";
push( @params, $branchcode );
}
my $sth = $dbh->prepare($query);
$sth->execute(@params);
my $result = $sth->fetchrow_hashref();
return $result->{'count'};
}
=head GetPendingModifications
$arrayref = Koha::Borrower::Modifications->GetPendingModifications();
Returns an arrayref of hashrefs for all pending modifications for existing borrowers.
=cut
sub GetPendingModifications {
my ( $self, $branchcode ) = @_;
my $dbh = C4::Context->dbh;
my $query = "
SELECT borrower_modifications.*
FROM borrower_modifications, borrowers
WHERE borrower_modifications.borrowernumber > 0
AND borrower_modifications.borrowernumber = borrowers.borrowernumber
";
my @params;
if ($branchcode) {
$query .= " AND borrowers.branchcode = ? ";
push( @params, $branchcode );
}
my $sth = $dbh->prepare($query);
$sth->execute(@params);
my @m;
while ( my $row = $sth->fetchrow_hashref() ) {
foreach my $key ( keys %$row ) {
delete $row->{$key} unless defined $row->{$key};
}
push( @m, $row );
}
return \@m;
}
=head ApproveModifications
Koha::Borrower::Modifications->ApproveModifications( $borrowernumber );
Commits the pending modifications to the borrower record and removes
them from the modifications table.
=cut
sub ApproveModifications {
my ( $self, $borrowernumber ) = @_;
if ( ref($self) ) {
$borrowernumber =
($borrowernumber) ? $borrowernumber : $self->{'borrowernumber'};
}
return unless $borrowernumber;
my $data = $self->GetModifications( borrowernumber => $borrowernumber );
if ( UpdateInTable( "borrowers", $data ) ) {
$self->DelModifications( borrowernumber => $borrowernumber );
}
}
=head DenyModifications
Koha::Borrower::Modifications->DenyModifications( $borrowernumber );
Removes the modifications from the table for the given borrower,
without commiting the changes to the borrower record.
=cut
sub DenyModifications {
my ( $self, $borrowernumber ) = @_;
if ( ref($self) ) {
$borrowernumber =
($borrowernumber) ? $borrowernumber : $self->{'borrowernumber'};
}
return unless $borrowernumber;
return $self->DelModifications( borrowernumber => $borrowernumber );
}
=head DelModifications
Koha::Borrower::Modifications->DelModifications(
[ borrowernumber => $borrowernumber ],
[ verification_token => $verification_token ]
);
Deletes the modifications for the given borrowernumber or verification token.
=cut
sub DelModifications {
my ( $self, %params ) = @_;
my ( $field, $value );
if ( $params{'borrowernumber'} ) {
$field = 'borrowernumber';
$value = $params{'borrowernumber'};
}
elsif ( $params{'verification_token'} ) {
$field = 'verification_token';
$value = $params{'verification_token'};
}
if ( ref($self) && !$value ) {
if ( $self->{'borrowernumber'} ) {
$field = 'borrowernumber';
$value = $self->{'borrowernumber'};
}
elsif ( $self->{'verification_token'} ) {
$field = 'verification_token';
$value = $self->{'verification_token'};
}
}
return unless $value;
my $dbh = C4::Context->dbh;
$field = $dbh->quote_identifier($field);
my $query = "
DELETE
FROM borrower_modifications
WHERE $field = ?
";
my $sth = $dbh->prepare($query);
return $sth->execute($value);
}
=head GetModifications
$hashref = Koha::Borrower::Modifications->GetModifications(
[ borrowernumber => $borrowernumber ],
[ verification_token => $verification_token ]
);
Gets the modifications for the given borrowernumber or verification token.
=cut
sub GetModifications {
my ( $self, %params ) = @_;
my ( $field, $value );
if ( $params{'borrowernumber'} ) {
$field = 'borrowernumber';
$value = $params{'borrowernumber'};
}
elsif ( $params{'verification_token'} ) {
$field = 'verification_token';
$value = $params{'verification_token'};
}
if ( ref($self) && !$value ) {
if ( $self->{'borrowernumber'} ) {
$field = 'borrowernumber';
$value = $self->{'borrowernumber'};
}
elsif ( $self->{'verification_token'} ) {
$field = 'verification_token';
$value = $self->{'verification_token'};
}
}
return unless $value;
my $dbh = C4::Context->dbh;
$field = $dbh->quote_identifier($field);
my $query = "
SELECT *
FROM borrower_modifications
WHERE $field = ?
";
my $sth = $dbh->prepare($query);
$sth->execute($value);
my $data = $sth->fetchrow_hashref();
foreach my $key ( keys %$data ) {
delete $data->{$key} unless ( defined( $data->{$key} ) );
}
return $data;
}
1;
......@@ -105,3 +105,15 @@ Date due: <<issues.date_due>><br />
<li><<items.barcode>></li>
<li><<items.itemcallnumber>></li>
</ul>', 1);
INSERT INTO `letter` (`module`,`code`,`branchcode`,`name`,`is_html`,`title`,`content`)
VALUES (
'members', 'OPAC_REG_VERIFY', '', 'Opac Self-Registration Verification Email', '1', 'Verify Your Account', 'Hello!
Your library account has been created. Please verify your email address by clicking this link to complete the signup process:
http://<<OPACBaseURL>>/cgi-bin/koha/opac-registration-verify.pl?token=<<borrower_modifications.verification_token>>
If you did not initiate this request, you may safely ignore this one-time message. The request will expire shortly.'
);
\ No newline at end of file
......@@ -2977,6 +2977,84 @@ CREATE TABLE borrower_attribute_types_branches( -- association table between bor
FOREIGN KEY (b_branchcode) REFERENCES branches(branchcode) ON DELETE CASCADE
) ENGINE=INNODB DEFAULT CHARSET=utf8;
--
-- Table structure for table `borrower_modifications`
--
CREATE TABLE IF NOT EXISTS `borrower_modifications` (
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`verification_token` varchar(255) NOT NULL DEFAULT '',
`borrowernumber` int(11) NOT NULL DEFAULT '0',
`cardnumber` varchar(16) DEFAULT NULL,
`surname` mediumtext,
`firstname` text,
`title` mediumtext,
`othernames` mediumtext,
`initials` text,
`streetnumber` varchar(10) DEFAULT NULL,
`streettype` varchar(50) DEFAULT NULL,
`address` mediumtext,
`address2` text,
`city` mediumtext,
`state` text,
`zipcode` varchar(25) DEFAULT NULL,
`country` text,
`email` mediumtext,
`phone` text,
`mobile` varchar(50) DEFAULT NULL,
`fax` mediumtext,
`emailpro` text,
`phonepro` text,
`B_streetnumber` varchar(10) DEFAULT NULL,
`B_streettype` varchar(50) DEFAULT NULL,
`B_address` varchar(100) DEFAULT NULL,
`B_address2` text,
`B_city` mediumtext,
`B_state` text,
`B_zipcode` varchar(25) DEFAULT NULL,
`B_country` text,
`B_email` text,
`B_phone` mediumtext,
`dateofbirth` date DEFAULT NULL,
`branchcode` varchar(10) DEFAULT NULL,
`categorycode` varchar(10) DEFAULT NULL,
`dateenrolled` date DEFAULT NULL,
`dateexpiry` date DEFAULT NULL,
`gonenoaddress` tinyint(1) DEFAULT NULL,
`lost` tinyint(1) DEFAULT NULL,
`debarred` date DEFAULT NULL,
`debarredcomment` varchar(255) DEFAULT NULL,
`contactname` mediumtext,
`contactfirstname` text,
`contacttitle` text,
`guarantorid` int(11) DEFAULT NULL,
`borrowernotes` mediumtext,
`relationship` varchar(100) DEFAULT NULL,
`ethnicity` varchar(50) DEFAULT NULL,
`ethnotes` varchar(255) DEFAULT NULL,
`sex` varchar(1) DEFAULT NULL,
`password` varchar(30) DEFAULT NULL,
`flags` int(11) DEFAULT NULL,
`userid` varchar(75) DEFAULT NULL,
`opacnote` mediumtext,
`contactnote` varchar(255) DEFAULT NULL,
`sort1` varchar(80) DEFAULT NULL,
`sort2` varchar(80) DEFAULT NULL,
`altcontactfirstname` varchar(255) DEFAULT NULL,
`altcontactsurname` varchar(255) DEFAULT NULL,
`altcontactaddress1` varchar(255) DEFAULT NULL,
`altcontactaddress2` varchar(255) DEFAULT NULL,
`altcontactaddress3` varchar(255) DEFAULT NULL,
`altcontactstate` text,
`altcontactzipcode` varchar(50) DEFAULT NULL,
`altcontactcountry` text,
`altcontactphone` varchar(50) DEFAULT NULL,
`smsalertnumber` varchar(50) DEFAULT NULL,
`privacy` int(11) DEFAULT NULL,
PRIMARY KEY (`verification_token`,`borrowernumber`),
KEY `verification_token` (`verification_token`),
KEY `borrowernumber` (`borrowernumber`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
......
......@@ -388,3 +388,10 @@ INSERT INTO systempreferences (variable, value, options, explanation, type) VALU
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('HoldsToPullStartDate','2','Set the default start date for the Holds to pull list to this many days ago',NULL,'Integer');
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('alphabet','A B C D E F G H I J K L M N O P Q R S T U V W X Y Z','Alphabet than can be expanded into browse links, e.g. on Home > Patrons',NULL,'free');
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('RefundLostItemFeeOnReturn', '1', 'If enabled, the lost item fee charged to a borrower will be refunded when the lost item is returned.', NULL, 'YesNo');
INSERT INTO systempreferences (`variable`, `value`, `options`, `explanation`, `type`) VALUES
('PatronSelfRegistration', '0', NULL, 'If enabled, patrons will be able to register themselves via the OPAC.', 'YesNo'),
('PatronSelfRegistrationVerifyByEmail', '0', NULL, 'If enabled, any patron attempting to register themselves via the OPAC will be required to verify themselves via email to activate his or her account.', 'YesNo'),
('PatronSelfRegistrationDefaultCategory', '', '', 'A patron registered via the OPAC will receive a borrower category code set in this system preference.', 'free'),
('PatronSelfRegistrationExpireTemporaryAccountsDelay', '0', NULL, 'If PatronSelfRegistrationDefaultCategory is enabled, this system preference controls how long a patron can have a temporary status before the account is deleted automatically. It is an integer value representing a number of days to wait before deleting a temporary patron account. Setting it to 0 disables the deleting of temporary accounts.', 'Integer'),
('PatronSelfRegistrationBorrowerMandatoryField', 'surname|firstname', NULL , 'Choose the mandatory fields for a patron''s account, when registering via the OPAC.', 'free'),
('PatronSelfRegistrationBorrowerUnwantedField', '', NULL , 'Name the fields you don''t want to display when registering a new patron via the OPAC.', 'free');
......@@ -5714,6 +5714,110 @@ if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
) ENGINE=InnoDB DEFAULT CHARSET=utf8");
print "Upgrade to $DBversion done (creating `transport_cost` table; adding UseTransportCostMatrix systempref, in circulation)\n";
SetVersion($DBversion);
}
$DBversion = '3.09.00.XXX';
if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
$dbh->do("
CREATE TABLE IF NOT EXISTS `borrower_modifications` (
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`verification_token` varchar(255) NOT NULL DEFAULT '',
`borrowernumber` int(11) NOT NULL DEFAULT '0',
`cardnumber` varchar(16) DEFAULT NULL,
`surname` mediumtext,
`firstname` text,
`title` mediumtext,
`othernames` mediumtext,
`initials` text,
`streetnumber` varchar(10) DEFAULT NULL,
`streettype` varchar(50) DEFAULT NULL,
`address` mediumtext,
`address2` text,
`city` mediumtext,
`state` text,
`zipcode` varchar(25) DEFAULT NULL,
`country` text,
`email` mediumtext,
`phone` text,
`mobile` varchar(50) DEFAULT NULL,
`fax` mediumtext,
`emailpro` text,
`phonepro` text,
`B_streetnumber` varchar(10) DEFAULT NULL,
`B_streettype` varchar(50) DEFAULT NULL,
`B_address` varchar(100) DEFAULT NULL,
`B_address2` text,
`B_city` mediumtext,
`B_state` text,
`B_zipcode` varchar(25) DEFAULT NULL,
`B_country` text,
`B_email` text,
`B_phone` mediumtext,
`dateofbirth` date DEFAULT NULL,
`branchcode` varchar(10) DEFAULT NULL,