X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=members%2Fmemberentry.pl;h=14a11361a204cae670a5cf9ac7874a490ea35f45;hb=461a6f53b85becbefb18c0cb9356384a479aa9f1;hp=27e6687cf7f0dd580dddcf317e116f49e5254a78;hpb=d711d62a4801f77c553e51c31bcc1cea6e8d13fb;p=koha.git diff --git a/members/memberentry.pl b/members/memberentry.pl index 27e6687cf7..14a11361a2 100755 --- a/members/memberentry.pl +++ b/members/memberentry.pl @@ -19,13 +19,11 @@ # along with Koha; if not, see . # pragma -use strict; -use warnings; +use Modern::Perl; # external modules use CGI qw ( -utf8 ); use List::MoreUtils qw/uniq/; -use Digest::MD5 qw(md5_base64); # internal modules use C4::Auth; @@ -38,20 +36,18 @@ use C4::Koha; use C4::Log; use C4::Letters; use C4::Form::MessagingPreferences; +use Koha::AuthUtils; use Koha::AuthorisedValues; use Koha::Patron::Debarments; use Koha::Cities; use Koha::DateUtils; use Koha::Libraries; +use Koha::Patrons; use Koha::Patron::Categories; use Koha::Patron::HouseboundRole; use Koha::Patron::HouseboundRoles; use Koha::Token; use Email::Valid; -use Module::Load; -if ( C4::Context->preference('NorwegianPatronDBEnable') && C4::Context->preference('NorwegianPatronDBEnable') == 1 ) { - load Koha::NorwegianPatronDB, qw( NLGetSyncDataFromBorrowernumber ); -} use Koha::SMS::Providers; use vars qw($debug); @@ -71,17 +67,23 @@ my ($template, $loggedinuser, $cookie) query => $input, type => "intranet", authnotrequired => 0, - flagsrequired => {borrowers => 1}, + flagsrequired => {borrowers => 'edit_borrowers'}, debug => ($debug) ? 1 : 0, }); +my $borrowernumber = $input->param('borrowernumber'); +my $patron = Koha::Patrons->find($borrowernumber); + +if ( $borrowernumber and not $patron ) { + output_and_exit( $input, $cookie, $template, 'unknown_patron' ); +} + if ( C4::Context->preference('SMSSendDriver') eq 'Email' ) { my @providers = Koha::SMS::Providers->search(); $template->param( sms_providers => \@providers ); } my $guarantorid = $input->param('guarantorid'); -my $borrowernumber = $input->param('borrowernumber'); my $actionType = $input->param('actionType') || ''; my $modify = $input->param('modify'); my $delete = $input->param('delete'); @@ -104,10 +106,9 @@ my $borrower_data; my $NoUpdateLogin; my $userenv = C4::Context->userenv; - ## Deal with debarments $template->param( - debarments => GetDebarments( { borrowernumber => $borrowernumber } ) ); + debarments => scalar GetDebarments( { borrowernumber => $borrowernumber } ) ); my @debarments_to_remove = $input->multi_param('remove_debarment'); foreach my $d ( @debarments_to_remove ) { DelDebarment( $d ); @@ -117,8 +118,7 @@ if ( $input->param('add_debarment') ) { my $expiration = $input->param('debarred_expiration'); $expiration = $expiration - ? output_pref( - { 'dt' => dt_from_string($expiration), 'dateformat' => 'iso' } ) + ? dt_from_string($expiration)->ymd : undef; AddDebarment( @@ -133,9 +133,6 @@ if ( $input->param('add_debarment') ) { $template->param("uppercasesurnames" => C4::Context->preference('uppercasesurnames')); -my $minpw = C4::Context->preference('minPasswordLength'); -$template->param("minPasswordLength" => $minpw); - # function to designate mandatory fields (visually with css) my $check_BorrowerMandatoryField=C4::Context->preference("BorrowerMandatoryField"); my @field_check=split(/\|/,$check_BorrowerMandatoryField); @@ -153,7 +150,14 @@ $template->param( "add" => 1 ) if ( $op eq 'add' ); $template->param( "quickadd" => 1 ) if ( $quickadd ); $template->param( "duplicate" => 1 ) if ( $op eq 'duplicate' ); $template->param( "checked" => 1 ) if ( defined($nodouble) && $nodouble eq 1 ); -( $borrower_data = GetMember( 'borrowernumber' => $borrowernumber ) ) if ( $op eq 'modify' or $op eq 'save' or $op eq 'duplicate' ); +if ( $op eq 'modify' or $op eq 'save' or $op eq 'duplicate' ) { + my $logged_in_user = Koha::Patrons->find( $loggedinuser ) or die "Not logged in"; + output_and_exit_if_error( $input, $cookie, $template, { module => 'members', logged_in_user => $logged_in_user, current_patron => $patron } ); + + $borrower_data = $patron->unblessed; + $borrower_data->{category_type} = $patron->category->category_type; +} + my $categorycode = $input->param('categorycode') || $borrower_data->{'categorycode'}; my $category_type = $input->param('category_type') || ''; unless ($category_type or !($categorycode)){ @@ -197,7 +201,7 @@ if ( $op eq 'insert' || $op eq 'modify' || $op eq 'save' || $op eq 'duplicate' ) } } -# remove keys from %newdata that ModMember() doesn't like +# remove keys from %newdata that is not part of patron's attributes { my @keys_to_delete = ( qr/^BorrowerMandatoryField$/, @@ -217,6 +221,10 @@ if ( $op eq 'insert' || $op eq 'modify' || $op eq 'save' || $op eq 'duplicate' ) qr/^\d+$/, qr/^\d+-DAYS/, qr/^patron_attr_/, + qr/^csrf_token$/, + qr/^add_debarment$/, qr/^debarred_expiration$/, # We already dealt with debarments previously + qr/^housebound_chooser$/, qr/^housebound_deliverer$/, + qr/^select_city$/, ); for my $regexp (@keys_to_delete) { for (keys %newdata) { @@ -234,7 +242,7 @@ if ( ( $op eq 'insert' ) and !$nodouble ) { $conditions->{dateofbirth} = $newdata{dateofbirth} if $newdata{dateofbirth}; } $nodouble = 1; - my $patrons = Koha::Patrons->search($conditions); + my $patrons = Koha::Patrons->search($conditions); # FIXME Should be search_limited? if ( $patrons->count > 0) { $nodouble = 0; $check_member = $patrons->next->borrowernumber; @@ -243,7 +251,8 @@ if ( ( $op eq 'insert' ) and !$nodouble ) { #recover all data from guarantor address phone ,fax... if ( $guarantorid ) { - if (my $guarantordata=GetMember(borrowernumber => $guarantorid)) { + if (my $guarantor = Koha::Patrons->find( $guarantorid )) { + my $guarantordata = $guarantor->unblessed; $category_type = $guarantordata->{categorycode} eq 'I' ? 'P' : 'C'; $guarantorinfo=$guarantordata->{'surname'}." , ".$guarantordata->{'firstname'}; $newdata{'contactfirstname'}= $guarantordata->{'firstname'}; @@ -266,17 +275,28 @@ $newdata{'city'} = $input->param('city') if defined($input->param('city')) $newdata{'zipcode'} = $input->param('zipcode') if defined($input->param('zipcode')); $newdata{'country'} = $input->param('country') if defined($input->param('country')); +$newdata{'lang'} = $input->param('lang') if defined($input->param('lang')); + # builds default userid # userid input text may be empty or missing because of syspref BorrowerUnwantedField -if ( ( defined $newdata{'userid'} && $newdata{'userid'} eq '' ) || $check_BorrowerUnwantedField =~ /userid/ ) { - if ( ( defined $newdata{'firstname'} ) && ( defined $newdata{'surname'} ) ) { +if ( ( defined $newdata{'userid'} && $newdata{'userid'} eq '' ) || $check_BorrowerUnwantedField =~ /userid/ && !defined $data{'userid'} ) { + my $fake_patron = Koha::Patron->new; + $fake_patron->userid($patron->userid) if $patron; # editing + if ( ( defined $newdata{'firstname'} || $category_type eq 'I' ) && ( defined $newdata{'surname'} ) ) { # Full page edit, firstname and surname input zones are present - $newdata{'userid'} = Generate_Userid( $borrowernumber, $newdata{'firstname'}, $newdata{'surname'} ); + $fake_patron->firstname($newdata{firstname}); + $fake_patron->surname($newdata{surname}); + $fake_patron->generate_userid; + $newdata{'userid'} = $fake_patron->userid; } - elsif ( ( defined $data{'firstname'} ) && ( defined $data{'surname'} ) ) { + elsif ( ( defined $data{'firstname'} || $category_type eq 'I' ) && ( defined $data{'surname'} ) ) { # Partial page edit (access through "Details"/"Library details" tab), firstname and surname input zones are not used # Still, if the userid field is erased, we can create a new userid with available firstname and surname - $newdata{'userid'} = Generate_Userid( $borrowernumber, $data{'firstname'}, $data{'surname'} ); + # FIXME clean thiscode newdata vs data is very confusing + $fake_patron->firstname($data{firstname}); + $fake_patron->surname($data{surname}); + $fake_patron->generate_userid; + $newdata{'userid'} = $fake_patron->userid; } else { $newdata{'userid'} = $data{'userid'}; @@ -289,8 +309,7 @@ if ($op eq 'save' || $op eq 'insert'){ die "Wrong CSRF token" unless Koha::Token->new->check_csrf({ - id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + session_id => scalar $input->cookie('CGISESSID'), token => scalar $input->param('csrf_token'), }); @@ -307,15 +326,15 @@ if ($op eq 'save' || $op eq 'insert'){ my $dateofbirth; if ($op eq 'save' && $step == 3) { - my $borrower = C4::Members::GetMember(borrowernumber => $borrowernumber); - $dateofbirth = $borrower->{dateofbirth}; + $dateofbirth = $patron->dateofbirth; } else { $dateofbirth = $newdata{dateofbirth}; } if ( $dateofbirth ) { - my $age = GetAge($dateofbirth); + my $patron = Koha::Patron->new({ dateofbirth => $dateofbirth }); + my $age = $patron->get_age; my $borrowercategory = Koha::Patron::Categories->find($categorycode); my ($low,$high) = ($borrowercategory->dateofbirthrequired, $borrowercategory->upperagelimit); if (($high && ($age > $high)) or ($age < $low)) { @@ -341,14 +360,24 @@ if ($op eq 'save' || $op eq 'insert'){ # the edited values list when editing certain sub-forms. Get it straight # from the DB if absent. my $userid = $newdata{ userid } // $borrower_data->{ userid }; - unless (Check_Userid($userid,$borrowernumber)) { + my $p = $borrowernumber ? Koha::Patrons->find( $borrowernumber ) : Koha::Patron->new; + $p->userid( $userid ); + unless ( $p->has_valid_userid ) { push @errors, "ERROR_login_exist"; } - + my $password = $input->param('password'); my $password2 = $input->param('password2'); push @errors, "ERROR_password_mismatch" if ( $password ne $password2 ); - push @errors, "ERROR_short_password" if( $password && $minpw && $password ne '****' && (length($password) < $minpw) ); + + if ( $password and $password ne '****' ) { + my ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( $password ); + unless ( $is_valid ) { + push @errors, 'ERROR_password_too_short' if $error eq 'too_short'; + push @errors, 'ERROR_password_too_weak' if $error eq 'too_weak'; + push @errors, 'ERROR_password_has_whitespaces' if $error eq 'has_whitespaces'; + } + } # Validate emails my $emailprimary = $input->param('email'); @@ -400,8 +429,15 @@ if ((!$nok) and $nodouble and ($op eq 'insert' or $op eq 'save')){ $debug and warn "$op dates: " . join "\t", map {"$_: $newdata{$_}"} qw(dateofbirth dateenrolled dateexpiry); if ($op eq 'insert'){ # we know it's not a duplicate borrowernumber or there would already be an error - $borrowernumber = &AddMember(%newdata); - $newdata{'borrowernumber'} = $borrowernumber; + delete $newdata{password2}; + my $patron = eval { Koha::Patron->new(\%newdata)->store }; + if ( $@ ) { + # FIXME Urgent error handling here, we cannot fail without relevant feedback + # Lot of code will need to be removed from this script to handle exceptions raised by Koha::Patron->store + warn "Patron creation failed! - $@"; # Maybe we must die instead of just warn + } else { + $borrowernumber = $patron->borrowernumber; + } # If 'AutoEmailOpacUser' syspref is on, email user their account details from the 'notice' that matches the user's branchcode. if ( C4::Context->preference("AutoEmailOpacUser") == 1 && $newdata{'userid'} && $newdata{'password'}) { @@ -443,10 +479,6 @@ if ((!$nok) and $nodouble and ($op eq 'insert' or $op eq 'save')){ if (C4::Context->preference('EnhancedMessagingPreferences') and $input->param('setting_messaging_prefs')) { C4::Form::MessagingPreferences::handle_form_action($input, { borrowernumber => $borrowernumber }, $template, 1, $newdata{'categorycode'}); } - # Try to do the live sync with the Norwegian national patron database, if it is enabled - if ( exists $data{'borrowernumber'} && C4::Context->preference('NorwegianPatronDBEnable') && C4::Context->preference('NorwegianPatronDBEnable') == 1 ) { - NLSync({ 'borrowernumber' => $borrowernumber }); - } # Create HouseboundRole if necessary. # Borrower did not exist, so HouseboundRole *cannot* yet exist. @@ -494,10 +526,18 @@ if ((!$nok) and $nodouble and ($op eq 'insert' or $op eq 'save')){ delete $newdata{'password'}; delete $newdata{'userid'}; } - &ModMember(%newdata) unless scalar(keys %newdata) <= 1; # bug 4508 - avoid crash if we're not + + my $patron = Koha::Patrons->find( $borrowernumber ); + $newdata{debarredcomment} = $newdata{debarred_comment}; + delete $newdata{debarred_comment}; + delete $newdata{password2}; + $patron->set(\%newdata)->store if scalar(keys %newdata) > 1; # bug 4508 - avoid crash if we're not # updating any columns in the borrowers table, # which can happen if we're only editing the # patron attributes or messaging preferences sections + + $patron->update_password($newdata{userid}, $newdata{password}); + if (C4::Context->preference('ExtendedPatronAttributes') and $input->param('setting_extended_patron_attributes')) { C4::Members::Attributes::SetBorrowerAttributes($borrowernumber, $extended_patron_attributes); } @@ -505,10 +545,18 @@ if ((!$nok) and $nodouble and ($op eq 'insert' or $op eq 'save')){ C4::Form::MessagingPreferences::handle_form_action($input, { borrowernumber => $borrowernumber }, $template); } } - print scalar ($destination eq "circ") ? - $input->redirect("/cgi-bin/koha/circ/circulation.pl?borrowernumber=$borrowernumber") : - $input->redirect("/cgi-bin/koha/members/moremember.pl?borrowernumber=$borrowernumber") ; - exit; # You can only send 1 redirect! After that, content or other headers don't matter. + + if ( $destination eq 'circ' and not C4::Auth::haspermission( C4::Context->userenv->{id}, { circulate => 'circulate_remaining_permissions' } ) ) { + # If we want to redirect to circulation.pl and need to check if the logged in user has the necessary permission + $destination = 'not_circ'; + } + print scalar( $destination eq "circ" ) + ? $input->redirect( + "/cgi-bin/koha/circ/circulation.pl?borrowernumber=$borrowernumber") + : $input->redirect( + "/cgi-bin/koha/members/moremember.pl?borrowernumber=$borrowernumber" + ); + exit; # You can only send 1 redirect! After that, content or other headers don't matter. } if ($delete){ @@ -522,7 +570,7 @@ if ($nok or !$nodouble){ %data=%newdata; $template->param( updtype => ($op eq 'add' ?'I':'M')); # used to check for $op eq "insert"... but we just changed $op! unless ($step){ - $template->param( step_1 => 1,step_2 => 1,step_3 => 1, step_4 => 1, step_5 => 1, step_6 => 1); + $template->param( step_1 => 1,step_2 => 1,step_3 => 1, step_4 => 1, step_5 => 1, step_6 => 1, step_7 => 1 ); } } if (C4::Context->preference("IndependentBranches")) { @@ -535,31 +583,21 @@ if (C4::Context->preference("IndependentBranches")) { } } if ($op eq 'add'){ - $template->param( updtype => 'I', step_1=>1, step_2=>1, step_3=>1, step_4=>1, step_5 => 1, step_6 => 1); + $template->param( updtype => 'I', step_1=>1, step_2=>1, step_3=>1, step_4=>1, step_5 => 1, step_6 => 1, step_7 => 1); } if ($op eq "modify") { $template->param( updtype => 'M',modify => 1 ); - $template->param( step_1=>1, step_2=>1, step_3=>1, step_4=>1, step_5 => 1, step_6 => 1) unless $step; + $template->param( step_1=>1, step_2=>1, step_3=>1, step_4=>1, step_5 => 1, step_6 => 1, step_7 => 1) unless $step; if ( $step == 4 ) { $template->param( categorycode => $borrower_data->{'categorycode'} ); } - # Add sync data to the user data - if ( C4::Context->preference('NorwegianPatronDBEnable') && C4::Context->preference('NorwegianPatronDBEnable') == 1 ) { - my $sync = NLGetSyncDataFromBorrowernumber( $borrowernumber ); - if ( $sync ) { - $template->param( - sync => $sync->sync, - ); - } - } } if ( $op eq "duplicate" ) { $template->param( updtype => 'I' ); - $template->param( step_1 => 1, step_2 => 1, step_3 => 1, step_4 => 1, step_5 => 1, step_6 => 1 ) unless $step; + $template->param( step_1 => 1, step_2 => 1, step_3 => 1, step_4 => 1, step_5 => 1, step_6 => 1, step_7 => 1 ) unless $step; $data{'cardnumber'} = ""; } -$data{'cardnumber'}=fixup_cardnumber($data{'cardnumber'}) if ( ( $op eq 'add' ) or ( $op eq 'duplicate' ) ); if(!defined($data{'sex'})){ $template->param( none => 1); } elsif($data{'sex'} eq 'F'){ @@ -585,7 +623,7 @@ foreach my $category_type (qw(C A S P I X)) { { 'categorycode' => $patron_category->categorycode, 'categoryname' => $patron_category->description, 'categorycodeselected' => - ( ( defined( $borrower_data->{'categorycode'} ) && $patron_category->categorycode eq $borrower_data->{'categorycode'} ) || ( defined($categorycode) && $patron_category->categorycode eq $categorycode ) ), + ( defined($categorycode) && $patron_category->categorycode eq $categorycode ), }; } my %typehash; @@ -734,10 +772,14 @@ $template->param( check_member => $check_member,#to know if the borrower already exist(=>1) or not (=>0) "op$op" => 1); +$guarantorid = $borrower_data->{'guarantorid'} || $guarantorid; +my $guarantor = $guarantorid ? Koha::Patrons->find( $guarantorid ) : undef; $template->param( + patron => $patron, # Used by address include templates now nodouble => $nodouble, borrowernumber => $borrowernumber, #register number - guarantorid => ($borrower_data->{'guarantorid'} || $guarantorid), + guarantor => $guarantor, + guarantorid => $guarantorid, relshiploop => \@relshipdata, btitle=> $default_borrowertitle, guarantorinfo => $guarantorinfo, @@ -749,17 +791,13 @@ $template->param( ); # Generate CSRF token -$template->param( - csrf_token => Koha::Token->new->generate_csrf( - { id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), - } - ), +$template->param( csrf_token => + Koha::Token->new->generate_csrf( { session_id => scalar $input->cookie('CGISESSID'), } ), ); # HouseboundModule data $template->param( - housebound_role => Koha::Patron::HouseboundRoles->find($borrowernumber), + housebound_role => scalar Koha::Patron::HouseboundRoles->find($borrowernumber), ); if(defined($data{'flags'})){ @@ -778,6 +816,11 @@ if ( defined $min ) { ); } +if ( C4::Context->preference('TranslateNotices') ) { + my $translated_languages = C4::Languages::getTranslatedLanguages( 'opac', C4::Context->preference('template') ); + $template->param( languages => $translated_languages ); +} + output_html_with_http_headers $input, $cookie, $template->output; sub parse_extended_patron_attributes {