Commit Graph

6121 Commits

Author SHA1 Message Date
Martin Renvoize 4b4bffdf2d
Bug 39190: Update API to use new Transport classes
As the title says, use the new polymorphic classes in the API
controllers

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-19 13:23:15 -06:00
Martin Renvoize 277a02daeb
Bug 39190: Add key handling to SFTP Transports
We add triggers to store in the base class and then use them in the SFTP
transport class to write out the key file to the filesystem for later
use in connect.

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-19 13:23:15 -06:00
Martin Renvoize 3354bed6ef
Bug 39190: Rework (S)FTP into File::Transport classes
This patch adds polymorphic transport classes to Koha for FTP and SFTP
file transport configurations.

We introduce a base class for interacting with the base configuration
storage and subclasses to impliment the protocol specific transport
handling.

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-19 13:23:14 -06:00
Martin Renvoize 9d76089166
Bug 39190: Update polymorhpic base class to identify itself
This patch adds _polymorphic_field and _polymorphic_map private methods
to the Koha::File::Transports class to more clearly identify this as a
polymorphic class base for TestBuilder.

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-19 13:23:14 -06:00
Martin Renvoize 1878288ae9
Bug 39488: Add template for required polymorphic class methods
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-19 13:23:12 -06:00
Martin Renvoize 616de7bf61
Bug 39488: Add $result to Koha::Objects `object_class` calls
This allows us to do dynamic polymorphic classing on calls to 'find',
'find_or_create', 'single', 'next', 'last' and 'as_list' etc.

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-19 13:23:12 -06:00
Jake Deery f33638f14b
Bug 35761: Introduce central FTP/SFTP management
This patch adds a central FTP/SFTP management UI, with an associated
database object and class, plus the beginnings of an API. We can use
this code as a building block for adding FTP/SFTP connections to
other parts of the system, as well as to improve the usability of the
EDI transports. It is also now possible to test these connections
from within the Koha UI.

To test:-
You will need access to an FTP or SFTP server
Contact me if you need a disposable FTP/SFTP server

a)  Go to Koha Administration
b)  Notice no FTP/SFTP referenced on this page
c)  APPLY PATCH, reset_all
d)  Create new user, let's say sftpuser
e)  Set permissions for new user to include:
    1)  catalogue
    2)  parameters -> manage_sftp_servers
f)  Log in with this new user, go back to Koha Administration
    1)  Notice the FTP/SFTP servers option
g)  Undo step e2) for the sftpuser via the koha admin user
    1)  Refresh the Koha Administration page as the sftpuser
    2)  Notice how FTP/SFTP servers has disappeared
h)  Back to koha admin, go to Koha Administration -> FTP/SFTP Servers -> New
i)  Complete form depending on the FTP or SFTP server you have access to, Submit
    1)  Notice you are prompted to confirm before saving
j)  Select Edit, observe your details are the same, and Submit again
k)  Repeat step J one additional time
l)  Select Test, observe all tests passing
m)  Select Delete, confirm deletion, and observe server disappear
n)  Optionally, run prove on new tests
    1)  t/Koha/Auth/Permissions.t
    2)  t/db_dependent/Koha/SFTP/Server.t
    3)  t/db_dependent/api/v1/sftp_servers.t
o)  SIGN-OFF

Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-19 13:23:11 -06:00
Jake Deery 112bdeb2fa
Bug 35761: DBIC Schema
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Edit: Added POD to the defined methods to make tests pass:

```
prove xt/author/pod_coverage.t
```

Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-19 13:23:11 -06:00
Thomas Klausner c4a6c7584d
Bug 39526: Unify syspref variable names to Elasticsearch
We currently have a sysprefs named "Elasticsearch*" and some name only "ES*". This patch unifies the names to always start with "Elasticsearch".

Test plan:

* Start koha-testing-docker, open the staff interface and go to Administration.
* Enter "Elasticsearch" into the System Preference search box and click "search"
* You will find a bunch of sysprefs
* Now search for "ESPreventAutoTruncate", which should find one match

* Apply the patch
* run (in ktd) the script `updatedatabase`

* You should see output like
DEV atomic update /kohadevbox/koha/installer/data/mysql/atomicupdate/bug_39526_unify_syspref_variable_names_for_elasticsearch.pl  [09:35:03]: Bug 39526 - Unify system preference variable names for Elasticsearch
	Renamed system preference 'ES..' to 'Elasticsearch..'

* Go again to to sysprefs and search again for "Elasticsearch"
* you should now find "ElasticsearchPreventAutoTruncate"
* Search for "ESPreventAutoTruncate", which should show "No system preferences matched your search for .." (and the list of ALL sysprefs)

Please note that the qa script explains about installer/data/mysql/mandatory/sysprefs.sql, but the last line is not touched by this patch, so not sure why this happens.

Sponsored-by: HKS3
Signed-off-by: Roman Dolny <roman.dolny@jezuici.pl>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-19 08:42:52 -06:00
Lucas Gass 99fd185b41
Bug 36831: (follow-up): Add formula injection protection
Without patch:

prove /kohadevbox/koha/xt/author/Text_CSV_Various.t FAIL

With patch:

prove /kohadevbox/koha/xt/author/Text_CSV_Various.t PASS

Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-19 08:42:35 -06:00
Matt Blenkinsop a869b7297f
Bug 36942: Use an exception for a failed KBART file parse
Test plan:
1) prove t/db_dependent/Koha/BackgroundJob/ImportKBARTFile.t

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-18 14:31:03 -06:00
Matt Blenkinsop 41e198bfcd
Bug 36831: Allow for multiple file types
This patch allows the KBART import tool to accept different filetypes and then work out whether they are CSV or TSV files.

Test plan:
1) Try to import the file attached to the bug using the KBART import tool (E-resource management > eHoldings > Local > Titles > Import from a KBART file)
2) It should return an error saying that the file must be .csv or .tsv
3) Apply patch
4) yarn build
5) restart_all
6) Repeat step 1
7) The file should now successfully import

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-18 14:31:02 -06:00
Matt Blenkinsop e4a19c945e
Bug 36831: Move logic from the background job to the Title object class
This patch moves logic out of the background job file and into the Koha::ERM::EHoldings::Title class where it should belong. Methods are also renamed to differentiate between object methods and helper methods

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-18 14:31:00 -06:00
Matt Blenkinsop fb2c66189f
Bug 36831: Add a method to determine the file delimiter
This patch adds a method that will detect the delimiter and quote character for a file

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-18 14:31:00 -06:00
Nick Clemens f7897d7d81
Bug 31460: Merge item groups when merging records
Test:
1. Have a record (A) with 3 items.
2. Create an item group with 2 of these items.
3. Have a second record (B) with 4 items
4. Create an item group with 2 of these items.
5. Merge the two records together keeping record A
6. Results will show that all items are moved over to record A, but the item group from record B, is not there.
7. Apply patch
8. Create a new record (C) with 3 items.
9. Create an item group with 2 of these items
10. Merge this into record A
11. The item groups are moved!

Signed-off-by: Miranda Nero <mnero@oslri.net>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-18 13:52:09 -06:00
Julian Maurice 4df64c79f0
Bug 39980: Add license and POD to Koha::App::Controller::CGI
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-18 13:52:08 -06:00
Julian Maurice b92fda21ce
Bug 39980: Fix vendors pages when using Koha as a Mojo app
Bug 38010 broke the vendors pages when Koha is running as a Mojolicious
application

This adds new routes to Koha::App::Intranet to mimic the Apache rewrite
rules added in bug 38010.

To be able to do that, the CGIBinKoha plugin's code had to be moved to a
controller. The logic remains the same.

Test plan:
1. Run `bin/intranet daemon -l http://*:3000/`
2. Point your browser to http://localhost:3000 (replace localhost by the
   hostname/IP of koha's container, if needed)
3. Go to Acquisitions and search for a vendor. You should see the list
   of vendors.
4. Click on "New vendor" button. Notice the URL changed to
   .../acquisition/vendors/add.
5. Reload the page. You should still see the form to create a new vendor
6. Verify that you can create a vendor and that you are then redirected
   to the list of vendors

Signed-off-by: David Nind <david@davidnind.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-18 13:52:06 -06:00
Lucas Gass a16f1d4032
Bug 31698: Disallow moving waiting or intransit holds
Signed-off-by: kristi <kkrueger@cuyahogalibrary.org>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-05 15:10:41 -06:00
Lucas Gass 88a9eb7a2f
Bug 40665: DBIC Schema changes
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-05 15:10:37 -06:00
Paul Derscheid c0f191b79c
Bug 40665: Link checkouts to bookings
This patch adds a booking_id field to the issues and old_issues tables
to create a linkage between checkouts and the bookings that generated
them. When a patron with a booking checks out the reserved item, the
checkout is linked to their booking and the booking status is updated
to 'completed'.

The booking_id is preserved during renewals and when checkouts are
moved to old_issues upon return.

Database changes:
- Add booking_id column to issues and old_issues tables
- Add foreign key constraints to maintain referential integrity

Test plan:
1. Apply the database update
2. Restart services
3. Create a booking for a patron
4. When the patron checks out the booked item:
 a. Verify the checkout links to the booking (booking_id is set)
 b. Verify the booking status changes to 'completed'
5. Renew the checkout
 a. Verify the booking_id is preserved after renewal
 b. Check the database: SELECT booking_id FROM issues WHERE issue_id = X
6. Return the item
 a. Verify the checkout moves to old_issues
 b. Verify the booking_id is preserved in old_issues
7. Test the new Koha::Booking methods:
 a. For a booking with a checkout, verify $booking->checkout returns
    the correct Koha::Checkout object
 b. For a booking with an old checkout, verify $booking->old_checkout
    returns the correct Koha::Old::Checkout object
8. Test the API:
 a. Verify checkout endpoints include booking_id in responses
 b. Verify the booking relationship can be embedded using
    x-koha-embed: booking
9. Run the test suite:
 prove t/db_dependent/Circulation.t
 prove t/db_dependent/Koha/Booking.t
 prove t/db_dependent/Koha/Checkout.t

NOTE: I also thought about the inverse: linking to a checkout from the
booking, but as Koha is a circulation centric system, this approach makes
more sense in my opinion. I also thought about bidirectional linking via
FKs but that is too much maintenance overhead (and potential error source)
that we don't need. The inverse lookups should still be performant through
the FKs.

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-05 15:10:36 -06:00
Pedro Amorim 9482590909
Bug 39345: (QA follow-up): Add exception handling for unsupported counter release
To test this on the UI, you can add the following line of code at the beginning on 'new' in SushiCounter.pm:
->{response}->{Report_Header}->{Release} = 6;

This will force the release to be '6'. Then you can perform a harvest using the UI. The background job will fail with the error message saying that counter release 6 is not supported

prove t/db_dependent/Koha/BackgroundJobs/ErmSushiHarvester.t

Signed-off-by: Eric Phetteplace <phette23@gmail.com>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-05 15:10:31 -06:00
Pedro Amorim dcf28e5b8a
Bug 39345: (QA follow-up): Fix QA complaints
QA script still fails but I believe these are false positives caused by the tests files being moved

Signed-off-by: Eric Phetteplace <phette23@gmail.com>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-05 15:10:30 -06:00
Pedro Amorim ff82cd37f5
Bug 39345: Use data provider report release to establish service URL
Signed-off-by: Eric Phetteplace <phette23@gmail.com>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-05 15:10:29 -06:00
Pedro Amorim f58e2110ca
Bug 39345: Add COUNTER 5.1 support
This moves the original SUSHI COUNTER logic to a new
Koha::ERM::EUsage::COUNTER::5 class that extends
Koha::ERM::EUsage::SushiCounter.

Adds a new Koha::ERM::EUsage::COUNTER::5_1 class with COUNTER 5.1
specific logic.

Keeps common logic in Koha::ERM::EUsage::SushiCounter.

This ensures we support both COUNTER 5.0 and COUNTER 5.1, but should
hopefully help us better maintain COUNTER 5.1 going forward, without having
to worry about COUNTER 5.0, as the code is seperated.
This should also better set us up for adding support for possible future COUNTER releases.

Test plan, k-t-d:
1) Enable ERMModule
2) Add a new usage data provider at:
   <staff_url>/cgi-bin/koha/erm/eusage/usage_data_providers/add
3) Add the required credential parameters e.g. Customer ID and Requestor ID
4) Update the 'Report release' to '5.1', no single quote.
   (If you add anything other than '5', it'll default to '5.1')
5) Visit the list of data providers and click the 'Run now' button for your data provider:
   <staff_url>/cgi-bin/koha/erm/eusage/usage_data_providers
6) Click the background job link at the top. Verify the background job runs as expected.
7) After the successful harvest, run a custom report at, ensure the data is all correct:
   <staff_url>/cgi-bin/koha/erm/eusage/reports
8) Visit the data provider at:
   <staff_url>/cgi-bin/koha/erm/eusage/usage_data_providers/<provider_id>
9) Click the 'Import logs' tab, download the COUNTER 5.1 counter file.
   Open the file and verify the data is correct.

Signed-off-by: Eric Phetteplace <phette23@gmail.com>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-05 15:10:28 -06:00
Tomas Cohen Arazi 2bfb86afb5
Bug 40636: Add `Koha::Calendar->has_business_days_between()` method
This patch adds a new method to Koha::Calendar that returns a boolean indicating
whether there are any business days between two given dates (exclusive).

Implementation details:
* Returns 1 if any business days exist between start and end dates
* Returns 0 for consecutive days, same dates, or only holidays between
* Uses exclusive range (does not include start or end dates)
* Handles date comparison and timezone normalization
* Efficient early return when first business day is found

This is designed specifically for use cases like detecting missed
business days due to server downtime or scheduling issues.

To test:
1. Apply patch
2. Run:
   $ ktd --shell
  k$ prove t/db_dependent/Koha/Calendar.t
=> SUCCESS: All tests pass!
3. Sign off :-D

Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-05 08:02:30 -06:00
Pedro Amorim 6a729b4442
Bug 40644: Only count checkouts that have not yet been counted as bookings
Test plan:
1) Have a record with 8 items.
2) Place a booking on 6 of the items (6 bookings total) for a full month
   (e.g. August)
3) Check-out all 6 of those bookings
4) Attempt to place a new booking for one of the 2 free items for end of month, e.g. (Aug 26 -> Aug 28).
5) It will fail with error "Booking conflicts". This is because the code
   is adding 6 checkouts with 6 bookings = 12 which is higher than 8
bookable items.
6) With this patch, check-outs that refer to an existing booking are
   excluded, so the check becomes if 8 - 6 > 0 (which passes the check) rather than 8 - 12 > 0 (which fails the check)

Run existing tests:
prove t/db_dependent/Koha/Item.t
prove t/db_dependent/Koha/Biblio.t
prove t/db_dependent/Koha/Booking.t

Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-05 08:02:29 -06:00
Tomas Cohen Arazi cd4e1da3ec
Bug 40275: Use Koha::Patrons->find_by_identifier in the codebase
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>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-03 14:00:46 -06:00
Tomas Cohen Arazi 3f19d4bf85
Bug 40275: Introduce `Koha::Patrons->find_by_identifier()`
In our codebase, there's a pattern we tend to use for searching patrons
by userid and falling back to find them by cardnumber:

* C4::Auth
* C4::SIP::ILS::Patron
* (slightly different) Koha::REST::V1::Auth::Password
* (slightly different) Koha::REST::V1::Auth
* C4::Circulation
* C4::Auth_with_cas

It generally uses the following pattern:

```perl
my $patron = Koha::Patrons->find( { userid => $identifier } );
$patron //= Koha::Patrons->find( { cardnumber => $identifier } );
```

The problem with this is that `find` actually produces a DBIX::Class
warn because `find` is being called without primary key parameters. I
haven't seen it in the wild, until the latest change in
`checkpw_internal` which made it throw warnings in SIP. My
interpretation is that SIP's special approach with the Trapper.pm class
made it show where other places just get it hidden.

That said, I implemented this using `search()` to overcome this.

To test:
1. Apply the patches
2. Run:
   $ ktd --shell
  k$ prove t/db_dependent/Koha/Patrons.t
=> SUCCESS: Tests pass!
3. 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>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-03 14:00:45 -06:00
Martin Renvoize 5350a9276e
Bug 9762: (Alternative) Log circulation overrides
An alternative approach to the original submission for bug 9762. Instead
of recording a distinct action log line for a set of override messages
in addition to the standard issue record, this patch updates the
existing issue log to include any confirmation or impossible responses
from the preceeding CanBookBeIssued call.

We continue to record these as a JSON structure as the prior patch did,
but instead of human messages we use the predefined codes as returned
from the existing CanBookBeIssued response.

To test:

After each step, a single action log message should be displayed under
`Tools > Log viewer`. The message itself will now consist of a JSON
string with an array of 'confirmations' and 'forced' strings
representing the overriden feedback from CanBookBeIssued.

Circulation -- Checking out

1) Check out an item that is age-restricted (AgeRestrictionOverride syspref)
2) Check out an item that has a “not for loan” status (AllowNotForLoanOverride
   syspref)
3) Check out an item that has a “lost” status (IssueLostItem syspref)
4) Check out an item to a patron who has reached the checkout limit
   (AllowTooManyOverride syspref)
5) Check out an item to a patron who is not allowed to borrow this item type
6) Check out an item to a patron who has unpaid fines (AllFinesNeedOverride
   and/or AllowFineOverride + noissuescharge sysprefs)
7) Check out an item on hold for someone else
8) Check out an item on hold ready for pickup by someone else
9) Check out an item already checked out to someone else
   (AutoReturnCheckedOutItems syspref)
10) Check out to a patron who has restrictions

Circulation -- Checking in

11) Ignore a hold upon check in
12) Ignore a hold and transfer upon check in

Circulation – Renewing

13) Renew an item on hold for someone else
    (AllowRenewalOnHoldOverride syspref)
14) Renew an item that has reached the maximum number of renewals
    (AllowRenewalLimitOverride syspref)

Holds

15) Place a hold for a patron who is not allowed to place this item
    type on hold (AllowHoldPolicyOverride syspref)
16) Place a hold for a patron who has reached the maximum number of
    holds
17) Place an item-level hold when rules dictate that this is not
    allowed

Sponsored-by: OpenFifth <https://openfifth.co.uk/>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-03 11:42:10 -06:00
Lucas Gass 4c2eae043b
Bug 15516: DBIC Schema Updates
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-03 11:42:06 -06:00
David Cook c0ea7bd469
Bug 15516: (follow-up) fix count_holds() for CanBookBeReserved()
This patch adds search_attrs to count_holds() since these get
used with CanBookBeReserved.

Test plan:
0. Apply the patch
1. prove t/db_dependent/Koha/Holds.t t/db_dependent/Reserves/HoldGroup.t t/db_dependent/Reserves.t

Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-03 11:42:04 -06:00
David Cook 4864cd79cc
Bug 15516: (follow-up) Fix some merge bugs
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-03 11:42:02 -06:00
David Cook c1e7da6eed
Bug 15516: (follow-up) Tweaks to new feature
Bug 15516: Add ability to create and view hold groups from OPAC

This patch adds a "Treat as hold group" to opac-reserve.pl,
which lets OPAC users create a hold group which can include
1+ bibs and either bib-level holds, or item-level holds, or both.

This patch shows the item-level and bib-level holds in a hold group
for the user's holds in the OPAC. This includes both the opac-user.pl
page and the self-checkout hold display.

Bug 15516: (follow-up) Only show hold groups for multi hold in OPAC
Bug 15516: (follow-up) Only show hold groups for multi hold in staff interface
Bug 15516: Add 'DisplayAddHoldGroups' system preference to toggle ability to add titles to hold groups

These patches add the ability to create hold groups across multiple bibs in the staff interface or OPAC.
These hold groups are fulfilled by the first item checked in across the hold group.

Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-03 11:42:01 -06:00
Aleisha Amohia 8bfe38b3ba
Bug 15516: Relevant controller changes and tests
Signed-off-by: Michal Denar <black23@gmail.com>
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>

Signed-off-by: Michal Denar <black23@gmail.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-03 11:42:00 -06:00
Nick Clemens acdc512cea
Bug 40331: Return existing transfer if requesting a new transfer that is identical
Currently request_transfer checks for the existence of a current transfer on the item, and a new one can either be
enqueued or replace this transfer. This patch adds a check to see if the requested transfer matches an existing transfer
on the item. In the case that it does we simply return that transfer rather than create a new transfer.

This has the effect of eliminating 'WrongTransfer' generation if an item is checked in twice at the same branch, which feels correct.

To test:
 1 - place a hold on an item that is currently at branch A, for pickup at branch B
 2 - check your item in at Branch A, click to confirm the hold and transfer (print slip if you want to)
 3 - sudo koha-mysql kohadev: SELECT * FROM branchtransfers -- See one transfer
 4 - check your item in at Branch A again, get a message that the item is supposed to go to Branch B. Don't click on the modal yet
 5 - repeat 3 -- See two transfers, one cancelled as WrongTransfer, one pending
 6 - Click 'Confirm and transfer' on the modal
 7 - repeat 3 -- See three tranfers - the two from before and a new active transfer
 8 - DELETE FROM branchtransfers
 9 - Apply patch, restart all
10 - repeat 3 - no transfers
11 - Check item in at branch A again and confirm
12 - repeat 3, one transfer
13 - Check item in, don't confirm the modal
14 - repeat 3, one transfer
15 - Confirm the modal
16 - repeat 3, one transfer
17 - Check the item in at branch C
18 - repeat 3, two transfers - one cancelled WrongTransfer, one active
19 - Confirm modal
20 - repeat 3, two transfers
21 - Check item in at branch B
22 - repeat 3, two transfers, one cancelled, one completed

Signed-off-by: Christine Lee <chlee@pascolibraries.org>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-03 11:41:58 -06:00
Tomas Cohen Arazi 2da5c04c2d
Bug 40672: Reset desk_id when reverting waiting holds
This patch adds desk_id reset functionality to the revert_found method,
but only for waiting holds where desk_id is actually relevant.

Changes:
* Modified revert_found() to conditionally reset desk_id
* Only resets desk_id for waiting holds (found=W)
* Leaves desk_id unchanged for in transit (T) and in processing (P) holds
* Added comprehensive test coverage for all scenarios
* Updated POD documentation to explain desk_id behavior

The logic is conservative and only clears desk_id when it makes sense:
waiting holds have their desk assignment cleared since they are no longer
waiting at a specific desk, while transit and processing holds remain
unchanged as they do not use desk_id.

To test:
1. Apply patch
2. Run tests:
   $ ktd --shell
  k$ cd /kohadevbox/koha
  k$ prove t/db_dependent/Koha/Hold.t
=> SUCCESS: All tests pass including new desk_id handling tests
3. Verify all hold test suites still pass:
  k$ prove t/db_dependent/Koha/Hold*.t
=> SUCCESS: All hold-related tests pass
4. Sign off :-D

Signed-off-by: Emily Lamancusa <emily.lamancusa@montgomerycountymd.gov>

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-08-29 11:08:52 -06:00
CJ Lynce ba43483f4d
Bug 36536: Make REST APIs validateUserAndPassword update borrowers.lastseen
This patch added the option to update borrowers.lastseen when a patron username
    and password is verified via the REST API. This can be enabled or disabled
    selectively using the TrackLastPatronActivityTriggers system preference
    using the [ ] Patron authentication via API option..

To test:
1.  Create a new user, ensuring to set the Username and password fields.
	    *Import to do this first*
2.  Edit the TrackLastPatronActivityTriggers syspref and check all options.
3.  Ensure the RESTBasicAuth syspref is set to Enable.
4.  Check the lastseen date of your new user using a SQL report
        SELECT borrowernumber, userid, lastseen FROM borrowers WHERE userid = 'USERNAME'
        (Replace USERNAME with your chosen username for the new patron)
        NOTE: **Ensure the cache expiry of the SQL report is set to 0**
5.  The lastseen for your new user should be null
6.  'restart_all' Koha services to clear plack cache.
7.  Run the attached api_verify_lastseen.pl test script
        **Change P_USERNAME and P_PASSWORD to the username and password of your new user.
        (script contains expected output for successful verification)
8.  Re-check the lastseen date of your new user again via SQL (step 4)
        The lastseen should still be null.

9.  Apply Patch
10. 'restart_all' Koha services

11. Edit the TrackLastPatronActivityTriggers syspref and check the '[ ] Patron authentication via API' option
12. Rerun the api_verify_lastseen.pl
13. Re-check the lastseen date of your new user again via SQL (step 4)
        The lastseen should now be updated to the time of the last script run.

For good measure:
14. Edit the TrackLastPatronActivityTriggers syspref and **UNcheck** the '[ ] Patron authentication via API' option
15. 'restart_all' Koha services to clear plack cache.
16. Rerun the api_verify_lastseen.pl
17. Re-check the lastseen date of your new user again via SQL (step 4)
        The lastseen should have remained the same as previous.

Sponsored-by: Westlake Porter Public Library <https://westlakelibrary.org>
Signed-off-by: Bernard Scaife <bernard.scaife@openfifth.co.uk>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-08-29 11:08:44 -06:00
Pedro Amorim f16187e605
Bug 40653: Add cookie to output_html
Test plan, k-t-d, don't apply patch yet:
1) Install a plugin that sends the cookie to output_html e.g.:
https://github.com/openfifth/koha-ill-libkey-lending-tool/releases/tag/v2.3.8
2) Log out. Access this plugin's tool link directly:
<staff_url>/cgi-bin/koha/plugins/run.pl?class=Koha%3A%3APlugin%3A%3ACom%3A%3APTFSEurope%3A%3AIncDocs&method=tool
3) Notice you're presented the login screen. Login using koha:koha
4) Notice you're shown the plugin's respective tool page. It looks like you're authenticated but you're not. Click on any of the top links e.g. 'Circulation' or 'Patrons'.
5) Notice you're shown the login page again.
6) Apply patch. Repeat. Step 5 should no longer show the login page but instead the page you clicked on.

Signed-off-by: Tomas Jiglind <tomas.jiglind@mariestad.se>
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-08-29 10:43:44 -06:00
Tomas Cohen Arazi ca8ef54949
Bug 40579: Fix CSV formula injection vulnerabilities
This patch addresses CSV formula injection vulnerabilities by ensuring
all Text::CSV instances use formula protection.

Changes made:
* Add formula => 'empty' to all Text::CSV constructors in:
  - Koha::Patrons::Import
  - Koha::BackgroundJob::ImportKBARTFile
  - Koha::ERM::EUsage::CounterFile

The 'empty' formula mode causes potentially dangerous formulas (starting
with =, +, -, @) to be treated as empty strings rather than executed,
preventing CSV injection attacks while maintaining data integrity.

Security impact:
* Prevents execution of malicious formulas in CSV imports
* Protects against data exfiltration via CSV formula injection
* Maintains backward compatibility for legitimate CSV data

To test:
1. Apply the previous patch (author test)
2. Run:
   $ ktd --shell
  k$ prove xt/author/Text_CSV_Various.t
=> FAIL: Should show 3 files without formula protection
3. Apply this patch
4. Repeat 2
=> SUCCESS: All tests should now pass
5. Try importing CSV with formula content (=cmd|"/c calc",test,data)
=> SUCCESS: Formula content is rejected/emptied, not executed
6. Import normal CSV data
=> SUCCESS: Normal data imports correctly
7. Sign off :-D

Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-08-29 10:43:39 -06:00
Marcel de Rooy c11dce94c1
Bug 37651: (follow-up) Still skip future holds for renewals
We need a skip_future_holds flag in item->current_holds to make renewals
act as they did before. There is no need to add it to biblio->current_holds.

Test plan:
Run t/db_dependent/Holds.t
Interface test: Issue a book, place hold on tomorrow, set ConfirmFutureHolds
to 2 days. Verify that renew is not blocked by this hold.

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-08-29 10:43:33 -06:00
Martin Renvoize d2f20b00f1
Bug 37651: (QA follow-up) Add POD for Biblio method
We were missing POD here.

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-08-29 10:43:31 -06:00
Marcel de Rooy eedd4bcf2e
Bug 37651: Add ConfirmFutureHolds to biblio->current_holds
Test plan:
Easy way is to run the unit tests in the next patch.
One call of biblio->current_holds is hidden in acqui/parcel.pl. The
table column "Item holds / Total holds" should now make a difference
for an order referring to an item having future holds.

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-08-29 10:43:30 -06:00
Marcel de Rooy 503a81efe1
Bug 37651: Add ConfirmFutureHolds to item->current_holds
Test plan:
Add future item level hold for another branch.
Check in. Confirm and transfer.
Note that without this patch, there is no patron info for the column
On hold for on transferstoreceive.

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-08-29 10:43:29 -06:00
Tomas Cohen Arazi bd9fa395e5
Bug 40671: Refactor Koha::Hold->revert_waiting into revert_found
This patch refactors the revert_waiting method to handle all found statuses
instead of just waiting holds, making it more versatile and consistent.

Changes:
* Renamed method from revert_waiting() to revert_found()
* Expanded functionality to handle all found statuses (W, T, P)
* Updated exception logic to check is_found instead of is_waiting
* Changed exception message from hold_not_waiting to hold_not_found
* Added comprehensive tests for all found statuses
* Updated POD documentation to reflect new behavior

The method now reverts any hold with a found status back to a regular
hold with priority 1, regardless of whether it was waiting, in transit,
or in processing.

To test:
1. Apply the patches
2. Run tests:
   $ ktd --shell
  k$ cd /kohadevbox/koha
  k$ prove t/db_dependent/Koha/Hold.t
=> SUCCESS: All tests pass including new subtests for T and P statuses
3. Verify all hold test suites pass:
  k$ prove t/db_dependent/Koha/Hold*.t
=> SUCCESS: All hold-related tests pass
4. Sign off :-D

Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Emily Lamancusa <emily.lamancusa@montgomerycountymd.gov>

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-08-29 10:43:14 -06:00
Lucas Gass 80caf086fd
Bug 37901: Fix DBIC Schema by removing PseudonymizedBorrowerAttribute.pm
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-08-25 09:08:12 -06:00
Lucas Gass 3420b021e8
Bug 37901: Fix Schema
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-08-21 11:44:19 -06:00
Lucas Gass 45a4f81830
Revert "Bug 39482: Correct the link to edit OpacLibraryInfo from library edit page"
This reverts commit 699ea73a93.

Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-08-20 15:57:00 -06:00
Lucas Gass 6ff3ce8037
Bug 37901: Schema updates
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-08-20 13:43:27 -06:00
Pedro Amorim 4a9c2a3655
Bug 37901: UpdateStats after new ILL request is created or completed
Signed-off-by: Jeremy Evans <Jeremy.Evans@ukhsa.gov.uk>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-08-20 13:43:24 -06:00
Pedro Amorim eb23776a3b
Bug 37901: Update Statistic.pm
Consider 'ill' as a category and 'illreq_created' and 'illreq_comp'  as allowed types

Signed-off-by: Jeremy Evans <Jeremy.Evans@ukhsa.gov.uk>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-08-20 13:43:23 -06:00