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>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
MySQL 8.4 requires foreign keys to reference PRIMARY KEY or UNIQUE keys.
Since authorised_values.authorised_value is only unique in combination
with category (composite UNIQUE key av_uniq), the FK constraint is not
compatible with MySQL 8.4+.
Data integrity for illrequests.status_alias is maintained at the application layer:
- Koha::ILL::Request->status_alias() validates values against
authorised_values (category='ILL_STATUS_ALIAS') before storing
- All ILL request operations in Koha use this object layer
- CASCADE behaviors (ON DELETE SET NULL, ON UPDATE CASCADE) are already
handled by the application layer when modifying/deleting authorised values.
Test Plan, using KTD:
1. Prepare KTD for MySQL 8.4
- In koha-testing-docker, edit 'compose/db-mysql.yml'
- Comment out the line 5:
`# command: --default-authentication-plugin=mysql_native_password`
Note: This is required because MySQL 8.4 doesn't support the native password plugin.
2. Start a new instance with MySQL 8.4
- `DB_IMAGE=mysql:8.4 ktd up`
- Observe that it fails to start with the errors such as 'DBD::mysql::st execute failed'
3. Apply the patch
- `git bz apply 39107`
4. Start the instance again
- `DB_IMAGE=mysql:8.4 ktd up`
- Observe that it starts successfully
5. Update the database (Optional, only for existing instances)
- `perl installer/data/mysql/updatedatabase.pl`
6. Access Koha Staff and OPAC interfaces and verify that everything works as expected
7. Sign off
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Emily Lamancusa <emily.lamancusa@montgomerycountymd.gov>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
I don't know if this is appropriate for master as it requires Koha objects,
but this is helpful for upgrading sites to avoid any problems from old mappings
for local-number
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Thomas Klausner <domm@plix.at>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
See comment 4 for a detail explanation of the problem.
Test plan:
hit /cgi-bin/koha/installer/install.pl
login with the DB credentials
upgrade
=> Without this patch you get
```
ISBN_RANGE_MESSAGE is set to [] but that file does not exist!
Trying to use the default locations
```
=> With this patch applied: "Everything went okay. Update done."
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Emily Lamancusa <emily.lamancusa@montgomerycountymd.gov>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This patch removes an ISBN_RANGE_MESSAGE env variable that is
accidentally set by Business::ISBN::Data.
Test plan:
- git checkout v25.11.03-2
- reset_all
- git checkout -b 42374 origin/main
- Apply the patch
- restart_all
- Go to staff interface (e.g. http://localhost:8081/)
- Log into web installer
- Click "Update your database"
- Note it works
- Repeat the process but instead of using the web installer
use updatedatabase.pl directly (say through koha-upgrade-schema)
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Emily Lamancusa <emily.lamancusa@montgomerycountymd.gov>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This patch splits delete_reports into delete_own_reports and delete_all_reports
While delete_all_reports supercedes delete_own_reports it seems to make more sense than
delete_own_reports and delete_others_reports.
With delete_all_reports we can have a user who can delete all, without specific permission to delete their own
The other way we would have delete others, and you could not delete your own, which seems more odd
To test:
1 - Have 2 users - 1 with delete_reports, 1 without
2 - Apply patches, update database
3 - Confirm user with permission now has 'delete_all_reports' and other user still has no reports deletion permission
4 - Give the second user 'delete_own_reports' permission
5 - Create 4 reports as each user
6 - Confirm view/edit pages show the delete button for each user, and confirm they both work
7 - You shoudl have 2 reports left for each user
8 - Confirm each user can delete their own report from the saved SQL list:
http://localhost:8081/cgi-bin/koha/reports/guided_reports.pl?op=list
9 - There should be 1 report from each
10 - Give the second user 'delete_all_reports' permission in one tab and reload the saved reports in another tab
11 - Select both reports in the second tab
12 - Remove 'delete_all_reports' from the second user, leaving 'delete_own_reports' in the first tab
13 - Click 'Delete selected' in the reports tab
14 - Confirm you get 'You do not have permission to continue'
15 - Hit back, deselect other users report, confirm you can delete your own with 'Delete selected'
16 - Sign off
Signed-off-by: Judy Poyer <jpoyer@aacpl.net>
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
The atomicupdate converts AllowItemsOnHoldCheckoutSCO and
AllowItemsOnHoldCheckoutSIP from YesNo to Choice (0|1|2), where
value 1 now means "Allow pending holds only" and value 2 means
"Allow pending and waiting holds".
For AllowItemsOnHoldCheckoutSCO, pre-upgrade value 1 meant "allow
all on-hold checkouts (pending AND waiting)" at SCO. Post-upgrade,
sco-main.pl reads value 1 as "pending only", silently downgrading
sites that previously allowed waiting-hold checkouts. Remap SCO
value 1 -> 2 at upgrade time to preserve prior behavior.
For AllowItemsOnHoldCheckoutSIP, the SIP checkout code was already
gated on >= 1 for pending and >= 2 for waiting, so value 1 meant
"pending only" in practice even under the old YesNo type. No value
migration is needed -- leaving it at 1 preserves current behavior.
The value remap lives inside the branch that only runs when the
type is not already Choice, so re-running the atomicupdate is safe
and will not double-remap.
Test plan:
1) On a pre-upgrade DB, set both prefs to YesNo/1:
UPDATE systempreferences SET type='YesNo', options=NULL,
value='1'
WHERE variable IN ('AllowItemsOnHoldCheckoutSCO',
'AllowItemsOnHoldCheckoutSIP');
2) Run installer/data/mysql/updatedatabase.pl.
3) Verify:
SELECT variable, type, options, value FROM systempreferences
WHERE variable IN ('AllowItemsOnHoldCheckoutSCO',
'AllowItemsOnHoldCheckoutSIP');
SCO -> type=Choice, options=0|1|2, value=2.
SIP -> type=Choice, options=0|1|2, value=1.
4) Re-run updatedatabase.pl; confirm both prefs report
"already migrated, skipping" and values are unchanged.
5) Spot-check other starting values: SCO=0 stays 0, SCO=2
stays 2, SIP=0 stays 0.
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>
AllowItemsOnHoldCheckoutSCO and AllowItemsOnHoldCheckoutSIP become
Choice (0|1|2) so libraries can distinguish pending from waiting holds:
0 = Don't allow (unchanged)
1 = Allow pending holds only (new semantics; previously "Allow")
2 = Allow pending and waiting holds (preserves old permissive behaviour)
A new AllowHoldCheckoutOverride YesNo preference (default 1) follows
the existing Allow*Override family and lets libraries block the
"check out anyway" override in the staff interface when an item is on
hold for another patron.
Note: installations that previously had either Allow*CheckoutSCO/SIP
set to 1 will migrate to "Allow pending only". Libraries that relied
on the previous behaviour (silently allowing checkout of items already
waiting on the hold shelf) need to manually switch to 2.
Test plan:
- Apply the patch and restart Koha.
- Run the web installer / updatedatabase.pl.
- Confirm no errors and the log mentions the three sysprefs.
- Run it a second time; confirm the "already migrated" / "already
exists" skip messages appear.
- In Administration > System preferences, search for
AllowItemsOnHoldCheckoutSCO and AllowItemsOnHoldCheckoutSIP and
confirm the dropdown now has three options.
- Confirm AllowHoldCheckoutOverride appears in the same section with
the Allow/Don't allow choices and defaults to Allow.
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>
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>
- Replace IFNULL with COALESCE in the atomicupdate to satisfy the
forbidden_patterns check (IFNULL is non-standard SQL).
- Run misc/devel/tidy.pl over the modified catalogue_detail.inc to
satisfy the tidiness check.
Test plan:
1. Run the QA script against the patch series and confirm both
forbidden_patterns and tidiness checks pass.
2. Re-run the parent commit's test plan and confirm spine-label column
visibility behaves identically.
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
- Set the executable bit on the atomicupdate so it passes the QA
file_permissions check.
- Drop the unused 'say_info' import; only 'say_warning' and 'say_success'
are now needed.
- Capture the row count from the DELETE so we report 'say_warning' on a
re-run (when the syspref is already gone) instead of falsely claiming
to have deleted it again.
- Add an inline comment explaining the conservative
'(is_hidden OR VALUES(is_hidden))' conflict-resolution rule used when a
table-settings row already exists alongside the old syspref value.
Test plan:
1. Verify the atomicupdate file has the executable bit set.
2. On a database where the syspref is still present, run the
atomicupdate. Confirm output reads
"Deleted 'SpineLabelShowPrintOnBibDetails' syspref".
3. Run the atomicupdate a second time. Confirm output now reads
"'SpineLabelShowPrintOnBibDetails' syspref already removed".
4. Confirm the columns_settings rows are unchanged on re-run.
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
The catalogue_detail.inc include is shared by both the holdings_table
and otherholdings_table tabs, so the column visibility migration must
seed both. Without this, sites that previously had
'SpineLabelShowPrintOnBibDetails' set to "Don't show" would still see
the spine-label column appear in the other-holdings tab.
Also mark 'spinelabel' as is_hidden by default in admin/columns_settings.yml
for both tables, so fresh installs (where the atomicupdate doesn't run)
match the previous syspref default of 0 (Don't show).
Test plan:
1. Reset the database, do not apply the parent patch yet.
2. With the syspref still present, set it to "Don't show" and save.
3. Apply the parent patch and this follow-up, then update the database.
4. Navigate to a record with items in both 'Holdings' and 'Other holdings'
tabs.
5. Verify the 'Spine label' column is hidden in BOTH tabs.
6. Reset the database again. Set the syspref to "Show", save, then apply
patches and update the database.
7. Verify the 'Spine label' column is visible in BOTH tabs.
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
With the ability to customise which columns are hidden by default as
part of "Table settings", this syspref is redundant. As part of the
atomicupdate, we incorporate the previous syspref value into
columns_settings.
As there are six possible states the migration could start from (the
syspref can be 0 or 1, and the table setting can be 0, 1, or NULL) and
two final states it must be idempotent from, the test plan is
unfortunately quite cumbersome.
Test plan:
1. Reset the database, to clear the table settings.
2. Apply patch and update the database.
3. Navigate to Administration > System preferences > Cataloging.
4. Verify that "SpineLabelShowPrintOnBibDetails" does not appear.
5. Navigate to a catalogue detail page.
6. Verify that the "Spine label" column is hidden.
7. Update the database again.
8. Navigate to a catalogue detail page.
9. Verify that the "Spine label" column is hidden.
10. Revert the patch.
11. Reset the database, to clear the table settings.
12. Navigate to Administration > System preferences > Cataloging.
13. Set "SpineLabelShowPrintOnBibDetails" to "Show" and save.
14. Apply patch and update the database.
15. Navigate to a catalogue detail page.
16. Verify that the "Spine label" column is visible.
17. Update the database again.
18. Navigate to a catalogue detail page.
19. Verify that the "Spine label" column is visible.
20. Revert the patch.
21. Reset the database, to clear the table settings.
22. Navigate to Administration > Table settings.
23. Under Catalog > holdings_table, check "Is hidden by default" for
"spinelabel" and save.
24. Apply patch and update the database.
25. Navigate to a catalogue detail page.
26. Verify that the "Spine label" column is hidden.
27. Revert the patch.
28. Reset the database, to clear the table settings.
29. Navigate to Administration > System preferences > Cataloging.
30. Set "SpineLabelShowPrintOnBibDetails" to "Show" and save.
31. Navigate to Administration > Table settings.
32. Under Catalog > holdings_table, check "Is hidden by default" for
"spinelabel" and save.
33. Apply patch and update the database.
34. Navigate to a catalogue detail page.
35. Verify that the "Spine label" column is hidden.
36. Revert the patch.
37. Reset the database, to clear the table settings.
38. Navigate to Administration > Table settings.
39. Under Catalog > holdings_table, uncheck "Is hidden by default" for
"spinelabel" and save.
40. Apply patch and update the database.
41. Navigate to a catalogue detail page.
42. Verify that the "Spine label" column is hidden.
43. Revert the patch.
44. Reset the database, to clear the table settings.
45. Navigate to Administration > System preferences > Cataloging.
46. Set "SpineLabelShowPrintOnBibDetails" to "Show" and save.
47. Navigate to Administration > Table settings.
48. Under Catalog > holdings_table, uncheck "Is hidden by default" for
"spinelabel" and save.
49. Apply patch and update the database.
50. Navigate to a catalogue detail page.
51. Verify that the "Spine label" column is visible.
Thanks-to: Katrin Fischer
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>
Adds a new nullable longtext column `composite_scores` to the
`import_record_matches` table to store a JSON object mapping each
matchpoint search_index to the score it contributed to the total.
This allows the UI to display a breakdown of match scores (e.g.
"title:50, author:50") rather than just the aggregate total.
Sponsored-by: Main Library Alliance <https://www.mainlib.org/>
Signed-off-by: Jeanne Mauriello <jeanne.mauriello@mainlib.org>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
When a refund is processed through Point of Sale, the system creates:
1. A credit account line (the refund)
2. A debit account line (the payout)
The receipt printing logic currently only accounts for RECEIPTs against
credits.
This patch adds a new 'PAYOUT' template for dealing with the negative
debits that make up a payout so we can construct a proper receipt for
this action.
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Introduces a new system preference, autoMemberNumValue, which tracks
the highest auto-generated cardnumber ever issued. It is seeded from
the MAX cardnumber across both borrowers and deletedborrowers so
pre-upgrade deletions do not free numbers for re-issuance.
This preference is managed internally by Koha::Patron::fixup_cardnumber
and has no UI (no YAML entry).
Test plan:
1. Apply the atomicupdate:
perl installer/data/mysql/updatedatabase.pl
2. Verify the preference exists:
SELECT * FROM systempreferences WHERE variable = 'autoMemberNumValue';
3. Confirm the seed value matches:
SELECT GREATEST(
COALESCE((SELECT MAX(CAST(cardnumber AS SIGNED)) FROM borrowers
WHERE cardnumber REGEXP '^-?[0-9]+\$'), 0),
COALESCE((SELECT MAX(CAST(cardnumber AS SIGNED)) FROM deletedborrowers
WHERE cardnumber REGEXP '^-?[0-9]+\$'), 0)
);
4. Re-run the atomicupdate and confirm the already-exists warning.
5. Drop the syspref, re-apply the atomicupdate, confirm it seeds
correctly on fresh installs via mandatory/sysprefs.sql.
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
The SIP fields in the database are too small for the templates of some configurations, and are truncated during upgrade resulting in invalid templates. It's likely we need more than 255 characters for some templates. We should convert all sip template fields to TEXT fields.
Test Plan:
1) For each template field on a sip account attempt to save a template like:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXY
2) Note error preventing you from doing so
3) Apply this patch
4) Run updatedatabase.pl
5) Repeat step 1
6) Note you can now do so without error!
Signed-off-by: Charlie Arthur <carthur@slolibrary.org>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Also include a reference to the notice template from sysprefs
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This adds a new 'open_helper_plugin' keyboard shortcut to the
keyboard_shortcuts table, used by the advanced cataloging editor to
open the value_builder popup for the Leader, 006, 007 and 008 fixed
length fields. The default key combination is Shift-Ctrl-H ("Helper")
and is rebindable from Administration > Keyboard shortcuts. The
behaviour bound to this shortcut is added in a follow-up patch.
Test plan:
1. Apply this patch and run installer/data/mysql/updatedatabase.pl in
KTD.
2. Run:
SELECT * FROM keyboard_shortcuts
WHERE shortcut_name = 'open_helper_plugin';
Confirm a row exists with shortcut_keys = 'Shift-Ctrl-H'.
3. Re-run updatedatabase.pl and confirm the atomic update is idempotent
(no error, no duplicate row).
4. On a fresh install (or by re-loading mandatory/keyboard_shortcuts.sql
on an empty table) confirm the same row is created.
Sponsored-by: Main Library Alliance <https://www.mainlib.org/>
Signed-off-by: Jeanne Mauriello <jeanne.mauriello@mainlib.org>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Adding an entry to admin/searchengine/elasticsearch/mappings.yaml is only
picked up by fresh installs or when an administrator explicitly resets the
search mappings (rebuild_elasticsearch.pl -r). Existing installations would
otherwise never see the new 'authid' index in the admin UI nor have it
available as a matching index until they ran the reset.
This atomicupdate inserts:
- a search_field row for 'authid' (type 'stdno', staff_client + opac on)
- search_marc_map rows for authorities/marc21/001 and authorities/unimarc/001
(INSERT IGNORE - the rows are shared with 'local-number' and usually
already exist)
- search_marc_to_field rows linking those MARC maps to the new field with
sort on, matching mappings.yaml
It is a no-op if 'authid' is already present.
Administrators still need to rebuild the Elasticsearch index for the new
field to become queryable - this is noted with say_info at the end.
Test plan:
1 - On an existing instance without the patch: note there is no 'authid'
field under Administration > Search engine configuration (Elasticsearch)
for authorities.
2 - Apply the whole patchset.
3 - perl installer/data/mysql/updatedatabase.pl
4 - Re-check the search engine configuration: 'authid' appears for the
authorities index, mapped to 001 for both MARC flavours.
5 - Run the update again - confirm the "already exists, skipping" warning.
6 - misc/search_tools/rebuild_elasticsearch.pl -r -v -a
7 - Confirm a matching rule using index 'authid' now works.
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>