Commit Graph

62313 Commits

Author SHA1 Message Date
Tomás Cohen Arazi 3522dc2bca
Bug 42567: Remove C4::Koha::GetNormalizedEAN in favor of MetadataExtractor
Adds get_normalized_ean to the flavor-specific extractors:
- MARC21: 024$a with indicator 1 = 3
- UNIMARC: 073$a

Exposes it as $biblio->normalized_ean and migrates all callers.

Assisted-by: Sonnet 4.6 (Anthropic)

Test plan:
1. Apply patch
2. Run:
   $ ktd --shell
   k$ prove t/db_dependent/Koha.t \
          t/db_dependent/Koha/Biblio.t \
          t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/MARC21.t \
          t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/UNIMARC.t
=> SUCCESS: Tests pass
3. Verify EAN numbers still display in OPAC and staff detail pages
4. Sign off :-D

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

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-20 15:34:10 +00:00
Tomás Cohen Arazi 3d3f625b56
Bug 42566: Remove C4::Koha::GetNormalizedUPC in favor of MetadataExtractor
GetNormalizedUPC duplicated logic already available via the
MetadataExtractor (Bug 34828) and exposed as $biblio->normalized_upc.

All callers migrated:
- Scripts with $biblio available: use $biblio->normalized_upc
- C4::Search (only MARC::Record): reuses the extractor instance
  already created for OCLC

Assisted-by: Sonnet 4.6 (Anthropic)

Test plan:
1. Apply patch
2. Run:
   $ ktd --shell
   k$ prove t/db_dependent/Koha.t \
          t/db_dependent/Koha/Biblio.t
=> SUCCESS: Tests pass
3. Verify UPC numbers still display in OPAC and staff detail pages
   (Syndetics cover images)
4. Sign off :-D

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

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-20 15:34:08 +00:00
Tomás Cohen Arazi 5fb7fd5f2d
Bug 35142: Remove GetNormalizedOCLCNumber, oclc_number, strip_orgcode
All callers migrated. Removes dead code:

- C4::Koha::GetNormalizedOCLCNumber
- Koha::Util::MARC::oclc_number
- Koha::Util::MARC::strip_orgcode
- Koha::Util::MARC::OCLC_REGEX constant

Test plan:
   $ prove t/Koha/Util/MARC.t t/db_dependent/Koha.t

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Assisted-by: Sonnet 4.6 (Anthropic)
Signed-off-by: David Nind <david@davidnind.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-20 15:34:07 +00:00
Tomás Cohen Arazi 263a1bd536
Bug 35142: Migrate callers to use metadata extractor
Replaces all calls to GetNormalizedOCLCNumber() and
Koha::Util::MARC::oclc_number() with the extractor pattern.

OPAC scripts pass their already ViewPolicy-filtered $record directly
to the extractor. This preserves the existing filtering behavior
without introducing new abstraction layers:

    Koha::Biblio::Metadata::Extractor->new( { metadata => $record } )->get_normalized_oclc

Intranet scripts and the Koha::Biblio convenience method use the
raw cached extractor (035 visibility is not affected by ViewPolicy
in practice, and intranet doesn't filter):

    $biblio->normalized_oclc

Test plan:
1. Verify OCLC numbers display on OPAC detail, ISBD, MARC detail
2. Verify staff catalogue detail and search results
3. prove t/db_dependent/Koha/Biblio.t

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Assisted-by: Sonnet 4.6 (Anthropic)
Signed-off-by: David Nind <david@davidnind.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-20 15:34:06 +00:00
Tomás Cohen Arazi 6b77f28dd7
Bug 35142: Move get_normalized_oclc to base MARC extractor
Moves get_normalized_oclc from the MARC21-specific extractor to the
base ::MARC class (035$a is flavor-independent) with improved matching:

- Case-insensitive OCoLC detection (matches ocolc, OCOLC, etc.)
- Generic orgcode prefix stripping (any parenthesized prefix, not
  just literal "(OCoLC)") for resilience against cataloging typos

Test plan:
   $ prove t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/MARC21.t

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Assisted-by: Sonnet 4.6 (Anthropic)
Signed-off-by: David Nind <david@davidnind.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-20 15:34:02 +00:00
Pedro Amorim 4dae704301
Bug 41029: DBRev 26.06.00.016
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-19 16:07:59 +00:00
Martin Renvoize 575e90f88f
Bug 41029: (QA follow-up) Seed add_to_basket record source and tidy atomicupdate
Without a matching entry in the record_sources table, the new
"Add to basket" option never appears in the Source filter dropdown
of the marc-overlay-rules admin page for module=source, since that
dropdown is populated from Koha::RecordSources, not the template's
label switch. Seed it in both the mandatory install-time data and
the upgrade atomicupdate, matching how batchimport/z3950/etc. were
introduced.

Also drop the unused say_warning import, route success messages
through say_success instead of a bare say, and simplify the
selectrow_array calls.

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-19 16:07:58 +00:00
Nick Clemens f473c7d451
Bug 41029: Add option for marc overlay rules to apply when adding to a basket
This patch adds a new option to allow defining overlay rules for 'Add to basket' - such that they
will be used when adding orders in acquisition. Existing 'Staged MARC Import' rules will be copied to
the new fitler in order to preserve behavior

To test:
 1 - Paste the following into MarcFieldsToOrder and save
  price: 975$p
  quantity: 975$q
  budget_code: 975$h
 2 - Paste the following into MarcItemFieldsToOrder and save
  homebranch: 949$a
  holdingbranch: 949$b
  itype: 949$y
  nonpublic_note: 949$x
  public_note: 949$z
  loc: 949$c
  ccode: 949$8
  notforloan: 949$7
  uri: 949$u
  copyno: 949$t
  price: 949$g
  replacementprice: 949$v
  itemcallnumber: 949$o
  quantity: 949$k
  budget_code: 949$l
 3 - Go to Admin -> Record overlay rules
 4 - Define 2 rules:
  Source - Staged Marc Import - 949 - Add and append (the rest of the options are set when add and append is selected
  Source - Staged Marc Import - * - Protect (the rest of the options are set when add and append is selected
 5 - Grab test file from bug 39518
 6 - Import the records, ignoring items
 7 - Edit the test file and change some values for the 949 rows
 8 - Go to Acquisitions, find a basket for a vendor, add to basket from a new file
 9 - Stage the file to find matches (already imported above) and to replace
10 - Complete the orders
11 - View the record and confirm the new 949 are added
12 - Edit the 949 in the file again
13 - Apply patch, update database, restart all
14 - Edit overlay rules and remove the 'Staged Marc Import' rules, leaving only the 'Add to basket rules'
15 - Add to basket again using the updated file and confirm new 949 are added
16 - Success!

Signed-off-by: Benjamin Daeuber <BDaeuber@fargolibrary.org>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-19 16:07:57 +00:00
John Doe 9fc9f84b8d
Bug 28740: (follow-up) Add missing C4::Log import for cronlogaction
The patch added cronlogaction() calls but did not import the function.
This caused a runtime error: Undefined subroutine &main::cronlogaction.

Test plan:
1. Apply patch
2. Run:
   $ ktd --shell
   k$ perl misc/cronjobs/cleanup_database.pl --illrequests-days 30 \
       --illrequests-status COMP -v
=> SUCCESS: Dry-run works, reports count of requests that would be removed
3. Run with --confirm to actually purge
4. Sign off :-D

Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-19 16:07:56 +00:00
Lari Strand 5ebc4d79a1
Bug 28740: Add option for cleaning up ILL requests
This adds two new parameters:
--illrequests-status
--illrequests-days (optional, defaults to 30 days)

These can be repeated to include specific statuses for cleanup. At least one status must be specified.

To test:
0 - Apply patch
1 - Create several ILL requests with different statuses (e.g., CANCELLED, REJECTED, COMPLETED, PENDING)
2 - Set some requests to be older than 30 days (update their updated timestamp)
3 - Run cleanup_database.pl with --illrequests-status CANCELLED
4 - CANCELLED requests older than 30 days are removed, others remain
5 - Run cleanup_database.pl with --illrequests-status CANCELLED --illrequests-status REJECTED
6 - Both CANCELLED and REJECTED requests older than 30 days are removed, other statuses remain
7 - Run cleanup_database.pl with --illrequests-days 5 --illrequests-status PENDING
8 - PENDING requests older than 5 days are removed
9 - Verify dry-run mode (no --confirm) correctly counts records that would be deleted without deleting them
10 - Run cleanup_database.pl with --illrequests-days without any --illrequests-status
11 - Error message displayed requiring at least one status to be specified

Sponsored-by: Koha-Suomi Oy
Signed-off-by: John Doe <tomascohen@gmail.com>
edit: tidied the file (tcohen)
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-19 16:07:54 +00:00
Pedro Amorim f2003e3e52
Bug 35104: (RM follow-up) Restore StripNonXmlChars in TransformHtmlToMarc
Removed by 6726b1a254 on the assumption store() strips centrally -
but TransformHtmlToMarc never calls store(), so callers like
addbiblio.pl (FindDuplicate, duplicate redisplay) see unstripped
control characters again, the same failure Bug 34549 fixed.

repair_marcxml covers more faults but works on full MARCXML and can
throw - too big a change here; left as a follow-up.

Test plan:
prove t/db_dependent/Biblio/TransformHtmlToMarc.t

Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-19 14:34:00 +00:00
Olivia Reynolds dd7777c8b9
Bug 43313: Fix catalogue detail shelving location display
During the tidying up of Bug 41566, av_loc was accidentally changed to
map descriptions to codes, rather than vice-versa. This broke the
formatting of item permanent locations.

Test plan (for KTD):
1.  Navigate to an catalogue detail page, for example
    http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=262
2.  Run the following SQL, replacing 262 with the biblionumber of your
    chosen page:
      UPDATE items SET location='CHILD' SET permanent_location='GEN' WHERE biblionumber=262;
3.  Refresh the page and verify the items' shelving locations display
    "(Children's area)" only.
4.  Apply patch and force refresh.
5.  Verify the shelving location now correctly displays "General
    stacks" and "(Children's area)" on separate lines.

Sponsored-by: Open Fifth
Signed-off-by: John Vinke <jvinke@austinseminary.edu>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-19 14:33:59 +00:00
Martin Renvoize bad9bb47ae
Bug 43215: preferences.js: Report one save confirmation per preference, not per checkbox option
Checkbox-group system preferences (multiple_sortable, ill_backends, and
the OPAC/staff interface language selectors) render one checkbox per
option. All the checkboxes for a given preference share its 'name'
attribute, but each has its own unique 'id'.

Saving such a preference produced one "Saved preference ..."
confirmation line per checkbox instead of a single line for the
preference as a whole, because KOHA.Preferences.Success() built the
message from each modified element's 'id' rather than its 'name'.

A related issue: the checkbox 'change' handler marked every
'.preference-checkbox' on the whole page as modified, regardless of
which preference it belonged to. This meant editing one checkbox-group
preference silently re-saved (and, before this patch, also reported as
saved) any other checkbox-group preference sharing the same tab - for
example, editing OPACLanguages would also touch the unrelated
StaffInterfaceLanguages preference on the I18N/L10N tab.

This patch:
* Scopes the 'modified' marking to checkboxes sharing the same
  preference name, so unrelated checkbox-group preferences on the same
  tab are left alone.
* Groups the save confirmation message by preference name
  (deduplicated), so each preference produces exactly one "Saved
  preference" line regardless of how many options it has.

Test plan:
1. Go to Administration > System preferences and search for
   OPACAuthorIdentifiersAndInformation.
2. Select two or more identifier types and click Save.
3. Confirm the confirmation banner shows a single "Saved preference
   OPACAuthorIdentifiersAndInformation" line, not one per selected
   identifier.
4. Drag one of the selected items to reorder it, click Save again,
   confirm you still get only one confirmation line, then reload the
   page and confirm the new order was kept.
5. Go to Administration > System preferences > I18N/L10N tab.
6. Toggle one of the checkboxes under "Enable the following languages
   on the OPAC" (OPACLanguages) and click Save.
7. Confirm the confirmation only reports OPACLanguages as saved - the
   staff interface language list (StaffInterfaceLanguages) should not
   appear in the message.
8. Reload the page and confirm the staff interface language selection
   is unchanged.
9. As a sanity check, modify an ordinary non-checkbox preference (e.g.
   a free text or yes/no preference) and confirm it still reports
   exactly one "Saved preference" line, same as before this patch.

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-19 14:33:58 +00:00
Andrew Fuerste Henry 549e0b3068
Bug 42553: (QA Follow-up) tidy preferences.pl
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-19 14:33:57 +00:00
Martin Renvoize eb93c2b2e7
Bug 42553: preferences.pl: Allow 'multiple_sortable' to use 'authval' source
The 'choices' renderer in admin/preferences.pl already supports a
dynamic 'authval' source: the YAML can say

    choices: authval
    source: SOMECATEGORY

and the choices are populated from the named authorised value category
at render time.

The 'multiple_sortable' renderer (the SortableJS-backed drag-and-drop
multi-select used by OPACAuthorIdentifiersAndInformation and
ArticleRequestsSupportedFormats) had no equivalent — choices had to be
hardcoded in the .pref YAML.

This patch adds the same dispatcher to 'multiple_sortable' so prefs
needing an ordered, picker-driven multi-select of authorised values
can declare:

    multiple_sortable: authval
    source: PAYMENT_TYPE

Behaviour for existing prefs (which pass a hash directly to
'multiple_sortable') is unchanged — the new branch only fires when the
value is a scalar.

Test plan:
1. Create a temporary system preference using the new pattern, e.g. by
   adding to admin/preferences/accounting.pref:
       - pref: TestSortableAV
         multiple_sortable: authval
         source: PAYMENT_TYPE
   and seeding INSERT INTO systempreferences with type='Free'.
2. Visit Administration > System preferences and find the pref.
3. Verify the widget renders as a sortable list of every value in the
   PAYMENT_TYPE authorised value category, with checkboxes and drag
   handles, matching the look of OPACAuthorIdentifiersAndInformation.
4. Pick two or three, reorder them, save.
5. Reload the page and verify the order and selection are preserved.
6. With 'source' omitted or 'multiple_sortable' set to a string other
   than 'authval', verify the page raises a clear error.
7. Existing prefs (OPACAuthorIdentifiersAndInformation,
   ArticleRequestsSupportedFormats) continue to render unchanged.

Sponsored-by: OpenFifth <https://openfifth.co.uk/>
Signed-off-by: Jackie Usher <jackie.usher@westsussex.gov.uk>
Signed-off-by: Debbie McCarthy <debbie.mccarthy@westsussex.gov.uk>
Signed-off-by: Hannah Dunne-Howrie <hdunne-howrie@westminster.gov.uk>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-19 14:33:56 +00:00
Kyle M Hall 812ac7155d
Bug 41197: Don't require a CSRF token for opac-account-pay-return.pl
This page is intended for redirect/return from external payment vendors - they are not going to have/get a CSRF token from Koha for this.
The payments are handled in a POST to the API, so this should not be a sensitive page, it just provides user confirmation.
Some vendors use only a POST, we should not require CSRF on this page.

Test Plan:
1) Apply the first patch
2) prove t/Koha/Middleware/CSRF.t
3) Note the tests fail!
4) Apply this patch
5) prove t/Koha/Middleware/CSRF.t
6) All tests pass!

Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-19 14:33:55 +00:00
Kyle M Hall 3e87d13e67
Bug 41197: Add unit tests
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-19 14:33:52 +00:00
Pedro Amorim 22fad96c0d
Bug 35104: (RM follow-up) Fix regressions.t for Metadata's new auto-repair
Koha::Biblio::Metadata->store() now repairs recoverable MARCXML faults
before saving, so this test's invalid data no longer reaches the DB
and detail.pl never hits a decoding error.

Write the metadata directly via the DBIC row instead, bypassing
store()'s repair, so the test still exercises detail.pl's own
defensive handling of corrupt metadata.

Test plan:
prove t/db_dependent/selenium/regressions.t

Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-19 11:03:34 +00:00
Pedro Amorim 868751b221
Bug 43091: (RM follow-up) Give the OPAC self-renewal island a Pinia store
hydrate() only installs Pinia for an island when its config.stores is
non-empty. patron-self-renewal kept config: {} after islands-opac.ts
was split out, so it never got one.

http-client.js's post() calls submitting(), which needs Pinia's
useMainStore(). With none active, it throws before fetch() runs -
get() skips submitting() by default, so only the actual renewal
submission failed.

Test plan:
prove t/cypress/integration/Islands/SelfRenewal.ts

Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-19 11:03:33 +00:00
Pedro Amorim c4e70ad745
Bug 35797: (RM follow-up): Fix xt/api.t
prove xt/api.t

Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-19 11:03:30 +00:00
Pedro Amorim 0e69e8d3a1
Bug 41996: DBRev 26.06.00.015
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:39 +00:00
Kyle M Hall d9b06c79e3
Bug 41996: (QA follow-up) Fix up atomic update
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:37 +00:00
Kyle M Hall d576dbadcb
Bug 41996: (QA follow-up) Test that invoicenumber is recorded on EDI invoice errors
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:36 +00:00
Kyle M Hall 7e445f1ce6
Bug 41996: (QA follow-up) Update EDI.t for improved invoice error messages
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:35 +00:00
Martin Renvoize e9a442e933
Bug 41996: Filter EDI errors on invoice page by invoicenumber
The invoice page previously fetched all edifact_errors for the EDI
message, causing errors from unrelated invoice lines to appear on every
invoice generated from the same EDI file. For example, one unmatched
ordernumber in a file with 20 invoices would flag all 20 as having
errors.

Now only errors where invoicenumber matches the current invoice (or
where invoicenumber is NULL, indicating a message-level error) are
displayed.

Signed-off-by: Ray Delahunty <lib-systems@arts.ac.uk>
Signed-off-by: Hannah Dunne-Howrie <hdunne-howrie@westminster.gov.uk>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:34 +00:00
Martin Renvoize a3889a7d90
Bug 41996: Thread invoicenumber through EDI invoice error recording
All errors generated during process_invoice and receipt_items now
store the invoicenumber of the specific invoice being processed. This
allows errors to be displayed only on the relevant invoice page rather
than appearing on every invoice generated from the same EDI file.

Also fixes two pre-existing spacing bugs in error message strings
("itemnumberis missing" and "barcode"for invoice line").

Signed-off-by: Ray Delahunty <lib-systems@arts.ac.uk>
Signed-off-by: Hannah Dunne-Howrie <hdunne-howrie@westminster.gov.uk>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:33 +00:00
Martin Renvoize 51e4567ca6
Bug 41996: Schema Updates
Signed-off-by: Ray Delahunty <lib-systems@arts.ac.uk>
Signed-off-by: Hannah Dunne-Howrie <hdunne-howrie@westminster.gov.uk>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:32 +00:00
Martin Renvoize 60cde3718a
Bug 41996: Add invoicenumber column to edifact_errors table
Adds an optional invoicenumber column to edifact_errors so that errors
generated during invoice processing can be associated with the specific
invoice they relate to, rather than only the EDI message as a whole.

Message-level errors (e.g. unmatched vendor EAN) leave invoicenumber
NULL, indicating they apply to the whole file.

Signed-off-by: Ray Delahunty <lib-systems@arts.ac.uk>
Signed-off-by: Hannah Dunne-Howrie <hdunne-howrie@westminster.gov.uk>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:31 +00:00
Martin Renvoize 52d3cd3835
Bug 41996: Improve EDI invoice error messages for branch mismatches
When EDI invoice processing fails to match an item to a branch, the
error message now includes:
- The ordernumber referenced in the invoice (RFF+LI segment)
- The branches that order actually has items at
- A hint that the ordernumber in the invoice may be incorrect

Also adds a warning when an invoice line references an order that is
already marked as complete, which can indicate the supplier sent the
wrong ordernumber.

These improvements help acquisitions staff and vendors quickly diagnose
whether the problem is a supplier error (wrong RFF+LI value) rather
than a Koha data issue.

Signed-off-by: Ray Delahunty <lib-systems@arts.ac.uk>
Signed-off-by: Hannah Dunne-Howrie <hdunne-howrie@westminster.gov.uk>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:30 +00:00
Kyle M Hall 9e8075eaaf
Bug 42789: (QA follow-up) Add test for cancelling an order with a held item
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:29 +00:00
Kyle M Hall 220b09c4e0
Bug 42789: (QA follow-up) Log item deletion failures during EDI cancellation
This patch logs any object messages returned by cancel() to the EDI log,
including the itemnumber if available.

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:28 +00:00
Martin Renvoize 45a60d487c
Bug 42789: Add tests for process_ordrsp() cancellation handling
Tests verify that EDI ORDRSP cancellations now use
Koha::Acquisition::Order->cancel() rather than a raw ModOrder call:

- Order status, cancellation reason and date are set correctly
- On-order items linked via aqorders_items are deleted
- Purchase suggestions linked to the biblio are reverted from
  ORDERED back to ACCEPTED
- Non-cancellation actions update suppliers_report only
- Missing ordernumbers are handled gracefully without dying

Sponsored-by: OpenFifth <https://openfifth.co.uk/>
Signed-off-by: Sharon Dugdale <sharon.dugdale@cumberland.gov.uk>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:27 +00:00
Martin Renvoize 70f5d1d3f1
Bug 42789: Add missing POD for _validate_location_code and _validate_collection_code
These private subs were added without pod_coverage documentation,
causing a QA failure. Add minimal =head3 blocks to resolve it.

Sponsored-by: OpenFifth <https://openfifth.co.uk/>
Signed-off-by: Sharon Dugdale <sharon.dugdale@cumberland.gov.uk>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:26 +00:00
Martin Renvoize 6c55a4e7d4
Bug 42789: EDI ORDRSP cancellation should use Koha::Acquisition::Order->cancel()
The process_ordrsp() function was calling C4::Acquisition::ModOrder()
directly when processing a supplier cancellation, which only updated
the order status fields and left associated items and purchase
suggestions untouched.

Replace with Koha::Acquisition::Order->cancel(), which mirrors the
behaviour of manual cancellation via the acquisitions UI:
- Deletes on-order items via safe_delete() with error capture
- Reverts any linked purchase suggestion from ORDERED back to ACCEPTED
- Updates orderstatus, cancellationreason and datecancellationprinted

The delete_biblio option is intentionally omitted (defaults to false)
as silent biblio deletion is not appropriate for an automated EDI flow.

ModOrder is retained for the non-cancellation branch which only needs
to update suppliers_report.

Sponsored-by: OpenFifth <https://openfifth.co.uk/>
Signed-off-by: Sharon Dugdale <sharon.dugdale@cumberland.gov.uk>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:25 +00:00
Kyle M Hall 1031a1ba73
Bug 42700: Remove dead $flags->{WAITING} code from C4::Members::patronflags
After the previous patch, $flags->{WAITING} from
C4::Members::patronflags is no longer read anywhere in Koha.

Test Plan:
1) Apply this patch
2) prove t/db_dependent/SIP/ t/db_dependent/Members.t
3) Note all tests pass!

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Aleisha Amohia <aleisha@catalyst.net.nz>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:24 +00:00
Kyle M Hall 69d9cc4e59
Bug 42700: Avoid duplicate holds query query when building SIP patron object
This patch fetches the patron's holds once into a list of
Koha::Hold objects and derives both hold_items and unavail_holds
from that single fetch.

Test Plan:
1) Apply this patch
2) prove t/db_dependent/SIP/
3) Note all tests pass!

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Aleisha Amohia <aleisha@catalyst.net.nz>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:23 +00:00
Kyle M Hall eb57856091
Bug 42700: hold_items in SIP patron info should contain all holds, not just waiting
Some 3rd party SIP clients calculate the number of holds ready
for pickup as:

  holds ready for pickup = hold_items - unavail_holds

Right now this can produce a negative number since hold_items
contains only waiting holds.

This patch makes hold_items contain all of the patron's holds,
so hold_items - unavail_holds correctly gives the count of holds
ready to be picked up.

Test Plan:
1) Apply the first patch only
2) prove t/db_dependent/SIP/Patron.t
3) Note the new "hold_items counts all holds" subtest fails
4) Apply this patch
5) prove t/db_dependent/SIP/Patron.t
6) Note the tests pass!

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Aleisha Amohia <aleisha@catalyst.net.nz>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:22 +00:00
Kyle M Hall d8cf6da3a2
Bug 42700: Add unit tests
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Aleisha Amohia <aleisha@catalyst.net.nz>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:21 +00:00
Pedro Amorim b33dae39ad
Bug 41649: DBIC
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-18 11:21:17 +00:00
Matt Blenkinsop 72b8e1d9ea
Bug 42018: Prevent null values from breaking patron duplicate matching
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-14 12:09:37 +00:00
Matt Blenkinsop dbd680caec
Bug 42018: Add unit test
Test plan:
1) Apply just the unit test patch
2) Run t/db_dependent/Koha/Patrons.t
3) Test should fail
4) Apply remaining patch
5) Repeat step 3
6) Test should pass

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-14 12:09:36 +00:00
Aleisha Amohia 37ef59a9c8
Bug 35729: Normalize ISBNs as ISBN-13 if cannot fallback to ISBN-10
ISBNs beginning with 979 do not have an ISBN-10 version, and need to be normalized to an ISBN-13 format. All others, if valid, can safely be normalized to ISBN-10 format (current behaviour).

To set up

1. Download the attached sample records with 979 ISBNs
2. Log into the staff interface and go to Cataloguing
3. Go to Stage MARC records for import and upload the sample MARC file
4. Stage and import the biblio records
5. Once imported, open the detail pages for some of the records
6. In another tab, do a catalogue search and open the detail pages for ISBN-10 records, for example biblionumbers 6 and 54

To test

1. Apply the patch and restart services
2. Log into the staff interface and go to Koha Administration, Global system preferences, Enhanced Content tab
3. Cycle through each cover image service, enabled by the system preferences
4. With each cover image service is enabled, refresh the record detail pages you have open. The ISBN-10 records should CONTINUE to show their cover images. The newly imported ISBN-13 records should NOW show their cover images.
5. Confirm tests pass: t/db_dependent/Koha.t

testing with ISBN 9798885795692 should return this image from Amazon: https://images-na.ssl-images-amazon.com/images/P/9798885795692.01.LZZZZZZZ.jpg
testing with ISBN 9798876536914 should return this image from Amazon: https://images-na.ssl-images-amazon.com/images/P/9798876536914.01.LZZZZZZZ.jpg

Sponsored-by: Horowhenua Libraries Trust
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>
2026-08-14 12:09:35 +00:00
Andrew Fuerste Henry d3d4a6ca96
Bug 40799: (QA Follow-up) tidy template file
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-14 12:09:34 +00:00
Hammat Wele be7436b429
Bug 40799: Loading spinner not removed because .cover-slider is now used instead of .cover-slides
After Bug 32642, the spinner on cover images is hidden by verify_cover_images() which removes the .cover-slides class from the cover container.

However, Bug 33848 modified the SCSS so that the spinner is now triggered by .cover-slider instead of .cover-slides.

As a result, the spinner is never removed, because verify_cover_images() only removes .cover-slides.

Test plan

1- Follow the test plan from Bug 32642.
   ==> The spinner is displayed and never disappears.
2- Apply the patch
3- Reload the page.
   ==> The spinner disappears once the cover image is loaded.

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-14 12:09:33 +00:00
Owen Leonard 813fb3d143
Bug 43260: (follow-up) Move debug menu JS into js_includes.inc
The _() function isn't available to JS in intranet-bottom.inc.

To test, apply the patch and test that the correct strings are
translatable. In this example I'm testing fr-FR:

- Update a translation:

  > gulp po:update
  > cd misc/translator
  > perl translate update fr-FR

- Open the corresponding .po file for the strings pulled from
  the template e.g.  misc/translator/po/fr-FR-staff-prog.po
- Locate strings pulled from includes/js_includes.inc for
  translation, e.g.:

  #: koha-tmpl/intranet-tmpl/prog/en/includes/js_includes.inc:105
  #, fuzzy
  msgid "Disable custom CSS"
  msgstr "Désactiver "

- Remove the "fuzzy" line.
- Edit the "msgstr" string however you want (it's just for testing)
- Install the updated translation:

  > perl translate install fr-FR

Log in to the staff interface as a user with debug permission. Test the
debug menu in the header, confirming that the strings look correct and
that the toggles work correctly.

Switch to your translated templates and test again.

Sponsored-by: Athens County Public Libraries
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>
2026-08-14 12:09:32 +00:00
Owen Leonard b567a5589f
Bug 43260: Debug options in navigation bar untranslatable
These patches update the templates which control the display of the
debug menu item in the staff interface header. The strings need to be
wrapped in the _() i18n function.

The patch also corrects capitalization and uses the term "custom"
instead of "user."

A follow-up patch will move this JS into js_includes.inc so that the _()
is available. This patch is separate to make it easier to view the diff.

Testing requires the follow-up.

Sponsored-by: Athens County Public Libraries
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>
2026-08-14 12:09:31 +00:00
Baptiste Wojtkowski 3d41c25c08
Bug 43245: Redirect user if no email was provided
TO TEST:
0 - Apply patch
1 - Make sure OPACResetPassword is activated
2 - Go to that good old Henry Acevedo's page and reset their password
3 - Notice you have been redirected with an error message telling you
have no email

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-14 12:09:30 +00:00
Pedro Amorim 1a5be8e287
Bug 42112: DBRev 26.06.00.014
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-14 12:09:29 +00:00
Lucas Gass 74130f08df
Bug 42112: Add option when changing a patron's category: allow choosing what to do for the expiry date and messaging preferences
To test:
1. APPLY PATCH, updatedatabase, restart_all
2. Find 2 new system preferences UpdateDateExpiryOnCategoryChange and UpdateMessagingPrefsOnCategoryChange
3. Each was the same options:
    -Never update
    -Always ask, default to no
    -Always ask, default to yes
    -Always update without asking

4. Go to  Administration > Patron categories
5. Edit or create some categories with different Enrollment periods and messaaging preferences
6. Try each of the options for BOTH system preferences, making sure they work as described.

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Emily Lamancusa <emily.lamancusa@montgomerycountymd.gov>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-14 12:09:28 +00:00
Jonathan Druart e1072702f8
Bug 41896: Remove C4::Context from Koha::Cache
Signed-off-by: Julian Maurice <julian.maurice@biblibre.com>

Amended-by: Jonathan Druart
Restore ||= op
-    $self->{namespace} = Koha::Config->get_instance->get('memcached_namespace') || 'koha';
+    $self->{namespace} ||= Koha::Config->get_instance->get('memcached_namespace') || 'koha';

Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-08-14 12:09:27 +00:00