Bug 41932

Summary: Allow optional zero-padding in items.cn_sort
Product: Koha Reporter: Marcel de Rooy <m.de.rooy>
Component: CatalogingAssignee: Marcel de Rooy <m.de.rooy>
Status: ASSIGNED --- QA Contact: David Cook <dcook>
Severity: enhancement    
Priority: P5 - low CC: dcook, m.de.rooy
Version: unspecified   
Hardware: All   
OS: All   
See Also: https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=41936
GIT URL: Initiative type: ---
Sponsorship status: --- Comma delimited list of Sponsors:
Crowdfunding goal: 0 Patch complexity: ---
Documentation contact: Documentation submission:
Text to go in the release notes:
Version(s) released in:
Circulation function:
Attachments: Bug 41932: Adjust generic class sort to allow zero-padding

Description Marcel de Rooy 2026-02-25 14:36:27 UTC
We have callnumbers like 1 A 1, 10 A 10, 100 A 100 and 1000 A 100.
Alphabetically sorting those does not work (100 A 100 < 2 A 2)

This proposal includes adding a syspref to define callnumber formats that also specify the desired length when zero-padding cn_sort. This would be active when using C4::ClassSortRoutine::Generic.

In the above case we would like to sort them with 0001 A 001, 0010 A 010, 0100 A 100 and 1000 A 100. So the first digit block has length 4, the second block 3.
Comment 1 David Cook 2026-02-26 04:34:13 UTC
I'm interested in this. I'm having a similar problem with the generic classification source. 

I have one library where it would be nice to detect digits and zero pad them to N places to have a more intelligent sort rather than lexicographic sorting.
Comment 2 David Cook 2026-02-26 04:35:00 UTC
Are you likely to work on this, Marcel?
Comment 3 Marcel de Rooy 2026-02-26 07:02:16 UTC
(In reply to David Cook from comment #2)
> Are you likely to work on this, Marcel?

Yeah see Assignee/status.
Comment 4 Marcel de Rooy 2026-02-26 08:12:29 UTC
Removing 'cruft' from the callnumber should be done after zero padding:

| RCE TEST 1.33.45 Mid (1) | RCE_TEST_001033045_MID_1 |

We want 1.33.45 not to be interpreted as one digit group (13345) but as three digit groups since the dot serves as delimiter.
Comment 5 Marcel de Rooy 2026-02-26 12:51:02 UTC
Created attachment 193984 [details] [review]
Bug 41932: Adjust generic class sort to allow zero-padding

Test plan:
Run t/ClassSortRoutine_Generic.t
Add a few callnumber formats in ClassSortGenericFormats like:
    ^A:1,3;1,2;;^B:1,2
    In words: callnumber starts with A, 1 or more digits (pad to 3),
    then 1 or more digits (pad to 2). Or callnumber starts with B,
    one or more digits (pad to 2).
Enable generic call number sorting rules in Classification
configuration.
Now save a few items with callnumbers: 1 A 1, 10 A 2, B2, B11.
Check if cn_sort now matches: 001_A_01, 100_A_02, B02, B11.

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Comment 6 Marcel de Rooy 2026-02-26 12:54:14 UTC
(In reply to David Cook from comment #2)
> Are you likely to work on this, Marcel?

Here is an impression of where I am at now. This comes from 24.11. I need to polish a bit still: add a preference and description, add a db revision, test on main etc. But it is almost ready.

Chose for a preference approach above plugin approach here. Many libraries may want to selectively zero pad with multiple schemes. This is possible by an intelligent use of the pref introduced here working with a filter regex and a list of minimum length versus minimum sort length values.
Comment 7 David Cook 2026-02-26 22:25:00 UTC
(In reply to Marcel de Rooy from comment #6)
> (In reply to David Cook from comment #2)
> > Are you likely to work on this, Marcel?
> 
> Here is an impression of where I am at now. This comes from 24.11. I need to
> polish a bit still: add a preference and description, add a db revision,
> test on main etc. But it is almost ready.
> 
> Chose for a preference approach above plugin approach here. Many libraries
> may want to selectively zero pad with multiple schemes. This is possible by
> an intelligent use of the pref introduced here working with a filter regex
> and a list of minimum length versus minimum sort length values.

Thanks for taking this on. I wanted to do it for one library but couldn't get sponsorship for it. 

I had thought about doing a totally separate name for it rather than generic though just to have a cleaner separation. 

Are you thinking of adding the syspref inside C4/ClassSortRoutine/Generic.pm? Or would it be in the caller of get_class_sort_key? Probably cleaner to do the latter.
Comment 8 David Cook 2026-02-26 22:26:14 UTC
I suppose whether we used a different name than Generic or used a syspref, there will be a little bit of work to do in applying it to existing items. I mean a touch_all_items.pl will do the trick but I suppose we don't want to alter existing behaviour without an option (like a syspref or a different name). 

Anyway, look forward to seeing more. Happy to QA this one.
Comment 9 Marcel de Rooy 2026-02-27 07:15:21 UTC
(In reply to David Cook from comment #7)
> Are you thinking of adding the syspref inside
> C4/ClassSortRoutine/Generic.pm? Or would it be in the caller of
> get_class_sort_key? Probably cleaner to do the latter.

Since the syspref is so tight to the routine that does the work, I think that the current handling within Generic is cleaner.