Bug 41383: SIP2 server does not search patrons by unique patron attributes (alternate IDs unusable in SIP2)

Currently, Koha::Patrons->find_by_identifier only searches for patrons by userid and cardnumber.

This patch extends this method to also search by unique borrower attributes (where unique_id=1).
This enhancement allows modules like SIP2 to identify patrons using alternative unique identifiers
defined in the system.

Test Plan:
1. Test current behaviour:
   - Go to Administration -> Patron attribute types
   - Create a new Patron attribute with:
      - Patron attribute type code = "AltID"
      - Description = "Alternate ID"
      - Unique identifier checkbox selected
      - Save
   - Edit any patron record and go to Additional attributes and identifiers
      - Add a value "altid123" to "Alternate ID"
      - Save
   - Use any SIP2 client to search for the patron using this attribute value. e.g.,
     `perl misc/sip_cli_emulator.pl -su term1 -sp term1 -l CPL --host localhost --patron altid123 -m patron_information`
   - Verify that the patron is NOT found with this message:
     'AFInvalid cardnumber'
     e.g.:
     READ: 64YYYY          00120260304    104611000000000000000000000000AOCPL|AAaltid123|AE|BLN|AFInvalid cardnumber|

2. Apply the patch.

3. Run the tests:
   prove t/db_dependent/Koha/Patrons.t
   - Verify that all tests pass, including the new cases for unique attribute lookup.

4. Test with patch applied:
   - Use any SIP2 client to search for the patron using this attribute value. e.g.,
     `perl misc/sip_cli_emulator.pl -su term1 -sp term1 -l CPL --host localhost --patron altid123 -m patron_information`
   - Verify that the patron is found with this message:
     'AFGreetings from Koha.'
     e.g.:
     READ: 64              00120260304    104328000000000000000000000000AOCPL|AA23529001000463|AEEdna Acosta|BLY|BHUSD|BV0|CC5|BD7896 Library Rd. Portland, OR 44240|BF(212) 555-1212|PB19800424|PCPT|PIY|AFGreetings from Koha. |

5. Test non-unique attribute:
   - Go to Administration -> Patron attribute types
   - Edit "Alternate ID" attribute type
      - Unique identifier checkbox NOT selected
      - Save
   - Use any SIP2 client to search for the patron using this attribute value. e.g.,
     `perl misc/sip_cli_emulator.pl -su term1 -sp term1 -l CPL --host localhost --patron altid123 -m patron_information`
   - Verify that the patron is NOT found with this message:
     'AFInvalid cardnumber'
     e.g.:
     READ: 64YYYY          00120260304    104611000000000000000000000000AOCPL|AAaltid123|AE|BLN|AFInvalid cardnumber|

6. Sign-off

Signed-off-by: Syed Faheemuddin <faheem@nexuslib.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
Saiful Amin 2025-12-08 19:18:32 +00:00 committed by Lucas Gass
parent 0bcf87df38
commit 7cdba6ba02
No known key found for this signature in database
GPG Key ID: 60B447398B0D36CA
2 changed files with 64 additions and 1 deletions

View File

@ -64,6 +64,20 @@ sub find_by_identifier {
# If not found by userid, try cardnumber
$patron = $self->search( { cardnumber => $identifier } )->next unless $patron;
# If not found by cardnumber, try unique patron attributes
unless ($patron) {
$patron = $self->search(
{
'borrower_attributes.attribute' => $identifier,
'code.unique_id' => 1,
},
{
join => { 'borrower_attributes' => 'code' },
rows => 1,
}
)->single;
}
return $patron;
}

View File

@ -39,6 +39,8 @@ use Koha::Holds;
use Koha::Old::Holds;
use Koha::Patrons;
use Koha::Old::Patrons;
use Koha::Patron::Attribute;
use Koha::Patron::Attribute::Type;
use Koha::Patron::Attribute::Types;
use Koha::Patron::Categories;
use Koha::Patron::Relationship;
@ -3770,7 +3772,7 @@ subtest 'filter_by_expired_opac_registrations' => sub {
subtest 'find_by_identifier() tests' => sub {
plan tests => 7;
plan tests => 9;
$schema->storage->txn_begin;
@ -3810,6 +3812,53 @@ subtest 'find_by_identifier() tests' => sub {
$found_patron = Koha::Patrons->find_by_identifier(undef);
is( $found_patron, undef, 'Returns undef for undef identifier' );
# Test with unique attributes
my $unique_code = 'UA_' . int( rand(100000) );
Koha::Patron::Attribute::Type->new(
{
code => $unique_code,
description => 'Unique Attribute',
unique_id => 1,
repeatable => 0,
}
)->store;
my $non_unique_code = 'NUA_' . int( rand(100000) );
Koha::Patron::Attribute::Type->new(
{
code => $non_unique_code,
description => 'Non-Unique Attribute',
unique_id => 0,
repeatable => 0,
}
)->store;
my $patron_u = $builder->build_object( { class => 'Koha::Patrons' } );
my $val_u = 'VAL_U_' . int( rand(100000) );
Koha::Patron::Attribute->new(
{
borrowernumber => $patron_u->borrowernumber,
code => $unique_code,
attribute => $val_u,
}
)->store;
my $patron_nu = $builder->build_object( { class => 'Koha::Patrons' } );
my $val_nu = 'VAL_NU_' . int( rand(100000) );
Koha::Patron::Attribute->new(
{
borrowernumber => $patron_nu->borrowernumber,
code => $non_unique_code,
attribute => $val_nu,
}
)->store;
$found_patron = Koha::Patrons->find_by_identifier($val_u);
is( $found_patron ? $found_patron->id : undef, $patron_u->id, 'Found patron by unique attribute' );
$found_patron = Koha::Patrons->find_by_identifier($val_nu);
is( $found_patron, undef, 'Did not find patron by non-unique attribute' );
$schema->storage->txn_rollback;
};