From b10b8f4b560e6e3821f1b1fd487dc856ad245885 Mon Sep 17 00:00:00 2001 From: Nick Clemens Date: Fri, 25 Aug 2023 12:03:20 +0000 Subject: [PATCH] Bug 34611: Add pseudonymize routine to Koha::Statistics This patch adds a new routine to pseudonymize a statistic and adjusts C4::Stats to use this new routine. Additionally Koha::PseudonymizedTransaction->new_from_statistic is updated to check for the existence of objects before using them (in the case of older stats where things may have been deleted) Tests are added and can be run using: 1. Run: $ ktd --shell k$ prove t/db_dependent/Koha/PseudonymizedTransaction.t \ t/db_dependent/Koha/Pseudonymization.t => SUCCESS: New tests pass, old tests keep passing Signed-off-by: AFHDubCoLib --- C4/Stats.pm | 7 ++-- Koha/PseudonymizedTransaction.pm | 60 +++++++++++++++++++------------- Koha/Statistic.pm | 17 +++++++++ 3 files changed, 55 insertions(+), 29 deletions(-) diff --git a/C4/Stats.pm b/C4/Stats.pm index f8f1aa03a82..a39ac12c74e 100644 --- a/C4/Stats.pm +++ b/C4/Stats.pm @@ -146,11 +146,8 @@ sub UpdateStats { } )->store; - Koha::PseudonymizedTransaction->new_from_statistic($statistic)->store - if C4::Context->preference('Pseudonymization') - && $borrowernumber # Not a real transaction if the patron does not exist - # For instance can be a transfer, or hold trigger - && grep { $_ eq $params->{type} } qw(renew issue return onsite_checkout); + $statistic->pseudonymize() if C4::Context->preference('Pseudonymization'); + } 1; diff --git a/Koha/PseudonymizedTransaction.pm b/Koha/PseudonymizedTransaction.pm index 70049a48c92..6d013fae2e8 100644 --- a/Koha/PseudonymizedTransaction.pm +++ b/Koha/PseudonymizedTransaction.pm @@ -17,6 +17,7 @@ package Koha::PseudonymizedTransaction; use Modern::Perl; use Crypt::Eksblowfish::Bcrypt qw( bcrypt ); +use List::MoreUtils qw(any); use Koha::Database; use Koha::Exceptions::Config; @@ -47,23 +48,30 @@ sub new_from_statistic { my @t_fields_to_copy = split ',', C4::Context->preference('PseudonymizationTransactionFields') || ''; - if ( grep { $_ eq 'transaction_branchcode' } @t_fields_to_copy ) { + my $statistic_item = $statistic->item; + + # These fields are treated separately as the column names do not match + if ( any { $_ eq 'transaction_branchcode' } @t_fields_to_copy ) { $values->{transaction_branchcode} = $statistic->branch; } - if ( grep { $_ eq 'holdingbranch' } @t_fields_to_copy ) { - $values->{holdingbranch} = $statistic->item->holdingbranch; - } - if ( grep { $_ eq 'homebranch' } @t_fields_to_copy ) { - $values->{homebranch} = $statistic->item->homebranch; - } - if ( grep { $_ eq 'transaction_type' } @t_fields_to_copy ) { + if ( any { $_ eq 'transaction_type' } @t_fields_to_copy ) { $values->{transaction_type} = $statistic->type; } - if ( grep { $_ eq 'itemcallnumber' } @t_fields_to_copy ) { - $values->{itemcallnumber} = $statistic->item->itemcallnumber; - } + # These fields are not captured in the statistic so must be pulled from the item + if ($statistic_item) { + if ( any { $_ eq 'homebranch' } @t_fields_to_copy ) { + $values->{homebranch} = $statistic_item->homebranch; + } + if ( any { $_ eq 'holdingbranch' } @t_fields_to_copy ) { + $values->{holdingbranch} = $statistic_item->holdingbranch; + } + if ( any { $_ eq 'itemcallnumber' } @t_fields_to_copy ) { + $values->{itemcallnumber} = $statistic_item->itemcallnumber; + } + } + # Remove fields we have already handled from the list @t_fields_to_copy = grep { $_ ne 'transaction_branchcode' && $_ ne 'holdingbranch' @@ -72,28 +80,32 @@ sub new_from_statistic { && $_ ne 'itemcallnumber' } @t_fields_to_copy; + # Populate the remaining columns $values = { %$values, map { $_ => $statistic->$_ } @t_fields_to_copy }; - my $patron = Koha::Patrons->find($statistic->borrowernumber); - my @p_fields_to_copy = split ',', C4::Context->preference('PseudonymizationPatronFields') || ''; - $values = { %$values, map { $_ => $patron->$_ } @p_fields_to_copy }; + my $patron = Koha::Patrons->find( $statistic->borrowernumber ); + if ($patron) { + my @p_fields_to_copy = split ',', C4::Context->preference('PseudonymizationPatronFields') || ''; + $values = { %$values, map { $_ => $patron->$_ } @p_fields_to_copy }; - $values->{branchcode} = $patron->branchcode; # FIXME Must be removed from the pref options, or FK removed (?) - $values->{categorycode} = $patron->categorycode; + $values->{branchcode} = $patron->branchcode; # FIXME Must be removed from the pref options, or FK removed (?) + $values->{categorycode} = $patron->categorycode; - $values->{has_cardnumber} = $patron->cardnumber ? 1 : 0; + $values->{has_cardnumber} = $patron->cardnumber ? 1 : 0; + } my $self = $class->SUPER::new($values); - my $extended_attributes = $patron->extended_attributes->unblessed; - for my $attribute (@$extended_attributes) { - next unless Koha::Patron::Attribute::Types->find( - $attribute->{code} )->keep_for_pseudonymization; + if ($patron) { + my $extended_attributes = $patron->extended_attributes->unblessed; + for my $attribute (@$extended_attributes) { + next unless Koha::Patron::Attribute::Types->find( $attribute->{code} )->keep_for_pseudonymization; - delete $attribute->{id}; - delete $attribute->{borrowernumber}; + delete $attribute->{id}; + delete $attribute->{borrowernumber}; - $self->_result->create_related('pseudonymized_borrower_attributes', $attribute); + $self->_result->create_related( 'pseudonymized_borrower_attributes', $attribute ); + } } return $self; diff --git a/Koha/Statistic.pm b/Koha/Statistic.pm index 397e440cdb1..bd224b4154a 100644 --- a/Koha/Statistic.pm +++ b/Koha/Statistic.pm @@ -20,6 +20,7 @@ use Modern::Perl; use Koha::Database; use Koha::Items; +use Koha::PseudonymizedTransaction; use base qw(Koha::Object); @@ -44,6 +45,22 @@ sub item { return Koha::Items->find( $self->itemnumber ); } +=head3 pseudonymize + +my $pseudonymized_stat = $statistic->pseudonymize; + +Generate a pesudonymized version of the statistic. + +=cut + +sub pseudonymize { + my ($self) = @_; + + return unless ( $self->borrowernumber && grep { $_ eq $self->type } qw(renew issue return onsite_checkout) ); + + return Koha::PseudonymizedTransaction->new_from_statistic($self)->store; +} + =head2 Internal methods =head3 _type -- 2.30.2