Bug 14826: account_offset_types.sql is not in the mandatory subdir
[koha.git] / tools / batch_delete_records.pl
1 #!/usr/bin/perl
2
3 # This file is part of Koha.
4 #
5 # Copyright 2013 BibLibre
6 #
7 # Koha is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as
9 # published by the Free Software Foundation; either version 3
10 # of the License, or (at your option) any later version.
11 #
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General
18 # Public License along with Koha; if not, see
19 # <http://www.gnu.org/licenses>
20
21 use Modern::Perl;
22
23 use CGI;
24 use List::MoreUtils qw( uniq );
25
26 use C4::Auth;
27 use C4::Output;
28 use C4::AuthoritiesMarc;
29 use C4::Biblio;
30
31 use Koha::Authorities;
32 use Koha::Biblios;
33
34 my $input = new CGI;
35 my $op = $input->param('op') // q|form|;
36 my $recordtype = $input->param('recordtype') // 'biblio';
37
38 my ($template, $loggedinuser, $cookie) = get_template_and_user({
39         template_name => 'tools/batch_delete_records.tt',
40         query => $input,
41         type => "intranet",
42         authnotrequired => 0,
43         flagsrequired => { tools => 'records_batchdel' },
44 });
45
46 my @records;
47 my @messages;
48 if ( $op eq 'form' ) {
49     # Display the form
50     $template->param( op => 'form' );
51 } elsif ( $op eq 'list' ) {
52     # List all records to process
53     my @record_ids;
54     if ( my $bib_list = $input->param('bib_list') ) {
55         # Come from the basket
56         @record_ids = split /\//, $bib_list;
57         $recordtype = 'biblio';
58     } elsif ( my $uploadfile = $input->param('uploadfile') ) {
59         # A file of id is given
60         while ( my $content = <$uploadfile> ) {
61             next unless $content;
62             $content =~ s/[\r\n]*$//;
63             push @record_ids, $content if $content;
64         }
65     } else {
66         # The user enters manually the list of id
67         push @record_ids, split( /\s\n/, $input->param('recordnumber_list') );
68     }
69
70     for my $record_id ( uniq @record_ids ) {
71         if ( $recordtype eq 'biblio' ) {
72             # Retrieve biblio information
73             my $biblio = Koha::Biblios->find( $record_id );
74             unless ( $biblio ) {
75                 push @messages, {
76                     type => 'warning',
77                     code => 'biblio_not_exists',
78                     biblionumber => $record_id,
79                 };
80                 next;
81             }
82             my $holds_count = $biblio->holds->count;
83             $biblio = $biblio->unblessed;
84             my $record = &GetMarcBiblio({ biblionumber => $record_id });
85             $biblio->{subtitle} = GetRecordValue( 'subtitle', $record, GetFrameworkCode( $record_id ) );
86             $biblio->{itemnumbers} = C4::Items::GetItemnumbersForBiblio( $record_id );
87             $biblio->{holds_count} = $holds_count;
88             $biblio->{issues_count} = C4::Biblio::CountItemsIssued( $record_id );
89             push @records, $biblio;
90         } else {
91             # Retrieve authority information
92             my $authority = C4::AuthoritiesMarc::GetAuthority( $record_id );
93             unless ( $authority ) {
94                 push @messages, {
95                     type => 'warning',
96                     code => 'authority_not_exists',
97                     authid => $record_id,
98                 };
99                 next;
100             }
101
102             $authority = {
103                 authid => $record_id,
104                 summary => C4::AuthoritiesMarc::BuildSummary( $authority, $record_id ),
105                 count_usage => Koha::Authorities->get_usage_count({ authid => $record_id }),
106             };
107             push @records, $authority;
108         }
109     }
110     $template->param(
111         records => \@records,
112         op => 'list',
113     );
114 } elsif ( $op eq 'delete' ) {
115     # We want to delete selected records!
116     my @record_ids = $input->multi_param('record_id');
117     my $schema = Koha::Database->new->schema;
118
119     my $error;
120     my $report = {
121         total_records => 0,
122         total_success => 0,
123     };
124     RECORD_IDS: for my $record_id ( sort { $a <=> $b } @record_ids ) {
125         $report->{total_records}++;
126         next unless $record_id;
127         $schema->storage->txn_begin;
128
129         if ( $recordtype eq 'biblio' ) {
130             # Biblios
131             my $biblionumber = $record_id;
132             # First, checking if issues exist.
133             # If yes, nothing to do
134             my $biblio = Koha::Biblios->find( $biblionumber );
135
136             # TODO Replace with $biblio->get_issues->count
137             if ( C4::Biblio::CountItemsIssued( $biblionumber ) ) {
138                 push @messages, {
139                     type => 'warning',
140                     code => 'item_issued',
141                     biblionumber => $biblionumber,
142                 };
143                 $schema->storage->txn_rollback;
144                 next;
145             }
146
147             # Cancel reserves
148             my $holds = $biblio->holds;
149             while ( my $hold = $holds->next ) {
150                 eval{
151                     $hold->cancel;
152                 };
153                 if ( $@ ) {
154                     push @messages, {
155                         type => 'error',
156                         code => 'reserve_not_cancelled',
157                         biblionumber => $biblionumber,
158                         reserve_id => $hold->reserve_id,
159                         error => $@,
160                     };
161                     $schema->storage->txn_rollback;
162                     next RECORD_IDS;
163                 }
164             }
165
166             # Delete items
167             my @itemnumbers = @{ C4::Items::GetItemnumbersForBiblio( $biblionumber ) };
168             ITEMNUMBER: for my $itemnumber ( @itemnumbers ) {
169                 my $error = eval { C4::Items::DelItemCheck( $biblionumber, $itemnumber ) };
170                 if ( $error != 1 or $@ ) {
171                     push @messages, {
172                         type => 'error',
173                         code => 'item_not_deleted',
174                         biblionumber => $biblionumber,
175                         itemnumber => $itemnumber,
176                         error => ($@ ? $@ : $error),
177                     };
178                     $schema->storage->txn_rollback;
179                     next RECORD_IDS;
180                 }
181             }
182
183             # Finally, delete the biblio
184             my $error = eval {
185                 C4::Biblio::DelBiblio( $biblionumber );
186             };
187             if ( $error or $@ ) {
188                 push @messages, {
189                     type => 'error',
190                     code => 'biblio_not_deleted',
191                     biblionumber => $biblionumber,
192                     error => ($@ ? $@ : $error),
193                 };
194                 $schema->storage->txn_rollback;
195                 next;
196             }
197
198             push @messages, {
199                 type => 'success',
200                 code => 'biblio_deleted',
201                 biblionumber => $biblionumber,
202             };
203             $report->{total_success}++;
204             $schema->storage->txn_commit;
205         } else {
206             # Authorities
207             my $authid = $record_id;
208             eval { C4::AuthoritiesMarc::DelAuthority({ authid => $authid }) };
209             if ( $@ ) {
210                 push @messages, {
211                     type => 'error',
212                     code => 'authority_not_deleted',
213                     authid => $authid,
214                     error => ($@ ? $@ : 0),
215                 };
216                 $schema->storage->txn_rollback;
217                 next;
218             } else {
219                 push @messages, {
220                     type => 'success',
221                     code => 'authority_deleted',
222                     authid => $authid,
223                 };
224                 $report->{total_success}++;
225                 $schema->storage->txn_commit;
226             }
227         }
228     }
229     $template->param(
230         op => 'report',
231         report => $report,
232     );
233 }
234
235 $template->param(
236     messages => \@messages,
237     recordtype => $recordtype,
238 );
239
240 output_html_with_http_headers $input, $cookie, $template->output;