commit 6c0a50e14a41b041b5f2eea736a9f1e810ade695 Author: Hammat Wele Date: Tue Oct 6 15:23:06 2026 +0000 Bug 41419 - Error javascript undefined is not valid JSON when showing the order edit modal in orderreceive.tt To reproduce 1. Go to Acquisitions → New vendor, enter a name, check Vendor is Active, and click Save. 2. Click the name of the vendor you just created in the table. 3. Click New → Basket, enter a basket name, and click Save. 4. Click Add to basket → From a new (empty) record. Enter a title, add an item, and click Save. 5. Click Close basket. 6. Click Receive shipments, enter a number in the Vendor invoice field, and click Next. 7. Click Receive for the created line. 8. Open the browser console. 9. In the modal, tick the Receive? checkbox for all the lines, then click Confirm 10. Go to the previous page → The console shows the error: undefined is not valid JSON at JSON.parse was shown 11. Apply the patch 12. Go to Acquisitions → Search for the vandor created on step 2 13. Repeat step 3, 4, 5, 6, 7, 8, 9, 10 → There is no js error commit 048b1ddcf4f3865d78af4a36084c81b23bd99add Author: Martin Renvoize Date: Mon Nov 2 15:00:32 2026 +0000 Bug 43025: (QA follow-up) Add 400 response to metadata error DELETE xt/api.t requires every route to declare a 400 response whose description starts with 'Bad request' and which references #/definitions/error. The new DELETE route had none, so the bundled spec fell back to the default response and the '400 response tests' subtest failed. To test: 1. Run yarn api:bundle 2. Run prove xt/api.t => SUCCESS: All tests pass Co-Authored-By: Claude Sonnet 5.5 Signed-off-by: Pedro Amorim commit 8848a4e4c9b40b7a4f1a95409885e723293363d0 Author: Paul Derscheid Date: Mon Nov 2 15:28:07 2026 +0100 Bug 42790: (QA follow-up) Only load booking modals on circulation.pl with EnableBooking - circulation.tt included the booking modals and their JS regardless of EnableBooking, unlike moremember.tt - Wrap them in the same preference check Test plan: 1. Set EnableBooking to 'Disable' 2. Go to /cgi-bin/koha/circ/circulation.pl?borrowernumber=51 and view the page source 3. Without this patch extendBookingModal is found; with it, it is not 4. Set EnableBooking to 'Enable', reload: the modals are present and the Bookings tab works as before Assisted-by: Opus 5.5 (Anthropic) Signed-off-by: Paul Derscheid Signed-off-by: Pedro Amorim commit cbb9dcede77277d36b339617a8bd291060cccb44 Author: Paul Derscheid Date: Mon Nov 2 15:28:00 2026 +0100 Bug 42790: (QA follow-up) Escape the cancellation reason in the status badge - The reason is free text and statusBadge() put it into the badge markup unescaped - Pass it through escape_str() Test plan: 1. Make item type BK bookable and place a booking on biblionumber 1 2. Go to /cgi-bin/koha/bookings/list.pl?biblionumber=1 3. Cancel the booking with the reason BOLD 4. Click 'Include cancelled' 5. Without this patch the badge shows 'Cancelled: BOLD' in bold; with it, the literal text 'Cancelled: BOLD' Assisted-by: Opus 5.5 (Anthropic) Signed-off-by: Paul Derscheid Signed-off-by: Pedro Amorim commit 2cdfcc803d0a7e23ae938934531d9639f3bf45cc Author: Paul Derscheid Date: Mon Nov 2 15:27:52 2026 +0100 Bug 42790: (QA follow-up) Provide timezone-aware dayjs to the Extend modal spec - The spec imported dayjs without the utc/timezone plugins and never set the global dayjs extend_booking_modal.js relies on, so the first .tz() call threw - Extend utc/timezone and expose dayjs on window, as js-date-format.inc does on staff pages Test plan: 1. yarn cypress run --component --spec t/cypress/component/ExtendBookingModal_spec.ts 2. Without this patch it fails with ".tz is not a function"; with it, it passes Assisted-by: Opus 5.5 (Anthropic) Signed-off-by: Paul Derscheid Signed-off-by: Pedro Amorim commit df36de3ccd92dd7034bd9a44eb41f4d0029bb083 Author: Martin Renvoize Date: Thu Sep 10 17:21:46 2026 +0100 Bug 42790: (QA follow-up) Escape error messages in the extend booking modal showError() interpolated its message argument directly into innerHTML. One call site passes result.error, API response text, through unescaped, making this a stored/reflected XSS vector if the API ever echoes attacker-influenced content in an error message. Build the alert with textContent instead of a template literal. Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit 3e1510c0ac094aefc1817ba1de9d7d68bc17b41c Author: Martin Renvoize Date: Thu Sep 10 17:21:32 2026 +0100 Bug 42790: (QA follow-up) Log and surface errors when extending a booking's checkout The renewal request's error handler silently swallowed every network/transport failure (.catch(() => null)), making a genuine connection error indistinguishable from a legitimate 400 response. The success path's response.json() was also unguarded, bypassing the HttpClient hardening added elsewhere in this series entirely; a malformed 200 body would throw with nothing to catch it. Log the raw error in both cases, and on the success path fall back to just reloading the bookings table (the extension already succeeded server-side) rather than throwing when the response body can't be parsed. Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit fece021c0804214465152a67410be233c1aa1326 Author: Martin Renvoize Date: Thu Sep 10 17:21:14 2026 +0100 Bug 42790: (QA follow-up) Fail closed when the extend-booking conflict check errors The conflict-check fetch in the Extend booking modal had no error handling: a network error or non-OK response silently resolved to an empty booking list, so the date picker showed no disabled days and no maxDate cap as if there were no conflicting bookings at all. Staff could then pick a genuinely conflicting date, with only the server-side renewal check as a backstop. Fail closed instead: on any conflict-check failure, disable the Confirm button and show an inline error, re-enabling it the next time the modal opens for a new booking. Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit 80c11586492242baa0b0dba512f55c869a914ddc Author: Martin Renvoize Date: Wed Sep 9 09:02:52 2026 +0100 Bug 42790: (QA follow-up) Add test coverage for the Extend action extend_booking_modal.js (the picker's min/max/disable range from sibling bookings, timezone-anchored due-date submission) and the booking-aware Extend button had no test coverage, unlike the server-side renewal endpoint. Add a component spec covering the successful path and a booking-conflict error response. Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit b81626591b59f6fcdd23050beb37dd5aa96c43b8 Author: Paul Derscheid Date: Fri Jul 24 13:05:20 2026 +0200 Bug 42790: (QA follow-up) Anchor the extend picker to the library timezone and floor it after the due date The extend picker did all of its date maths in the browser's local timezone while the API talks in instants and staff-facing displays are rendered in the library's configured timezone ($timezone()). With the two zones apart, the day boundaries drift: the floor, the blocked booking ranges and the submitted end-of-day all land on the wrong calendar day (e.g. a due date of 07/30 23:59 library time producing a floor of 08/01 in a +02:00 browser). The picker also floored at today, so with a due date a week out every selectable day but the last few shortened the loan instead of extending it - while still consuming a renewal. And the native required attribute fought the picker: submitting with an empty field popped the browser's own validation bubble over the calendar instead of the modal's styled error. - do all calendar maths in the library's timezone and hand flatpickr display dates via $toDisplayDate, mirroring the place booking modal (bug 42868) - anchor the submitted end date to the end of the selected day in the library's timezone - floor the picker at the day after the checkout due date (today for overdue checkouts) so only genuine extensions are selectable - mark the form novalidate; the submit handler's styled error message already covers the empty field Test plan: 1. Book an item, check it out and open Extend on the issued row: the first selectable date is the day after the checkout due date, also when the browser and the Koha instance are in different timezones 2. Backdate the checkout due date into the past (or let it lapse) and confirm the picker floors at today instead 3. Extend and confirm checkout due date and booking end date land on 23:59 of the selected day in the instance timezone 4. Submit with an empty date: the styled 'Please select a new end date' message appears in the modal, no browser bubble Signed-off-by: Paul Derscheid Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit 6198e65e5c82c1a8f6184fdd0c181b53b4672710 Author: Paul Derscheid Date: Fri Jul 24 13:04:27 2026 +0200 Bug 42790: (QA follow-up) Key status badge classes by status code The badge class lookup matched startsWith() against the translated status text. UI logic keyed on translated strings breaks as soon as one status's translation is a prefix of another's; the API status code is the stable key. - key the class map by row.status and keep the translations purely for display Test plan: 1. Load the patron and biblio bookings tables and confirm the badges keep their colours (new green, issued blue, cancelled/completed grey) Signed-off-by: Paul Derscheid Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit c40239388b0a70044b44357eadbbb53e568a6902 Author: Paul Derscheid Date: Fri Jul 24 12:57:52 2026 +0200 Bug 42790: (QA follow-up) Only treat the booking's own checkout as linked The issued-row due date display and the Extend action trusted the item.checkout embed to be the checkout that collected the booking. A stale 'issued' booking whose item has since been checked out to somebody else would display - and offer to renew - the wrong patron's loan, and that renewal would not touch the booking at all (AddRenewal only syncs bookings linked via issues.booking_id). - resolve the linked checkout by matching checkout.booking_id against the booking before rendering the due date or offering Extend Test plan: 1. Book an item, check it out to its patron; the issued row still shows the checkout due date and the Extend action works as before 2. Clear the link (UPDATE issues SET booking_id = NULL WHERE issue_id = ...) and reload; the due date and Extend action disappear instead of acting on an unlinked loan Signed-off-by: Paul Derscheid Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit 8cd79982e7dd6356d3b9fcbfc1d7759cf42357a5 Author: Martin Renvoize Date: Mon Jul 6 08:56:47 2026 +0100 Bug 42790: Add booking-aware Extend action for issued bookings This patch adds an Extend action to the bookings tables for issued bookings, visible to users with the circulate permission on both the patron bookings tab and the biblio bookings page. The button opens a new modal showing the current booking end date and the current checkout due date, with a flatpickr date picker that: * blocks the date ranges of any other new or issued booking for the same item * caps the maximum selectable date at the day before the earliest subsequent booking starts On confirm, the extension is performed as a staff authorised renewal of the linked checkout - a single call to POST /api/v1/checkouts/{checkout_id}/renewal with the requested due_date and the renewal_limit override. The server validates the date against bookings for the item and keeps booking.end_date in sync with the renewed due date. Errors (clash with the next booking, renewal limits with overrides disabled) are displayed inside the modal without closing it, so staff can pick an earlier date. The Extend button only renders when the booking has a linked checkout to renew. Test plan: 1) Create a booking, check the item out to the patron (booking becomes issued) and confirm the Extend button appears on both the patron bookings tab and the biblio bookings page 2) Click Extend; confirm the modal shows the current end date and the checkout due date 3) Create a subsequent booking for the same item; re-open the modal and confirm its dates are blocked in the picker and dates beyond its start cannot be selected 4) Select a valid new date and confirm; verify both the booking end_date and the checkout due date are updated 5) Confirm the checkout now shows a renewal in its renewal history Sponsored-by: OpenFifth Sponsored-by: Westminster City Council Signed-off-by: Hannah Dunne-Howrie Signed-off-by: Paul Derscheid Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit e5486ef4d546105d5ca77fa6774fd90e59776029 Author: Martin Renvoize Date: Mon Jul 6 08:41:10 2026 +0100 Bug 42790: Unify booking actions and display across patron and biblio tables The patron bookings tab (moremember/circulation) and the biblio bookings page previously offered different actions and rendered status, item and action cells with duplicated, subtly different code. This patch introduces a shared rendering helper (js/bookings/common.js) used by both tables, delivering: * A unified action set gated on booking status and the logged in user's permissions: - new: Edit + Cancel (manage_bookings), Checkout (circulate) - issued: no edit/cancel actions (Extend follows in a later patch) - completed/cancelled: no actions * "Transform to checkout" on the biblio bookings page is renamed "Checkout" and the same shortcut is now offered from the patron bookings tab, posting the patron, barcode and booking end date through to the checkout screen * The patron bookings tab gains the Edit action, opening the same place booking modal used elsewhere (the modal markup and assets are now included on moremember and circulation pages) * For issued bookings, the Item column now also shows the checkout due date and a link to the checkout record (via the item.checkout embed, newly allowed on the biblio bookings endpoint) * New bookings whose collection window has opened are highlighted with table-info; new bookings whose window has passed without collection are highlighted with table-warning Both pages now expose their booking permissions through Koha.addPermissions rather than bare globals. Test plan: 1) yarn api:bundle && restart_all 2) Create a booking; confirm the patron bookings tab (patron details and checkout pages) shows Edit, Cancel and Checkout actions, and that the biblio bookings page shows the same 3) Confirm Edit opens the booking modal pre-populated on all pages 4) Click Checkout; the checkout is submitted with the patron, item and the booking end date as due date - confirm you land on the patron's checkout screen with the checkout made (or its confirmation pending, e.g. for an early collection) 5) Check out a booked item; confirm the Item column shows the due date and a link to the checkout on both displays 6) Create bookings with past start/end dates; confirm the row highlights appear on both displays Sponsored-by: OpenFifth Sponsored-by: Westminster City Council Signed-off-by: Hannah Dunne-Howrie Signed-off-by: Paul Derscheid Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit 09ca978ca47862b193c4cd6a4aaccfaa82176f60 Author: Martin Renvoize Date: Mon Jul 6 10:22:26 2026 +0100 Bug 42790: Add missing Scalar::Util import in Koha::REST::V1::Bookings The error handling in add() already calls blessed() but the module never imported it, so hitting the Koha::Exceptions::Booking::Clash catch branch died with an undefined subroutine error (masked as a 500 either way, but for the wrong reason). Test plan: 1) prove t/db_dependent/api/v1/bookings.t Sponsored-by: OpenFifth Sponsored-by: Westminster City Council Signed-off-by: Hannah Dunne-Howrie Signed-off-by: Paul Derscheid Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit 15a35531c73eca351e59c4743068756f08ba0dbf Author: Martin Renvoize Date: Wed Jul 8 12:47:50 2026 +0100 Bug 43029: Guard maintenance scripts against biblios with corrupt metadata sanitize_records.pl and touch_all_biblios.pl both read a biblio's metadata record and unconditionally re-save it. Since Koha::Biblio::Metadata->record()/store() can now throw Koha::Exceptions::Metadata::Invalid for a record that was already corrupt before bug 35104 existed, wrap the read (and, for touch_all_biblios.pl, the resulting ModBiblio) so one such biblio is skipped and reported rather than aborting the whole maintenance run. Signed-off-by: Baptiste Bayche Signed-off-by: Baptiste Wojtkowski Sponsored-by: OpenFifth Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit ccc165a177a57600e8e6282dc0c0f8ed3bab9f04 Author: Martin Renvoize Date: Mon Oct 12 11:33:43 2026 +0100 Bug 43027: (QA follow-up) Handle undecodable metadata when displaying the merge form Loading the merge form decoded each record with $biblio->metadata->record, so a record with undecodable metadata produced a raw exception trace. Koha::Biblio::Metadata->record now repairs recoverable faults itself and saves the repair along with an error row for each fault (bug 43777), so a record that was already corrupt is shown with a warning listing the faults recorded for it. Metadata that cannot be repaired at all aborts the merge with an error naming the record, instead of a stack trace. The reference record's leader and the merge report no longer throw either. Sponsored-by: OpenFifth Co-Authored-By: Claude Sonnet 5.5 Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 0e48a2a69f0a1971cb794566ea95438fa72e569d Author: Martin Renvoize Date: Wed Jul 8 12:45:04 2026 +0100 Bug 43027: Handle undecodable metadata gracefully when merging bibliographic records Merging into a reference record calls ModBiblio, which can now throw Koha::Exceptions::Metadata::Invalid (bug 35104). Catch it, abort the merge (the reference record was not modified, so nothing has been merged away yet) and show the cataloguer why, instead of a raw exception or - worse - a partially-applied merge. Recoverable faults fixed during the merge are shown as a warning instead, same as the cataloguing edit form. Signed-off-by: Baptiste Bayche Signed-off-by: Baptiste Wojtkowski Sponsored-by: OpenFifth Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit a1ed4c6a8609c117ce8f2c0090b904b3a5f46e87 Author: Martin Renvoize Date: Wed Sep 2 12:54:15 2026 +0000 Bug 43026: Show the repairs made on read on the biblio detail and MARC detail pages The detail page fell back to a raw exception dump plus a hand-rolled StripNonXmlChars when a record was already undecodable, and the MARC detail page had no handling at all. Koha::Biblio::Metadata->record now repairs recoverable faults itself and saves the repair along with an error row for each fault (bug 43777), so the "Data quality warnings" banner already lists them on every view, not only on the one that did the repair. Both pages read the record before looking up those errors. Only metadata that cannot be repaired at all still shows the raw decoding error and degrades the view. Sponsored-by: OpenFifth Co-Authored-By: Claude Sonnet 5.5 Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 3e80708c4be1e5144375c8bbcef49ac8c3e16faa Author: Martin Renvoize Date: Wed Jul 8 12:44:27 2026 +0100 Bug 43026: Show metadata repair warnings on the biblio detail and MARC detail pages Cataloguers reviewing a record via catalogue/detail.pl or catalogue/MARCdetail.pl (rather than the edit form) had no way to know a record had been automatically repaired on last save (see bug 35104). List any unresolved biblio_metadata_errors as a warning banner on both pages. The banner is the shared metadata_repairs.inc (bug 43025), so it looks the same as the one in the cataloguing editor. Signed-off-by: Baptiste Bayche Signed-off-by: Baptiste Wojtkowski Sponsored-by: OpenFifth Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 82ebd8f097d16756b62dea53408280dd62a37421 Author: Martin Renvoize Date: Wed Sep 2 11:26:21 2026 +0000 Bug 43025: Show the repairs made on read when loading an already-corrupt record The cataloguing edit form load path fell back to record_strip_nonxml and a raw exception dump when a record was already undecodable before it could be opened for editing. That gave a much less useful message than the per-fault breakdown this bug already shows for faults introduced or fixed during a fresh save. Koha::Biblio::Metadata->record now repairs recoverable faults itself and saves the repair along with an error row for each fault (bug 43777), so the "Data quality warnings" list, with its links to the affected fields and its "Mark resolved" buttons, already shows them on every load, not only on the one that did the repair. Drop the separate, transient list built from object_messages, which would only repeat them, and say in the notice that the problems were repaired when saved or loaded. The list is now rendered by a new metadata_repairs.inc, taking the error rows directly, so the other pages that need to show the same thing (see the bugs depending on this one) can share it instead of each carrying their own copy. It shows one row per fault: the field, what was wrong, and where, with the offending character and its pointer kept on their own lines so it is still clear where it was. Only metadata that cannot be repaired at all still ends up as an error, and the message says the record cannot be loaded rather than claiming characters were stripped. Based-on-patch-by: Nick Clemens Sponsored-by: OpenFifth Co-Authored-By: Claude Sonnet 5.5 Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 7090b649e4e099f0447b8304cf9802a7bdd9e2ab Author: Martin Renvoize Date: Wed Jul 8 12:43:23 2026 +0100 Bug 43025: Show metadata repair warnings and existing errors in the cataloguing edit form Surfaces bug 35104's exception/recovery behaviour where cataloguers actually encounter it - saving a record: - If the record is unrecoverable, AddBiblio/ModBiblio's Koha::Exceptions::Metadata::Invalid is caught and shown instead of a generic error, with the form re-displayed so nothing is lost. - If the record was recoverable but modified, the save proceeds and a warning banner explains what was automatically fixed (via the new warnings option on AddBiblio/ModBiblio). - Any pre-existing (not yet resolved) errors on the record are listed when opening it for editing, each with a quick-link to the affected field (where the field survived the repair) and a "Mark resolved" action calling the new REST DELETE endpoint. Signed-off-by: Baptiste Bayche Signed-off-by: Baptiste Wojtkowski Sponsored-by: OpenFifth Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 9227fa64a2810ad1528b5dbf0caa69ba5a4cc6cc Author: Martin Renvoize Date: Wed Jul 8 12:43:01 2026 +0100 Bug 43025: Add REST endpoint to resolve a biblio metadata error Adds DELETE /api/v1/biblios/{biblio_id}/metadata/errors/{error_id} to mark a recorded metadata fault (see bug 35104) as resolved. Deletion is scoped through the biblio's own metadata_errors relation, so an error_id belonging to a different biblio correctly 404s rather than being deletable cross-biblio. Signed-off-by: Baptiste Bayche Signed-off-by: Baptiste Wojtkowski Sponsored-by: OpenFifth Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 251cc5d2177e83665efbf0bce80989fbab938563 Author: Jonathan Druart Date: Mon Nov 2 10:20:01 2026 +0100 Bug 30557: Fix xt/check-thead-tt-tags.t failures Signed-off-by: Pedro Amorim commit c3c7124b8e21721787d0b7537fc97e81c62fd2eb Author: Jonathan Druart Date: Mon Nov 2 10:29:19 2026 +0100 Bug 31391: Remove conditional TT tag from thead Fixes xt/check-thead-tt-tags.t # Failed test 'Table 'item_lists/items/items' in koha-tmpl/intranet-tmpl/prog/en/modules/recalls/request.tt has conditional TT tags in thead' # at xt/check-thead-tt-tags.t line 161. Signed-off-by: Pedro Amorim commit 16ac30e6a0c57b5c69a972ab24f7e817dea2717f Author: Paul Derscheid Date: Fri Oct 30 17:25:25 2026 +0100 Bug 42998: (QA follow-up) Describe what the renewal_limit override bypasses Assisted-by: Claude Opus 5.5 (Anthropic) Signed-off-by: Paul Derscheid Signed-off-by: Pedro Amorim commit 912deb7f4f77b027bba84b9764ce0eeeeed48cba Author: Paul Derscheid Date: Fri Oct 30 17:24:11 2026 +0100 Bug 42998: (QA follow-up) Log the renewal_limit override in the renewal log The staff interface records RENEWAL_LIMIT in the renewal log's confirmations when the limit is overridden. The API passed none, so overrides made through it left no audit trail. - Pass RENEWAL_LIMIT to AddRenewal when the override is in effect, as circ/renew.pl does - Test both the overridden and plain renewal log entries Test plan: 1. prove t/db_dependent/api/v1/checkouts.t Assisted-by: Claude Opus 5.5 (Anthropic) Signed-off-by: Paul Derscheid Signed-off-by: Pedro Amorim commit 311922ed09ebc682d8bea463fdccbd87d91f20ee Author: Martin Renvoize Date: Thu Sep 10 17:24:05 2026 +0100 Bug 42998: (QA follow-up) Document error_code values on the renew endpoints The requested-due-date work added error_code to the renew endpoints' 400/403 responses (Checkouts.pm's render_invalid_parameter_value and the CanBookBeRenewed error passthrough), but the swagger docs still just said "Bad request" / "Cannot renew checkout". Enumerate the values, matching the style already used for the booking endpoints in this same series. Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit d99e9ecf9d06c7fcdf3497f88f6fc78dbfb2cdb7 Author: Martin Renvoize Date: Wed Sep 9 09:02:29 2026 +0100 Bug 42998: (QA follow-up) Reject a malformed requested due_date cleanly A due_date that passes the swagger date-time format check (which permits an instant with no timezone offset) but fails Koha's own stricter RFC3339 parser was falling through to dt_from_string's uncaught exception, producing a generic 500 instead of a clear 400. Wrap the parse and return render_invalid_parameter_value on failure, and cover it with a test. Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit 51d44ee253946a079df69ebe98ee3a9d46aa0857 Author: Martin Renvoize Date: Mon Jul 6 10:22:09 2026 +0100 Bug 42998: Allow a requested due date on the checkout renewal endpoints This patch extends the checkout renewal endpoints so API consumers can renew a checkout through to a specific date, providing the server-side pathway for extending issued bookings through their linked checkout (bug 42997, bug 42790): * an optional request body may carry a `due_date` (RFC3339); it is passed through to CanBookBeRenewed - so it is validated against bookings for the item - and then to AddRenewal, which keeps any linked booking's end_date in sync * a new `renewal_limit` value is accepted in the x-koha-override header, skipping renewal count limits when AllowRenewalLimitOverride is enabled - staff extending a booked loan should not be blocked by the renewal count * the 403 error response now carries the CanBookBeRenewed error as a machine-readable `error_code` (e.g. 'booked', 'too_many') Both /checkouts/{checkout_id}/renewal and the newer /checkouts/{checkout_id}/renewals route to the same controller, so the body and override are accepted and documented on both. The requested due date is a body attribute rather than a query parameter or override: the POST creates a renewal resource and the date is data about that renewal. The existing 'seen' query parameter predates the current guidelines and has been left untouched. Test plan: 1) yarn api:bundle && restart_all 2) Run t/db_dependent/api/v1/checkouts.t and confirm the new 'renew() with requested due_date and bookings' subtest passes Sponsored-by: OpenFifth Sponsored-by: Westminster City Council Signed-off-by: Hannah Dunne-Howrie Signed-off-by: Paul Derscheid Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit 2370b516ed4f89b0d42179afa49f261ccf5710a3 Author: Jonathan Druart Date: Fri Oct 30 18:09:44 2026 +0100 Bug 38185: Fix Cypress paging selectors The new layout does not create the '.top.pager' wrapper any more, the paging buttons are inside '.dt-paging'. Co-Authored-By: Claude Sonnet 5.5 Signed-off-by: Pedro Amorim commit 42c2ef0b46ee86bc40b842521cfd5a2a726588a9 Author: Jonathan Druart Date: Tue Sep 15 10:43:27 2026 +0200 Bug 38185: Explode if deprecated DataTable options are passed to kohaTable 'dom' and 'pagingType' were replaced by 'layout' and 'tableFeatures' Other deprecated options should be excluded as well Signed-off-by: Pedro Amorim commit 3b13cf58619cba84a8c15c0e2035e4ac186dbc94 Author: Jonathan Druart Date: Tue Sep 15 10:36:55 2026 +0200 Bug 38185: Fix new occurrence in recalls/request.tt Signed-off-by: Pedro Amorim commit d0b49a617dbeaac3568a54649d4544910daef332 Author: Jonathan Druart Date: Thu Aug 27 16:24:16 2026 +0200 Bug 38185: Remove paging if pagination is not displayed Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 8fa76de98485653ff347f83fec366fe2bbf707b3 Author: Jonathan Druart Date: Thu Aug 27 12:47:46 2026 +0200 Bug 38185: Remove more 'dom' occurrences Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 908a886c9731185fd13b4febb3520a351264219e Author: Jonathan Druart Date: Thu Aug 27 12:38:23 2026 +0200 Bug 38185: (follow-up) Fix search clear icon position at narrow widths Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 4126b5d64e977f6577953b7af10bfb59d5d267a6 Author: Owen Leonard Date: Fri Jun 26 10:05:13 2026 -0400 Bug 38185: (follow-up) Additional CSS cleanup Signed-off-by: Owen Leonard Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 19778883e108d0d8b70061d1453bce1c352ded02 Author: Owen Leonard Date: Thu Jun 25 15:01:13 2026 -0400 Bug 38185: (follow-up) Hide "First" and "Last" links at narrow widths Signed-off-by: Owen Leonard Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit f719a90bd0592f4e5ada1f86490afe2d8961d8b2 Author: Jonathan Druart Date: Thu Jun 25 12:14:15 2026 +0200 Bug 38185: Move buttons to the right Signed-off-by: Owen Leonard Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 2279111057f1c1a64f5dfa1eb375079e2e88d938 Author: Jonathan Druart Date: Fri Apr 17 12:08:48 2026 +0200 Bug 38185: Remove pagingType and introduce tableFeatures pagingType is deprecated and will be removed in DT v3 https://datatables.net/reference/option/pagingType `pagingType: full_numbers` was the default, and 'full' was used in several places full_numbers is: First, Previous, Pages numbers, Next, Last full is: First, Previous, Next, Last I don't think it makes sense to keep 'full', if there are many pages the user cannot navigate correctly. This patch removes full and makes full_numbers the default. tableFeatures can now be passed to the kohaTable constructor with a list of features to include: info, search, paging, buttons. If not passed, all features will be added. If passed but empty, none will be added. Note that the UI has slightly changed on 3 tables: admin/credit_types.tt admin/debit_types.tt members/boraccount.tt Where the filters are now above the table's wrapper container. We could restore this later, but more work is needed. It feels like a separate work where we will uniformize the filters for all tables. Signed-off-by: Owen Leonard Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 368bd7bbb25b1e34367f7f8ef24384d98238ee14 Author: Jonathan Druart Date: Tue Apr 14 14:57:08 2026 +0200 Bug 38185: Restore display of First/Last buttons Signed-off-by: Owen Leonard Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 506b24693cb020deba04fb5af1cd02d75895edce Author: Owen Leonard Date: Wed Jul 30 13:15:07 2025 +0000 Bug 38185: Try to match current DataTable style using new layout option Signed-off-by: Owen Leonard Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 62b5ab1ee13e4608872997cef7d04e629203eb8d Author: Jonathan Druart Date: Tue Jul 29 14:34:18 2025 +0200 Bug 38185: DataTables - Replace 'dom' with 'layout' Signed-off-by: Owen Leonard Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 404eae72ff39c0c271678635f37a27c296b2af7d Author: Jonathan Druart Date: Fri Oct 30 17:10:09 2026 +0100 Bug 42925: (follow-up) Adjust KohaTable Cypress tests for the clear icon The 'Clear filter' button was replaced with an icon inside the search box (.dt-search-clear, toggled with the 'visible' class). Co-Authored-By: Claude Sonnet 5.5 Signed-off-by: Pedro Amorim commit 8c58c015735bb850cdfefed437c5ea359d53e663 Author: Owen Leonard Date: Fri Oct 30 12:39:13 2026 -0400 Bug 42925: (follow-up) Adjust position of the X icon Signed-off-by: Owen Leonard Signed-off-by: Pedro Amorim commit 5b16093a8effdb86de8673d08723ada0a6dcfa08 Author: Jonathan Druart Date: Fri Oct 30 15:03:03 2026 +0100 Bug 42925: (follow-up) Prevent clear button from following '#' link Signed-off-by: Pedro Amorim commit 68b915f4093c963ba21c794e2575e4d6ae29a23c Author: Owen Leonard Date: Thu Jun 25 08:10:42 2026 -0400 Bug 42925: (follow-up) Make clear button focusable Signed-off-by: David Nind Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit edf8731f18f95f5f01b08e9ed54342e3a2cf7ab2 Author: Jonathan Druart Date: Fri Jun 26 10:08:06 2026 +0200 Bug 42925: Replace the 'clear' button with an icon inside the search box On Chrome there is a builtin 'x' in the search box. The "Clear filter" button is then not needed. However it does not exist for Firefox. We could disable the builtin feature in Chrome add our own, so all browsers have it. Then the "Clear filter" button will no longer be needed. Test plan: 0. Rebuilt the CSS files: % yarn css:build Refresh the browser's cache, or use a private window Then, with both Firefox and Chrome (and any others web browsers you have): 1. Go to /cgi-bin/koha/admin/branches.pl => Notice that the "Clear filters" button is gone 2. Start typing in the global search => The table filters => The "x" icon is there when the input is not empty 3. Copy shareable link 4. Click the "x" icon => The table refreshes => The "x" is no longer visible 5. Use the shareable link => The global search is there => The "x" icon is visible Signed-off-by: David Nind Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit f1e8a24e223abcbccaf00317fdb1de5c45411ffb Author: Owen Leonard Date: Thu Aug 13 12:27:33 2026 -0400 Bug 43293: (follow-up) Make the same change to two other buttons There are also confirm buttons for pay_individual and writeoff_individual. This patch also makes a minor HTML correction:
should be
. Signed-off-by: Lucas Gass Signed-off-by: Pedro Amorim commit 4ef49073cbafb82a699525441ba0c4a7d183351b Author: Martin Renvoize Date: Thu Aug 13 15:08:17 2026 +0100 Bug 43293: Add IDs to the Pay/Write off confirm buttons on paycollect.tt The Confirm submit button on the combined pay/writeoff form doesn't have an id, making it hard for local customisations, hardware integrations (e.g. receipt printer triggers), and automated tests to reliably target the pay action versus the writeoff action - both render as the same markup with only the value/hidden op field differing. Add id="paysubmit" and id="writeoffsubmit" to the two branches of the existing type == 'WRITEOFF' conditional, matching the existing op=cud-pay/op=cud-writeoff split right above it. Test plan: 1) Go to a patron's Pay fines page and select multiple charges 2) Choose Pay - confirm the Confirm button has id="paysubmit" 3) Choose Write off - confirm the Confirm button has id="writeoffsubmit" 4) Confirm both flows still submit and behave exactly as before Signed-off-by: Owen Leonard Signed-off-by: Lucas Gass Signed-off-by: Pedro Amorim