diff --git a/Koha/EDI.pm b/Koha/EDI.pm index 6514d8ed02..4f133f07ca 100644 --- a/Koha/EDI.pm +++ b/Koha/EDI.pm @@ -34,6 +34,7 @@ use utf8; use English qw{ -no_match_vars }; use Business::ISBN; use DateTime; +use JSON qw( encode_json ); use C4::Context; use Koha::Database; use Koha::DateUtils qw( dt_from_string ); @@ -958,17 +959,50 @@ sub quote_item { $order_hash->{line_item_id} = $item->item_number_id; } - if ( $item->girfield('servicing_instruction') ) { - my $occ = 0; - my $txt = q{}; - my $si; - while ( $si = $item->girfield( 'servicing_instruction', $occ ) ) { - if ($occ) { - $txt .= q{: }; + # Extract servicing instructions (LVT freetext and/or LVC coded) + # Build JSON array structure: [[{type,value},...]] + my @servicing_groups; + my @current_group; + + # Read LVC (coded) instructions + my $occ = 0; + my $lvc_val; + while ( $lvc_val = $item->girfield( 'coded_servicing_instruction', $occ ) ) { + + # Validate against EDIFACT_SI authorized values + my $av = Koha::AuthorisedValues->find( + { + category => 'EDIFACT_SI', + authorised_value => $lvc_val } - $txt .= $si; - ++$occ; + ); + if ($av) { + push @current_group, { type => 'LVC', value => $lvc_val }; + } else { + $quote_message->add_to_edifact_errors( + { + section => "GIR+LVC validation", + details => + "Invalid servicing instruction code '$lvc_val' - not found in EDIFACT_SI authorized values" + } + ); + $logger->trace("Invalid servicing instruction code: $lvc_val"); } + ++$occ; + } + + # Read LVT (freetext) instructions + $occ = 0; + my $lvt_val; + while ( $lvt_val = $item->girfield( 'servicing_instruction', $occ ) ) { + push @current_group, { type => 'LVT', value => $lvt_val }; + ++$occ; + } + + # Store as JSON if we have any instructions + if (@current_group) { + push @servicing_groups, \@current_group; + $order_hash->{servicing_instruction} = encode_json( \@servicing_groups ); } if ($order_note) { $order_hash->{order_vendornote} = $order_note; diff --git a/Koha/Edifact/Order.pm b/Koha/Edifact/Order.pm index dc753e2f88..32ae4a75e8 100644 --- a/Koha/Edifact/Order.pm +++ b/Koha/Edifact/Order.pm @@ -26,7 +26,9 @@ use DateTime; use Readonly qw( Readonly ); use Koha::Database; use Koha::DateUtils qw( dt_from_string ); -use C4::Budgets qw( GetBudget ); +use Koha::Logger; +use C4::Budgets qw( GetBudget ); +use JSON qw( decode_json ); use Koha::Acquisition::Orders; @@ -432,7 +434,10 @@ sub order_line { } } my $budget = GetBudget( $orderline->budget_id ); - my $ol_fields = { budget_code => $budget->{budget_code}, }; + my $ol_fields = { + budget_code => $budget->{budget_code}, + servicing_instruction => $orderline->servicing_instruction, + }; my $item_fields = []; for my $item (@items) { @@ -616,13 +621,38 @@ sub gir_segments { { identity_number => 'LSM', data => encode_text( $item->{itemcallnumber} ) }; } - # itemcallnumber -> shelfmark + # Servicing instructions (LVT freetext and/or LVC coded) + # Format: JSON array of arrays: [[{type,value},...],[{type,value},...]] + # Each inner array is a group of instructions that work together if ( $orderfields->{servicing_instruction} ) { - push @gir_elements, - { - identity_number => 'LVT', - data => encode_text( $orderfields->{servicing_instruction} ) - }; + my $si_data = $orderfields->{servicing_instruction}; + my $servicing_groups; + + eval { $servicing_groups = decode_json($si_data); }; + if ($@) { + my $logger = Koha::Logger->get( { interface => 'edi' } ); + $logger->warn("Failed to parse servicing_instruction JSON: $@"); + } + + # Add all servicing instruction groups + if ( ref $servicing_groups eq 'ARRAY' ) { + foreach my $group (@$servicing_groups) { + if ( ref $group eq 'ARRAY' ) { + foreach my $instruction (@$group) { + if ( ref $instruction eq 'HASH' + && $instruction->{type} + && $instruction->{value} ) + { + push @gir_elements, + { + identity_number => $instruction->{type}, + data => encode_text( $instruction->{value} ) + }; + } + } + } + } + } } my $e_cnt = 0; # count number of elements so we dont exceed 5 per segment my $copy_no = sprintf 'GIR+%03d', $sequence_no; @@ -630,7 +660,8 @@ sub gir_segments { foreach my $e (@gir_elements) { if ( $e_cnt == 5 ) { push @segments, $seg; - $seg = $copy_no; + $seg = $copy_no; + $e_cnt = 0; } $seg .= add_gir_identity_number( $e->{identity_number}, $e->{data} );