store() only flushes the _holidays cache on insert, on the assumption that
updates only ever touch title/description. That assumption held for every
current caller (ModSingleholiday/ModExceptionholiday only ever change those
two fields), but nothing enforced it - a future caller updating date in
place would silently desync the cache for up to its TTL, with no error.
Make the assumption explicit: reject an update that changes date, rather
than silently allowing it. Callers that need to move a closure/exception to
a different date must delete and re-add.
Test plan:
1) prove t/db_dependent/Koha/Library/Calendar.t t/db_dependent/Calendar.t
t/db_dependent/Holidays.t t/db_dependent/HoldsQueue.t
Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
C4::Calendar::insert_week_day_holiday used to croak "Invalid weekday
$weekday" unless $weekday =~ m/^[0-6]$/. That guard was dropped when the
insert delegated to Koha::Library::Calendar::WeeklyClosure, and nothing
replaced it - an out-of-range or undef weekday now persists silently to
library_weekly_closures instead of failing at the API boundary.
Add the check to WeeklyClosure->store() rather than the legacy wrapper, so
every caller (C4::Calendar, Koha::Library::Calendar->add_weekly_closure,
and any future REST/admin caller) gets it, not just the old entry point.
Test plan:
1) prove t/db_dependent/Koha/Library/Calendar.t t/db_dependent/Calendar.t
t/db_dependent/Holidays.t t/db_dependent/HoldsQueue.t
t/db_dependent/Holds/WaitingReserves.t
Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
insert_single_holiday and insert_exception_holiday delegate to
Koha::Library::Calendar::SingleClosure/Exception, but stopped updating
$self->{single_holidays}/{exception_holidays} on the C4::Calendar object
itself, unlike the sibling insert_week_day_holiday/insert_day_month_holiday
methods which still do. isHoliday() reads exactly those hashes, so a date
just inserted via insert_single_holiday/insert_exception_holiday would read
back as "not a holiday" for the rest of that object's lifetime - reachable
from tools/newHolidays.pl and tools/exceptionHolidays.pl, which loop over
several dates on one $calendar object, checking isHoliday() before each
insert to skip duplicates.
While adding a regression test, also found that _init() has the same class
of bug on the DB-load path: it builds the single/exception lookup keys from
`split(/-/, $row->{date})`, which keeps the zero-padding from the DATE
string (e.g. "06"), while isHoliday() numifies its lookup key (e.g. "6").
Any single/exception holiday with a single-digit month or day was therefore
invisible to isHoliday() even on a freshly reloaded C4::Calendar object.
Both call sites now numify year/month/day before building the hash key.
Test plan:
1) prove t/db_dependent/Holidays.t t/db_dependent/Calendar.t
t/db_dependent/Koha/Library/Calendar.t t/db_dependent/HoldsQueue.t
Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
The normalization commit dropped `repeatable_holidays` and
`special_holidays` but t/db_dependent/Holidays.t still referenced them
directly via raw SQL, so the test blew up on the first
`DELETE FROM special_holidays` with "Table doesn't exist". The earlier
namespace follow-up touched this file but only renamed Koha::Calendar
references, missing the SQL.
Replace the legacy table references with the four new normalized tables:
repeatable_holidays (weekday set) -> library_weekly_closures
repeatable_holidays (weekday NULL) -> library_repeating_closures
special_holidays (isexception=0) -> library_single_closures
special_holidays (isexception=1) -> library_closure_exceptions
- Two fixture-cleanup DELETEs now wipe all four new tables.
- The copy_to_branch 'no duplicates' check, previously two raw-SQL
queries against the old two tables, becomes four queries against the
new tables, keyed on each table's natural unique key
(library_id+weekday / library_id+day+month / library_id+date).
- Plan for the copy_to_branch subtest bumps from 8 to 10 to cover the
two extra duplicate-check assertions.
Test plan:
1. prove t/db_dependent/Holidays.t
2. All 15 top-level tests pass, including the 10 subtest assertions in
copy_to_branch.
Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Koha::Calendar is, by construction, a per-library object — it croaks
without a branchcode argument and every method is branch-scoped. The
top-level namespace hides that. Move the whole tree under
Koha::Library::Calendar to match the actual semantics, the existing
/libraries/{library_id}/calendar REST routes, and the established
Koha::Library::* convention (Group, Hour, FloatLimit, OverDriveInfo).
This commit:
- renames the Koha::Calendar(::*) tree to Koha::Library::Calendar(::*)
- updates package declarations, POD and internal 'use' statements
within the moved tree
- updates the four DBIC Schema Result overrides (koha_object_class /
koha_objects_class) to the new namespace
- updates callers inside C4::* modules (Calendar, Circulation,
Reserves, Overdues, HoldsQueue), Koha::{Patron,Hold,Checkouts,
CurbsidePickup}, circ/returns.pl, the installer and cronjobs
- updates the 42310-owned tests (Calendar tests, HoldsQueue.t,
Holds/WaitingReserves.t, Holidays.t, Koha/CurbsidePickups.t,
Reserves/CancelExpiredReserves.t and the libraries.t CRUD block)
Koha::Library->calendar, the REST controllers and the 42311 tests
are updated in separate follow-up commits under their respective
bugs.
Test plan:
- prove t/db_dependent/Koha/Library/Calendar.t
- prove t/db_dependent/Calendar.t
- prove t/db_dependent/Holidays.t t/db_dependent/HoldsQueue.t
- prove t/db_dependent/Holds/WaitingReserves.t
- prove t/db_dependent/Reserves/CancelExpiredReserves.t
Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Introduces a public Koha::Calendar->closed_dates_in_range($from_dt,
$to_dt) method that returns an arrayref of ISO date strings representing
every closed day in the inclusive range, honouring weekly, annual
repeating, single and exception (open-override) closures.
This replaces callers that were reaching into Koha::Calendar private
state (_holidays, weekly_closed_days, day_month_closed_days) to
reconstruct the same logic. A follow-up under Bug 42206 converts the
REST controller; further callers can be migrated incrementally.
Test plan:
1. prove t/db_dependent/Koha/Calendar.t
2. Verify the new 'closed_dates_in_range' subtest passes
Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
The new calendar tables add UNIQUE(library_id, weekday),
UNIQUE(library_id, day, month) and UNIQUE(library_id, date) constraints
that did not exist on repeatable_holidays / special_holidays, so the
INSERT IGNORE migration can silently drop legacy duplicate rows.
This patch compares source vs destination row counts for each of the
four migrations and emits a say_warning naming the constraint and
pointing the operator at their pre-upgrade backup so titles or
descriptions can be recovered if needed. Success lines now include
the migrated row count. DROP statements for the legacy tables are
guarded with TableExists and reported via say_success for
consistency with the rest of the atomicupdate.
Test plan:
1) Apply the update on a database containing legacy duplicates and
verify the warning is emitted with the correct count.
2) Apply on a database with no duplicates and verify no warning
appears.
3) Re-run the update and verify it is idempotent (no warnings, no
re-migration).
Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Wrap the body in schema->txn_do so a failure partway through does not
leave the target library partially populated. Flush the target's
_holidays cache after the copy, and document the behaviour in POD:
weekly and repeating closures are always copied, but single closures
and exceptions are filtered to today-or-later dates by design.
Test plan:
1) prove t/db_dependent/Koha/Calendar.t
2) Confirm existing copy_to tests still pass.
Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
The four delete_*_closure / delete_exception methods in Koha::Calendar
were calling ResultSet->delete, which issues a single bulk SQL DELETE
and never calls the row-level delete() override. The cache-invalidation
hooks on Koha::Calendar::SingleClosure->delete and
Koha::Calendar::Exception->delete were therefore skipped when callers
went through $library->calendar->delete_single_closure(...) or
delete_exception(...), and the <library>_holidays cache kept reporting
deleted dates as closed until its TTL expired.
The underlying tables enforce UNIQUE constraints on (library_id, weekday),
(library_id, day, month) and (library_id, date), so each search can
match at most one row. Switch the four methods to ->search({...},
{ rows => 1 })->single followed by ->delete on the row, which both
makes the single-row expectation explicit and ensures the per-row
delete override runs.
A regression test is added to t/db_dependent/Koha/Calendar.t asserting
that the _holidays cache is cleared after delete_single_closure and
delete_exception.
Test plan:
1) prove t/db_dependent/Koha/Calendar.t
2) Confirm the new 'delete_*_closure clears _holidays cache' subtest
passes.
Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
When using the new Koha::Calendar::* classes for writing the CRUD API
endpoints I noticed that in my attempt to keep C4::Calendar similar to what it
was, I ended up with cache invalidation not always done in the right place.
The holidays cache (keyed by {branchcode}_holidays) stores dates and their
open/closed status, not titles or descriptions. This means only inserts and
deletes need to invalidate it — metadata updates (title/description) do not.
Following the pattern established by Koha::AuthorisedValue and Koha::ItemType,
I added store() and delete() overrides to Koha::Calendar::SingleClosure and
Koha::Calendar::Exception:
- store() flushes the cache only on insert (!in_storage), not on updates,
since the cache doesn't store titles or descriptions.
- delete() always flushes, since removing a closure changes the cached set.
This allowed removing the now-redundant _clear_cache calls from
Koha::Calendar::add_single_closure, add_exception, delete_single_closure,
delete_exception, and from C4::Calendar::ModSingleholiday and
ModExceptionholiday.
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: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Add to Koha::Calendar:
add_weekly_closure, add_repeating_closure, add_single_closure,
add_exception, delete_weekly_closure, delete_repeating_closure,
delete_single_closure, delete_exception, copy_to, _clear_cache
C4::Calendar write methods now delegate to Koha::Calendar instead
of using raw DBI. No old table references remain in C4::Calendar.
Tests in t/db_dependent/Koha/Calendar.t cover all CRUD operations:
create, verify via is_holiday, delete, copy_to (including
idempotency).
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: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Replace all references to the dropped tables (RepeatableHoliday,
SpecialHoliday resultsets and raw DBI inserts) with Koha::Object
classes: Koha::Calendar::WeeklyClosure, RepeatingClosure,
SingleClosure, and Exception.
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: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Add koha_object_class/koha_objects_class overrides for the four new
Result classes backing the normalized calendar tables, below the
auto-generated marker.
Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Regenerated via dbic --force after the library_weekly_closures,
library_repeating_closures, library_single_closures, and
library_closure_exceptions tables replaced repeatable_holidays and
special_holidays.
Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
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: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Replace raw DBI queries in _init() and _holidays() with
Koha::Calendar::WeeklyClosures, RepeatingClosures, SingleClosures,
and Exceptions searches.
The internal data structures remain identical (weekly_closed_days
array, day_month_closed_days hash, _holidays hash with YYYYMMDD
keys) so all consumers (is_holiday, addDuration, next_open_days)
continue to work unchanged.
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: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Four Koha::Object + Koha::Objects pairs following the Koha::City(ies)
pattern:
- Koha::Calendar::WeeklyClosure(s) -> library_weekly_closures
- Koha::Calendar::RepeatingClosure(s) -> library_repeating_closures
- Koha::Calendar::SingleClosure(s) -> library_single_closures
- Koha::Calendar::Exception(s) -> library_closure_exceptions
DBIC schema files to be generated via the 'dbic' alias in KTD
after the database migration runs.
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: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Replace the two overloaded tables (repeatable_holidays, special_holidays)
with four purpose-specific tables:
- library_weekly_closures: weekly closed days (e.g. every Sunday)
- library_repeating_closures: annual repeating closures (e.g. Dec 25)
- library_single_closures: one-off closures with a DATE column
- library_closure_exceptions: open overrides with a DATE column
All use library_id FK and follow current community standards. It points to API
usage in a short term so it follows the API naming conventions.
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: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
$due_interval and $due_date (and $recall itself) returned by
Koha::Recalls->add_recall were captured but never used in either
branch of the new rank => "recall" handling. Drop the unused
assignment - no behaviour change.
Test plan:
1) prove t/db_dependent/Holds.t t/db_dependent/Reserves.t - all pass
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Two code paths introduced by this bug had no direct test coverage:
- C4::Reserves::ModReserve's title-level branch of the new
`rank => "recall"` conversion (only the item-level branch was
tested).
- The `hold_convert` bypass in Koha::Item::can_be_recalled, which
skips the "patron already has a hold on this item" check so an
existing hold can be converted to a recall for the same patron.
No production code changes here, coverage only.
Test plan:
1) prove t/db_dependent/Holds.t t/db_dependent/Koha/Item.t - all pass
2) Confirm the new tests actually exercise the code they claim to:
reverting the `unless ( $params->{hold_convert} )` guard in
Koha/Item.pm locally makes the new Item.t subtest fail, as
expected.
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
UseRecalls was converted from a YesNo syspref to a Choice preference
("off"/"opac"/"staff"/"opac_and_staff") earlier in this bug, and every
call site was updated from a truthy check to `ne "off"` - except this
one. Since even the string "off" is truthy in Perl, the guard in
Koha::REST::V1::Transfers::cancel was silently defeated: cancelling a
transfer via the REST API always attempted to revert an in-transit
recall, even with recalls disabled.
Test plan:
1) prove t/db_dependent/api/v1/transfers.t - new subtest
'cancel() - UseRecalls disabled' fails against the old code
(the in-transit recall gets reverted even though UseRecalls is off)
2) Apply this patch
3) Same test now passes
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
js/tables/bookings.js unconditionally called AdditionalFilters.init()
for 'filter-completed' and 'filter-cancelled' on every page load where
the script is included. patron-detail-tabs.inc only renders those
filter elements (and #bookings_table itself) when the patron has at
least one booking, past or present. For any patron with no booking
history, this produced two console.debug 'Element not found' messages
on moremember.pl and circ/circulation.pl.
Guard the ready handler on the presence of #bookings_table, mirroring
the existing pattern in holds.js.
Test plan:
1) Open moremember.pl for a patron with no bookings; confirm no
AdditionalFilters console messages appear.
2) Open moremember.pl / circ/circulation.pl for a patron with
bookings; confirm the Bookings tab, filters, and table still work
as before.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
As a continuation of bug 41919, we should limit the total number of simultaneous reports that can be run at a time.
Test Plan:
1) Set total_running_reports_per_instance_limit to 2 in your koha-conf.xml
2) Create 3 long running reports like: SELECT COUNT(*) FROM items i1 JOIN items i2 JOIN items i3 JOIN items i4 JOIN items i5 JOIN items i6
3) Run each report in turn by opening a new tab, browsing to the reports
module, and choosing to run that report
5) Note the first two continue to run, but the last one gives an error
that you have too many reports running simultaneously!
Signed-off-by: Alex Carver [Acerock7] <alex@rcls.org>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
When an authorised value is limited to more than one library, the
no_limit query in GetAuthorisedValues joins authorised_values_branches
and returns one row per associated library, so the value was listed
several times in the item edition dropdown.
Group by the authorised value so each one is only returned once, and
aggregate the restricted flag with MIN() so the value stays
unrestricted as soon as one of its libraries matches the current one.
Sponsored-by: BibLibre
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
When we set an authorised value linked to one library,
users who do not belong to this library do not get the
value and can therefore overwrite it.
This patch add current value to the dropdown list even if it comes from an authorized value of another library.
Test plan :
1) Edit an item with one of these fields has an authorized value from
another library.
2) On 'edit' you will see AV but with '(Not an authorised value)' string
and a warn
3) Apply this patch
4) Refresh page and edit item again
5) Now if the authorised value belongs to another lib and is the current
value, you will see it with a tooltip and a warn. But if there are
authorised values restricted to another lib and isn't current value,
normally it will be not present in the option list.
Sponsored-by: BibLibre
Signed-off-by: Mathieu Saby <mathsabypro@gmail.com>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
The previous follow-up only blanked the button's label via JS for
users without the recalls permission; the button still rendered,
was still clickable, and modrequest.pl's cud-convertall had no
permission check at all, so the conversion still succeeded.
Adds CAN_user_recalls to the button's template condition (matching
the existing "Move selected holds" button) so it doesn't render at
all without the permission, drops the now-redundant JS check in
holds.js, and adds a manage_recalls check in modrequest.pl itself.
checkauth()'s userid is the login username, not a borrowernumber, so
this uses C4::Auth::haspermission() directly rather than
Koha::Patrons->find().
Test plan:
1) Set a default recalls rule in admin/smart-rules.pl.
2) Set UseRecalls to 'staff' or 'opac_and_staff'.
3) Give a test patron 'catalogue' + 'reserveforothers' but not
'recalls'.
4) Check out an item, place a hold on it for another patron.
5) As the test patron, go to that record's Holds tab, confirm
'Convert selected to recall' doesn't appear.
6) Since the button is gone, confirm the server side is enforced too:
post op=cud-convertall directly to modrequest.pl and confirm it no
longer converts the hold.
7) Grant 'recalls' and confirm the button reappears and works.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
This introduces a permission check on "recalls" for the link on the holds summary page.
1) Go to http://localhost:8081/cgi-bin/koha/admin/smart-rules.pl, and under the default rule, set:
- 'Recalls allowed (total)': 5
- 'Recalls per record': 3
- 'On shelf recalls allowed': if any unavailable
- 'Recall due date interval': 5
- 'Recall overdue fine amount': 5
- 'Recall pickup period': 2
2) Go to 'Administration' > 'Global system preferences' (http://localhost:8081/cgi-bin/koha/admin/preferences.pl?op=search&searchfield=UseRecalls), set 'UseRecalls' to 'can be placed through the staff interface only'.
3) Go to Henry's patron account, borrowernumber 19, set him a password (http://localhost:8081/cgi-bin/koha/members/member-password.pl?member=19), then edit his permissions (http://localhost:8081/cgi-bin/koha/members/member-flags.pl?member=19) and give him only 'catalogue' and 'reserveforothers' (place holds), do not give him 'recalls'.
4) As a superlibrarian, check out item 39999000003154 (biblionumber 76) to borrowernumber 23, then place a hold on that same record for borrowernumber 49
5) Log out and log back in as Henry.
6) Go to http://localhost:8081/cgi-bin/koha/reserve/request.pl?biblionumber=76, tick the checkbox next to the hold, click 'Convert selected to recall', confirm in the modal.
7) The hold gets cancelled and a recall gets created, even though Henry has no recalls permission at all, proving the action isn't actually gated by it.
8) Apply patch, re-run test plan to 6) - The link to convert should no longer display.
9) Toggle the recalls permission for Henry, link to convert should now reappear.
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
The code was using the patron's home library instead of passing the pickup-location
of the original hold. This is a simple variable change in 2 places for record level and item
level holds.
A) Set 'UseRecalls' to 'staff' at http://localhost:8081/cgi-bin/koha/admin/preferences.pl?op=search&searchfield=UseRecalls
B) At http://localhost:8081/cgi-bin/koha/admin/smart-rules.pl set the default rule: 'Recalls allowed' = 5, 'Recalls per record' = 3, 'On shelf recalls allowed' = 'if any unavailable' (not 'all').
C) Use biblionumber '437' (has just one item, barcode '39999000019186'), check that item out to 'Henry Acevedo' (Patron A).
D) Place a record-level hold on it for 'Johnny Bryan' (Patron B), who's from 'Midway' — but set the hold's pickup location to 'Centerville' instead.
E) On http://localhost:8081/cgi-bin/koha/reserve/request.pl?biblionumber=437, tick the hold, click 'Convert selected to recall', confirm.
F) Check the new recall's pickup location on http://localhost:8081/cgi-bin/koha/recalls/request.pl?biblionumber=437
- Expected: 'Centerville'
- Without the patch applied, it will be the patron's home library: Midway
- With the patch applied, the pickup-location of the hold is kept: Centerville.
G) Cancel the recall.
H) Repeat the test plan, but in step D) place an item level hold instead of a record level hold.
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
We are skipping the notice, if UseRecalls == "off".
This now matches the check in staff too.
A) Go to the KTD staff interface at http://localhost:8081/cgi-bin/koha/admin/preferences.pl?op=search&searchfield=UseRecalls and set 'UseRecalls' to any non-'off' value, e.g. 'can be placed through the OPAC only'.
B) Log into the OPAC at http://localhost:8080/cgi-bin/koha/opac-user.pl as any patron.
C) Go to http://localhost:8080/cgi-bin/koha/opac-messaging.pl
D) Look for the recall-related notice row (item recalled / recall notices) — it's missing, even though recalls are enabled.
E) Now flip 'UseRecalls' back to 'off' in step 1's page.
F) Reload http://localhost:8080/cgi-bin/koha/opac-messaging.pl — the recall notice row now shows up, even though recalls are off.
G) Steps 4 and 6 are the reverse of what should happen — confirms the condition is inverted.
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
This fixes a test to use 'opac' in transfers.t
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
The pref was mocked to '1' (the old value) in Holds.t
Test now uses 'opac_and_staff'
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Fixes a problem with the template variables that made the recall button
show in some places when UseRecalls was set to off.
As the problem was in item-status.inc that is used in several pages,
a small fix goes far here.
Part 1: opac-detail.tt / opac-basket.tt (default config, useRecalls = 'off')
1) Confirm UseRecalls is at its default (off)
2) Check out item 39999000003154 to patron 'Henry Acevedo'
3) Log into the OPAC as a different patron (e.g. koha user)
4) As koha user, go to the biblio detail page for the record we just checked out:
http://localhost:8080/cgi-bin/koha/opac-detail.pl?biblionumber=76
5) Look at the item's status row: next to "Checked out", a "Recall" button is visible, even though UseRecalls is off.
6) Click it, lands on opac-recall.pl, shows a "Recalls have not been enabled. Please contact your library.", which confirms it's a dead-end button that never should have rendered.
7) Same thing reproduces in the basket: as koha user, add that biblio to your cart (Add to cart on the results/detail page), then click the cart icon on the top left. The same button erroneous will show.
Part 2: opac-course-details.tt — staff-only mode still leaks the OPAC link
1) Continuing from the previous instructions: Set UseRecalls to "can be placed through the staff interface only".
2) Add the same checked-out item (39999000003154) to a course reserves list — http://localhost:8081/cgi-bin/koha/course_reserves/course-details.pl?course_id=1
3) Click "Add reserves"
4) As koha user on the OPAC, view that course's page: http://localhost:8080/cgi-bin/koha/opac-course-details.pl?course_id=1
5) The "Recall" button shows here too, even though UseRecalls=staff should mean OPAC patrons can't place recalls at all.
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
This follow-up includes the following changes:
- only allow a recall cancellation via the OPAC if UseRecalls is enabled for the OPAC.
- uses singleBranchMode var passed by C4::Auth in staff interface biblio recalls
- drops unused attribute_type_codes var
- drops unnecessary items var and uses biblio.items in template
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Adds a new entry "Place recall" to the detail page's toolbar, visible when:
- UseRecalls is set to allow recalls in staff
- User has recalls permission
This matches the behavior for holds and bookings, so seems to increase
consistency.
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
This enhancement adds the ability to place recalls via the staff
interface by changing the UseRecalls system preference to have choices which
describe where recalls can be placed. Recalls can either be placed via
the OPAC, or the staff interface, or both. To be set to OPAC would be
consistent with current 'on' behaviour. UseRecalls is turned off by default.
This enhancement also adds the ability to convert existing holds to
recalls easily via the staff interface. The hold will be cancelled
and a recall placed using the hold's information.
To test:
1) Update database and restart services
2) Set UseRecalls to OPAC and set the relevant recalls circulation rules
OPAC only by default
3) Check out Item A to Patron B.
4) Log into the OPAC as Patron A. Confirm you can place, view and cancel
recalls as normal.
5) In the staff interface, set UseRecalls to Staff interface only.
6) In the OPAC, confirm you can still view and cancel recalls, but can
no longer place recalls.
7) In the staff interface, search for Item A and go to the Holds tab.
Place a hold for Patron C.
8) Check the checkbox for your hold and confirm the counts in the buttons above the Holds table are incremented as expected.
9) Click the button to Convert selected holds to recalls, a modal should pop up. Confirm all of the information is correct.
10) Confirm the conversion and once the page refreshes, your hold should be correctly cancelled using the new RECALLED reason.
11) Go to the Recalls tab. Confirm your hold has been converted to a
recall, and details like the patron, expiration, and pickup location have
carried across to the recall.
12) On this Recalls page, use the patron search to find Patron D. Test
placing a record-level recall by choosing to recall the next available item.
13) When the page refreshes, confirm the recall was successfully placed
with the correct details stored.
14) Repeat steps 12 and 13 with Patron E, this time place an item-level
recall by choosing an item in the 'place a recall on a specific item'
table. When selecting one of these items, the 'recall next available
item' section should become disabled.
15) Set UseRecalls back to OPAC only. Go back to the record and
view the Recalls tab.
16) Confirm you cannot search for a patron to place a recall, but can
still view and cancel recalls. Confirm you also cannot convert holds
to recalls.
17) Set UseRecalls to both staff interface and OPAC. Confirm you
can place recalls on both interfaces.
18) On the staff interface, test placing recalls that your circulation
rules do not allow. For example, if 'recalls per record' is 1, ensure
you're blocked from placing a second recall on a record for a patron. Another example, testing converting a hold to a recall when there are NO checked out items, as recalls can only be placed if something is checked out.
19) Place a hold for one of the patron's that already has a recall.
Once complete, try to convert this hold into a recall. Confirm you
are blocked and shown a message that the hold cannot be converted to a
recall.
20) Confirm patron messaging preferences for recalls notices can still be configured as expected.
21) Ensure tests pass:
* t/db_dependent/Circulation.t
* t/db_dependent/Circulation/transferbook.t
* t/db_dependent/Holds.t
* t/db_dependent/Koha/Biblio.t
* t/db_dependent/Koha/Item.t
* t/db_dependent/SIP/Transaction.t
* t/db_dependent/Search.t
* t/db_dependent/XSLT.t
Sponsored-by: Auckland University of Technology
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>