use CGI qw ( -utf8 );
use Modern::Perl;
-use Try::Tiny;
-
-use C4::Auth;
-use C4::Output;
-use C4::Biblio;
-use C4::Items;
-use C4::Circulation;
+use Try::Tiny qw( catch try );
+
+use C4::Auth qw( get_template_and_user );
+use C4::Output qw( output_html_with_http_headers );
+use C4::Biblio qw(
+ DelBiblio
+ GetAuthorisedValueDesc
+ GetMarcFromKohaField
+ GetMarcStructure
+ IsMarcStructureInternal
+ TransformHtmlToXml
+);
+use C4::Items qw( GetItemsInfo Item2Marc ModItemFromMarc );
+use C4::Circulation qw( LostItem IsItemIssued );
use C4::Context;
use C4::Koha;
use C4::BackgroundJob;
-use C4::ClassSource;
-use C4::Debug;
-use C4::Members;
+use C4::ClassSource qw( GetClassSources GetClassSource );
use MARC::File::XML;
-use List::MoreUtils qw/uniq/;
+use List::MoreUtils qw( uniq );
use Koha::Database;
use Koha::Exceptions::Exception;
use Koha::AuthorisedValues;
use Koha::Biblios;
-use Koha::DateUtils;
+use Koha::DateUtils qw( dt_from_string );
use Koha::Items;
use Koha::ItemTypes;
use Koha::Patrons;
+use Koha::SearchEngine::Indexer;
-my $input = new CGI;
+my $input = CGI->new;
my $dbh = C4::Context->dbh;
my $error = $input->param('error');
my @itemnumbers = $input->multi_param('itemnumber');
my $del = $input->param('del');
my $del_records = $input->param('del_records');
my $completedJobID = $input->param('completedJobID');
-my $runinbackground = $input->param('runinbackground');
my $src = $input->param('src');
my $use_default_values = $input->param('use_default_values');
my $exclude_from_local_holds_priority = $input->param('exclude_from_local_holds_priority');
= get_template_and_user({template_name => $template_name,
query => $input,
type => "intranet",
- authnotrequired => 0,
flagsrequired => $template_flag,
});
$template->param( "job_completed" => 1 );
}
- # Setting the job as done
- my $job = C4::BackgroundJob->fetch($sessionID, $completedJobID);
-
- # Calling the template
- add_saved_job_results_to_template($template, $completedJobID, $items_display_hashref);
-
} else {
# While the job is getting done
- # Job size is the number of items we have to process
- my $job_size = scalar(@itemnumbers);
- my $job = undef;
-
- # If we asked for background processing
- if ($runinbackground) {
- $job = put_in_background($job_size);
- }
-
#initializing values for updates
my ( $itemtagfield, $itemtagsubfield) = &GetMarcFromKohaField( "items.itemnumber" );
if ($values_to_modify){
}
}
- my $yesno = Koha::AuthorisedValues->search({category => 'YES_NO'});
- my $ynhash = {};
-
- while(my $yn = $yesno->next) {
- $ynhash->{'av'.$yn->authorised_value} = $yn->lib;
- }
-
+ my $upd_biblionumbers;
+ my $del_biblionumbers;
try {
my $schema = Koha::Database->new->schema;
$schema->txn_do(
sub {
# For each item
my $i = 1;
- my $extra_headers = {};
foreach my $itemnumber (@itemnumbers) {
- $job->progress($i) if $runinbackground;
my $item = Koha::Items->find($itemnumber);
next
unless $item
my $return = $item->safe_delete;
if ( ref( $return ) ) {
$deleted_items++;
+ push @$upd_biblionumbers, $itemdata->{'biblionumber'};
}
else {
$not_deleted_items++;
if ($del_records) {
my $itemscount = Koha::Biblios->find( $itemdata->{'biblionumber'} )->items->count;
if ( $itemscount == 0 ) {
- my $error = DelBiblio( $itemdata->{'biblionumber'} );
+ my $error = DelBiblio( $itemdata->{'biblionumber'}, { skip_record_index => 1 } );
unless ($error) {
$deleted_records++;
+ push @$del_biblionumbers, $itemdata->{'biblionumber'};
if ( $src eq 'CATALOGUING' ) {
# We are coming catalogue/detail.pl, there were items from a single bib record
$template->param( biblio_deleted => 1 );
$item->exclude_from_local_holds_priority($exclude_from_local_holds_priority)->store;
$modified_holds_priority = 1;
}
- $extra_headers->{exclude_from_local_holds_priority} = {name => 'Exclude from local holds priority', items => {}} unless defined $extra_headers->{exclude_from_local_holds_priority};
- $extra_headers->{exclude_from_local_holds_priority}->{items}->{$item->itemnumber} = $ynhash->{'av'.$item->exclude_from_local_holds_priority};
}
my $modified = 0;
if ( $values_to_modify || $values_to_blank ) {
my $item = ModItemFromMarc(
$localmarcitem,
$itemdata->{biblionumber},
- $itemnumber
+ $itemnumber,
+ { skip_record_index => 1 },
)
)
{
- LostItem( $itemnumber, 'batchmod' )
- if $item->{itemlost}
+ LostItem(
+ $itemnumber,
+ 'batchmod',
+ undef,
+ { skip_record_index => 1 }
+ ) if $item->{itemlost}
and not $itemdata->{itemlost};
}
};
+ push @$upd_biblionumbers, $itemdata->{'biblionumber'};
}
}
- if ($runinbackground) {
- $modified_items++ if $modified || $modified_holds_priority;
- $modified_fields += $modified + $modified_holds_priority;
- $job->set(
- {
- modified_items => $modified_items,
- modified_fields => $modified_fields,
- extra_headers => $extra_headers,
- }
- );
- }
+ $modified_items++ if $modified || $modified_holds_priority;
+ $modified_fields += $modified + $modified_holds_priority;
}
$i++;
}
}
die "Something terrible has happened!"
if ($_ =~ /Rollback failed/); # Rollback failed
- }
+ };
+ $upd_biblionumbers = [ uniq @$upd_biblionumbers ]; # Only update each bib once
+
+ # Don't send specialUpdate for records we are going to delete
+ my %del_bib_hash = map{ $_ => undef } @$del_biblionumbers;
+ @$upd_biblionumbers = grep( ! exists( $del_bib_hash{$_} ), @$upd_biblionumbers );
+
+ my $indexer = Koha::SearchEngine::Indexer->new({ index => $Koha::SearchEngine::BIBLIOS_INDEX });
+ $indexer->index_records( $upd_biblionumbers, 'specialUpdate', "biblioserver", undef ) if @$upd_biblionumbers;
+ $indexer->index_records( $del_biblionumbers, 'recordDelete', "biblioserver", undef ) if @$del_biblionumbers;
}
+
+ # Calling the template
+ $template->param(
+ modified_items => $modified_items,
+ modified_fields => $modified_fields,
+ );
+
}
#
#-------------------------------------------------------------------------------
my $max_display_items = $del
? C4::Context->preference("MaxItemsToDisplayForBatchDel")
: C4::Context->preference("MaxItemsToDisplayForBatchMod");
- $template->param("too_many_items_process" => scalar(@itemnumbers)) if !$del && scalar(@itemnumbers) >= C4::Context->preference("MaxItemsToProcessForBatchMod");
+ $template->param("too_many_items_process" => scalar(@itemnumbers)) if !$del && scalar(@itemnumbers) > C4::Context->preference("MaxItemsToProcessForBatchMod");
if (scalar(@itemnumbers) <= ( $max_display_items // 1000 ) ) {
$items_display_hashref=BuildItemsData(@itemnumbers);
} else {
next if IsMarcStructureInternal( $tagslib->{$tag}{$subfield} );
next if (not $allowAllSubfields and $restrictededition && !grep { $tag . '$' . $subfield eq $_ } @subfieldsToAllow );
next if ($tagslib->{$tag}->{$subfield}->{'tab'} ne "10");
- # barcode and stocknumber are not meant to be batch-modified
- next if $tagslib->{$tag}->{$subfield}->{'kohafield'} eq 'items.barcode';
- next if $tagslib->{$tag}->{$subfield}->{'kohafield'} eq 'items.stocknumber';
+ # barcode is not meant to be batch-modified
+ next if $tagslib->{$tag}->{$subfield}->{'kohafield'} eq 'items.barcode';
my %subfield_data;
my $index_subfield = int(rand(1000000));
else {
push @authorised_values, ""; # unless ( $tagslib->{$tag}->{$subfield}->{mandatory} );
- my @avs = Koha::AuthorisedValues->search({ category => $tagslib->{$tag}->{$subfield}->{authorised_value}, branchcode => $branch_limit },{order_by=>'lib'});
+ my @avs = Koha::AuthorisedValues->search_with_library_limits(
+ {
+ category => $tagslib->{$tag}->{$subfield}->{authorised_value}
+ },
+ { order_by => 'lib' },
+ $branch_limit
+ );
for my $av ( @avs ) {
push @authorised_values, $av->authorised_value;
$authorised_lib{$av->authorised_value} = $av->lib;
$row_data{holds} = $row->{holds};
$row_data{item_holds} = $row->{item_holds};
$row_data{item} = $row->{item};
+ $row_data{safe_to_delete} = $row->{item}->safe_to_delete;
my $is_on_loan = C4::Circulation::IsItemIssued( $row->{itemnumber} );
$row_data{onloan} = $is_on_loan ? 1 : 0;
push(@item_value_loop,\%row_data);
}
my @header_loop=map { { header_value=> $witness{$_}} } @witnesscodessorted;
- return { item_loop => \@item_value_loop, item_header_loop => \@header_loop };
+ my @cannot_be_deleted = map {
+ $_->{safe_to_delete} == 1 ? () : $_->{item}->barcode
+ } @item_value_loop;
+ return {
+ item_loop => \@item_value_loop,
+ cannot_be_deleted => \@cannot_be_deleted,
+ item_header_loop => \@header_loop
+ };
}
#BE WARN : it is not the general case
}
return($indicator,$result);
}
-
-# ----------------------------
-# Background functions
-
-
-sub add_results_to_template {
- my $template = shift;
- my $results = shift;
- $template->param(map { $_ => $results->{$_} } keys %{ $results });
-}
-
-sub add_saved_job_results_to_template {
- my $template = shift;
- my $completedJobID = shift;
- my $items_display_hashref= shift;
- my $job = C4::BackgroundJob->fetch($sessionID, $completedJobID);
- my $results = $job->results();
- add_results_to_template($template, $results);
-
- my $fields = $job->get("modified_fields");
- my $items = $job->get("modified_items");
- my $extra_headers = $job->get("extra_headers");
-
- foreach my $header (keys %{$extra_headers}) {
- push @{$items_display_hashref->{item_header_loop}}, {header_value => $extra_headers->{$header}->{name}};
- foreach my $row (@{$items_display_hashref->{item_loop}}) {
- push @{$row->{item_value}}, {field => $extra_headers->{$header}->{items}->{$row->{itemnumber}}};
- }
- }
-
- $template->param(
- modified_items => $items,
- modified_fields => $fields,
- );
-}
-
-sub put_in_background {
- my $job_size = shift;
-
- my $job = C4::BackgroundJob->new($sessionID, "test", '/cgi-bin/koha/tools/batchMod.pl', $job_size);
- my $jobID = $job->id();
-
- # fork off
- if (my $pid = fork) {
- # parent
- # return job ID as JSON
-
- # prevent parent exiting from
- # destroying the kid's database handle
- # FIXME: according to DBI doc, this may not work for Oracle
- $dbh->{InactiveDestroy} = 1;
-
- my $reply = CGI->new("");
- print $reply->header(-type => 'text/html');
- print '{"jobID":"' . $jobID . '"}';
- exit 0;
- } elsif (defined $pid) {
- # child
- # close STDOUT to signal to Apache that
- # we're now running in the background
- close STDOUT;
- close STDERR;
- } else {
- # fork failed, so exit immediately
- warn "fork failed while attempting to run tools/batchMod.pl as a background job";
- exit 0;
- }
- return $job;
-}
-
-
-