use Modern::Perl;
use Moo;
-use namespace::clean;
-use Carp;
+use Carp qw( carp );
use Text::CSV;
use Encode qw( decode_utf8 );
-use Try::Tiny;
+use Try::Tiny qw( catch try );
-use C4::Members;
+use C4::Members qw( checkcardnumber );
+use C4::Letters qw( GetPreparedLetter EnqueueLetter );
use Koha::Libraries;
use Koha::Patrons;
use Koha::Patron::Categories;
-use Koha::Patron::Debarments;
-use Koha::DateUtils;
+use Koha::Patron::Debarments qw( AddDebarment );
+use Koha::DateUtils qw( dt_from_string output_pref );
=head1 NAME
=cut
has 'today_iso' => ( is => 'ro', lazy => 1,
+ # FIXME We shouldn't need to call output_pref here, passing a DateTime object should work
default => sub { output_pref( { dt => dt_from_string(), dateonly => 1, dateformat => 'iso' } ); }, );
has 'text_csv' => ( is => 'rw', lazy => 1,
my $matchpoint = $params->{matchpoint};
my $defaults = $params->{defaults};
+ my $preserve_fields = $params->{preserve_fields};
my $ext_preserve = $params->{preserve_extended_attributes};
my $overwrite_cardnumber = $params->{overwrite_cardnumber};
my $overwrite_passwords = $params->{overwrite_passwords};
my $dry_run = $params->{dry_run};
+ my $send_welcome = $params->{send_welcome};
my $extended = C4::Context->preference('ExtendedPatronAttributes');
my $set_messaging_prefs = C4::Context->preference('EnhancedMessagingPreferences');
+ my $update_dateexpiry = $params->{update_dateexpiry};
+ my $update_dateexpiry_from_today = $params->{update_dateexpiry_from_today};
my $schema = Koha::Database->new->schema;
$schema->storage->txn_begin if $dry_run;
}
$borrower{cardnumber} = undef if $borrower{cardnumber} eq "";
+ $borrower{auth_method} = undef if $borrower{auth_method} eq "";
# Check if borrower category code exists and if it matches to a known category. Pushing error to missing_criticals otherwise.
$self->check_borrower_category($borrower{categorycode}, $borrowerline, $line_number, \@missing_criticals);
# Default date enrolled and date expiry if not already set.
$borrower{dateenrolled} = $self->today_iso() unless $borrower{dateenrolled};
- $borrower{dateexpiry} = Koha::Patron::Categories->find( $borrower{categorycode} )->get_expiry_date( $borrower{dateenrolled} ) unless $borrower{dateexpiry};
+ my $expiration_start_date = $update_dateexpiry_from_today ? dt_from_string : $borrower{dateenrolled};
+ $borrower{dateexpiry} = Koha::Patron::Categories->find( $borrower{categorycode} )->get_expiry_date( $expiration_start_date ) if $update_dateexpiry;
my $borrowernumber;
my ( $member, $patron );
}
}
+ my $is_new = 0;
if ($patron) {
$member = $patron->unblessed;
$borrowernumber = $member->{'borrowernumber'};
} else {
$member = {};
+ $is_new = 1;
}
if ( C4::Members::checkcardnumber( $borrower{cardnumber}, $borrowernumber ) ) {
if exists $borrower{$field} and $borrower{$field} eq "";
}
+ my $success = 1;
if ($borrowernumber) {
# borrower exists
next LINE;
}
$borrower{'borrowernumber'} = $borrowernumber;
+
+ if ( $preserve_fields ) {
+ for my $field ( @$preserve_fields ) {
+ $borrower{$field} = $patron->$field;
+ }
+ }
+
for my $col ( keys %borrower ) {
# use values from extant patron unless our csv file includes this column or we provided a default.
}
}
- my $patron = Koha::Patrons->find( $borrowernumber );
- eval { $patron->set(\%borrower)->store };
- if ( $@ ) {
+ try {
+ $schema->storage->txn_do(sub {
+ $patron->set(\%borrower)->store;
+ # 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 $restrictions = $patron->restrictions->search(
+ {
+ expiration => $borrower{debarred},
+ comment => $borrower{debarredcomment}
+ }
+ );
+
+ # If it doesn't, then add it!
+ unless ($restrictions->count) {
+ AddDebarment(
+ {
+ borrowernumber => $borrowernumber,
+ expiration => $borrower{debarred},
+ comment => $borrower{debarredcomment}
+ }
+ );
+ }
+ }
+ if ($patron->category->category_type ne 'S' && $overwrite_passwords && defined $borrower{password} && $borrower{password} ne ''){
+ try {
+ $patron->set_password({ password => $borrower{password} });
+ }
+ catch {
+ if ( $_->isa('Koha::Exceptions::Password::TooShort') ) {
+ push @errors, { passwd_too_short => 1, borrowernumber => $borrowernumber, length => $_->{length}, min_length => $_->{min_length} };
+ }
+ elsif ( $_->isa('Koha::Exceptions::Password::WhitespaceCharacters') ) {
+ push @errors, { passwd_whitespace => 1, borrowernumber => $borrowernumber } ;
+ }
+ elsif ( $_->isa('Koha::Exceptions::Password::TooWeak') ) {
+ push @errors, { passwd_too_weak => 1, borrowernumber => $borrowernumber } ;
+ }
+ elsif ( $_->isa('Koha::Exceptions::Password::Plugin') ) {
+ push @errors, { passwd_plugin_err => 1, borrowernumber => $borrowernumber } ;
+ }
+ else {
+ push @errors, { passwd_unknown_err => 1, borrowernumber => $borrowernumber } ;
+ }
+ }
+ }
+ if ($extended && @$patron_attributes) {
+ if ($ext_preserve) {
+ $patron_attributes = $patron->extended_attributes->merge_and_replace_with( $patron_attributes );
+ }
+ # We do not want to filter by branch, maybe we should?
+ Koha::Patrons->find($borrowernumber)->extended_attributes->delete;
+ $patron->extended_attributes($patron_attributes);
+ }
+ $overwritten++;
+ push(
+ @feedback,
+ {
+ feedback => 1,
+ name => 'lastoverwritten',
+ value => $borrower{'surname'} . ' / ' . $borrowernumber
+ }
+ );
+ });
+ } catch {
$invalid++;
+ $success = 0;
+
+ my $patron_id = defined $matchpoint ? $borrower{$matchpoint} : $matchpoint_attr_type;
+ if ( $_->isa('Koha::Exceptions::Patron::Attribute::UniqueIDConstraint') ) {
+ push @errors, { patron_attribute_unique_id_constraint => 1, borrowernumber => $borrowernumber, attribute => $_->attribute };
+ } elsif ( $_->isa('Koha::Exceptions::Patron::Attribute::InvalidType') ) {
+ push @errors, { patron_attribute_invalid_type => 1, borrowernumber => $borrowernumber, attribute_type_code => $_->type };
+ } elsif ( $_->isa('Koha::Exceptions::Patron::Attribute::NonRepeatable') ) {
+ push @errors, { patron_attribute_non_repeatable => 1, borrowernumber => $borrowernumber, attribute => $_->attribute };
+ } else {
+ warn $_;
+ push @errors, { unknown_error => 1 };
+ }
push(
@errors,
value => $borrower{'surname'} . ' / ' . $borrowernumber
}
);
- next LINE;
}
- # 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(
- {
- borrowernumber => $borrowernumber,
- expiration => $borrower{debarred},
- comment => $borrower{debarredcomment}
- }
- );
-
- # If it doesn't, then add it!
- unless (@$debarrments) {
- AddDebarment(
- {
- borrowernumber => $borrowernumber,
- expiration => $borrower{debarred},
- comment => $borrower{debarredcomment}
- }
- );
- }
- }
- if ($patron->category->category_type ne 'S' && $overwrite_passwords && defined $borrower{password} && $borrower{password} ne ''){
- try {
- $patron->set_password({ password => $borrower{password} });
- }
- catch {
- if ( $_->isa('Koha::Exceptions::Password::TooShort') ) {
- push @errors, { passwd_too_short => 1, borrowernumber => $borrowernumber, length => $_->{length}, min_length => $_->{min_length} };
- }
- elsif ( $_->isa('Koha::Exceptions::Password::WhitespaceCharacters') ) {
- push @errors, { passwd_whitespace => 1, borrowernumber => $borrowernumber } ;
- }
- elsif ( $_->isa('Koha::Exceptions::Password::TooWeak') ) {
- push @errors, { passwd_too_weak => 1, borrowernumber => $borrowernumber } ;
- }
- elsif ( $_->isa('Koha::Exceptions::Password::Plugin') ) {
- push @errors, { passwd_plugin_err => 1, borrowernumber => $borrowernumber } ;
- }
- else {
- push @errors, { passwd_unknown_err => 1, borrowernumber => $borrowernumber } ;
- }
- }
- }
- if ($extended) {
- if ($ext_preserve) {
- $patron_attributes = $patron->extended_attributes->merge_and_replace_with( $patron_attributes );
- }
- eval {
- # We do not want to filter by branch, maybe we should?
- Koha::Patrons->find($borrowernumber)->extended_attributes->delete;
- $patron->extended_attributes($patron_attributes);
- };
- if ($@) {
- # FIXME This is not an unknown error, we can do better here
- push @errors, { unknown_error => 1 };
- }
- }
- $overwritten++;
- push(
- @feedback,
- {
- feedback => 1,
- name => 'lastoverwritten',
- value => $borrower{'surname'} . ' / ' . $borrowernumber
- }
- );
}
else {
try {
$schema->storage->txn_do(sub {
- my $patron = Koha::Patron->new(\%borrower)->store;
+ $patron = Koha::Patron->new(\%borrower)->store;
$borrowernumber = $patron->id;
if ( $patron->is_debarred ) {
);
}
- if ($extended) {
+ if ($extended && @$patron_attributes) {
# FIXME Hum, we did not filter earlier and now we do?
$patron->extended_attributes->filter_by_branch_limitations->delete;
$patron->extended_attributes($patron_attributes);
});
} catch {
$invalid++;
+ $success = 0;
+ my $patron_id = defined $matchpoint ? $borrower{$matchpoint} : $matchpoint_attr_type;
if ( $_->isa('Koha::Exceptions::Patron::Attribute::UniqueIDConstraint') ) {
- my $patron_id = defined $matchpoint ? $borrower{$matchpoint} : $matchpoint_attr_type;
push @errors, { patron_attribute_unique_id_constraint => 1, patron_id => $patron_id, attribute => $_->attribute };
+ } elsif ( $_->isa('Koha::Exceptions::Patron::Attribute::InvalidType') ) {
+ push @errors, { patron_attribute_invalid_type => 1, patron_id => $patron_id, attribute_type_code => $_->type };
+ } elsif ( $_->isa('Koha::Exceptions::Patron::Attribute::NonRepeatable') ) {
+ push @errors, { patron_attribute_non_repeatable => 1, patron_id => $patron_id, attribute => $_->attribute };
+
} else {
+ warn $_;
push @errors, { unknown_error => 1 };
}
push(
};
}
+ next LINE unless $success;
+
+ # Send WELCOME welcome email is the user is new and we're set to send mail
+ if ($send_welcome && $is_new) {
+ my $emailaddr = $patron->notice_email_address;
+
+ # if we manage to find a valid email address, send notice
+ if ($emailaddr) {
+ eval {
+ my $letter = GetPreparedLetter(
+ module => 'members',
+ letter_code => 'WELCOME',
+ branchcode => $patron->branchcode,,
+ lang => $patron->lang || 'default',
+ tables => {
+ 'branches' => $patron->branchcode,
+ 'borrowers' => $patron->borrowernumber,
+ },
+ want_librarian => 1,
+ ) or return;
+
+ my $message_id = EnqueueLetter(
+ {
+ letter => $letter,
+ borrowernumber => $patron->id,
+ to_address => $emailaddr,
+ message_transport_type => 'email'
+ }
+ );
+ };
+ if ($@) {
+ push @errors, { welcome_email_err => 1, borrowernumber => $borrowernumber };
+ } else {
+ push(
+ @feedback,
+ {
+ feedback => 1,
+ name => 'welcome_sent',
+ value => $borrower{'surname'} . ' / ' . $borrowernumber . ' / ' . $emailaddr
+ }
+ );
+ }
+ }
+ }
+
# Add a guarantor if we are given a relationship
if ( $guarantor_id ) {
my $relationship = Koha::Patron::Relationships->find(