commit 215b5d6c6fc5801810242bb33b5cf644c0bf6ef7 Author: Jonathan Druart Date: Thu Jul 2 15:37:41 2026 +0200 Bug 42981: Prevent toLowerCase to fail when comparing int and string If stateSave is turned on and one of the option has a value with _id set to an Integer, toLowerCase is not available and a JS error is raised: Uncaught (in promise) TypeError: this._id.toLowerCase is not a function Test plan: 1.) Admin - table settings: cgi-bin/koha/admin/columns_settings.pl#eholdings|packages Activate checkbox "Save search state on page change" 2.) Go to ERM : cgi-bin/koha/erm/eholdings/local/packages And create two packages: - One package with My Vendor assigned. - One package without a vendor. 3.) Filter the package results list by My Vendor. --> List is filtered to one package 4.) Leave the page, for example by navigating to Agreements. Return to the Packages list and you will see the issue (See also attached Screenshot) => Without the patch The package results list becomes unresponsive / hangs after returning to the page. => With the patch The package results list should load and display the filtered results correctly. commit b0fa3d7e6a97573f6e00e07a01d4e0143a0f4d3b Author: Owen Leonard Date: Fri May 15 13:33:21 2026 -0400 Bug 42618: Incorrect sidebar menu link to MARC order accounts The administration sidebar menu has an incorrect link for MARC ordering accounts. Clicking the link takes you to EDI accounts. This patch fixes it. To test, apply the patch and run 'yarn build' - Go to Administration -> Libraries (for example) - In the sidebar menu, click the MARC ordering accounts link. - You should be taken to the MARC ordering accounts page. Sponsored-by: Athens County Public Libraries Signed-off-by: Roman Dolny Signed-off-by: Laura_Escamilla Signed-off-by: Pedro Amorim commit 2b2b4b74babffb6e1838dade2d5ff5a62003903f Author: Caroline Cyr La Rose Date: Thu Jun 18 16:22:59 2026 -0400 Bug 42885: FineNoRenewals description mentions fines rather than charges This patch fixes the terminology in the FineNoRenewals system preference description to use the term 'charges' instead of 'fines'. To test: 1. Apply patch 2. Go to Administration > System preferences 3. Search for FineNoRenewals 4. Make sure the description is gramatically correct and doesn't have contain typos Signed-off-by: David Nind Signed-off-by: Laura_Escamilla Signed-off-by: Pedro Amorim commit 4003a4aa9090ae4c668c86a91efc049bd4d7edd6 Author: Chris Mathevet Date: Mon May 11 10:22:07 2026 -0400 Bug 42579: Added "no-export" class to ratings div "Title" column of Checkout history export contains too much informations, making the export file hard to read and understand. Test plan : 1 - Connect on OPAC 2 - Go to "Your account" 3 - Go to "Checkout history" 4 - Click on "CSV" 5 - Open file 6 - Notice that the "title" column is too long and contains ratings informations 7 - Go back on OPAC 8 - Click on "Copy" 9 - Copy to a .txt file 10 - Notice the same problem as the CSV export 11 - Apply patch 12 - Repeat previous instructions 13 - Notice that the "title" column contains only the title Signed-off-by: Owen Leonard Signed-off-by: Laura_Escamilla Signed-off-by: Pedro Amorim commit 839f3492bc8cc5243caefa5706209570c2d27c55 Author: Kyle M Hall Date: Fri May 8 15:55:15 2026 -0400 Bug 42571: Sending EDI order results in variable not available warnings The warnings look like: [2026/05/08 15:02:42] [32918] [WARN] Variable "@messages" is not available at /usr/share/koha/intranet/cgi-bin/acqui/basket.pl line 698. [2026/05/08 15:02:42] [32918] [WARN] Variable "$op" is not available at /usr/share/koha/intranet/cgi-bin/acqui/basket.pl line 704. Note in the fix, we are switching to the "our" keyword. When we declare things with "our", and we run this under plack, those variables and values persist across multiple requests! Due to this behavior we always need to reinitialize anything that uses "our" unless we specifically want that behavior ( like caching ). Test plan: 1) Send an EDI order, note the warnings in the logs 2) Apply this patch 3) Restart all the things! 4) Send another EDI order, note the warnings are gone! Signed-off-by: David Nind Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit 2472e423cb32c355f4e9e4ba9815a91f75c3d3c3 Author: Jonathan Druart Date: Tue Jun 30 11:41:34 2026 +0200 Bug 42551: Fix QA failures [FAIL] t/db_dependent/Koha/Plugins/C3.t FAIL file_permissions File must have the exec flag FAIL test_no_warnings 'use Test::NoWarnings' must be present in this test file. Signed-off-by: Jonathan Druart Signed-off-by: Pedro Amorim commit c79b0b9ef8bc9fa27d9549a30f2fece18362a660 Author: Kyle M Hall Date: Thu May 7 12:14:25 2026 +0000 Bug 42551: Skip preload when running perl with -c Signed-off-by: David Nind Signed-off-by: Jonathan Druart Signed-off-by: Pedro Amorim commit e48c124ac3dcdce4bddfe85d6287e32f367be21b Author: Kyle M Hall Date: Thu May 7 12:12:39 2026 +0000 Bug 42551: Add unit test Signed-off-by: David Nind Signed-off-by: Jonathan Druart Signed-off-by: Pedro Amorim commit 9be8db9c8add91875fe98dd5b6a97e305b76c6ea Author: Lisette Scheer Date: Fri Jun 26 14:40:54 2026 +0000 Bug 41889: Update API to allow for null patron_id to be returned when listing checkouts If a patron is deleted and there's a checkout associated with them, an api call to {url}/api/v1/checkouts?checked_in=true will result in an error. This patch updates the api to allow for a null value to be returned for patron_id To test: Before applying the patch: 1. In Administration->System preference enable the RESTBasicAuth system preference. 2. Checkout an item to a patron (I used item barcode: 39999000000252 and patron barcode 23529000121682) 3. Check the item back in 4. In your brower go to {sandbox/ktdurl}/api/v1/checkouts?checked_in=1 5. Observe there is a patron ID in the JSON response 6. Delete the patron 7. Repeat step 4 8. Observe an error because a "null" value was returned 9. Apply patch Sandbox: In sandbox management Actions->Apply patches Once complete Actions->Build CSS and JS Actions->Restart services KTD: ktd --shell git bz apply 41889 yarn build restart_all 10. Repeat step 4 11. Observe the checkout loads, but now has a null patron id. 12. Sign off On KTD can also run the script: qa to run tests. Signed-off-by: David Nind Signed-off-by: Tomás Cohen Arazi Signed-off-by: Pedro Amorim commit cb47e6fad7f2db0d79e420831de31240f58aee31 Author: Jonathan Druart Date: Tue Jun 30 19:04:23 2026 +0200 Bug 42278: Fix JS error Uncaught SyntaxError: redeclaration of non-configurable global property ClaimReturnedLostValue Signed-off-by: Pedro Amorim commit dd918e0de15e2e419827a4e54070c77ca2b16046 Author: Jonathan Druart Date: Mon May 4 15:34:40 2026 +0200 Bug 42522: Add link to biblio from eholding show view Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 4844c93a23f3a608c33666465fde8374d2a42e12 Author: Jonathan Druart Date: Fri Apr 3 11:45:51 2026 +0200 Bug 42290: Tidy all script tags - suggestion (auto tidy) Signed-off-by: Paul Derscheid Signed-off-by: Jan Kissig Signed-off-by: Pedro Amorim commit e4293f93d2949adf88236db42df8b32cdf3df47b Author: Jonathan Druart Date: Mon Mar 30 14:33:38 2026 +0200 Bug 42290: Tidy all script tags - suggestion In order to tidy all the script tags of the .tt files we isolate the interpolation of Template::Toolkit variables in a separate script tag. This patch focuses on the suggestion module. Trivial changes, the main changes have been done already, we only move them to a separate script tag. Signed-off-by: Paul Derscheid Signed-off-by: Jan Kissig Signed-off-by: Pedro Amorim commit 36e00f5aff00dc34aa3ec71fd46bc8b1e62f4e55 Author: Jan Kissig Date: Wed May 20 20:26:33 2026 +0000 Bug 42283: (QA follow-up) Change icons Changes the icon on concerns resolved filter to suit other filters set via AV TICKET_STATUS. Signed-off-by: Pedro Amorim commit a4ec38d5fa654f69ff62bdb3fd1cf39d1dbbebfc Author: Paul Derscheid Date: Fri Apr 17 12:02:16 2026 +0200 Bug 42283: (follow-up) URI-encode z3950 search params in GetZ3950Terms The original template rendered each Z39.50 search param with the "| uri" TT filter, so the generated query string was safe for values containing spaces, ampersands or other reserved characters. The JS port concatenates the raw values, producing a broken query string when any search field (title, author, subject, etc.) is not already URL-safe. Wrap name and value in encodeURIComponent to restore the original behaviour. To test: - Import or create a biblio whose title or author includes a space and an ampersand (e.g. "Q & A: Practical tests"). - From the cataloging search results, trigger the Z39.50 search for that record. - Confirm the request URL includes correctly encoded parameters (space as %20, & as %26) and that the Z39.50 results load. Signed-off-by: Paul Derscheid Signed-off-by: Jan Kissig Signed-off-by: Pedro Amorim commit c7422c5c78ef671848bf30300ff116991dd0099f Author: Paul Derscheid Date: Fri Apr 17 12:02:01 2026 +0200 Bug 42283: (follow-up) Fix checkbox selector in concerns status filter Porting the per-status click handler out of the TT loop dropped the "hide_" prefix on the checkbox selectors: - the `is(":checked")` test looked at `#` instead of `#hide_`, so the branch that removes the filter never fired - the toggle line read `!$("#hide${av}")` (no underscore) before writing `#hide_`, so the checkbox state was always forced to true and further clicks stopped toggling Restore `#hide_${av}` in both places so the filter toggles match the original TT-rendered selectors (IDs `hide_` on the hidden checkboxes). To test: - Set up TICKET_STATUS authorised values and enable CatalogConcerns and OpacCatalogConcerns. - Create concerns in multiple statuses, open /cgi-bin/koha/cataloguing/concerns.pl. - Click a "Filter " link: rows with that status disappear. - Click the same link again: it flips back to "Include " and rows reappear. Repeat across several statuses. Signed-off-by: Paul Derscheid Signed-off-by: Jan Kissig Signed-off-by: Pedro Amorim commit 2cf1f980d0e3bc0c1d12bea8915099914ec5f52d Author: Jonathan Druart Date: Tue Apr 7 13:13:13 2026 +0200 Bug 42283: Tidy all script tags - cataloguing (auto tidy) Signed-off-by: Paul Derscheid Signed-off-by: Jan Kissig Signed-off-by: Pedro Amorim commit 0aeb26417e4e85a16a6ce8658f4050c340d02487 Author: Jonathan Druart Date: Mon Mar 30 13:14:54 2026 +0200 Bug 42283: Tidy all script tags - cataloguing In order to tidy all the script tags of the .tt files we isolate the interpolation of Template::Toolkit variables in a separate script tag. This patch focuses on the cataloguing module. The 3 main changes are in the following files: * addbooks.tt * additem.tt * concerns.tt There are non-trivial changes in concerns.tt. You need to create several authorised values for TICKET_STATUS, turn on CatalogConcerns and OpacCatalogConcerns, create several concerns and go to /cgi-bin/koha/cataloguing/concerns.pl Confirm that the filters are working correctly Note that cataloguing/addbiblio.tt is on a separate bug (bug 42284) Signed-off-by: Paul Derscheid Signed-off-by: Jan Kissig Signed-off-by: Pedro Amorim commit 59888838980c4d5c058f23d33b9f389540427012 Author: Jan Kissig Date: Fri Jun 5 08:28:18 2026 +0000 Bug 42282: (QA follow-up) Split JS to TT block in results, auto tidy Splits JS to TT and non TT block. Auto tidy Signed-off-by: Pedro Amorim commit c9bfc6602631553b1408c346cdd605bd0fa3729c Author: Jan Kissig Date: Fri Jun 5 07:33:01 2026 +0000 Bug 42282: (QA follow-up) Split JS to TT block in advsearch, auto tidy Splits JS to TT and non TT block. Auto tidy Signed-off-by: Pedro Amorim commit a0c2e806785d1553f0c76ab0185b787cf6cee174 Author: Jan Kissig Date: Thu Jun 4 11:19:44 2026 +0000 Bug 42282: (QA follow-up) restore searchid in stockrotation This patch sets the TT param searchid to enable browsing though search results on stockrotation. Signed-off-by: Pedro Amorim commit 3bf91a73dcc80d9554f025b045d330fefde778a4 Author: Jan Kissig Date: Thu Jun 4 08:42:03 2026 +0000 Bug 42282: (QA follow-up): Fix call of HTML5MediaEnabled and HTML5MediaSets.size This switches the assignment of Koha.prefs.HTML5MediaEnabled from a non existant template param HTML5MediaEnabled to Koha.Preference('HTML5MediaEnabled'). Also a straying template param HTML5MediaSets.size was left in a JS block. Signed-off-by: Pedro Amorim commit 8147f968aacb507b30040515d38458ce79cac5a7 Author: Jonathan Druart Date: Tue May 5 14:13:03 2026 +0200 Bug 42282: Avoid JS error Fix conflict with "Bug 42177: bundlesEnabled fix" SyntaxError: redeclaration of const bundlesEnabled Signed-off-by: Jan Kissig Signed-off-by: Pedro Amorim commit 9db99a08e2f490df0e029705928c8277dbf0a959 Author: Paul Derscheid Date: Fri Apr 17 11:43:33 2026 +0200 Bug 42282: (follow-up) Switch Coce timeout log to console.warn qa script flags the stray console.log in the Coce wait-for-images helper under forbidden_patterns. The line is a genuine soft-failure diagnostic (Coce never resolved after 5s), matching the console.warn pattern used for AJAX failures elsewhere in the staff templates. To test: - qa script no longer flags forbidden_patterns on detail.tt. - With IntranetCoce enabled but Coce unreachable, loading a biblio logs "Could not retrieve the images" as a warning after ~5s. Signed-off-by: Paul Derscheid Signed-off-by: Jan Kissig Signed-off-by: Pedro Amorim commit 774c8d1e94bdb02626bcab2492a02ffea155e604 Author: Paul Derscheid Date: Fri Apr 17 10:50:10 2026 +0200 Bug 42282: (follow-up) Fix broken mailto concatenation in Elasticsearch 404 modal The port folded the admin email into a single string literal " " so the href became the literal text "mailto: + Koha.prefs..." instead of mailto:. Close the string and concatenate Koha.prefs.KohaAdminEmailAddress. To test: - Set KohaAdminEmailAddress syspref. - SearchEngine = Elasticsearch, open a biblio detail page. - Trigger the Elasticsearch preview with a bad id so the 404 branch renders, and confirm the "Send email" link points at mailto:. Signed-off-by: Paul Derscheid Signed-off-by: Jan Kissig Signed-off-by: Pedro Amorim commit f645702cd80b4b0f21108852bcda5293d8b93ab8 Author: Jonathan Druart Date: Tue Apr 7 12:14:15 2026 +0200 Bug 42282: Tidy all script tags - catalogue (auto tidy) Signed-off-by: Paul Derscheid Signed-off-by: Jan Kissig Signed-off-by: Pedro Amorim commit ee299e4b863de61ceb6f515ccb21fc4ec43e8a7a Author: Jonathan Druart Date: Mon Mar 30 12:58:13 2026 +0200 Bug 42282: Tidy all script tags - catalogue In order to tidy all the script tags of the .tt files we isolate the interpolation of Template::Toolkit variables in a separate script tag. This patch focuses on the catalogue module. The 7 main changes are in the following files: * ISBDdetail.tt * MARCdetail.tt * detail.tt * imageviewer.tt * labeledMARCdetail.tt * moredetail.tt * stockrotation.tt Several identical changes (logged_in_user_borrowernumber, searchid, biblio_id, browser, etc.) detail.tt needs to be tested a bit more thoroughly but the changes are still trivial. Signed-off-by: Paul Derscheid Signed-off-by: Jan Kissig Signed-off-by: Pedro Amorim commit ea62f3b835e4044d73b8ed576f8b2aee1344a630 Author: Owen Leonard Date: Fri Aug 15 16:18:46 2025 +0000 Bug 40610: Update OPAC templates to improve ease of translation This patch updates the markup structure of some OPAC include files in order to make the translation process easier. To test, apply the patch and test that the correct strings are translatable. In this example I'm testing fr-FR: - Update a translation: > gulp po:update --lang fr-FR > perl misc/translator/translate update fr-FR - Open the corresponding .po file for the strings pulled from the include file and locate the updated strings. - misc/translator/po/fr-FR-messages.po - opac-tmpl/bootstrap/en/includes/biblio-title.inc lines 4 & 5 - opac-tmpl/bootstrap/en/includes/date-format.inc lines 4, 6, 8 - opac-tmpl/bootstrap/en/includes/holds-table.inc lines 132 & 135 - opac-tmpl/bootstrap/en/includes/masthead.inc line 498 - misc/translator/po/fr-FR/fr-FR-opac-bootstrap.po - opac-tmpl/bootstrap/en/includes/biblio-title-head.inc - opac-tmpl/bootstrap/en/includes/holds-table.inc line 129 & 141 - Edit the "msgstr" string however you want (it's just for testing). - Remove the "fuzzy, " text if it's there. - Install the updated translation: > perl mis/translator/translate install fr-FR - Switch to your translated language in the OPAC. - Confirm that the strings you translated show up correctly on these pages: - The page title when viewing a bibliographic record detail page for a record without a title. - On a user summary page, under the hold tab: - A hold that is waiting - A hold that is in transit - In Administration -> Identity providers define a new identity provider (it doesn't have to be functional). - In the OPAC, test that the "Log in with [identity provider]" link is correct in each of the three login forms: - The modal triggered from the link in the header - The form in the right-hand sidebar - The form you see if you navigate directly to a user-related page e.g. /cgi-bin/koha/opac-user.pl - The changes to date-format.inc are only visible if JS is turned off because Flatpickr hides the format hint when it loads. Sponsored-by: Athens County Public Libraries Signed-off-by: Laura_Escamilla Signed-off-by: Jonathan Druart Signed-off-by: Pedro Amorim commit f7941aee28e23d0085f49f4b8f11a034608c9b48 Author: Jan Kissig Date: Fri May 29 10:58:00 2026 +0000 Bug 42278: (QA follow-up) Fix HIGHHOLDS to JSON serialisation Using Koha::Template::Plugin::To to serialize HIGHHOLDS to JSON led to the following error: Template process failed: undef error - encountered object '2026-05-31T23:59:00', but neither allow_blessed, convert_blessed nor allow_tags settings are enabled (or TO_JSON/FREEZE method missing) at /kohadevbox/koha/Koha/Template/Plugin/To.pm line 32. This patch fixes the handling of HIGHHOLDS. Signed-off-by: Pedro Amorim commit e0aee23fc16335e3ad02ed76eaf049d8c2aa01fa Author: Jan Kissig Date: Thu May 28 10:26:45 2026 +0000 Bug 42278: (QA follow-up) Fix Uncaught TypeError in request-article This fixes an Uncaught TypeError when searching for a patron and the search only returns a single patron. To test: a) go to /cgi-bin/koha/circ/request-article.pl?biblionumber=262 b) ienable dev tools console c) enter 'acev' and click Search d) The following error appears: Uncaught TypeError: can't access property "on", patrons_table is undefined e) apply patch and redo a) to c). The error is not thrown. Signed-off-by: Pedro Amorim commit c379c8301da713771aa84ce682e4ce28973589f1 Author: Jan Kissig Date: Thu May 28 10:19:42 2026 +0000 Bug 42278: (QA follow-up): Split JS to separate TT and tidy This puts ArticleRequestsSupportedFormats in a separate script tag. Auto tidy Signed-off-by: Pedro Amorim commit 0361fee0e447b5dba2918b7d771e2db602435458 Author: Paul Derscheid Date: Fri Apr 17 09:29:41 2026 +0200 Bug 42278: (follow-up) Guard bare-RHS TT interpolations Several unquoted const assignments rendered to `const X = ;` when their TT expression was empty (patron.borrowernumber without a patron, CAN_user_circulate_manage_bookings absent, or the AlwaysLoadCheckoutsTable syspref unset). The parser aborted the whole script block, so has_patron, AlwaysLoadCheckoutsTable, etc. were never defined and later scripts failed with ReferenceError. Add TT fallbacks so the RHS is always a valid JS literal. To test: - /cgi-bin/koha/circ/circulation.pl with no patron → no console errors - Search a patron, check out an item → still works Signed-off-by: Paul Derscheid Signed-off-by: Jan Kissig Signed-off-by: Pedro Amorim commit 72443454b2afc7965a2c0265c022267bbb541ce8 Author: Paul Derscheid Date: Fri Apr 17 09:26:39 2026 +0200 Bug 42278: (follow-up) Restore findborrower autofocus when no patron loaded The JS port inverted the original UNLESS condition, so the patron search field was focused only after a patron was already selected. Flip back to !borrowernumber. To test: - /cgi-bin/koha/circ/circulation.pl with no patron → cursor in findborrower - Select patron, reload → no focus jump Signed-off-by: Paul Derscheid Signed-off-by: Jan Kissig Signed-off-by: Pedro Amorim commit 7cca8e81a2257e556a8236a500cd8bb7ca83f455 Author: Jonathan Druart Date: Fri Apr 3 11:36:28 2026 +0200 Bug 42278: Tidy all script tags - circ (auto tidy) Signed-off-by: Paul Derscheid Signed-off-by: Jan Kissig Signed-off-by: Pedro Amorim commit 650a8d8a64561bedc424bb6cd0ee83b7c10ffa79 Author: Jonathan Druart Date: Mon Mar 30 09:51:06 2026 +0200 Bug 42278: Tidy all script tags - circ In order to tidy all the script tags of the .tt files we isolate the interpolation of Template::Toolkit variables in a separate script tag. This patch focuses on the circulation module. The 4 main changes are in the following files: * circulation.tt As expected this one is messy to test, we need to look at the diff and make sure the different features linked with the variables moved at still working correctly (yes, it's vague!) * circulation_batch_checkouts.tt On the batch checkout table the due date hidden input should have the value of the return date high demand items. * overdue.tt On the overdue report view, the "Return claims" column must be hidden if ClaimReturnedLostValue is not set. * transfers_to_send.tt The transfers to send view should show all libraries Signed-off-by: Paul Derscheid Signed-off-by: Jan Kissig Signed-off-by: Pedro Amorim commit acfd02af12de1221282498fea14fe1013fc6a0ac Author: Pedro Amorim Date: Tue May 19 14:28:50 2026 +0000 Bug 41950: (QA follow-up): Add more tests The tests were lacking a 'real' scenario proving the sorting on a _counts works at the DB level prove t/Koha/REST/Plugin/Query.t Signed-off-by: Pedro Amorim commit 713c5c33431d6c6f52f21bb2fae71fb671ae3b9c Author: Tomás Cohen Arazi Date: Tue May 12 10:11:33 2026 -0300 Bug 41950: (follow-up) Add DBIC relationship aliases for +count embeds Adds DBIC relationship aliases so that +count embeds advertised in the API specs are backed by actual database relationships, making them sortable via the SQL COUNT subquery infrastructure. New aliases: - Borrower: checkouts (issues) - Aqbookseller: baskets (aqbaskets), invoices (aqinvoices) - Ticket: updates (ticket_updates) - ErmEholdingsPackage: resources (erm_eholdings_resources) - Biblio: holds (reserves) Koha methods are updated to use the new relationship names directly, following the one-liner style: Koha::Foo->_new_from_dbic( scalar ... ) Note: checkouts on Borrower and subscriptions on Aqbookseller already had matching DBIC relationships. comments on Illrequest, requests on IllBatch, and items on Biblio also already existed. Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/Koha/REST/Plugin/Query.t \ t/db_dependent/api/v1/patrons.t \ t/db_dependent/api/v1/acquisitions_vendors.t \ t/db_dependent/Koha/REST/Plugin/Objects.t \ t/db_dependent/Koha/Biblio.t => SUCCESS: All tests pass 3. Verify sorting works: GET /api/v1/patrons x-koha-embed: checkouts+count _order_by: -me.checkouts_count => SUCCESS: Patrons sorted by checkout count 4. Sign off :-D Assisted-by: Sonnet 4.6 (Anthropic) Signed-off-by: Pedro Amorim commit e51334604fc61ecdf259686e778ba31a94697fe2 Author: Tomás Cohen Arazi Date: Fri Feb 27 12:31:30 2026 -0300 Bug 41950: Make +count embeds sortable via SQL COUNT subqueries Currently, +count embeds (e.g. claims+count) are computed in Perl via $object->$relation->count during to_api serialization. This means they cannot be used in _order_by and each count triggers a separate SQL query per row (N+1). This patch makes dbic_merge_prefetch detect +count embeds and, when a matching DBIC relationship exists, inject a correlated COUNT subquery via +select/+as instead of adding a prefetch. The order_by entries referencing count aliases are fixed up to strip the me. prefix, since +as aliases are virtual columns not bound to a table. In to_api, the is_count handler now checks for the pre-computed column via get_column before falling back to the Perl-level ->count call. This preserves backward compatibility for Koha-level methods that don't have a corresponding DBIC relationship. Test plan: 1. Apply patches 2. Run: $ ktd --shell k$ prove t/Koha/REST/Plugin/Query.t \ t/db_dependent/Koha/Object.t \ t/db_dependent/Koha/REST/Plugin/Objects.t => SUCCESS: Tests pass! 3. Sign off :-D Signed-off-by: Tomás Cohen Arazi Signed-off-by: David Nind Signed-off-by: Pedro Amorim commit 9bab8989223a43678690c9b24d10cb73cad6884f Author: Tomás Cohen Arazi Date: Fri Feb 27 12:31:20 2026 -0300 Bug 41950: Unit tests for sortable +count embeds Add tests to verify that +count embeds produce +select/+as attributes instead of a prefetch, enabling SQL-level sorting by count columns. Signed-off-by: Tomás Cohen Arazi Signed-off-by: David Nind Signed-off-by: Pedro Amorim commit 1c9e5ed2195d5fd116e8fcef313ff9d0d98be54f Author: Marcel de Rooy Date: Mon Apr 13 11:01:23 2026 +0200 Bug 42321: Improve handling of empty Z3950/SRU search results Skips the empty results; only reports the 'real failures'. Includes adding a grand total of hits to the form. Some preliminary work to remove the hardcoded 20 results per target in the code. This is not yet a complete solution, but an improvement. The code in C4/Breeding needs a larger overhaul. (And there might be an issue on the Folio server side at LOC.) Test plan: Without this patch: Use the LOC SRU server (since if frequently generates errcode 61). Try the same search several times in a row (with Go). You probably will come across the "LOC SRU record x: 0" messages. (Random behavior.) Apply this patch. Repeat the above. Notice that you will sometimes see the error 61 (and the tip to refresh) but not the code 0 messages. Run t/db../Breeding.t Signed-off-by: Marcel de Rooy Signed-off-by: David Nind Signed-off-by: Lisette Scheer Signed-off-by: Pedro Amorim commit ea670561977db4355eb8ab05e19ee61e3c45c5bd Author: Olivia Reynolds Date: Tue Jun 9 09:41:48 2026 +0000 Bug 38621: Use GetPreparedLetter in EmailReport As with guided reports through the admin interface, this patch switches EmailReport to use the same function for processing templates. This gives patron emails sent via cronjobs access to the same variables as other report locations. Test plan: 1. Under Tools > Notices and Slips, create a new notice in the Reports module. Choose a code and a name, and under Email assign a subject and the following body: Date: [% today %] 2. Under Reports, create a new report from SQL with a name and the following query: SELECT 1 AS borrowernumber, 'to@example.com' AS email 3. Run the following command from the base of Koha, replacing CODE with the notice code created earlier, and ID with the report ID created earlier: misc/cronjobs/patron_emailer.pl -module report -from from@example.com -notice CODE -report ID 4. Verify that the report runs successfully, and the console output includes "Date:" on a line with nothing following it. 5. Apply patch. 6. Run the following command from the base of Koha, replacing CODE with the notice code created earlier, and ID with the report ID created earlier: misc/cronjobs/patron_emailer.pl -module report -from from@example.com -notice CODE -report ID 7. Verify that the report runs successfully, and the console output includes "Date:" on a line with the current time following it. 8. Run `prove t/db_dependent/Reports/Guided.t`, and verify it passes. Sponsored-by: Open Fifth Signed-off-by: David Nind Signed-off-by: Lisette Scheer Signed-off-by: Pedro Amorim commit cbbfa8c8d285ebaa6e8cec11754eb8c79c7cf35a Author: Olivia Reynolds Date: Fri Jun 5 12:40:50 2026 +0000 Bug 38621: Use GetPreparedLetter for report templates Previously, report templates were rendered using process_tt directly. This made the available variables inconsistent with other notices and slips. This patch switches to rendering report templates through the same function as other notices. To match the arguments to this system, this patch also makes the report system reference templates by their code rather than ID. Test plan: 1. Under Tools > Notices and Slips, create a new notice in the Reports module. Choose a code and a name, and under Email assign a subject and the following body: [% today %] [% FOREACH d IN data %] [% d.title %] [% END %] 2. Under Reports, create a new report from SQL with a name and the following query: SELECT * FROM biblio LIMIT 1 3. Create another report from SQL with a different name and the following query, specifying a runtime parameter: SELECT * FROM biblio WHERE 'a'=<> LIMIT 1 4. On the first report, select "Run with template" and choose the template created earlier. 5. Verify that the report runs successfully, and the output does not include the current date. 6. On the second report, select "Run with template" and choose the template created earlier. Choose "a" as the runtime parameter value when asked. 7. Verify that the report runs successfully, and the output does not include the current date. 8. Apply patch. 9. On the first report, select "Run with template" and choose the template created earlier. 10. Verify that the report runs successfully, and the output now includes the current date along with the fetched data. 11. Under the Download dropdown, select "Rendered template (...)". 12. Verify the downloaded file matches the report output. 13. On the second report, select "Run with template" and choose the template created earlier. Choose "a" as the runtime parameter value when asked. 14. Verify that the report runs successfully, and the output now includes the current date along with the fetched data. 15. Under the Download dropdown, select "Rendered template (...)". 16. Verify the downloaded file matches the report output. Sponsored-by: Open Fifth Signed-off-by: David Nind Signed-off-by: Lisette Scheer Signed-off-by: Pedro Amorim commit d77897c20391137ed55bda69170b2a6f71b0c855 Author: Jonathan Druart Date: Mon May 4 13:51:36 2026 +0200 Bug 42453: Remove warning [WARN] Use of uninitialized value $index_count in numeric ne (!=) at /kohadevbox/koha/about.pl line 899. Signed-off-by: David Nind Signed-off-by: Lisette Scheer Signed-off-by: Pedro Amorim commit a1f8f35b70ca95c012e2921a31fe9ce0c5721849 Author: Jonathan Druart Date: Mon May 4 13:48:18 2026 +0200 Bug 42453: Prevent 500 on the about page if elastic is not runing If the elastic countainer is stopped, the about page crashes with a 500 "No nodes are available" Test plan: Startup ktd with `--search-engine es8` Go to the about page Notice that the "Elasticsearch" line contains the version and "running" Stop the es container: `docker start koha-es-1` Refresh the about page => Without this patch you get the 500 => With this patch applied the page is rendered with: "Version: Unkown" and "Status: not running" Signed-off-by: David Nind Signed-off-by: Lisette Scheer Signed-off-by: Pedro Amorim commit 88fd58dd6c3f12fc3402fa5364bff89cf623d9a0 Author: Martin Renvoize Date: Tue May 19 16:49:35 2026 +0100 Bug 42645: Add tests for FallbackToSMSIfNoEmail with alternate email fields Verify that the SMS fallback in ModSuggestion() respects EmailFieldPrimary and EmailFieldPrecedence: a patron with smsalertnumber and an emailpro address (but no borrowers.email) must receive the notice by email, not SMS. Sponsored-by: OpenFifth Signed-off-by: David Nind Signed-off-by: Lisette Scheer Signed-off-by: Pedro Amorim commit 57e110ee2c563b1b233234a4ccfc4aaa89a80b27 Author: Martin Renvoize Date: Tue May 19 16:40:34 2026 +0100 Bug 42645: Use notice_email_address in ModSuggestion SMS fallback check The FallbackToSMSIfNoEmail transport selection in ModSuggestion() was checking $patron->email (the raw borrowers.email column) rather than $patron->notice_email_address, which respects the EmailFieldPrimary and EmailFieldPrecedence system preferences. Patrons with only emailpro or B_email set were incorrectly receiving suggestion status-change notices via SMS even when a valid email address was available. Sponsored-by: OpenFifth Signed-off-by: David Nind Signed-off-by: Lisette Scheer Signed-off-by: Pedro Amorim commit c0477bc9f1570fde67c0f8f3f66160e7f2e48a88 Author: Lucas Gass Date: Thu Jun 25 17:22:30 2026 +0000 Bug 42909: Use createdRow to add back suspend class To test: 0/ APPLY PATCH 1/ View a record with some holds on it 2/ Look at the holds table ( reserve/request.pl?biblionumber=32 ) 3/ Suspend at least one hold and notice the 'suspend' class on the 4/ Unsuspend the hold and notice the class is removed Signed-off-by: David Nind Signed-off-by: Emily Lamancusa Signed-off-by: Pedro Amorim commit fc5ce2dd7e0088a1dccb8e789eaa991269ebfb26 Author: Paul Derscheid Date: Thu Feb 26 18:09:54 2026 +0100 Bug 41946: Allow superlibrarians to set protected flag on patron creation Since bug 36085, the protected flag in a patron account was removed from the patron creation form, regardless of if the user is a superlibrarian. - Hoist $logged_in_user lookup before the edit_form block - Move superlibrarian capability checks after the block so they apply to all operations including patron creation To test: 1. Sign in as a superlibrarian 2. Go to Patrons > New patron > choose any category 3. Without this patch: the "Protected" yes/no field is missing from the "Library management" section 4. Apply this patch 5. Repeat step 2 - The "Protected" yes/no field is now visible 6. Create the patron with Protected set to "Yes" 7. Confirm the patron is saved as protected 8. Sign in as a non-superlibrarian with edit_borrowers permission 9. Repeat step 2 - The "Protected" field should still be hidden 10. Edit an existing patron as superlibrarian - The "Protected" field is visible and functional 11. Edit an existing patron as non-superlibrarian - The "Protected" field is hidden 12. Sign off Signed-off-by: Caroline Cyr La Rose Signed-off-by: Jonathan Druart Signed-off-by: Pedro Amorim commit 38cbe6b19503903307a42f6d0cdf272e5f590ab6 Author: Martin Renvoize Date: Mon Jan 26 10:12:03 2026 +0000 Bug 41709: Fix EDIfact special character escaping in GIR segments and other fields Apply encode_text function to all text fields in EDIfact Order messages to properly escape special characters (?, ', :, +) that could break message parsing. Previously only bibliographic description fields were escaped, but GIR segments containing collection codes, branch codes, item types, call numbers, and other data were vulnerable. Test plan: - Verify all existing tests pass - Added comprehensive tests for special character escaping in GIR segments - Confirmed that fields containing ?, ', :, + are properly escaped Sponsored-by: OpenFifth Signed-off-by: Laura_Escamilla Signed-off-by: Kyle M Hall Signed-off-by: Pedro Amorim commit b302481a4da694c97c8cb0a5fd03fd0abb7c0f6d Author: Kyle M Hall Date: Wed Jun 17 07:55:35 2026 -0400 Bug 42862: Use current-relative dates in bookingsModalDatePicker_spec.ts The booking date picker tests fake "today" with cy.clock and create bookings on hardcoded June 2026 dates. The modal fetches existing bookings from from the api and that query uses the real current time, not the fake one in the browser. Once the real date passes the hardcoded dates, the server stops returning those bookings ( they are now in the past ), so the modal sees no conflicts and assertions such as "the date should have the leadDisable class" fail. This patch anchors each test's "today" to the start of next month based on the current date so the bookings always stay in the future and are returned no matter when the test runs. The 'any item' test also sets cy.clock before its second page reload because the freeze does not survive the reload. Test Plan: 1) On main run: yarn cypress run --spec t/cypress/integration/Circulation/bookingsModalDatePicker_spec.ts 2) Note the test fails 3) Apply this patch 4) Run the command again 5) Note all tests pass! Signed-off-by: David Nind Signed-off-by: Lucas Gass Signed-off-by: Pedro Amorim