From 435c229961b713f8e9c99ed1c68199579ddc8893 Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Wed, 23 Apr 2025 14:17:28 +0100 Subject: [PATCH] Bug 9762: (Alternative) Log circulation overrides MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- C4/Circulation.pm | 29 +++++++++++++--- Koha/CurbsidePickup.pm | 10 +++++- Koha/REST/V1/Checkouts.pm | 10 +++++- circ/circulation.pl | 8 +++-- .../prog/en/includes/action-logs.inc | 9 +++++ .../prog/en/modules/tools/viewlog.tt | 19 +++++++++++ opac/sco/sco-main.pl | 8 ++++- tools/viewlog.pl | 34 +++++++++++++++++-- 8 files changed, 114 insertions(+), 13 deletions(-) diff --git a/C4/Circulation.pm b/C4/Circulation.pm index 60dc4dc765e..7c8166d181d 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -22,6 +22,7 @@ use Modern::Perl; use DateTime; use POSIX qw( floor ); use Encode; +use JSON; use C4::Context; use C4::Stats qw( UpdateStats ); @@ -1590,6 +1591,8 @@ sub AddIssue { my $auto_renew = $params && $params->{auto_renew}; my $cancel_recall = $params && $params->{cancel_recall}; my $recall_id = $params && $params->{recall_id}; + my $confirmations = $params->{confirmations}; + my $forced = $params->{forced}; my $dbh = C4::Context->dbh; my $barcodecheck = CheckValidBarcode($barcode); @@ -1894,11 +1897,27 @@ sub AddIssue { } ); } - logaction( - "CIRCULATION", "ISSUE", - $patron->borrowernumber, - $item_object->itemnumber, - ) if C4::Context->preference("IssueLog"); + + # Log the checkout + if ( C4::Context->preference('IssueLog') ) { + my $info = $item_object->itemnumber; + if ( defined($confirmations) || defined($forced) ) { + $info = to_json( + { + issue => $issue->issue_id, + itemnumber => $item_object->itemnumber, + confirmations => $confirmations, + forced => $forced + }, + { pretty => 1, canonical => 1 } + ); + } + logaction( + "CIRCULATION", "ISSUE", + $patron->borrowernumber, + $info, + ); + } Koha::Plugins->call( 'after_circ_action', diff --git a/Koha/CurbsidePickup.pm b/Koha/CurbsidePickup.pm index 6c75a8525bd..59b35dd8e54 100644 --- a/Koha/CurbsidePickup.pm +++ b/Koha/CurbsidePickup.pm @@ -252,7 +252,15 @@ sub mark_as_delivered { C4::Circulation::CanBookBeIssued( $patron, $hold->item->barcode ); unless ( keys %$issuingimpossible ) { - my $issue = C4::Circulation::AddIssue( $patron, $hold->item->barcode ); + my $issue = C4::Circulation::AddIssue( + $patron, + $hold->item->barcode, + undef, undef, undef, undef, + { + confirmations => [ grep { /^[A-Z_]+$/ } keys %{$needsconfirmation} ], + forced => [ keys %{$issuingimpossible} ] + } + ); if ($issue) { Koha::CurbsidePickupIssue->new( { diff --git a/Koha/REST/V1/Checkouts.pm b/Koha/REST/V1/Checkouts.pm index 8ff774edc2d..578a093cfef 100644 --- a/Koha/REST/V1/Checkouts.pm +++ b/Koha/REST/V1/Checkouts.pm @@ -299,7 +299,15 @@ sub add { } # Call 'AddIssue' - my $checkout = AddIssue( $patron, $item->barcode ); + my $checkout = AddIssue( + $patron, + $item->barcode, + undef, undef, undef, undef, + { + confirmations => [ grep { /^[A-Z_]+$/ } keys %{$confirmation} ], + forced => [ keys %{$impossible} ] + } + ); if ($checkout) { $c->res->headers->location( $c->req->url->to_string . '/' . $checkout->id ); return $c->render( diff --git a/circ/circulation.pl b/circ/circulation.pl index e7732bfdc7b..f572b2d4b29 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -542,9 +542,13 @@ if ( @$barcodes && $op eq 'cud-checkout' ) { $cancelreserve, undef, undef, { - onsite_checkout => $onsite_checkout, auto_renew => $session->param('auto_renew'), - switch_onsite_checkout => $switch_onsite_checkout, cancel_recall => $cancel_recall, + onsite_checkout => $onsite_checkout, + auto_renew => $session->param('auto_renew'), + switch_onsite_checkout => $switch_onsite_checkout, + cancel_recall => $cancel_recall, recall_id => $recall_id, + confirmations => [ grep { /^[A-Z_]+$/ } keys %{$needsconfirmation} ], + forced => [ keys %{$issuingimpossible} ] } ); $template_params->{issue} = $issue; diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/action-logs.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/action-logs.inc index 73d5a819e63..733b5b689f6 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/action-logs.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/action-logs.inc @@ -170,3 +170,12 @@ [% log_interface | html %] [% END %] [% END %] + +[% BLOCK translate_log_override %] + [% SWITCH override %] + [% CASE 'ISSUED_TO_ANOTHER' %] + Item was issued to another patron prior to this checkout + [% CASE %] + [% override | html %] + [% END %] +[% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/viewlog.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/viewlog.tt index 23b9c7b8764..a7028fcd036 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/viewlog.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/viewlog.tt @@ -332,6 +332,25 @@ title="Display detail for this item" >Item [% loopro.barcode | html %] + [% ELSIF ( loopro.module == 'CIRCULATION' && loopro.json_found ) %] +
+
+ Item [% loopro.json.barcode | html %] +
+ [% FOREACH force IN loopro.json.forces %] +
+ [% PROCESS translare_log_override override=force %] +
+ [% END %] + [% FOREACH confirmation IN loopro.json.confirmations %] +
+ [% PROCESS translate_log_override override=confirmation %] +
+ [% END %] +
[% ELSIF loopro.module == "SYSTEMPREFERENCE" || loopro.module == "REPORTS" || loopro.module == "NEWS" %]
[% loopro.info | trim | html %]
diff --git a/opac/sco/sco-main.pl b/opac/sco/sco-main.pl index 9ecae7c76c4..fa198ab8869 100755 --- a/opac/sco/sco-main.pl +++ b/opac/sco/sco-main.pl @@ -281,7 +281,13 @@ if ( $patron && $op eq "cud-returnbook" && $allowselfcheckreturns ) { )->count; } - my $new_issue = AddIssue( $patron, $barcode ); + my $new_issue = AddIssue( + $patron, $barcode, undef, undef, undef, undef, + { + confirmations => [ grep { /^[A-Z_]+$/ } keys %{$needconfirm} ], + forced => [ keys %{$impossible} ] + } + ); $template->param( issued => 1, new_issue => $new_issue ); push @newissueslist, $barcode unless ( grep /^$barcode$/, @newissueslist ); diff --git a/tools/viewlog.pl b/tools/viewlog.pl index 21157e94f37..5d5341168f4 100755 --- a/tools/viewlog.pl +++ b/tools/viewlog.pl @@ -22,6 +22,7 @@ use Modern::Perl; use C4::Auth qw( get_template_and_user ); use CGI qw ( -utf8 ); +use JSON; use Text::CSV::Encoded; use C4::Context; use C4::Output qw( output_html_with_http_headers ); @@ -152,12 +153,11 @@ if ($do_it) { $result->{'biblioitemnumber'} = q{}; $result->{'barcode'} = q{}; - if ( substr( $log->info, 0, 4 ) eq 'item' || $log->module eq "CIRCULATION" ) { + if ( substr( $log->info, 0, 4 ) eq 'item' ) { # get item information so we can create a working link my $itemnumber = $log->object; - $itemnumber = $log->info if ( $log->module eq "CIRCULATION" ); - my $item = Koha::Items->find($itemnumber); + my $item = Koha::Items->find($itemnumber); if ($item) { $result->{'object_found'} = 1; $result->{'biblionumber'} = $item->biblionumber; @@ -166,6 +166,34 @@ if ($do_it) { } } + if ( $log->module eq "CIRCULATION" ) { + my $info = $log->info; + my $decoded; + my $is_json = eval { + $decoded = decode_json($info); + 1; + }; + + if ( $is_json && ref($decoded) ) { + $result->{'json_found'} = 1; + my $item = Koha::Items->find( $decoded->{itemnumber} ); + if ($item) { + $decoded->{biblionumber} = $item->biblionumber; + $decoded->{biblioitemnumber} = $item->biblionumber; + $decoded->{barcode} = $item->barcode; + } + $result->{'json'} = $decoded; + } else { + my $item = Koha::Items->find($info); + if ($item) { + $result->{'object_found'} = 1; + $result->{'biblionumber'} = $item->biblionumber; + $result->{'biblioitemnumber'} = $item->biblionumber; + $result->{'barcode'} = $item->barcode; + } + } + } + #always add firstname and surname for librarian/user if ( $log->user ) { my $patron = Koha::Patrons->find( $log->user ); -- 2.49.0