From 12e472c63df42e7a755f06617492c3edd050d18a Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Sat, 21 Dec 2024 16:11:30 +0000 Subject: [PATCH] Bug 38769: Process consents on patron self-registration This patch adds support for plugin consent types to self-registration: - Add proper display of plugin consents with consent_[type] naming - Only show plugin consents for new registrations (not edit mode) Backend changes (opac-memberentry.pl): - Add ParsePluginConsents() to extract consent checkbox values - Save plugin consents when creating patron directly - Store consents as JSON for email verification workflow Email verification (opac-registration-verify.pl): - Process stored plugin consents after email verification - Create Koha::Patron::Consent records for each agreed consent Test plan: 1. Enable a plugin that provides patron_consent_type hook 2. Go to OPAC self-registration page 3. Verify plugin consents are displayed 4. Submit registration with/without email verification 5. Verify consents are saved to patron_consents table --- .../bootstrap/en/modules/opac-memberentry.tt | 34 +++++++++++- opac/opac-memberentry.pl | 54 +++++++++++++++++-- opac/opac-registration-verify.pl | 24 +++++++-- 3 files changed, 103 insertions(+), 9 deletions(-) diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt index 8a7563c7756..5c870c9d1c7 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt @@ -1356,6 +1356,35 @@ [% END %] + [% IF consent_types.size && op != 'edit' %] + [% FOREACH consent_type IN consent_types.keys %] + [% IF consent_type != 'GDPR_PROCESSING' %] + [% SET consent_title = ( consent_types.$consent_type.title.$lang || consent_types.$consent_type.title.en ) %] + [% SET consent_desc = ( consent_types.$consent_type.description.$lang || consent_types.$consent_type.description.en ) %] +
+
+

[% consent_title | html %]

+ +
+ +
+ + [% END %] + [% END %] + [% END %] +
[% IF op == 'edit' %] @@ -1375,8 +1404,9 @@
-
+ + + diff --git a/opac/opac-memberentry.pl b/opac/opac-memberentry.pl index ce530d4bb15..1c8436a70e2 100755 --- a/opac/opac-memberentry.pl +++ b/opac/opac-memberentry.pl @@ -33,6 +33,7 @@ use C4::Members::Messaging qw( SetMessagingPreferencesFromDefaults ); use Koha::AuthUtils; use Koha::Patrons; use Koha::Patron::Consent; +use Koha::Patron::Consents; use Koha::Patron::Modification; use Koha::Patron::Modifications; use C4::Scrubber; @@ -205,7 +206,12 @@ if ( $op eq 'cud-create' ) { $borrower{verification_token} = $verification_token; $borrower{extended_attributes} = to_json($attributes); - $borrower{borrowernumber} = 0; # prevent warn Missing value for PK column + + # Store plugin consents for processing after email verification + my $plugin_consents = ParsePluginConsents($cgi); + $borrower{consents} = to_json($plugin_consents) if keys %$plugin_consents; + + $borrower{borrowernumber} = 0; # prevent warn Missing value for PK column Koha::Patron::Modification->new( \%borrower )->store(); #Send verification email @@ -230,7 +236,8 @@ if ( $op eq 'cud-create' ) { } else { $borrower{password} ||= Koha::AuthUtils::generate_password( Koha::Patron::Categories->find( $borrower{categorycode} ) ); - my $consent_dt = delete $borrower{gdpr_proc_consent}; + my $consent_dt = delete $borrower{gdpr_proc_consent}; + my $plugin_consents = ParsePluginConsents($cgi); my $patron; try { $patron = Koha::Patron->new( \%borrower )->store; @@ -238,6 +245,19 @@ if ( $op eq 'cud-create' ) { { borrowernumber => $patron->borrowernumber, type => 'GDPR_PROCESSING', given_on => $consent_dt } ) ->store if $patron && $consent_dt; + + # Store plugin consents + foreach my $consent_type ( keys %$plugin_consents ) { + Koha::Patron::Consent->new( + { + borrowernumber => $patron->borrowernumber, + type => $consent_type, + given_on => $plugin_consents->{$consent_type} + } + )->store + if $patron; + } + C4::Members::Messaging::SetMessagingPreferencesFromDefaults( { borrowernumber => $patron->borrowernumber, categorycode => $patron->categorycode } ); } catch { @@ -277,7 +297,7 @@ if ( $op eq 'cud-create' ) { my $letter = GetPreparedLetter( module => 'members', letter_code => 'WELCOME', - branchcode => $patron->branchcode,, + branchcode => $patron->branchcode, lang => $patron->lang || 'default', tables => { 'branches' => $patron->branchcode, @@ -404,7 +424,11 @@ if ( $op eq 'cud-create' ) { } else { # Render self-registration page - $template->param( patron_attribute_classes => GeneratePatronAttributesForm() ); + my $consent_types = Koha::Patron::Consents->available_types; + $template->param( + consent_types => $consent_types, + patron_attribute_classes => GeneratePatronAttributesForm() + ); } my $captcha = random_string("CCCCC"); @@ -817,4 +841,26 @@ sub ParsePatronAttributes { return \@attributes; } +sub ParsePluginConsents { + my ($cgi) = @_; + + my $consent_types = Koha::Patron::Consents->available_types; + my %consents; + + foreach my $consent_type ( keys %$consent_types ) { + + # Skip GDPR_PROCESSING as it's handled separately + next if $consent_type eq 'GDPR_PROCESSING'; + + my $param_name = "consent_$consent_type"; + my $value = $cgi->param($param_name); + + if ( $value && $value eq 'agreed' ) { + $consents{$consent_type} = dt_from_string(); + } + } + + return \%consents; +} + 1; diff --git a/opac/opac-registration-verify.pl b/opac/opac-registration-verify.pl index 76386e02939..14f60259349 100755 --- a/opac/opac-registration-verify.pl +++ b/opac/opac-registration-verify.pl @@ -17,7 +17,8 @@ use Modern::Perl; -use CGI qw ( -utf8 ); +use CGI qw ( -utf8 ); +use JSON qw( from_json ); use Try::Tiny; use C4::Auth qw( get_template_and_user ); @@ -28,6 +29,7 @@ use C4::Members; use C4::Members::Messaging qw( SetMessagingPreferencesFromDefaults ); use C4::Form::MessagingPreferences; use Koha::AuthUtils; +use Koha::DateUtils qw( dt_from_string ); use Koha::Patrons; use Koha::Patron::Consent; use Koha::Patron::Modifications; @@ -80,7 +82,8 @@ if ( $rego_found my $patron_attrs = $m->unblessed; $patron_attrs->{password} ||= Koha::AuthUtils::generate_password( Koha::Patron::Categories->find( $patron_attrs->{categorycode} ) ); - my $consent_dt = delete $patron_attrs->{gdpr_proc_consent}; + my $consent_dt = delete $patron_attrs->{gdpr_proc_consent}; + my $consents_json = delete $patron_attrs->{consents}; $patron_attrs->{categorycode} ||= C4::Context->preference('PatronSelfRegistrationDefaultCategory'); delete $patron_attrs->{timestamp}; delete $patron_attrs->{verification_token}; @@ -93,6 +96,21 @@ if ( $rego_found Koha::Patron::Consent->new( { borrowernumber => $patron->borrowernumber, type => 'GDPR_PROCESSING', given_on => $consent_dt } )->store if $patron && $consent_dt; + + # Process plugin consents + if ( $patron && $consents_json ) { + my $plugin_consents = from_json($consents_json); + foreach my $consent_type ( keys %$plugin_consents ) { + Koha::Patron::Consent->new( + { + borrowernumber => $patron->borrowernumber, + type => $consent_type, + given_on => dt_from_string( $plugin_consents->{$consent_type} ) + } + )->store; + } + } + C4::Members::Messaging::SetMessagingPreferencesFromDefaults( { borrowernumber => $patron->borrowernumber, categorycode => $patron->categorycode } ); } catch { @@ -133,7 +151,7 @@ if ( $rego_found my $letter = GetPreparedLetter( module => 'members', letter_code => 'WELCOME', - branchcode => $patron->branchcode,, + branchcode => $patron->branchcode, lang => $patron->lang || 'default', tables => { 'branches' => $patron->branchcode, -- 2.52.0