Bug 40334: Add EDIFACT message display to basket page

This patch extends the EDIFACT message display functionality from the invoice page
to the basket page, providing comprehensive access to EDIFACT messages and error
reporting.

Features added:
- Toolbar buttons for viewing EDIFACT messages (quote/order)
- Smart button display: single button for one message type, dropdown for multiple
- EDIFACT parsing errors section with inline error display
- Errors grouped by message type with detailed information
- Conditional display: only shows when relevant data exists

Changes:
- acqui/basket.pl: Added EDIFACT message and error collection logic
- basket.tt: Added toolbar buttons and parsing errors section
- Uses existing modal system for raw message display

Sponsored-by: Open Fifth <https://openfith.co.uk>
Signed-off-by: Hannah Dunne-Howrie <hdunne-howrie@westminster.gov.uk>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
Martin Renvoize 2025-07-09 17:06:51 +01:00 committed by Lucas Gass
parent 17cea3929c
commit 4f120d8666
No known key found for this signature in database
GPG Key ID: 60B447398B0D36CA
2 changed files with 181 additions and 1 deletions

View File

@ -40,6 +40,7 @@ use Koha::Database;
use Koha::EDI qw( create_edi_order );
use Koha::CsvProfiles;
use Koha::Patrons;
use Koha::Edifact::Files;
use Koha::AdditionalFields;
use Koha::Old::Biblios;
@ -180,6 +181,45 @@ if ($ediaccount) {
);
}
# Check for EDIFACT messages associated with this basket
my $edifact_enabled = C4::Context->preference('EDIFACT');
my @edifact_messages = ();
my @edifact_errors = ();
if ( $edifact_enabled && $basketno ) {
my $edifact_messages_rs = Koha::Edifact::Files->search(
{ basketno => $basketno },
{ order_by => 'message_type' }
);
while ( my $message = $edifact_messages_rs->next ) {
push @edifact_messages, {
id => $message->id,
message_type => $message->message_type,
transfer_date => $message->transfer_date,
status => $message->status,
filename => $message->filename,
};
# Get errors for this message
my $errors = $message->errors;
while ( my $error = $errors->next ) {
push @edifact_errors, {
message_id => $message->id,
message_type => $message->message_type,
section => $error->section,
details => $error->details,
};
}
}
}
$template->param(
edifact_enabled => $edifact_enabled,
edifact_messages => \@edifact_messages,
edifact_errors => \@edifact_errors,
);
unless ( CanUserManageBasket( $loggedinuser, $basket, $userflags ) ) {
$template->param(
cannot_manage_basket => 1,

View File

@ -123,6 +123,51 @@
[% PROCESS csv_export %]
[% IF edifact_enabled && edifact_messages.size > 0 %]
[% SET quote_messages = [] %]
[% SET order_messages = [] %]
[% FOR message IN edifact_messages %]
[% IF message.message_type == 'QUOTE' %]
[% quote_messages.push(message) %]
[% ELSIF message.message_type == 'ORDERS' %]
[% order_messages.push(message) %]
[% END %]
[% END %]
[% IF quote_messages.size > 0 && order_messages.size > 0 %]
<!-- Both quote and order messages exist -->
<div class="btn-group">
<button class="btn btn-default dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false"> <i class="fa fa-file-text"></i> View EDIFACT messages </button>
<ul class="dropdown-menu">
[% FOR message IN quote_messages %]
<li>
<a class="dropdown-item view_edifact_message" href="#" data-message-id="[% message.id | html %]">
<i class="fa fa-quote-left"></i> View quote ([% message.transfer_date | $KohaDates %])
</a>
</li>
[% END %]
[% FOR message IN order_messages %]
<li>
<a class="dropdown-item view_edifact_message" href="#" data-message-id="[% message.id | html %]">
<i class="fa fa-shopping-cart"></i> View order ([% message.transfer_date | $KohaDates %])
</a>
</li>
[% END %]
</ul>
</div>
[% ELSIF quote_messages.size > 0 %]
<!-- Only quote messages exist -->
<div class="btn-group">
<button type="button" class="btn btn-default view_edifact_message" data-message-id="[% quote_messages.0.id | html %]"> <i class="fa fa-quote-left"></i> View EDIFACT quote </button>
</div>
[% ELSIF order_messages.size > 0 %]
<!-- Only order messages exist -->
<div class="btn-group">
<button type="button" class="btn btn-default view_edifact_message" data-message-id="[% order_messages.0.id | html %]"> <i class="fa fa-shopping-cart"></i> View EDIFACT order </button>
</div>
[% END %]
[% END %]
[% IF Koha.Preference('EDIFACT') && ediaccount %]
[% UNLESS eans.size %]
<div class="btn-group" title="You must define an EAN in Administration -> Library EANs">
@ -283,8 +328,54 @@
<button type="submit" class="btn btn-default"><i class="fa-solid fa-rotate"></i> Reopen basket</button>
</form>
</div>
[% PROCESS csv_export %]
[% IF edifact_enabled && edifact_messages.size > 0 %]
[% SET quote_messages = [] %]
[% SET order_messages = [] %]
[% FOR message IN edifact_messages %]
[% IF message.message_type == 'QUOTE' %]
[% quote_messages.push(message) %]
[% ELSIF message.message_type == 'ORDERS' %]
[% order_messages.push(message) %]
[% END %]
[% END %]
[% IF quote_messages.size > 0 && order_messages.size > 0 %]
<!-- Both quote and order messages exist -->
<div class="btn-group">
<button class="btn btn-default dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false"> <i class="fa fa-file-text"></i> View EDIFACT messages </button>
<ul class="dropdown-menu">
[% FOR message IN quote_messages %]
<li>
<a class="dropdown-item view_edifact_message" href="#" data-message-id="[% message.id | html %]">
<i class="fa fa-quote-left"></i> View quote ([% message.transfer_date | $KohaDates %])
</a>
</li>
[% END %]
[% FOR message IN order_messages %]
<li>
<a class="dropdown-item view_edifact_message" href="#" data-message-id="[% message.id | html %]">
<i class="fa fa-shopping-cart"></i> View order ([% message.transfer_date | $KohaDates %])
</a>
</li>
[% END %]
</ul>
</div>
[% ELSIF quote_messages.size > 0 %]
<!-- Only quote messages exist -->
<div class="btn-group">
<button type="button" class="btn btn-default view_edifact_message" data-message-id="[% quote_messages.0.id | html %]"> <i class="fa fa-quote-left"></i> View EDIFACT quote </button>
</div>
[% ELSIF order_messages.size > 0 %]
<!-- Only order messages exist -->
<div class="btn-group">
<button type="button" class="btn btn-default view_edifact_message" data-message-id="[% order_messages.0.id | html %]"> <i class="fa fa-shopping-cart"></i> View EDIFACT order </button>
</div>
[% END %]
[% END %]
[% END %]
[% PROCESS csv_export %]
</div>
[% END # /UNLESS ( closedate ) %]
[% END # /UNLESS ( selectbasketg ) %]
@ -342,6 +433,47 @@
[% IF ( basketno ) %]
<div id="acqui_basket_summary" class="row">
[% IF edifact_enabled && edifact_errors.size > 0 %]
<div class="col-md-12 col-sm-12">
<div class="page-section">
<h2>EDIFACT parsing errors</h2>
[% SET errors_by_message = {} %]
[% FOR error IN edifact_errors %]
[% SET msg_id = error.message_id %]
[% IF !errors_by_message.$msg_id %]
[% errors_by_message.$msg_id = [] %]
[% END %]
[% errors_by_message.$msg_id.push(error) %]
[% END %]
[% FOR message IN edifact_messages %]
[% SET msg_id = message.id %]
[% IF errors_by_message.$msg_id %]
<div class="alert alert-warning">
<h4><i class="fa fa-exclamation-triangle"></i> [% message.message_type | html %] message ([% message.transfer_date | $KohaDates %])</h4>
[% IF message.filename %]
<p><strong>Filename:</strong> [% message.filename | html %]</p>
[% END %]
<ul>
[% FOR error IN errors_by_message.$msg_id %]
<li>
<strong>[% error.details | html %]</strong>
[% IF error.section %]
<br /><pre class="mt-1 mb-0 small text-muted">[% error.section | html %] section</pre>
[% END %]
</li>
[% END %]
</ul>
</div>
[% END %]
[% END %]
</div>
<!-- /.page-section -->
</div>
<!-- /.col-md-12 col-sm-12 -->
[% END %]
<div class="col-md-6 col-sm-12">
<div class="page-section rows">
<h2>General information</h2>
@ -1130,6 +1262,10 @@
</div>
<!-- /.modal#dateEditor -->
[% IF edifact_enabled && edifact_messages.size > 0 %]
[% INCLUDE 'modals/edifact-modal.inc' %]
[% END %]
[% MACRO jsinclude BLOCK %]
[% Asset.js("js/acquisitions-menu.js") | $raw %]
[% INCLUDE 'datatables.inc' %]
@ -1378,6 +1514,10 @@
[% SET filter = 'baskets_managers' %]
[% PROCESS patron_search_modal columns => columns, modal_title => t("Add user") %]
[% PROCESS patron_search_js columns => columns, actions => ["add"], preview_on_name_click => 1 %]
[% IF edifact_enabled && edifact_messages.size > 0 %]
[% Asset.js("js/modals/edifact-modal.js") | $raw %]
[% END %]
[% END %]
[% INCLUDE 'intranet-bottom.inc' %]