Commit Graph

951 Commits

Author SHA1 Message Date
Pedro Amorim 8e87fae1cc
Bug 37762: ISO18626 KOHA classes
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-05-08 12:25:41 -06:00
Pedro Amorim f9b9bc77b2
Bug 37762: ISO18626 REST API specs
Reference:
https: //illtransactions.org/schemas/ISO-18626-2021-2.xsd
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-05-08 12:25:40 -06:00
Pedro Amorim 55fa4609fa
Bug 37762: REST API: Convert XML payload to JSON for swagger definition validation
Convert JSON response to XML if header content_type: application/xml

Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-05-08 12:25:39 -06:00
Martin Renvoize cd5e4d22a1
Bug 29016: (QA follow-up) Document the action_logs list controller
Replace the empty =head3 stub with a proper synopsis explaining the URL,
the supported filtering / ordering / embed surface, and the permission
requirement. Aligns the controller with the documentation density of
other Koha REST controllers and removes the "Missing POD" QA noise.

Test plan:
  1. perl -MKoha::REST::V1::ActionLogs -e ''  (still loads)
  2. perl -c Koha/REST/V1/ActionLogs.pm        (still parses)
  3. perldoc Koha/REST/V1/ActionLogs.pm        (renders the new POD)

Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-05-05 13:42:11 -06:00
Kyle M Hall cfa349ccaf
Bug 29016: Add REST API for action logs
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-05-05 13:42:06 -06:00
Tomás Cohen Arazi 42b2758a76
Bug 42206: (follow-up) Rename to /closed_dates, improve efficiency
Rename /libraries/{id}/holidays to /libraries/{id}/closed_dates
for consistency with existing sub-resource naming (desks,
cash_registers).

Efficiency: instead of calling $calendar->is_holiday() per day
(which re-checks all three data sources each time), access the
pre-loaded data structures directly: weekly_closed_days array,
day_month_closed_days hash, and _holidays hash. The logic properly
handles exceptions (dates marked open despite a weekly/annual
closure).

Additional fixes:
- Add 365-day max range guard
- Add missing 401/403 responses in swagger spec
- Add request_id_header parameter
- Test exception handling (open on normally-closed day)
- Remove fragile 'empty defaults' assertion

Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-05-01 11:04:25 -06:00
Paul Derscheid 2a3376b243
Bug 42206: Add GET /libraries/{id}/holidays endpoint
- Add list_holidays controller to Koha::REST::V1::Libraries
- Returns closed days for a library within a configurable date range
- Uses Koha::Calendar to determine holidays
- Defaults to today + 3 months if no range specified
- Add OpenAPI spec for the new endpoint
- Register route in swagger.yaml
- Add unit tests in t/db_dependent/api/v1/libraries.t

To test:
1. Apply patch
2. prove t/db_dependent/api/v1/libraries.t
3. Verify all tests pass, including the new list_holidays subtest
   which covers:
   - Holidays returned within a specified date range
   - Empty list when no holidays exist in range
   - 400 response when 'to' date precedes 'from' date
   - 404 response for non-existent library
   - Default range (no params) returns successfully

Sponsored-by: Büchereizentrale Schleswig-Holstein <https://www.bz-sh.de/>
Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-05-01 11:04:25 -06:00
Martin Renvoize b80dafc210
Bug 23909: Apply hold policy to OPAC REST self-checkout
The OPAC REST self-checkout path (guarded by OpacTrustedCheckout) is
functionally SCO-over-API, so it should honour the same hold policy
as the SCO web interface. Previously _check_availability unconditionally
promoted RESERVED, RESERVE_WAITING, TRANSFERRED and PROCESSING from
the confirmation hash to the blockers hash for any public caller. This
meant the OPAC REST endpoint always refused held items regardless of
the librarian's AllowItemsOnHoldCheckoutSCO configuration.

With this patch the promotion is gated on AllowItemsOnHoldCheckoutSCO:

* 0 - Promote all four hold confirmations to blockers (previous
      behaviour for pending holds)
* 1 - Promote only waiting/transit/processing; silently allow
      checkout of items with a pending hold
* 2 - Promote none; silently allow checkout of items with any hold

Remaining hold confirmations are stripped from the response so the
caller does not have to resolve a confirmation token for a policy the
admin has already granted.

Test plan:
1. prove t/db_dependent/api/v1/checkouts.t
2. Enable OpacTrustedCheckout. POST an item with a pending hold for
   another patron to /api/v1/public/patrons/X/checkouts:
   - AllowItemsOnHoldCheckoutSCO=0: 403 Checkout not authorized
   - AllowItemsOnHoldCheckoutSCO=1: 201 Created
3. Place a waiting hold for another patron on an item. Repeat:
   - AllowItemsOnHoldCheckoutSCO=1: 403
   - AllowItemsOnHoldCheckoutSCO=2: 201

Signed-off-by: Kristi Krueger <kkrueger@cuyahogalibrary.org>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-05-01 11:04:20 -06:00
Matt Blenkinsop bce9aad974
Bug 26355: (follow-up) Fix handling of extended attributes
Extended attributes weren't being identified as changes and so need to be checked to see if any of them have changed

Sponsored-by: Westminster City Council <https://www.westminster.gov.uk/>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-05-01 09:30:04 -06:00
Matt Blenkinsop cb9e70f8c2
Bug 26355: (follow-up) Allow the setting of multiple information messages
Signed-off-by: Christopher Brannon <cbrannon@cdalibrary.org>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-05-01 09:30:02 -06:00
Matt Blenkinsop a76eb18bed
Bug 26355: Add unit tests
Signed-off-by: Christopher Brannon <cbrannon@cdalibrary.org>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-05-01 09:30:02 -06:00
Matt Blenkinsop d04923b3b9
Bug 26355: Add cypress tests
Adds categories to the db insertion mechanics and allows values to be passed to the patron insertion method

Signed-off-by: Christopher Brannon <cbrannon@cdalibrary.org>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-05-01 09:30:01 -06:00
Matt Blenkinsop 01f5214f0f
Bug 26355: Add the class methods and endpoint to handle renewal
This is part of a sponsored piece of development from one of our customers. There was a specification of requirements but I was conscious of the ideas already discussed on this bug and wanted to try and develop a solution that would balance both sets of requirements. The concept works as follows:
- Self-renewal can be enabled and controlled at a category level
    - The window within which it is available is customisable (both pre and post-expiry)
        - Defaults to the NotifyBorrowerDeparture syspref
    - The amount in fines that block self-renewal is customisable
        - Defaults to the category level charges and then the noissescharge preference
    - The message to display if renewal fails is customisable
- Libraries can also add information to display to the patron at the start of the process.
- The self-renewal process will also respect the OPACPatronDetails and AutoApprovePatronProfileSettings sysprefs. If OPACPatronDetails is enabled, the renewal will redirect the patron to the OPAC details form and ask them to confirm their details are still correct. Any changes will be logged as patron modifications and approved in line with the auto approval syspref
- Renewal happens regardless of whether OPACPatronDetails is enabled, only the details changes are logged as modification requests
- Notifications are sent to the patron in line with their messaging preferences

Test plan:
1. Apply all patches and reset_all
2. In the intranet, navigate to patron categories and edit the ‘Patron’ category
3. Scroll to the bottom, there should be a section called ‘Account expiry and self-renewal’
4. Set ‘Allow self-renewal’ to Yes
5. Set Self-renewal availability period to be 10 days
6. Set Self-renewal availability post-expiry’ to also be 10 days and save
7. In system preferences, set the OPACPatronDetails preference to ‘Don’t allow’
8. Choose a patron that has the ‘Patron’ type category
9. Edit that patron so that you can log into the OPAC and set their expiry date to be yesterday’s date
10. Log into the OPAC as that patron (it may be easiest to do this in incognito as we will be swapping between the intranet and OPAC throughout the test plan and it will remove the need to keep logging out and in)
11. You should see a message that says “You are eligible for self-renewal. Please click here to renew your account.”
12. Click that link - you will be presented with a modal that says “Are you sure you want to renew your account?”
13. Click “Close” - we don’t want to complete renewal yet as there is more functionality available to test
14. Navigate to the patron category again, set ‘Self-renewal availability post-expiry’ to be 0
15. Refresh the OPAC, the self-renewal link should not be there as we are now outside the patron self-renewal window
16. Undo that change in the patron category, the link should reappear when refreshing the OPAC
17. Now set the patron’s expiry date to be tomorrow
18. In the category, set ‘Self-renewal availability period’ to be blank
19. Refresh the OPAC, it should still show the link as it is defaulting to NotifyBorrowerDeparture
20. Set NotifyBorrowerDeparture to 0
21. Refresh the OPAC, the link should vanish
22. In the category, restore ‘Self-renewal availability period’ to 10 days
23. Refresh the OPAC, the link should reappear
24. In the intranet, set the patron to be debarred using a manual restriction
25. In the OPAC refresh the page - self-renewal should no longer be available
26. Remove the restriction - the renewal link will be visible again
27. Set a fine on the patron record of 6 USD
28. Refresh the OPAC, the self-renewal link will be gone because we are over the global ‘noissuescharge’ preference value of 5
29. In the category, set ‘Checkout charge limit’ to 7
30. Refresh the OPAC, the link will be visible because we are now under the category charge
31. Add an additional fine of 2 to the patron account
32. Refresh the OPAC, the self-renewal link is gone
33. In the category, set ‘Self-renewal charge limit’ to be 10
34. Refresh the OPAC, the link will be visible again
35. In the category, set ‘Self-renewal failure message’ to be whatever you want
36. In the OPAC, refresh the page and then click into the self-renewal process
37. This time, click “No” - you should see the failure message you have just set
38. Click “Close” and refresh the page to reset this message
39. In the category, set a message in the “Self-renewal information message”
40. In the OPAC, refresh the page and then click the renewal link again
41. You should be met with the modal, this time displaying the information message we just set up in the patron attributes
42. Click “Yes” - you should see the “Are you sure you want to renew your account?” message again
43. This time when prompted with the “Are you sure” message, click “Yes”
44. The page should refresh and display a confirmation with the new expiry date.
45. In the intranet, view the patron’s record - the date should have been updated
46. In the Modification log tab, there should be a log entry for “Membership renewed”
47. Change the patron’s expiry date again, this time to be yesterday’s date
48. In the OPAC, click on “Personal detail”, the new expiry date should show there
49. Now set the OPACPatronDetails syspref to be “Allow”
50. Click on “Summary” again, the self-renewal link should be there again
51. Click into the self-renewal process and click “Yes” on your verification step
52. This time you should be met with a message that says “Confirm your account details”
53. Click “Continue” - you will be redirected to the OPAC details form
54. There should be a message at the top that says “Please verify your details to proceed with your self-renewal.”
55. Update a field somewhere on the patron form
56. Scroll to the bottom - the button should say “Submit renewal request”
57. Click this button
58. You will be shown the renewal confirmation message
59. In the intranet, on the homepage you should now see a modification request
60. Check the request, it should match the fields you changed - don’t approve or deny for now
61. Set ‘AutoApprovePatronProfileSettings’ in sysprefs to “Enable”
62. Reset your patron’s expiry date to today’s date
63. In the OPAC, click into Personal details and then back into Summary again (we need to do this to remove the success parameter from the URL)
64. The renewal link will be visible again - go through the process again
65. On the form, you should see an alert that you have already sent a modification request
66. This time, change a different field to the previous attempt
67. Submit the form
68. In the intranet there should be no modification this time and the change should be visible in the patron record as it has been automatically approved and handled as per the syspref
69. prove t/db_dependent/Koha/Patron.t
70. prove t/db_dependent/api/v1/patrons_self_renewal.t
71. yarn cypress run --spec t/cypress/integration/Islands/SelfRenewal.ts
72. Sign off!

Signed-off-by: Christopher Brannon <cbrannon@cdalibrary.org>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-05-01 09:30:00 -06:00
Martin Renvoize cb8f1ff9d5
Bug 41901: Allow duplicate check when adding authority via API
POST /api/v1/authorities currently offers only the heading-based
C4::AuthoritiesMarc::FindDuplicateAuthority check, and the only
escape hatch is the `x-koha-override` header.

Koha already ships configurable record matching rules (see
Administration > Record matching rules) and C4::Matcher already
supports `record_type = authority`. This patch lets an API caller
opt into one of those rules when creating an authority by sending
its numeric id in a new `x-koha-matchrule` header.

Behaviour:
* If no `x-koha-matchrule` header is sent the existing heading-based
  duplicate check is used. Existing clients are unaffected.
* If `x-koha-matchrule: <id>` is sent:
    * non-existent id          -> 400 `matching_rule_not_found`
    * matcher not record_type=authority
                               -> 400 `invalid_matching_rule_type`
    * matcher returns matches  -> 409 `duplicate`; the response
                                  body additionally contains a
                                  `matches: [{authid, score}, ...]`
                                  array listing every hit returned
                                  by the matcher
    * matcher returns nothing  -> record is created (201)
* `x-koha-override: any|duplicate` continues to bypass all duplicate
  checks, including the matcher.

A non-integer header value is rejected by the OpenAPI schema
validator before the controller runs.

Test plan:
 1) Apply the patch series.
 2) Run `prove t/db_dependent/api/v1/authorities.t`
    => all subtests pass.
 3) Log in to the staff interface as a user with the
    'manage_matching_rules' subpermission and go to
    Administration > Record matching rules > New record matching
    rule:
     a) Set Matching rule code e.g. `AUTH_HEADING`
     b) Set Description e.g. `Authority heading match`
     c) Set Record type to `authority`
     d) Set Threshold to e.g. `1000`
     e) Add a match point:
         * Search index:  `Heading-Main`  (or your authorities index)
         * Score:         `1000`
         * Tag:           `110` (or the heading tag used by your
                          authority type)
         * Subfields:     `a`
     f) Save. Note the numeric matching rule id in the edit URL
        (`admin/matching-rules.pl?op=edit_matching_rule&matcher_id=N`).
 4) Export an existing authority record as MARCXML (for example
    from the authority details page). Save it as `duplicate.xml`.
 5) From the command line, POST the record back to Koha using the
    new header (replace <N>, credentials and host):

    curl -u <user>:<pass> -X POST \
      -H 'Content-Type: application/marcxml+xml' \
      -H 'x-authority-type: CORPO_NAME' \
      -H 'x-koha-matchrule: <N>' \
      --data-binary @duplicate.xml \
      http://<your-koha>/api/v1/authorities

    => Expect HTTP 409. The JSON response body contains
       `error_code: "duplicate"` and a `matches` array listing the
       authid(s) that were found along with their score.
 6) Edit `duplicate.xml` so the main heading is something that is
    not already in the catalogue. POST it again with the same
    header.
    => Expect HTTP 201 and a `Location` header pointing to the new
       authority.
 7) Re-run the POST from step 5 but additionally send
    `-H 'x-koha-override: duplicate'`.
    => Expect HTTP 201 (override bypasses the matcher).
 8) Send a POST with `x-koha-matchrule: 999999`.
    => Expect HTTP 400 with `error_code: "matching_rule_not_found"`.
 9) Create a second matching rule with Record type `biblio` and
    note its id. POST with `x-koha-matchrule` set to that id.
    => Expect HTTP 400 with
       `error_code: "invalid_matching_rule_type"`.
10) POST with `x-koha-matchrule: abc`.
    => Expect HTTP 400 from the OpenAPI schema validator.
11) POST without `x-koha-matchrule`.
    => Expect the existing heading-based duplicate check to run
       exactly as before (409 for a known duplicate, 201 otherwise).
12) Sign off.

Signed-off-by: Brian J. Barr <brian.barr@churchofjesuschrist.org>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-04-29 09:09:12 -06:00
Martin Renvoize fc6e5839d4
Bug 42221: Fix EAN-13 autoBarcode not incrementing
The EAN-13 barcode query used max(abs(barcode)) which allowed non-EAN-13
barcodes (e.g. 14-digit KTD sample barcodes) to dominate the result.
The saved 13-digit EAN-13 barcodes were always smaller, so $nextnum
never advanced and the same barcode was generated on every page load.

Fix by extracting EAN-13 logic into C4::Barcodes::ValueBuilder::EAN13
(consistent with other barcode type packages) and scoping the query to
WHERE length(barcode) = 13 so only valid-length barcodes contribute to
the max. Both barcode.pl and Koha::REST::V1::Biblios now call the shared
function, eliminating the duplicated inline code.

Tests: adds EAN-13 test cases to t/db_dependent/Barcodes_ValueBuilder.t
Signed-off-by: Caroline Cyr La Rose <caroline.cyr-la-rose@inlibro.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-04-16 15:54:09 -06:00
Jacob O'Mara b6eeffb79f
Bug 17387: (follow-up) fix embed items on get deleted biblio
Add x-koha-embed parameter to GET /deleted/biblios/{biblio_id} and use
$c->objects->to_api() to properly handle embedding items.

Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-04-15 14:10:28 -06:00
Martin Renvoize 06f4abbf9a
Bug 17387: (follow-up) address review feedback
- Fix permission description to explicitly mention bibliographic records
  and items (not just 'records')
- Fix date filter to use correct DB column per table: deletedbiblio uses
  'timestamp', deleteditems uses 'deleted_on'
- Remove leftover CAN_user_editcatalogue_edit_catalogue condition from
  the Batch editing section in cat-menu.inc; a user with only
  edit_catalogue would see an empty section heading
- Wrap biblio and item restore operations in DB transactions so that a
  failed store cannot leave a record inserted without being removed from
  the deleted table (or vice-versa)
- Catch Koha::Exceptions::Object::DuplicateID in the item restore
  controller and return a human-readable 409 instead of a generic 500
- When 'Restore bibliographic record' is clicked in the deleted-bib
  warning modal, fetch the biblio and open the full restore modal with
  the originally clicked item pre-selected, rather than restoring
  immediately without item selection

Signed-off-by: Michaela <michaela.sieber@kit.edu>
Sponsored-by: ByWater Solutions
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-04-15 14:10:27 -06:00
Jacob O'Mara c07639777d
Bug 17387: (follow-up) take library groups in to account for permissions check
Signed-off-by: Michaela <michaela.sieber@kit.edu>
Sponsored-by: ByWater Solutions
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-04-15 14:10:26 -06:00
Jacob O'Mara 321e9647ea
Bug 17387: add pagination headers and support comma-delimited Accept headers
Signed-off-by: Michaela <michaela.sieber@kit.edu>
Sponsored-by: ByWater Solutions
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-04-15 14:10:21 -06:00
Jacob O'Mara 98d74ff6bc
Bug 17387: item cannot be restored if associated biblio does not exist
Signed-off-by: Michaela <michaela.sieber@kit.edu>
Sponsored-by: ByWater Solutions
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-04-15 14:10:20 -06:00
Jacob O'Mara 6272f438d5
Bug 17387: add deleted biblios restore api
Signed-off-by: Michaela <michaela.sieber@kit.edu>
Sponsored-by: ByWater Solutions
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-04-15 14:10:18 -06:00
Jacob O'Mara d7ce637ed4
Bug 17387: add deleted items restore api
Signed-off-by: Michaela <michaela.sieber@kit.edu>
Sponsored-by: ByWater Solutions
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-04-15 14:10:18 -06:00
Tomás Cohen Arazi caa52ddf91
Bug 22639: Add GET /config/search_mappings endpoint
This patch adds a new API endpoint to retrieve the search field
mappings configuration (search fields and their MARC mappings, grouped
by index).

The endpoint supports content negotiation:
- application/json (default)
- application/yaml (for export/import compatibility)

An optional 'type' query parameter allows filtering mappings by MARC
type (marc21 or unimarc).

Implementation notes:
- New controller: Koha::REST::V1::Config::SearchMappings
- Reuses Koha::SearchEngine::Elasticsearch::raw_elasticsearch_mappings
- Registers 'application/yaml' MIME type in Koha::REST::V1
- Permission: manage_search_engine_config

To test:
1. Apply this patch
2. Rebuild the API bundle:
   $ yarn api:bundle
3. Restart Plack
4. Run:
   $ prove t/db_dependent/api/v1/config_search_mappings.t
=> SUCCESS: Tests pass
5. Test manually:
   $ curl -u user:pass /api/v1/config/search_mappings
=> SUCCESS: Returns JSON with search field mappings
   $ curl -u user:pass -H 'Accept: application/yaml' \
     /api/v1/config/search_mappings
=> SUCCESS: Returns YAML output
   $ curl -u user:pass /api/v1/config/search_mappings?type=marc21
=> SUCCESS: Only marc21 mappings are returned
6. Sign off :-D

Signed-off-by: Laurence <laurence.rault@biblibre.com>
Signed-off-by: Thomas Klausner <domm@plix.at>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-04-15 11:37:17 -06:00
Nick Clemens 99eb693cd9
Bug 41733: Honor EmailPatronRegistrations in the API
This patch adds new overrides opac_reg_yes and opac_reg_no to the patrons api
and will send a notice to the library when a patron is registered via the API if the pref is
active and the NO override is not sent, or the YES override is sent

To test:
1 - Apply patches
2 - yarn build
3 - restart_all
4 - run unit tests

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-04-15 11:37:13 -06:00
Jonathan Druart 6eed79ccf8
Bug 41994: Implement /sysprefs route to list system preferences
This new route will be used in a follow-up bug to auto-complete
sysprefs when using the header to search for sysprefs.

Note that this is based on top of bug 41834 that NULL options,
explanation and type in DB, but a future enhancement will populate the
response to return the values present in the yaml files.

Test plan:
1. Bundle the swagger specs and reload plack:
   yarn api:bundle && koha-plack --reload kohadev
2. Fetch the sysprefs using the new route:
 curl -u koha:koha --request GET 'http://${INSTANCE}-intra.localhost/api/v1/sysprefs' --header "Content-Type: application/json" | jq
3. Confirm that the tests pass
   prove t/db_dependent/api/v1/sysprefs.t

Signed-off-by: Owen Leonard <oleonard@myacpl.org>
Signed-off-by: Jan Kissig <bibliothek@th-wildau.de>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-04-15 11:37:05 -06:00
Pedro Amorim 5ae5ac3330
Bug 41849: Add cancel hold_group REST API endpoint
Signed-off-by: Bob Bennhoff <bbennhoff@clicweb.org>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-04-10 09:48:04 -06:00
Pedro Amorim b0714a0b22
Bug 40504: Add ill/users API endpoint
Required to get users filtered by 'ill' permission for patron search modal

prove t/db_dependent/api/v1/ill_users.t

Signed-off-by: Jeremy Evans <Jeremy.Evans@ukhsa.gov.uk>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
2026-03-26 14:21:21 +01:00
Jan Kissig ce42c3b5ec
Bug 35380: Make updateBiblio-API respect Record overlay rules
This patch moves hardcoded source filter from 'MARC overlay rules' (batchmod, intranet, z3950, staged import, bulk import, import_lexile) to 'Record Sources' and makes them untouchable. They cannot be renamed or modified.
New record sources can be added and modified though.
All default and newly created record sources are available as filter for the module "Source" in 'MARC overlay rules'.
The API route for PUT /biblios/:biblio_id now checks for a given header x-record-source-id.
If an id is given the name of the rule is retrieved and forwarded as an overlay_context to ModBiblio.
If no id is given the fallback '*' is added as overlay_context.
Also the record source id is getting saved.

Test plan:
pre) run perl installer/data/mysql/updatedatabase.pl to add new is_system column
pre) run dbic to build Koha::Schema::Result::RecordSource as it gets a new columns is_system
pre) run 'redocly bundle --ext json api/v1/swagger/swagger.yaml --output api/v1/swagger/swagger_bundle.json' or 'yarn build'

a) enable system preference MARCOverlayRules and RESTBasicAuth
b) create new record source in /cgi-bin/koha/admin/record_sources and recognize its <NAME> and <ID>
c) create overlay rules in /cgi-bin/koha/admin/marc-overlay-rules.pl
f.e.
+----+-----+--------+----------+-----------+
| id | tag | module | filter   | preset    |
+----+-----+--------+----------+-----------+
|  1 | 245 | source | *        | protect   |
+----+-----+--------+----------+-----------+

This will make the 245 field protected from change, unless the record source matches
d) go to /cgi-bin/koha/catalogue/detail.pl?biblionumber=262 and change 245 (title)  via edit -> edit record
e) save and take a look the title is still the same
f) run the updateBiblio-Request from below with a API-testing client like REST Client
g) check that title gets overwritten even though it is protected. This is due the fact the updateBiblio is not setting an overlay context.

h) apply patch
redo d) and e)
i) add another overlay rule allowing your record source to change 245:
+----+-----+--------+----------+-----------+
| id | tag | module | filter   | preset    |
+----+-----+--------+----------+-----------+
|  1 | 245 | source | *        | protect   |
|  2 | 245 | source | <NAME>   | overwrite |
+----+-----+--------+----------+-----------+

j) run the updateBiblio-Request from below, be sure to fill out x-record-source-id:with your ID from step b)
k) check that title gets overwritten
l) run the updateBiblio-Request from below, but omit x-record-source-id or set it to another value than <ID>
m) check that title is not overwritten

PUT http://main-intra.localhost/api/v1/biblios/262
Authorization: Basic koha:koha
Authorization: Basic koha:koha
Content-Type: application/marcxml+xml
x-record-source-id: <ID>

<?xml version="1.0" encoding="UTF-8"?>
<record
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
    xmlns="http://www.loc.gov/MARC21/slim">

  <leader>01075cam a2200313 a 4500</leader>
  <controlfield tag="001">foo</controlfield>
  <controlfield tag="005">20200421093825.0</controlfield>
  <controlfield tag="008">120417s2012    ch a     b    001 0 eng  </controlfield>
  <datafield tag="040" ind1=" " ind2=" ">
    <subfield code="c">482</subfield>
  </datafield>
  <datafield tag="100" ind1="1" ind2=" ">
    <subfield code="a">Christiansen, Tom.</subfield>
    <subfield code="9">482</subfield>
  </datafield>
  <datafield tag="245" ind1="1" ind2="0">
    <subfield code="a">New Title</subfield>
    <subfield code="c">Tom Christiansen, Brian D. Foy &amp; Larry Wall.</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
    <subfield code="a">City</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
    <subfield code="a">Pages and more</subfield>
  </datafield>
  <datafield tag="942" ind1=" " ind2=" ">
    <subfield code="c">BKS</subfield>
  </datafield>
</record>

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
2026-03-26 09:50:08 +01:00
Jan Kissig 86443b8437
Bug 35380: Change record sources to by systemdefined
This changes the structure of record source with an is_system column which controls whether this value can be deleted.
Also predefined values are inserted to reflect the default hard coded values from 'Record overlay rules' sources

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
2026-03-26 09:46:15 +01:00
Tomás Cohen Arazi 68c8b8f13f
Bug 41107: Add /status/version API endpoint
Adds a new REST API endpoint to retrieve Koha version information.

This implementation includes:
- Koha::Status class for instance status information
- /status/version endpoint returning structured version data
- OpenAPI specification with koha_version definition
- REST controller for handling the endpoint

The returned version object includes:
- version: full version string (e.g., '25.06.00.029')
- major: major version number
- minor: minor version number
- release: major.minor version
- maintenance: major.minor.maintenance version
- development: development version (if applicable)

This prepares the foundation for a future /status endpoint that will
include all information displayed in the about page.

To test:
1. Apply the patch
2. Run:
   $ ktd --shell
  k$ yarn api:bundle
3. Run the tests:
  k$ prove t/Koha/Status.t \
           t/db_dependent/api/v1/status.t
=> SUCCESS: Tests pass!
4. Sign off :-D

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
2026-03-23 09:33:54 +01:00
Martin Renvoize 018e65c811
Bug 23415: Add REST API support for fine override on renewal
This commit adds support for the AllowFineOverrideRenewing functionality
to the REST API renewal endpoints using the standard x-koha-override pattern.

Changes:
1. Added x-koha-override header parameter to both renewal endpoints:
   - POST /checkouts/{checkout_id}/renewal
   - POST /checkouts/{checkout_id}/renewals
2. Updated Koha::REST::V1::Checkouts::renew() to:
   - Check for 'debt_limit' in the overrides stash
   - Check AllowFineOverrideRenewing preference when override is requested
   - Allow renewal override only when both:
     * x-koha-override header contains 'debt_limit' AND
     * AllowFineOverrideRenewing preference is enabled
   - Follows the established x-koha-override pattern used by other endpoints
3. Updated OpenAPI specification (swagger) to document the new header
   using the standard pattern with enum values

Usage:
  curl -X POST /api/v1/checkouts/123/renewal \
    -H "x-koha-override: debt_limit"

The override only works for too_much_owing errors and requires
the AllowFineOverrideRenewing system preference to be enabled.

This implementation follows the same pattern as holds and other
endpoints that support overrides, maintaining consistency across
the REST API.

Sponsored-by: OpenFifth <https://openfifth.co.uk/>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
2026-03-22 23:27:26 +01:00
Nick Clemens 48386d8570
Bug 41801: (QA follow-up) Ensure toggling priority sets correct rank 2026-03-21 20:28:16 +00:00
Johanna Räisä b58f945270
Bug 23269: use REST API for patron_holds_table
This patch uses the REST API to populate the holds table

Test plan:
1) Apply the patch
2) Go to a record with holds
3) Check that the holds table is populated correctly
4) Check that hold tables functions work correctly
5) Change HoldsSplitQueue and HoldsSplitQueueNumbering system preference, try all variations
6) Repeat steps 3 and 4
7) Search for records and place holds to multiple records
8) Repeat steps 3 and 4
9) Try with lesser permissions

Sponsored-by: Koha-Suomi Oy
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-03-21 20:28:14 +00:00
Lari Taskula c42848609c
Bug 38365: Make swagger-cli happy
Schema type [array,object] is not valid in OpenAPI version 2.

There are two different CSP reporting directives.

One is the now deprecated "report-uri" directive. Browsers typically send a single
JSON object following the CSP2 specification.

"report-uri" is deprecated in CSP3 in favor of the newer "report-to" directive. It
is expected to contain an array of report objects.

There are browser that do not yet support the "report-to" directive, so both
directives should be supported.

There are also variations among the "report-uri" format. See
https://www.tollmanz.com/content-security-policy-report-samples/

Because of these variations, it becomes quite complex to handle the most common
cases in a single API endpoint.

We could build two separate endpoints for both directives.

Or we can accept any type of input and handle the variations in a single endpoint.
This patch attempts to do that.

Before this patch input parameters were validated by JSON::Validator. That is the
normal and recommended way to build OpenAPI endpoints in Koha. After this patch we
remove all input parameter restrictions from the OpenAPI spec, and simply accept
any type of body.

This means the controller will now always return a HTTP 204 regardless of the type
of data passed to the controller. It instead truncates too long input before
writing them into log files.

As this is not an endpoint that developers will build new Koha clients for, we
do not have to offer a very in-depth input parameter spec for this endpoint.

To test:
1. t/db_dependent/api/v1/public/csp_reports.t

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
2026-03-16 11:57:37 +01:00
Lari Taskula b14528e2f8
Bug 38365: Disable the endpoint when CSP is disabled in KOHA_CONF
To test:
1. prove t/db_dependent/api/v1/public/csp_reports.t

Signed-off-by: David Cook <dcook@prosentient.com.au>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
2026-03-16 11:57:24 +01:00
Lari Taskula 8da256080d
Bug 38365: Restore violated-directive
The violated-directive is a historic name for the effective-directive field and
contains the same value.

Signed-off-by: David Cook <dcook@prosentient.com.au>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
2026-03-16 11:57:22 +01:00
David Cook ffa7290fd1
Bug 38365: Add support for both CSP report syntaxes
Signed-off-by: Lari Taskula <lari.taskula@hypernova.fi>
Signed-off-by: David Cook <dcook@prosentient.com.au>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
2026-03-16 11:57:21 +01:00
Lari Taskula d3d0592eb7
Bug 38365: Add application/reports+json as accepted Content-Type
report-to directive uses application/reports+json

To test:
1. prove t/db_dependent/api/v1/public/csp_reports.t

Signed-off-by: David Cook <dcook@prosentient.com.au>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
2026-03-16 11:57:20 +01:00
Lari Taskula a7b51e6701
Bug 38365: Add default log4perl configuration
This patch adds the default configuration to log4perl.conf.

Note we are passing a non-standard interface 'csp' to Koha::Logger. This is to
avoid log entries from propagating up to api-error.log.

To test:
1. prove t/db_dependent/api/v1/public/csp_reports.t

Signed-off-by: David Cook <dcook@prosentient.com.au>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
2026-03-16 11:57:17 +01:00
Martin Renvoize 4971626204
Bug 38365: Add CSP violation reporting API endpoint
Add /api/v1/public/csp-reports endpoint to receive and log
Content-Security-Policy violation reports from browsers.

When CSP is configured with a report-uri directive pointing to this
endpoint, browsers will POST violation reports whenever a CSP rule
is violated. These reports are logged using Koha's logging system
for administrator review.

Features:
- Public endpoint (no authentication required, as browsers send
  these reports automatically)
- Logs violations at WARN level with key details (violated directive,
  blocked URI, document URI, source location)
- Logs full report at DEBUG level for detailed analysis
- Accepts both application/csp-report and application/json content types

Configuration example (in koha-conf.xml csp_header_value):
  ...; report-uri /api/v1/public/csp-reports

Log4perl configuration to capture CSP violations:
  log4perl.logger.api.csp = WARN, CSP
  log4perl.appender.CSP = Log::Log4perl::Appender::File
  log4perl.appender.CSP.filename = /var/log/koha/csp-violations.log
  log4perl.appender.CSP.layout = PatternLayout
  log4perl.appender.CSP.layout.ConversionPattern = [%d] %m%n

Also updates koha-conf.xml documentation with CSP configuration guidance.

Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Lari Taskula <lari.taskula@hypernova.fi>
Signed-off-by: David Cook <dcook@prosentient.com.au>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
2026-03-16 11:57:15 +01:00
Olli Kautonen 9445ffc9aa
Bug 40154: prevent deletion of items with holds
This patch prevents deletion of items that have item level holds on
them.

Test plan:
1. Create an item level hold.
2. Delete the item using alternative A or B:
   A. Open the biblios Detail-view -> From the toolbar, open
      "Edit"-dropdown menu -> Manage items -> Delete the item that has
      an item level hold attached to it from "Actions"-dropdown menu
   B. Open the biblios Detail-view -> Select the item that has an item
      level hold attached to it -> Click "Delete selected items" ->
      Confirm deletion
3. Notice that the item is deleted without any warning and the item
   level hold has disappeared.
4. Apply this patch.
5. Repeat steps 1-3.
6. Notice that the item cannot be deleted and a warning is shown.
7. prove t/db_dependent/Koha/Item.t
8. Run the REST API tests: prove t/db_dependent/api/v1/items.t

Sponsored-by: Koha-Suomi Oy
Signed-off-by: Owen Leonard <oleonard@myacpl.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-02-10 10:52:04 -07:00
Martin Renvoize c7fa646929
Bug 40134: Implement optimal item selection for 'any item' bookings
This patch implements an algorithm for selecting the item that would
leave the largest gap after the proposed booking to maximize the
opportunity for future bookings.

Key Changes:

Koha::Booking:
- Added set_itemtype_filter() method for transient itemtype parameter
- Added _select_optimal_item() method using single aggregated query
  * Groups bookings by item_id with MIN(start_date)
  * Selects items with no future bookings (optimal)
  * Among items with bookings, selects one with latest next booking
  * O(1) complexity - single database query with GROUP BY
- Updated _assign_item_for_booking() to use optimal selection
  * Filters by itemtype when itemtype_id is provided
  * Replaces previous random selection (RAND())

API Changes:
- Added itemtype_id parameter support to add() endpoint
- Added itemtype_id parameter support to update() endpoint
- Validates exactly one of item_id or itemtype_id is provided
- itemtype_id is transient - not persisted to database
- Extracted and applied via set_itemtype_filter() before store()

Architecture:
- itemtype_id is NOT a database column (transient only)
- Used as selection criterion, then discarded

Test plan:
1. Apply patch and restart services
2. Create "any item" booking via staff interface
3. Verify item with longest future availability is selected
4. Test via API with itemtype_id parameter
5. Verify itemtype_id is not persisted to database
6. Run t/db_dependent/Koha/Booking.t
7. Run t/db_dependent/api/v1/bookings.t

Signed-off-by: Kristi Krueger <kkrueger@cuyahogalibrary.org>
Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-02-10 08:50:56 -07:00
Jonathan Druart 849f67988f
Bug 41076: Adjust our perl tidiness for v20250105
Generated using
  `perl misc/devel/tidy.pl --perl`

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-02-05 09:03:51 -07:00
Jonathan Druart e7325583f3
Bug 39438: (bug 38446 follow-up) Add agreement_period to /erm/extended_attribute_types
Sponsored-by: Karlsruhe Institute of Technology (KIT)
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-01-30 10:54:11 -07:00
Matt Blenkinsop 080fccc0c5
Bug 39438: Add additional fields support to ERM agreement periods
This patch enables additional fields functionality for agreement periods
in the ERM (Electronic Resource Management) module, allowing libraries
to define custom metadata fields for agreement period records.

Changes include:
- Update Koha::AdditionalField to support erm_agreement_periods table
- Modify API definitions to include extended_attributes in responses
- Add erm_agreement_periods option to additional fields admin interface
- Enhance Vue components to display and manage additional field values
- Update ShowElement component to handle period-specific attributes

Test plan:
1. Navigate to Administration > Additional fields
2. Create new fields for "Agreement periods"
3. Edit an ERM agreement and add/edit period information
4. Verify additional fields appear and can be populated
5. Confirm values are saved and displayed correctly

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-01-30 10:54:10 -07:00
Jonathan Druart 0a3ed65e70
Bug 40192: (bug 38446 follow-up) Add title to /erm/extended_attribute_types
Sponsored-by: Karlsruhe Institute of Technology (KIT)
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-01-22 09:25:58 -07:00
Matt Blenkinsop 806ac743f0
Bug 40192: Add additional fields support to ERM titles
This patch extends the additional fields framework to ERM e-holdings
titles, allowing libraries to configure custom metadata fields for
managing electronic resources.

Implementation details:
- Extended Koha::ERM::EHoldings::Title and ::Titles with
  AdditionalFields mixin for object-level support
- Added 'erm_titles' table mapping to AdditionalField.pm for API
  serialization
- Updated OpenAPI schema definitions to include extended_attributes
  in erm_eholdings_title.yaml and expose extended_attribute_types
  endpoint
- Enhanced REST API controller to handle additional fields in title
  creation/updates
- Updated admin interface to allow configuring additional fields for
  the 'title' table name
- Modified Vue.js EHoldingsLocalTitleResource component to display
  and manage custom fields

This enables institutions to track custom metadata (e.g., license
details, administrative notes, local identifiers) alongside standard
ERM title information.

Test plan:
1. Configure additional fields:
   - Go to Administration > Additional fields
   - Click "New field" and select table name "title"
   - Create a text field: Name="License notes", Searchable=Yes
   - Create an authorized value field: Name="Access level",
     AV category=LOC (or any available category)
   - Save both fields

2. Test with local ERM titles:
   - Navigate to E-resource management > Local titles
   - Create a new local title or edit an existing one
   - Verify the "Additional fields" section appears with your
     configured fields
   - Fill in "License notes" with test text
   - Select a value for "Access level"
   - Save the title

3. Verify persistence:
   - Reopen the title you just edited
   - Confirm both additional field values are displayed correctly
   - Edit one field value and save
   - Confirm the update persists

Signed-off-by: Michaela <michaela.sieber@kit.edu>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-01-22 09:25:57 -07:00
Tomás Cohen Arazi ac9944f7b0
Bug 29668: Adapt to current guidelines
The added patches make some changes:

* $c->req->json is used to access the request body, as explained by the
  Mojolicious OpenAPI plugin author it should be done.
* Instead of calling `$basket->to_api` we use the `$c->objects->to_api`
  helper which deals with calling context (embeds, etc). Otherwise it
  would require doing it manually if embeds are added.
* Tests are grouped together the same way the rest of them are.

To test:
1. Apply this patches
2. Run:
   $ ktd --shell
  k$ prove t/db_dependent/api/v1/acquisitions_baskets.t
=> SUCCESS: Tests pass!

Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Laura_Escamilla <laura.escamilla@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-01-21 15:28:16 -07:00
Julian Maurice 5e0a72f8a8
Bug 29668: Add API route to add a basket
Example usage:

POST /api/v1/acquisitions/baskets

{
    "vendor_id": 1,
    "name": "Basket #1",
}

Test plan:
1. Try requesting this endpoint with your favorite API tool
   (I recommend https://github.com/frigus02/RESTer)
2. Run `prove t/db_dependent/api/v1/acquisitions_baskets/post.t`

Edit (tcohen): Re-did the commit with some fixes in the spec

Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Laura_Escamilla <laura.escamilla@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-01-21 15:28:09 -07:00
Nick Clemens f21255ca54
Bug 41416: Add skip_fix_priority option to ModReserve
This patch adds a new parameter to ModReserve: skip_fix_priority

The page for altering priority ensures each hold has a unique rank, so doesn't allow for setting two
holds to the same rank, so we don't need to reorder everything until the end (in case of some cancellations etc)

This patch also makes FixPriority exported and updates the name as it is already called in a few places outside of
C4:Reserve

To test:
 1 - Place many holds on a record, 50 - 150
     https://github.com/kidclamp/handy-koha-script/blob/main/randhold.pl
 2 - View the record in the staff interface:
     http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=312
 3 - Click on the 'Holds' tab
 4 - Adjust the priority of several holds using the dropdowns
 5 - Open the network tab in the browser console (F12) to view the timing
 6 - Click 'Update hold(s)' and note the time
 7 - Apply patch, restart all
 8 - Repeat
 9 - Confirm timing is better and numbering updates correctly
10 - Sign off!

Note: The script adds holds that may be marked as 'lowestPriority' these will always all group at the bottom of the record
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Jan Kissig <bibliothek@th-wildau.de>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-01-16 14:07:18 -07:00