From 1e2e89e43f027a24ca0a99632a6e6bba8c8373e2 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 Signed-off-by: Hannah Dunne-Howrie Sponsored-by: Westminster City Council Sponsored-by: Royal Borough of Kensington and Chelsea Sponsored-by: OpenFifth Signed-off-by: Kyle M Hall Signed-off-by: Lucas Gass --- 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 ebdbce6190..9ea54b48e4 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 26848d36c5..5a1162d5b4 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 1468aab6da..e50b1e8947 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 %]