From 9ceae2f153dbc3e37fb2bd547b4b6229c1c03f56 Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Fri, 11 Jul 2025 12:31:34 +0100 Subject: [PATCH] Bug 20253: (follow-up) Make basket name read-only when derived from EDI purchase order number When a basket is created from an EDI quote with the vendor EDI account configured to use purchase order numbers, the basket name should be protected from changes to maintain the integrity of the purchase order number reference. This patch: - Makes the basket name field read-only in the UI when the basket was created from EDI with purchase order number setting - Adds explanatory text when the field is protected - Implements server-side protection to prevent basket name changes even if the UI is bypassed - Preserves the original purchase order number derived name --- Koha/Acquisition/Basket.pm | 24 ++++++++++ acqui/basketheader.pl | 47 ++++++++++++++++++- .../prog/en/modules/acqui/basketheader.tt | 10 +++- 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/Koha/Acquisition/Basket.pm b/Koha/Acquisition/Basket.pm index a5452414b6e..0bea7f34234 100644 --- a/Koha/Acquisition/Basket.pm +++ b/Koha/Acquisition/Basket.pm @@ -135,6 +135,30 @@ sub edi_order { return $order_rs->single; } +=head3 edi_quote + + my $edi_order = $basket->edi_quote; + +Returns the EDI quote object if one was used to generate this basket. + +NOTE: This currently returns a bare DBIx::Class result or undefined. This is consistent with the rest of EDI; +However it would be beneficial to convert these to full fledge Koha::Objects in the future. + +=cut + +sub edi_quote { + my ($self) = @_; + + my $order_rs = $self->_result->edifact_messages( + { + message_type => 'QUOTE', + deleted => 0 + }, + { order_by => { '-desc' => 'transfer_date' }, rows => 1 } + ); + return $order_rs->single; +} + =head3 effective_create_items Returns C for this basket, falling back to C if unset. diff --git a/acqui/basketheader.pl b/acqui/basketheader.pl index 4ab854258d4..84a6a58f043 100755 --- a/acqui/basketheader.pl +++ b/acqui/basketheader.pl @@ -56,6 +56,7 @@ use C4::Contract qw( GetContracts GetContract ); use Koha::Acquisition::Booksellers; use Koha::Acquisition::Baskets; use Koha::AdditionalFields; +use Koha::Database; my $input = CGI->new; my ( $template, $loggedinuser, $cookie ) = get_template_and_user( @@ -122,6 +123,24 @@ if ( $op eq 'add_form' ) { ); } + # Check if basket name should be read-only (EDI-generated with PO number setting) + my $basket_name_readonly = 0; + if ( $basketno && $basket ) { + my $basket_obj = Koha::Acquisition::Baskets->find($basketno); + if ($basket_obj) { + my $edi_quote = $basket_obj->edi_quote; + if ($edi_quote) { + + # This basket was created from an EDI quote + # Check if the vendor EDI account is configured to use purchase order numbers + my $vendor_edi_account = $edi_quote->edi_acct; + if ( $vendor_edi_account && $vendor_edi_account->po_is_basketname ) { + $basket_name_readonly = 1; + } + } + } + } + $template->param( add_form => 1, basketname => $basket->{'basketname'}, @@ -132,6 +151,7 @@ if ( $op eq 'add_form' ) { basketno => $basketno, is_standing => $basket->{is_standing}, create_items => $basket->{create_items}, + basket_name_readonly => $basket_name_readonly, ); my $billingplace = $basket->{'billingplace'} || C4::Context->userenv->{"branch"}; @@ -145,9 +165,34 @@ if ( $op eq 'add_form' ) { #we are confirming the changes, save the basket if ($is_an_edit) { + + # Check if basket name should be protected from changes + my $basket_name = scalar $input->param('basketname'); + my $current_basket = GetBasket($basketno); + + # If this basket was created from EDI with PO number setting, prevent name changes + my $basket_obj = Koha::Acquisition::Baskets->find($basketno); + if ($basket_obj) { + my $edi_order = $basket_obj->edi_order; + if ($edi_order) { + + # This basket was created from an EDI order/quote + # Check if the vendor EDI account is configured to use purchase order numbers + my $schema = Koha::Database->new()->schema(); + my $vendor_edi_account = $schema->resultset('VendorEdiAccount') + ->search( { vendor_id => scalar $input->param('basketbooksellerid') } )->first; + + if ( $vendor_edi_account && $vendor_edi_account->po_is_basketname ) { + + # Preserve the original basket name + $basket_name = $current_basket->{'basketname'}; + } + } + } + ModBasketHeader( $basketno, - scalar $input->param('basketname'), + $basket_name, scalar $input->param('basketnote'), scalar $input->param('basketbooksellernote'), scalar $input->param('basketcontractnumber') || undef, diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basketheader.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basketheader.tt index 1468aab6da8..e50b1e89473 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basketheader.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basketheader.tt @@ -68,8 +68,14 @@ [% END %]
  • - - Required + [% IF basket_name_readonly %] + + Required +
    This basket name is derived from the purchase order number and cannot be changed.
    + [% ELSE %] + + Required + [% END %]
  • -- 2.50.0