From ff9e479244e70aa437e5dde513897509261da941 Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Tue, 8 Jul 2025 14:45:19 +0100 Subject: [PATCH] Bug 20253: Optionally use buyer's purchase order number from EDIFACT quote in basket name This enhancement allows libraries to configure vendors to use the buyer's purchase order number (from RFF+ON segments) as the basket name instead of the EDIFACT filename, improving searchability and reference tracking. Backend Changes: - Added purchase_order_number() method to Koha::Edifact::Message to extract RFF+ON segments from message-level data (before first LIN segment) - Modified process_quote() in Koha::EDI to use purchase order number for basket naming when configured, with fallback to filename Frontend Changes: - Updated admin/edi_accounts.pl to handle basket_name_source parameter - Added "Basket name source" dropdown to EDI accounts template with options: - "Quote filename" (default) - "Purchase order number (RFF+ON)" Test Plan: 1. Apply patches and run database update 2. Go to Administration > Acquisitions > EDI accounts 3. Create or edit a vendor EDI account 4. Verify "Basket name source" dropdown appears with options: - "Quote filename" (default) - "Purchase order number (RFF+ON)" 5. Set to "Purchase order number (RFF+ON)" and save 6. Process an EDIFACT quote file that contains RFF+ON segments 7. Verify the created basket name uses the purchase order number instead of filename 8. Process a quote file without RFF+ON segments 9. Verify the basket name falls back to the filename 10. Test with "Quote filename" setting 11. Verify basket names use filenames regardless of RFF+ON presence 12. Run tests: prove t/Edifact_RFF_ON.t t/db_dependent/Koha/EDI.t The feature is optional and backward compatible - existing behavior is unchanged unless explicitly configured. --- Koha/EDI.pm | 26 ++++++++++++++----- Koha/Edifact/Message.pm | 16 ++++++++++++ admin/edi_accounts.pl | 23 ++++++++-------- .../prog/en/modules/admin/edi_accounts.tt | 13 ++++++++++ 4 files changed, 60 insertions(+), 18 deletions(-) diff --git a/Koha/EDI.pm b/Koha/EDI.pm index 6b485bf864c..8291615e987 100644 --- a/Koha/EDI.pm +++ b/Koha/EDI.pm @@ -646,10 +646,27 @@ sub process_quote { my @added_baskets; # if auto & multiple baskets need to order all if ( @{$messages} && $quote_message->vendor_id ) { + # Get vendor EDI account configuration + my $v = $schema->resultset('VendorEdiAccount')->search( + { + vendor_id => $quote_message->vendor_id, + } + )->single; + foreach my $msg ( @{$messages} ) { ++$message_count; + + # Determine basket name based on vendor configuration + my $basket_name = $quote_message->filename; + if ( $v && $v->basket_name_source && $v->basket_name_source eq 'purchase_order_number' ) { + my $purchase_order_number = $msg->purchase_order_number; + if ( $purchase_order_number ) { + $basket_name = $purchase_order_number; + } + } + my $basketno = NewBasket( - $quote_message->vendor_id, 0, $quote_message->filename, q{}, + $quote_message->vendor_id, 0, $basket_name, q{}, q{} . q{} ); push @added_baskets, $basketno; @@ -691,12 +708,7 @@ sub process_quote { $quote_message->status($status); $quote_message->update; # status and basketno link # Do we automatically generate orders for this vendor - my $v = $schema->resultset('VendorEdiAccount')->search( - { - vendor_id => $quote_message->vendor_id, - } - )->single; - if ( $v->auto_orders ) { + if ( $v && $v->auto_orders ) { for my $b (@added_baskets) { create_edi_order( { diff --git a/Koha/Edifact/Message.pm b/Koha/Edifact/Message.pm index 5983b4b670e..ec3ba180ec0 100644 --- a/Koha/Edifact/Message.pm +++ b/Koha/Edifact/Message.pm @@ -183,6 +183,22 @@ sub supplier_ean { } +sub purchase_order_number { + my $self = shift; + foreach my $s ( @{ $self->{datasegs} } ) { + if ( $s->tag eq 'LIN' ) { + last; + } + if ( $s->tag eq 'RFF' ) { + my $qualifier = $s->elem( 0, 0 ); + if ( $qualifier eq 'ON' ) { + return $s->elem( 0, 1 ); + } + } + } + return; +} + sub lineitems { my $self = shift; if ( $self->{quotation_lines} ) { diff --git a/admin/edi_accounts.pl b/admin/edi_accounts.pl index 410bcb8eaf4..2ad68b16aa9 100755 --- a/admin/edi_accounts.pl +++ b/admin/edi_accounts.pl @@ -75,25 +75,26 @@ if ( $op eq 'acct_form' ) { my $password = scalar $input->param('password'); $password = $crypt->encrypt_hex($password); my $fields = { - description => scalar $input->param('description'), - host => scalar $input->param('host'), - username => scalar $input->param('username'), - password => $password, - upload_port => scalar $input->param('upload_port') || $input->param('transport') eq 'FTP' ? 21 : 22, - download_port => scalar $input->param('download_port') || $input->param('transport') eq 'FTP' ? 21 : 22, + description => scalar $input->param('description'), + host => scalar $input->param('host'), + username => scalar $input->param('username'), + password => $password, + upload_port => scalar $input->param('upload_port') || $input->param('transport') eq 'FTP' ? 21 : 22, + download_port => scalar $input->param('download_port') || $input->param('transport') eq 'FTP' ? 21 : 22, vendor_id => scalar $input->param('vendor_id'), upload_directory => scalar $input->param('upload_directory'), download_directory => scalar $input->param('download_directory'), san => scalar $input->param('san'), standard => scalar $input->param('standard'), transport => scalar $input->param('transport'), - quotes_enabled => $input->param('quotes_enabled') ? 1 : 0, - invoices_enabled => $input->param('invoices_enabled') ? 1 : 0, - orders_enabled => $input->param('orders_enabled') ? 1 : 0, - responses_enabled => $input->param('responses_enabled') ? 1 : 0, - auto_orders => $input->param('auto_orders') ? 1 : 0, + quotes_enabled => $input->param('quotes_enabled') ? 1 : 0, + invoices_enabled => $input->param('invoices_enabled') ? 1 : 0, + orders_enabled => $input->param('orders_enabled') ? 1 : 0, + responses_enabled => $input->param('responses_enabled') ? 1 : 0, + auto_orders => $input->param('auto_orders') ? 1 : 0, id_code_qualifier => scalar $input->param('id_code_qualifier'), plugin => scalar $input->param('plugin'), + basket_name_source => scalar $input->param('basket_name_source') || 'filename', }; if ($id) { diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/edi_accounts.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/edi_accounts.tt index 4e554f03eb7..1006655d44c 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/edi_accounts.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/edi_accounts.tt @@ -251,6 +251,19 @@ [% END %]
With automatic ordering quotes generate orders without staff intervention.
+
  • + + +
    Determines how basket names are generated from quotes. Purchase order number uses RFF+ON segment from EDIFACT message if available, otherwise falls back to filename.
    +
  • -- 2.50.0