From aa84e99db84214b56ece9fccfbfaa21c9320eff5 Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Tue, 21 Apr 2026 10:56:58 +0100 Subject: [PATCH] Bug 34000: Add autoMemberNumValue system preference Introduces a new system preference, autoMemberNumValue, which tracks the highest auto-generated cardnumber ever issued. It is seeded from the MAX cardnumber across both borrowers and deletedborrowers so pre-upgrade deletions do not free numbers for re-issuance. This preference is managed internally by Koha::Patron::fixup_cardnumber and has no UI (no YAML entry). Test plan: 1. Apply the atomicupdate: perl installer/data/mysql/updatedatabase.pl 2. Verify the preference exists: SELECT * FROM systempreferences WHERE variable = 'autoMemberNumValue'; 3. Confirm the seed value matches: SELECT GREATEST( COALESCE((SELECT MAX(CAST(cardnumber AS SIGNED)) FROM borrowers WHERE cardnumber REGEXP '^-?[0-9]+\$'), 0), COALESCE((SELECT MAX(CAST(cardnumber AS SIGNED)) FROM deletedborrowers WHERE cardnumber REGEXP '^-?[0-9]+\$'), 0) ); 4. Re-run the atomicupdate and confirm the already-exists warning. 5. Drop the syspref, re-apply the atomicupdate, confirm it seeds correctly on fresh installs via mandatory/sysprefs.sql. Signed-off-by: Andrew Fuerste Henry Signed-off-by: Jacob O'Mara --- .../data/mysql/atomicupdate/bug_34000.pl | 48 +++++++++++++++++++ installer/data/mysql/mandatory/sysprefs.sql | 1 + 2 files changed, 49 insertions(+) create mode 100755 installer/data/mysql/atomicupdate/bug_34000.pl diff --git a/installer/data/mysql/atomicupdate/bug_34000.pl b/installer/data/mysql/atomicupdate/bug_34000.pl new file mode 100755 index 0000000000..07eec95787 --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_34000.pl @@ -0,0 +1,48 @@ +use Modern::Perl; +use Koha::Installer::Output qw(say_warning say_success say_info); + +return { + bug_number => "34000", + description => "Prevent re-issuance of auto-generated cardnumbers", + up => sub { + my ($args) = @_; + my ( $dbh, $out ) = @$args{qw(dbh out)}; + + my $exists = $dbh->selectrow_array(q{SELECT 1 FROM systempreferences WHERE variable = 'autoMemberNumValue'}); + + if ($exists) { + say_warning( $out, "System preference 'autoMemberNumValue' already exists, skipping" ); + return; + } + + # Seed from the highest numeric cardnumber ever issued, considering both live + # and deleted patrons so pre-upgrade deletions don't free up their numbers. + my ($seed) = $dbh->selectrow_array( + q{ + SELECT COALESCE( + GREATEST( + COALESCE( + (SELECT MAX(CAST(cardnumber AS SIGNED)) FROM borrowers + WHERE cardnumber REGEXP '^-?[0-9]+$'), + 0 + ), + COALESCE( + (SELECT MAX(CAST(cardnumber AS SIGNED)) FROM deletedborrowers + WHERE cardnumber REGEXP '^-?[0-9]+$'), + 0 + ) + ), + 0 + ) + } + ); + $seed //= 0; + + $dbh->do( + q{INSERT IGNORE INTO systempreferences (variable, value) VALUES ('autoMemberNumValue', ?)}, + undef, $seed + ); + + say_success( $out, "Added new system preference 'autoMemberNumValue' seeded to $seed" ); + }, +}; diff --git a/installer/data/mysql/mandatory/sysprefs.sql b/installer/data/mysql/mandatory/sysprefs.sql index c442345d39..f295a3b39c 100644 --- a/installer/data/mysql/mandatory/sysprefs.sql +++ b/installer/data/mysql/mandatory/sysprefs.sql @@ -101,6 +101,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('AutomaticEmailReceipts','0',NULL,'Send email receipts for payments and write-offs','YesNo'), ('AutomaticItemReturn','1',NULL,'If ON, Koha will automatically set up a transfer of this item to its homebranch','YesNo'), ('autoMemberNum','0',NULL,'If ON, patron number is auto-calculated','YesNo'), +('autoMemberNumValue','0',NULL,'Stores the last auto-generated cardnumber to prevent re-issuance','Integer'), ('AutoRemoveOverduesRestrictions','no','no|when_no_overdue|when_no_overdue_causing_debarment', 'Defines if and on what conditions OVERDUES debarments should automatically be lifted when overdue items are returned by the patron.','Choice'), ('AutoRenewalNotices','preferences','cron|preferences|never','How should Koha determine whether to end autorenewal notices','Choice'), ('AutoResumeSuspendedHolds','1',NULL,'Allow suspended holds to be automatically resumed by a set date.','YesNo'),