From 10865dd69af163a5aa15f2f20d8bfb65abc1006c Mon Sep 17 00:00:00 2001 From: Kyle Hall Date: Tue, 25 Oct 2022 12:44:57 -0400 Subject: [PATCH] Bug 20817: Add ability to retain 9xx fields when adding on order item to existing record This patchset intends to add the use of MarcItemFieldsToOrder and MarcFieldsToOrder to neworderempty.pl When adding to a basket fomr a staged file the above preferences create orders on addorderiso2709.pl if the records are unique, or if the records have been matched during staging If the records are not matched at staging, but a duplicate is found you must add the orders individually, and the info is not pulled from the incoming record Setup -- Set systempreferences below MarcFieldsToOrder: price: 949$g quantity: 949$k budget_code: 949$l discount: 949$m sort1: 949$n sort2: 949$q MarcItemFieldsToOrder: homebranch: 949$a holdingbranch: 949$b itype: 949$y nonpublic_note: 949$x public_note: 949$z loc: 949$c ccode: 949$8 notforloan: 949$7 uri: 949$u copyno: 949$t price: 949$g replacementprice: 949$v itemcallnumber: 949$o quantity: 949$k budget_code: 949$l To test: 1 - Stage the sample record for bib303 without looking for matching records (if not using Koha testing docker smaple data import this record, then stage again without matching) 2 - From acqusitions, find a vendor and an open basket and 'Add to basket' 'From a staged file' 3 - On the record in question, check the checbox, then click the 'Add order' link 4 - You are taken to page notifying of duplicate - click 'Use existing record' 5 - You are taken to new order empty, and item forms are prepopulated with order info 6 - Save the orders and confirm all added to basket as expected Additional Authors: Devinim Marcel de Rooy Signed-off-by: Liz Rea Signed-off-by: Marcel de Rooy --- C4/Items.pm | 11 +- Koha/Acquisition/Utils.pm | 176 ++++++++++++++++++ acqui/addorderiso2709.pl | 119 +----------- acqui/neworderempty.pl | 98 +++++++++- .../prog/en/modules/acqui/neworderempty.tt | 69 ++++++- .../modules/acqui/neworderempty_duplicate.tt | 3 +- koha-tmpl/intranet-tmpl/prog/js/additem.js | 2 +- t/Acquisition/Utils.t | 158 ++++++++++++++++ 8 files changed, 517 insertions(+), 119 deletions(-) create mode 100644 Koha/Acquisition/Utils.pm create mode 100755 t/Acquisition/Utils.t diff --git a/C4/Items.pm b/C4/Items.pm index 9d443bb6ec..0831b8cf36 100644 --- a/C4/Items.pm +++ b/C4/Items.pm @@ -1262,7 +1262,7 @@ sub _find_value { =head2 PrepareItemrecordDisplay - PrepareItemrecordDisplay($bibnum,$itemumber,$defaultvalues,$frameworkcode); + PrepareItemrecordDisplay($bibnum,$itemumber,$defaultvalues,$frameworkcode, $use_defaults); Returns a hash with all the fields for Display a given item data in a template @@ -1270,11 +1270,13 @@ $defaultvalues should either contain a hashref of values for the new item, or be The $frameworkcode returns the item for the given frameworkcode, ONLY if bibnum is not provided +If $use_defaults is true, the returned item values will be generated from the default values only. + =cut sub PrepareItemrecordDisplay { - my ( $bibnum, $itemnum, $defaultvalues, $frameworkcode ) = @_; + my ( $bibnum, $itemnum, $defaultvalues, $frameworkcode, $use_defaults ) = @_; my $dbh = C4::Context->dbh; $frameworkcode = C4::Biblio::GetFrameworkCode($bibnum) if $bibnum; @@ -1294,7 +1296,10 @@ sub PrepareItemrecordDisplay { # return nothing if we don't have found an existing framework. return q{} unless $tagslib; my $itemrecord; - if ($itemnum) { + if ($use_defaults) { + $itemrecord = $defaultvalues->{'itemrecord'}; + } + elsif ($itemnum) { $itemrecord = C4::Items::GetMarcItem( $bibnum, $itemnum ); } my @loop_data; diff --git a/Koha/Acquisition/Utils.pm b/Koha/Acquisition/Utils.pm new file mode 100644 index 0000000000..c898a00f38 --- /dev/null +++ b/Koha/Acquisition/Utils.pm @@ -0,0 +1,176 @@ +package Koha::Acquisition::Utils; + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use YAML::XS; + +use C4::Context; + +=head1 NAME + +Koha::Acquisition::Utils - Additional Koha functions for dealing with orders and acquisitions + +=head2 SUBROUTINES + +=head3 GetMarcFieldsToOrderValues($syspref_name, $record, $field_list) + +my $data = Koha::Acquisition::Utils::GetMarcFieldsToOrderValues('MarcFieldsToOrder', $marcrecord, ['price', 'quantity', 'budget_code', etc.]); + +The return value is a hashref of key value pairs, where the keys are the field list parameters, +and the values are extracted from the MARC record based on the key to MARC field mapping from the +system preference MarcFieldsToOrder. + +=cut + +sub GetMarcFieldsToOrderValues { + my ($record, $field_list) = @_; + my $syspref = C4::Context->preference('MarcFieldsToOrder'); + $syspref = "$syspref\n\n"; # YAML is anal on ending \n. Surplus does not hurt + my $yaml = eval { + YAML::XS::Load($syspref); + }; + if ( $@ ) { + warn "Unable to parse $syspref syspref : $@"; + return (); + } + my $r; + for my $field_name ( @$field_list ) { + next unless exists $yaml->{$field_name}; + my @fields = split /\|/, $yaml->{$field_name}; + for my $field ( @fields ) { + my ( $f, $sf ) = split /\$/, $field; + next unless $f and $sf; + if ( my $v = $record->subfield( $f, $sf ) ) { + $r->{$field_name} = $v; + } + last if $yaml->{$field}; + } + } + return $r; +} + +=head3 GetMarcItemFieldsToOrderValues($syspref_name, $record, $field_list) + +my $data = GetMarcItemFieldsToOrderValues('MarcItemFieldsToOrder', $marcrecord, ['homebranch', 'holdingbranch', 'itype', 'nonpublic_note', 'public_note', 'loc', 'ccode', 'notforloan', 'uri', 'copyno', 'price', 'replacementprice', 'itemcallnumber', 'quantity', 'budget_code']); + +The return value is a hashref of key value pairs, where the keys are the field list parameters, +and the values are extracted from the MARC record based on the key to MARC field mapping from the +system preference MarcFieldsToOrder. + +The largest difference between GetMarcFieldsToOrderValues and GetMarcItemFieldsToOrderValues is that the former deals +with singular marc fields, while the latter works on multiple matching marc fields and returns -1 if it cannot +find a matching number of all fields to be looked up. + +=cut + +sub GetMarcItemFieldsToOrderValues { + my ($record, $field_list) = @_; + my $syspref = C4::Context->preference('MarcItemFieldsToOrder'); + $syspref = "$syspref\n\n"; # YAML is anal on ending \n. Surplus does not hurt + my $yaml = eval { + YAML::XS::Load($syspref); + }; + if ( $@ ) { + warn "Unable to parse $syspref syspref : $@"; + return (); + } + my @result; + my @tags_list; + + # Check tags in syspref definition + for my $field_name ( @$field_list ) { + next unless exists $yaml->{$field_name}; + my @fields = split /\|/, $yaml->{$field_name}; + for my $field ( @fields ) { + my ( $f, $sf ) = split /\$/, $field; + next unless $f and $sf; + push @tags_list, $f; + } + } + @tags_list = List::MoreUtils::uniq(@tags_list); + + my $tags_count = equal_number_of_fields(\@tags_list, $record); + # Return if the number of these fields in the record is not the same. + return -1 if $tags_count == -1; + + # Gather the fields + my $fields_hash; + foreach my $tag (@tags_list) { + my @tmp_fields; + foreach my $field ($record->field($tag)) { + push @tmp_fields, $field; + } + $fields_hash->{$tag} = \@tmp_fields; + } + + for (my $i = 0; $i < $tags_count; $i++) { + my $r; + for my $field_name ( @$field_list ) { + next unless exists $yaml->{$field_name}; + my @fields = split /\|/, $yaml->{$field_name}; + for my $field ( @fields ) { + my ( $f, $sf ) = split /\$/, $field; + next unless $f and $sf; + my $v = $fields_hash->{$f}[$i] ? $fields_hash->{$f}[$i]->subfield( $sf ) : undef; + $r->{$field_name} = $v if (defined $v); + last if $yaml->{$field}; + } + } + push @result, $r; + } + return \@result; +} + +=head3 equal_number_of_fields($tags_list, $record) + +$value = equal_number_of_fields(\@tags_list, $record); + +Returns -1 if the number of instances of the given tags are not equal. + +For example, if you need to verify there are equal 975$i's and 975$a's, +this will let you know. + +=cut + +sub equal_number_of_fields { + my ($tags_list, $record) = @_; + my $tag_fields_count; + for my $tag (@$tags_list) { + my @fields = $record->field($tag); + $tag_fields_count->{$tag} = scalar @fields; + } + + my $tags_count; + foreach my $key ( keys %$tag_fields_count ) { + if ( $tag_fields_count->{$key} > 0 ) { # Having 0 of a field is ok + $tags_count //= $tag_fields_count->{$key}; # Start with the count from the first occurrence + return -1 if $tag_fields_count->{$key} != $tags_count; # All counts of various fields should be equal if they exist + } + } + + return $tags_count; +} + +1; +__END__ + +=head1 AUTHOR + +Koha Development Team + +=cut diff --git a/acqui/addorderiso2709.pl b/acqui/addorderiso2709.pl index b65663d862..cdbb4541dd 100755 --- a/acqui/addorderiso2709.pl +++ b/acqui/addorderiso2709.pl @@ -44,14 +44,17 @@ use C4::Items qw( PrepareItemrecordDisplay AddItemFromMarc ); use C4::Budgets qw( GetBudget GetBudgets GetBudgetHierarchy CanUserUseBudget GetBudgetByCode ); use C4::Suggestions; # GetSuggestion use C4::Members; - -use Koha::Number::Price; -use Koha::Libraries; +use C4::Output; +use C4::Search qw/FindDuplicate/; +use C4::Suggestions; # GetSuggestion use Koha::Acquisition::Baskets; +use Koha::Acquisition::Booksellers; use Koha::Acquisition::Currencies; use Koha::Acquisition::Orders; -use Koha::Acquisition::Booksellers; +use Koha::Acquisition::Utils; use Koha::Import::Records; +use Koha::Libraries; +use Koha::Number::Price; use Koha::Patrons; my $input = CGI->new; @@ -489,7 +492,7 @@ sub import_biblios_list { ); my $marcrecord = $import_record->get_marc_record || die "couldn't translate marc information"; - my $infos = get_infos_syspref('MarcFieldsToOrder', $marcrecord, ['price', 'quantity', 'budget_code', 'discount', 'sort1', 'sort2','replacementprice']); + my $infos = Koha::Acquisition::Utils::GetMarcFieldsToOrderValues( $marcrecord, [ 'price', 'quantity', 'budget_code', 'discount', 'sort1', 'sort2', 'replacementprice' ] ); my $price = $infos->{price}; my $replacementprice = $infos->{replacementprice}; my $quantity = $infos->{quantity}; @@ -508,7 +511,7 @@ sub import_biblios_list { # Items my @itemlist = (); my $all_items_quantity = 0; - my $alliteminfos = get_infos_syspref_on_item('MarcItemFieldsToOrder', $marcrecord, ['homebranch', 'holdingbranch', 'itype', 'nonpublic_note', 'public_note', 'loc', 'ccode', 'notforloan', 'uri', 'copyno', 'price', 'replacementprice', 'itemcallnumber', 'quantity', 'budget_code']); + my $alliteminfos = Koha::Acquisition::Utils::GetMarcItemFieldsToOrderValues( $marcrecord, [ 'homebranch', 'holdingbranch', 'itype', 'nonpublic_note', 'public_note', 'loc', 'ccode', 'notforloan', 'uri', 'copyno', 'price', 'replacementprice', 'itemcallnumber', 'quantity', 'budget_code' ] ); if ($alliteminfos != -1) { foreach my $iteminfos (@$alliteminfos) { my $item_homebranch = $iteminfos->{homebranch}; @@ -643,107 +646,3 @@ sub add_matcher_list { } $template->param(available_matchers => \@matchers); } - -sub get_infos_syspref { - my ($syspref_name, $record, $field_list) = @_; - my $syspref = C4::Context->preference($syspref_name); - $syspref = "$syspref\n\n"; # YAML is anal on ending \n. Surplus does not hurt - my $yaml = eval { - YAML::XS::Load(Encode::encode_utf8($syspref)); - }; - if ( $@ ) { - warn "Unable to parse $syspref syspref : $@"; - return (); - } - my $r; - for my $field_name ( @$field_list ) { - next unless exists $yaml->{$field_name}; - my @fields = split /\|/, $yaml->{$field_name}; - for my $field ( @fields ) { - my ( $f, $sf ) = split /\$/, $field; - next unless $f and $sf; - if ( my $v = $record->subfield( $f, $sf ) ) { - $r->{$field_name} = $v; - } - last if $yaml->{$field}; - } - } - return $r; -} - -sub equal_number_of_fields { - my ($tags_list, $record) = @_; - my $tag_fields_count; - for my $tag (@$tags_list) { - my @fields = $record->field($tag); - $tag_fields_count->{$tag} = scalar @fields; - } - - my $tags_count; - foreach my $key ( keys %$tag_fields_count ) { - if ( $tag_fields_count->{$key} > 0 ) { # Having 0 of a field is ok - $tags_count //= $tag_fields_count->{$key}; # Start with the count from the first occurrence - return -1 if $tag_fields_count->{$key} != $tags_count; # All counts of various fields should be equal if they exist - } - } - - return $tags_count; -} - -sub get_infos_syspref_on_item { - my ($syspref_name, $record, $field_list) = @_; - my $syspref = C4::Context->preference($syspref_name); - $syspref = "$syspref\n\n"; # YAML is anal on ending \n. Surplus does not hurt - my $yaml = eval { - YAML::XS::Load(Encode::encode_utf8($syspref)); - }; - if ( $@ ) { - warn "Unable to parse $syspref syspref : $@"; - return (); - } - my @result; - my @tags_list; - - # Check tags in syspref definition - for my $field_name ( @$field_list ) { - next unless exists $yaml->{$field_name}; - my @fields = split /\|/, $yaml->{$field_name}; - for my $field ( @fields ) { - my ( $f, $sf ) = split /\$/, $field; - next unless $f and $sf; - push @tags_list, $f; - } - } - @tags_list = List::MoreUtils::uniq(@tags_list); - - my $tags_count = equal_number_of_fields(\@tags_list, $record); - # Return if the number of these fields in the record is not the same. - return -1 if $tags_count == -1; - - # Gather the fields - my $fields_hash; - foreach my $tag (@tags_list) { - my @tmp_fields; - foreach my $field ($record->field($tag)) { - push @tmp_fields, $field; - } - $fields_hash->{$tag} = \@tmp_fields; - } - - for (my $i = 0; $i < $tags_count; $i++) { - my $r; - for my $field_name ( @$field_list ) { - next unless exists $yaml->{$field_name}; - my @fields = split /\|/, $yaml->{$field_name}; - for my $field ( @fields ) { - my ( $f, $sf ) = split /\$/, $field; - next unless $f and $sf; - my $v = $fields_hash->{$f}[$i] ? $fields_hash->{$f}[$i]->subfield( $sf ) : undef; - $r->{$field_name} = $v if (defined $v); - last if $yaml->{$field}; - } - } - push @result, $r; - } - return \@result; -} diff --git a/acqui/neworderempty.pl b/acqui/neworderempty.pl index a584ea1d11..0ffb1eed29 100755 --- a/acqui/neworderempty.pl +++ b/acqui/neworderempty.pl @@ -66,7 +66,6 @@ the item's id in the breeding reservoir use Modern::Perl; use CGI qw ( -utf8 ); -use C4::Context; use C4::Auth qw( get_template_and_user ); use C4::Budgets qw( GetBudget GetBudgetHierarchy CanUserUseBudget ); @@ -85,6 +84,7 @@ use C4::Biblio qw( use C4::Output qw( output_and_exit output_html_with_http_headers ); use C4::Members; use C4::Search qw( FindDuplicate ); +use C4::Items qw( PrepareItemrecordDisplay ); #needed for z3950 import: use C4::ImportBatch qw( SetImportRecordStatus SetMatchedBiblionumber GetImportRecordMarc ); @@ -92,10 +92,11 @@ use C4::ImportBatch qw( SetImportRecordStatus SetMatchedBiblionumber GetImportRe use Koha::Acquisition::Booksellers; use Koha::Acquisition::Currencies qw( get_active ); use Koha::Biblios; +use Koha::Acquisition::Utils; use Koha::BiblioFrameworks; use Koha::DateUtils qw( dt_from_string ); -use Koha::MarcSubfieldStructures; use Koha::ItemTypes; +use Koha::MarcSubfieldStructures; use Koha::Patrons; use Koha::RecordProcessor; use Koha::Subscriptions; @@ -321,6 +322,19 @@ if ( not $ordernumber or $biblionumber ) { } } +my $usebreedingid = $input->param('use_breedingid'); +if ( $usebreedingid ) { + my $item_list = staged_items_field( $usebreedingid ); + $listprice = $item_list->{'price'}; + $budget_id = $item_list->{'budget_id'}; + $data->{replacementprice} = $item_list->{'replacementprice'}; + $data->{'sort1'} = $item_list->{'sort1'}; + $data->{'sort2'} = $item_list->{'sort2'}; + $data->{'discount'} = $item_list->{'discount'}; + $data->{quantity} = $item_list->{quantity}; + $template->param( item_list => $item_list->{'iteminfos'} ); +} + $template->param( catalog_details => \@catalog_details, ); my $suggestion; @@ -608,3 +622,83 @@ sub Load_Duplicate { output_html_with_http_headers $input, $cookie, $template->output; } + +sub staged_items_field { + my ($breedingid) = @_; + my %cellrecord = (); + + my ($marcrecord, $encoding) = MARCfindbreeding($breedingid); + die("Could not find the selected record in the reservoir, bailing") unless $marcrecord; + + my $infos = Koha::Acquisition::Utils::GetMarcFieldsToOrderValues( $marcrecord, [ 'price', 'quantity', 'budget_code', 'discount', 'sort1', 'sort2', 'replacementprice' ] ); + my $price = $infos->{price}; + my $replacementprice = $infos->{replacementprice}; + my $quantity = $infos->{quantity}; + my $budget_code = $infos->{budget_code}; + my $discount = $infos->{discount}; + my $sort1 = $infos->{sort1}; + my $sort2 = $infos->{sort2}; + my $budget_id; + if($budget_code) { + my $biblio_budget = GetBudgetByCode($budget_code); + if($biblio_budget) { + $budget_id = $biblio_budget->{budget_id}; + } + } + # Items + my @itemlist = (); + my $all_items_quantity = 0; + my $alliteminfos = Koha::Acquisition::Utils::GetMarcItemFieldsToOrderValues( $marcrecord, [ 'homebranch', 'holdingbranch', 'itype', 'nonpublic_note', 'public_note', 'loc', 'ccode', 'notforloan', 'uri', 'copyno', 'price', 'replacementprice', 'itemcallnumber', 'quantity', 'budget_code' ] ); + if ($alliteminfos != -1) { + foreach my $iteminfos (@$alliteminfos) { + my %itemrecord=( + 'homebranch' => _trim( $iteminfos->{homebranch} ), + 'holdingbranch' => _trim( $iteminfos->{holdingbranch} ), + 'itype' => _trim( $iteminfos->{itype} ), + 'itemnotes_nonpublic' => $iteminfos->{nonpublic_note}, + 'itemnotes' => $iteminfos->{public_note}, + 'location' => _trim( $iteminfos->{loc} ), + 'ccode' => _trim( $iteminfos->{ccode} ), + 'notforloan' => _trim( $iteminfos->{notforloan} ), + 'uri' => $iteminfos->{uri}, + 'copynumber' => $iteminfos->{copyno}, + 'price' => $iteminfos->{price}, + 'replacementprice' => $iteminfos->{replacementprice}, + 'itemcallnumber' => $iteminfos->{itemcallnumber}, + ); + + my $item_quantity = $iteminfos->{quantity} || 1; + + for (my $i = 0; $i < $item_quantity; $i++) { + my %defaultvalues=( + 'itemrecord'=> C4::Items::Item2Marc( \%itemrecord), + 'branchcode'=>_trim($iteminfos->{homebranch}) + ); + $all_items_quantity++; + my $itemprocessed = PrepareItemrecordDisplay('', '', \%defaultvalues , 'ACQ', 1); + push @itemlist, $itemprocessed->{'iteminformation'}; + } + } + $cellrecord{'iteminfos'} = \@itemlist; + } else { + $cellrecord{'item_error'} = 1; + } + $cellrecord{price} = $price || ''; + $cellrecord{replacementprice} = $replacementprice || ''; + $cellrecord{quantity} = $quantity || ''; + $cellrecord{budget_id} = $budget_id || ''; + $cellrecord{discount} = $discount || ''; + $cellrecord{sort1} = $sort1 || ''; + $cellrecord{sort2} = $sort2 || ''; + unless ($alliteminfos == -1 && scalar(@$alliteminfos) == 0) { + $cellrecord{quantity} = $all_items_quantity; + } + + return (\%cellrecord); +} + +sub _trim { + my $string = shift // q{}; + $string =~ s/^\s+|\s+$//g; + return $string; +} diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt index 49142ebc3d..5e560db62b 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt @@ -5,6 +5,11 @@ [% USE Price %] [% USE ItemTypes %] [% SET footerjs = 1 %] + +[% IF item_list %] + [% SET footerjs = 0 %] +[% END %] + [% INCLUDE 'doc-head-open.inc' %] [% IF ( ordernumber ) %]Modify order details (line #[% ordernumber | html %])[% ELSE %]New order[% END %] › Basket [% basketno | html %] › Acquisitions › Koha [% INCLUDE 'doc-head-close.inc' %] @@ -322,7 +327,59 @@
The autoBarcode system preference is set to [% Koha.Preference('autoBarcode') | html %] and items with blank barcodes will have barcodes generated upon save to database
[% END %] -
+
+ [% FOREACH item IN item_list %] + [% SET itemID = loop.count %] +
+
    + [% FOREACH iteminfo IN item %] + [% IF ( iteminfo.hidden ) %] +
  1. + [% ELSE %] +
  2. + [% END %] +
    + [% IF (iteminfo.mandatory) %] + + [% ELSE %] + + [% END %] + [% IF ( iteminfo.marc_value.type == 'select' ) %] + + [% ELSE %] + [% iteminfo.marc_value | $raw %] + [% END %] + + + + + + [% IF (iteminfo.mandatory) %] Required[% END %] +
    +
  3. + [% END %] +
+
+ + + + +
+
+ [% END %] +
[% END %][%# | html UNLESS subscriptionid %] @@ -630,7 +687,12 @@ } $(document).ready(function(){ - [% IF AcqCreateItemOrdering and not basket.is_standing %] + var events = $('#outeritemblock > div').filter(function () { + var el = BindPluginEvents(this.innerHTML); + return el; + }); + + [% IF AcqCreateItemOrdering and not basket.is_standing and not item_list %] cloneItemBlock(0, '[% UniqueItemFields | html %]'); [% END %] @@ -727,6 +789,9 @@ [% END %] +[% UNLESS ( footerjs ) %] + [% jsinclude | $raw # Parse the page template's JavaScript block if necessary %] +[% END %] [% INCLUDE 'intranet-bottom.inc' %] [% BLOCK display_subfield %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty_duplicate.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty_duplicate.tt index 4ed47e9066..023f8ba5a3 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty_duplicate.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty_duplicate.tt @@ -52,6 +52,7 @@ + @@ -76,7 +77,7 @@ - + diff --git a/koha-tmpl/intranet-tmpl/prog/js/additem.js b/koha-tmpl/intranet-tmpl/prog/js/additem.js index fac6b2648c..479a647d72 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/additem.js +++ b/koha-tmpl/intranet-tmpl/prog/js/additem.js @@ -11,7 +11,7 @@ function addItem( node, unique_item_fields ) { } if ( $("#items_list table").find('tr[idblock="' + index + '"]').length == 0 ) { if ( current_qty < max_qty ) { - if ( current_qty < max_qty - 1 ) + if ( current_qty < max_qty - 1 && $('#outeritemblock > div:visible').length == 1 ) cloneItemBlock(index, unique_item_fields); addItemInList(index, unique_item_fields); $("#" + index).find("input[name='buttonPlus']").val( __("Update item") ); diff --git a/t/Acquisition/Utils.t b/t/Acquisition/Utils.t new file mode 100755 index 0000000000..6105402e81 --- /dev/null +++ b/t/Acquisition/Utils.t @@ -0,0 +1,158 @@ +#!/usr/bin/perl + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; +use utf8; + +use Test::More tests => 4; +use Test::MockModule; + +use t::lib::Mocks; +use t::lib::TestBuilder; + +use MARC::Record; + +use_ok('Koha::Acquisition::Utils'); + +my $schema = Koha::Database->schema; +$schema->storage->txn_begin; +my $builder = t::lib::TestBuilder->new; +my $dbh = C4::Context->dbh; + +subtest "GetMarcFieldsToOrderValues" => sub { + plan tests => 4; + + my $record = MARC::Record->new; + $record->append_fields( + MARC::Field->new( '500', '', '', a => 'Test 1' ), + MARC::Field->new( '505', '', '', a => 'Test 2', u => 'http://example.com' ), + MARC::Field->new( '520', '', '', a => 'Test 3' ), + MARC::Field->new( '541', '', '', a => 'Test 4' ), + ); + + my $MarcFieldsToOrder = q{ +test1: 500$a +test2: 505$a +test3: 520$a +test4: 541$a + }; + t::lib::Mocks::mock_preference('MarcFieldsToOrder', $MarcFieldsToOrder); + my $data = Koha::Acquisition::Utils::GetMarcFieldsToOrderValues( + $record, + [ 'test1', 'test2', 'test3', 'test4' ] + ); + + is( $data->{test1}, "Test 1", "Got test 1 correctly" ); + is( $data->{test2}, "Test 2", "Got test 2 correctly" ); + is( $data->{test3}, "Test 3", "Got test 3 correctly" ); + is( $data->{test4}, "Test 4", "Got test 4 correctly" ); +}; + +subtest "GetMarcItemFieldsToOrderValues" => sub { + plan tests => 13; + + my $record = MARC::Record->new; + $record->append_fields( + MARC::Field->new( '500', '', '', a => 'Test 1' ), + MARC::Field->new( '505', '', '', a => 'Test 2', u => 'http://example.com' ), + MARC::Field->new( '975', '', '', a => 'Test 3', b => "Test 4" ), + MARC::Field->new( '975', '', '', a => 'Test 5', b => "Test 6" ), + MARC::Field->new( '975', '', '', a => 'Test 7', b => "Test 8" ), + MARC::Field->new( '976', '', '', a => 'Test 9', b => "Test 10" ), + MARC::Field->new( '976', '', '', a => 'Test 11', b => "Test 12" ), + MARC::Field->new( '976', '', '', a => 'Test 13', b => "Test 14" ), + ); + + my $MarcItemFieldsToOrder = q{ +testA: 975$a +testB: 975$b +testC: 976$a +testD: 976$b + }; + t::lib::Mocks::mock_preference('MarcItemFieldsToOrder', $MarcItemFieldsToOrder); + my $data = Koha::Acquisition::Utils::GetMarcItemFieldsToOrderValues( + $record, + [ 'testA', 'testB', 'testC', 'testD' ] + ); + + is( $data->[0]->{testA}, "Test 3", 'Got first 975$a correctly' ); + is( $data->[0]->{testB}, "Test 4", 'Got first 975$b correctly' ); + is( $data->[1]->{testA}, "Test 5", 'Got second 975$a correctly' ); + is( $data->[1]->{testB}, "Test 6", 'Got second 975$b correctly' ); + is( $data->[2]->{testA}, "Test 7", 'Got third 975$a correctly' ); + is( $data->[2]->{testB}, "Test 8", 'Got third 975$b correctly' ); + + is( $data->[0]->{testC}, "Test 9", 'Got first 976$a correctly' ); + is( $data->[0]->{testD}, "Test 10", 'Got first 976$b correctly' ); + is( $data->[1]->{testC}, "Test 11", 'Got second 976$a correctly' ); + is( $data->[1]->{testD}, "Test 12", 'Got second 976$b correctly' ); + is( $data->[2]->{testC}, "Test 13", 'Got third 976$a correctly' ); + is( $data->[2]->{testD}, "Test 14", 'Got third 976$b correctly' ); + + # Test with bad record where fields are not one-to-one + $record->append_fields( + MARC::Field->new( '500', '', '', a => 'Test 1' ), + MARC::Field->new( '505', '', '', a => 'Test 2', u => 'http://example.com' ), + MARC::Field->new( '975', '', '', a => 'Test 3', b => "Test 4" ), + MARC::Field->new( '975', '', '', b => "Test 6" ), + MARC::Field->new( '975', '', '', b => 'Test 7' ), + MARC::Field->new( '976', '', '', a => 'Test 9', b => "Test 10" ), + MARC::Field->new( '976', '', '', a => 'Test 11', b => "Test 12" ), + ); + + $data = Koha::Acquisition::Utils::GetMarcItemFieldsToOrderValues( + $record, + [ 'testA', 'testB', 'testC', 'testD' ] + ); + is( $data, -1, "Got -1 if record fields are not one-to-one"); +}; + +subtest "equal_number_of_fields" => sub { + plan tests => 2; + + my $record = MARC::Record->new; + $record->append_fields( + MARC::Field->new( '500', '', '', a => 'Test 1' ), + MARC::Field->new( '505', '', '', a => 'Test 2', u => 'http://example.com' ), + MARC::Field->new( '975', '', '', a => 'Test a', b => "Test b" ), + MARC::Field->new( '975', '', '', a => 'Test a', b => "Test b" ), + MARC::Field->new( '975', '', '', a => 'Test a', b => "Test b" ), + MARC::Field->new( '976', '', '', a => 'Test a', b => "Test b" ), + MARC::Field->new( '976', '', '', a => 'Test a', b => "Test b" ), + MARC::Field->new( '976', '', '', a => 'Test a', b => "Test b" ), + ); + + my $data = Koha::Acquisition::Utils::equal_number_of_fields( [ '975', '976' ], $record ); + is( $data, '3', "Got correct number of fields in return value" ); + + # Test with non-matching field sets + $record->append_fields( + MARC::Field->new( '500', '', '', a => 'Test 1' ), + MARC::Field->new( '505', '', '', a => 'Test 2', u => 'http://example.com' ), + MARC::Field->new( '975', '', '', a => 'Test a', b => "Test b" ), + MARC::Field->new( '975', '', '', a => 'Test a', b => "Test b" ), + MARC::Field->new( '975', '', '', a => 'Test a', b => "Test b" ), + MARC::Field->new( '976', '', '', a => 'Test a', b => "Test b" ), + MARC::Field->new( '976', '', '', a => 'Test a', b => "Test b" ), + ); + + $data = Koha::Acquisition::Utils::equal_number_of_fields( [ '975', '976' ], $record ); + is( $data, '-1', "Got -1 in return value" ); +}; + +$schema->storage->txn_rollback; +C4::Context->clear_syspref_cache(); -- 2.30.2