#
# 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 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 3 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.
+# 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.
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
# Script to take some borrowers data in a known format and load it into Koha
#
# alternate streetnumber, alternate streettype, alternate address line 1, alternate city,
# alternate zipcode, alternate country, alternate email, alternate phone, date of birth, branchcode,
# categorycode, enrollment date, expiry date, noaddress, lost, debarred, contact surname,
-# contact firstname, contact title, borrower notes, contact relationship, ethnicity, ethnicity notes
+# contact firstname, contact title, borrower notes, contact relationship
# gender, username, opac note, contact note, password, sort one, sort two
#
# any fields except cardnumber can be blank but the number of fields must match
# dates should be in the format you have set up Koha to expect
# branchcode and categorycode need to be valid
-use strict;
-use warnings;
+use Modern::Perl;
use C4::Auth;
use C4::Output;
-use C4::Dates qw(format_date_in_iso);
use C4::Context;
-use C4::Branch qw/GetBranchesLoop GetBranchName/;
use C4::Members;
use C4::Members::Attributes qw(:all);
use C4::Members::AttributeTypes;
use C4::Members::Messaging;
use C4::Reports::Guided;
use C4::Templates;
-use Koha::Borrower::Debarments;
+use Koha::Patron::Debarments;
+use Koha::Patrons;
+use Koha::DateUtils;
+use Koha::Token;
+use Koha::Libraries;
+use Koha::Patron::Categories;
+use Koha::List::Patron;
use Text::CSV;
# Text::CSV::Unicode, even in binary mode, fails to parse lines with these diacriticals:
# č
use CGI qw ( -utf8 );
-# use encoding 'utf8'; # don't do this
my (@errors, @feedback);
my $extended = C4::Context->preference('ExtendedPatronAttributes');
my $set_messaging_prefs = C4::Context->preference('EnhancedMessagingPreferences');
-my @columnkeys = C4::Members::columns();
+my @columnkeys = Koha::Patrons->columns();
@columnkeys = map { $_ ne 'borrowernumber' ? $_ : () } @columnkeys;
if ($extended) {
push @columnkeys, 'patron_attributes';
debug => 1,
});
-# get the branches and pass them to the template
-my $branches = GetBranchesLoop();
-$template->param( branches => $branches ) if ( $branches );
# get the patron categories and pass them to the template
-my $categories = GetBorrowercategoryList();
-$template->param( categories => $categories ) if ( $categories );
+my @patron_categories = Koha::Patron::Categories->search_limited({}, {order_by => ['description']});
+$template->param( categories => \@patron_categories );
my $columns = C4::Templates::GetColumnDefs( $input )->{borrowers};
$columns = [ grep { $_->{field} ne 'borrowernumber' ? $_ : () } @$columns ];
$template->param( borrower_fields => $columns );
);
$csv->combine(@columnkeys);
print $csv->string, "\n";
- exit 1;
+ exit 0;
}
my $uploadborrowers = $input->param('uploadborrowers');
my $matchpoint = $input->param('matchpoint');
}
my $overwrite_cardnumber = $input->param('overwrite_cardnumber');
-$template->param( SCRIPT_NAME => $ENV{'SCRIPT_NAME'} );
+#create a patronlist
+my $createpatronlist = $input->param('createpatronlist') || 0;
+my $dt = dt_from_string();
+my $timestamp = $dt->ymd('-').' '.$dt->hms(':');
+my $patronlistname = $uploadborrowers . ' (' . $timestamp .')';
+
+$template->param( SCRIPT_NAME => '/cgi-bin/koha/tools/import_borrowers.pl' );
if ( $uploadborrowers && length($uploadborrowers) > 0 ) {
+ die "Wrong CSRF token"
+ unless Koha::Token->new->check_csrf({
+ session_id => scalar $input->cookie('CGISESSID'),
+ token => scalar $input->param('csrf_token'),
+ });
+
push @feedback, {feedback=>1, name=>'filename', value=>$uploadborrowers, filename=>$uploadborrowers};
my $handle = $input->upload('uploadborrowers');
my $uploadinfo = $input->uploadInfo($uploadborrowers);
foreach (keys %$uploadinfo) {
push @feedback, {feedback=>1, name=>$_, value=>$uploadinfo->{$_}, $_=>$uploadinfo->{$_}};
}
+
my $imported = 0;
+ my @imported_borrowers;
my $alreadyindb = 0;
my $overwritten = 0;
my $invalid = 0;
}
push @feedback, {feedback=>1, name=>'headerrow', value=>join(', ', @csvcolumns)};
- my $today_iso = C4::Dates->new()->output('iso');
+ my $today = output_pref;
my @criticals = qw(surname branchcode categorycode); # there probably should be others
my @bad_dates; # I've had a few.
- my $date_re = C4::Dates->new->regexp('syspref');
- my $iso_re = C4::Dates->new->regexp('iso');
LINE: while ( my $borrowerline = <$handle> ) {
my %borrower;
my @missing_criticals;
#warn join(':',%borrower);
if ($borrower{categorycode}) {
push @missing_criticals, {key=>'categorycode', line=>$. , lineraw=>$borrowerline, value=>$borrower{categorycode}, category_map=>1}
- unless GetBorrowercategory($borrower{categorycode});
+ unless Koha::Patron::Categories->find($borrower{categorycode});
} else {
push @missing_criticals, {key=>'categorycode', line=>$. , lineraw=>$borrowerline};
}
if ($borrower{branchcode}) {
push @missing_criticals, {key=>'branchcode', line=>$. , lineraw=>$borrowerline, value=>$borrower{branchcode}, branch_map=>1}
- unless GetBranchName($borrower{branchcode});
+ unless Koha::Libraries->find($borrower{branchcode});
} else {
push @missing_criticals, {key=>'branchcode', line=>$. , lineraw=>$borrowerline};
}
# Popular spreadsheet applications make it difficult to force date outputs to be zero-padded, but we require it.
foreach (qw(dateofbirth dateenrolled dateexpiry)) {
my $tempdate = $borrower{$_} or next;
- if ($tempdate =~ /$date_re/) {
- $borrower{$_} = format_date_in_iso($tempdate);
- } elsif ($tempdate =~ /$iso_re/) {
+ $tempdate = eval { output_pref( { dt => dt_from_string( $tempdate ), dateonly => 1, dateformat => 'iso' } ); };
+ if ($tempdate) {
$borrower{$_} = $tempdate;
} else {
$borrower{$_} = '';
push @missing_criticals, {key=>$_, line=>$. , lineraw=>$borrowerline, bad_date=>1};
}
}
- $borrower{dateenrolled} = $today_iso unless $borrower{dateenrolled};
- $borrower{dateexpiry} = GetExpiryDate($borrower{categorycode},$borrower{dateenrolled}) unless $borrower{dateexpiry};
+ $borrower{dateenrolled} ||= $today;
+ $borrower{dateexpiry} ||= Koha::Patron::Categories->find( $borrower{categorycode} )->get_expiry_date( $borrower{dateenrolled} );
my $borrowernumber;
my $member;
if ( ($matchpoint eq 'cardnumber') && ($borrower{'cardnumber'}) ) {
- $member = GetMember( 'cardnumber' => $borrower{'cardnumber'} );
- if ($member) {
- $borrowernumber = $member->{'borrowernumber'};
- }
+ $member = Koha::Patrons->find( { cardnumber => $borrower{'cardnumber'} } );
+ } elsif ( ($matchpoint eq 'userid') && ($borrower{'userid'}) ) {
+ $member = Koha::Patrons->find( { userid => $borrower{'userid'} } );
} elsif ($extended) {
if (defined($matchpoint_attr_type)) {
foreach my $attr (@$patron_attributes) {
}
}
+ if ($member) {
+ $member = $member->unblessed;
+ $borrowernumber = $member->{'borrowernumber'};
+ } else {
+ $member = {};
+ }
+
if ( C4::Members::checkcardnumber( $borrower{cardnumber}, $borrowernumber ) ) {
push @errors, {
invalid_cardnumber => 1,
next;
}
-
if ($borrowernumber) {
# borrower exists
unless ($overwrite_cardnumber) {
$borrower{$col} = $member->{$col} if($member->{$col}) ;
}
}
+
+ # Check if the userid provided does not exist yet
+ if ( exists $borrower{userid}
+ and $borrower{userid}
+ and not Check_Userid( $borrower{userid}, $borrower{borrowernumber} ) ) {
+ push @errors, { duplicate_userid => 1, userid => $borrower{userid} };
+ $invalid++;
+ next LINE;
+ }
+
unless (ModMember(%borrower)) {
$invalid++;
- # untill we have better error trapping, we have no way of knowing why ModMember errored out...
+ # until we have better error trapping, we have no way of knowing why ModMember errored out...
push @errors, {unknown_error => 1};
$template->param('lastinvalid'=>$borrower{'surname'}.' / '.$borrowernumber);
next LINE;
}
- if ( $borrower{debarred} ) {
+
+ # Don't add a new restriction if the existing 'combined' restriction matches this one
+ if ( $borrower{debarred} && ( ( $borrower{debarred} ne $member->{debarred} ) || ( $borrower{debarredcomment} ne $member->{debarredcomment} ) ) ) {
# Check to see if this debarment already exists
my $debarrments = GetDebarments(
{
);
}
}
+
if ($extended) {
if ($ext_preserve) {
my $old_attributes = GetBorrowerAttributes($borrowernumber);
$patron_attributes = extended_attributes_merge($old_attributes, $patron_attributes); #TODO: expose repeatable options in template
}
- push @errors, {unknown_error => 1} unless SetBorrowerAttributes($borrower{'borrowernumber'}, $patron_attributes);
+ push @errors, {unknown_error => 1} unless SetBorrowerAttributes($borrower{'borrowernumber'}, $patron_attributes, 'no_branch_limit' );
}
$overwritten++;
$template->param('lastoverwritten'=>$borrower{'surname'}.' / '.$borrowernumber);
$imported++;
$template->param('lastimported'=>$borrower{'surname'}.' / '.$borrowernumber);
+ push @imported_borrowers, $borrowernumber; #for patronlist
} else {
$invalid++;
push @errors, {unknown_error => 1};
}
}
}
+
+ if ( $imported && $createpatronlist ) {
+ my $patronlist = AddPatronList({ name => $patronlistname });
+ AddPatronsToList({ list => $patronlist, borrowernumbers => \@imported_borrowers });
+ $template->param('patronlistname' => $patronlistname);
+ }
+
(@errors ) and $template->param( ERRORS=>\@errors );
(@feedback) and $template->param(FEEDBACK=>\@feedback);
$template->param(
}
$template->param(matchpoints => \@matchpoints);
}
+
+ $template->param(
+ csrf_token => Koha::Token->new->generate_csrf(
+ { session_id => scalar $input->cookie('CGISESSID'), }
+ ),
+ );
+
}
output_html_with_http_headers $input, $cookie, $template->output;