Bug 34478: op =~ ^cud- in pl/pm - Manual cud-email => email
[koha.git] / tools / batchMod.pl
1 #!/usr/bin/perl
2
3
4 # Copyright 2000-2002 Katipo Communications
5 #
6 # This file is part of Koha.
7 #
8 # Koha is free software; you can redistribute it and/or modify it
9 # under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # Koha is distributed in the hope that it will be useful, but
14 # WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with Koha; if not, see <http://www.gnu.org/licenses>.
20
21 use CGI qw ( -utf8 );
22 use Modern::Perl;
23 use Try::Tiny qw( catch try );
24
25 use C4::Auth qw( get_template_and_user haspermission );
26 use C4::Output qw( output_html_with_http_headers );
27 use C4::Circulation qw( barcodedecode );
28 use C4::Context;
29 use MARC::File::XML;
30 use List::MoreUtils qw( uniq );
31 use Encode qw( encode_utf8 );
32
33 use Koha::Database;
34 use Koha::Exception;
35 use Koha::Biblios;
36 use Koha::Items;
37 use Koha::Patrons;
38 use Koha::Item::Attributes;
39 use Koha::BackgroundJob::BatchDeleteItem;
40 use Koha::BackgroundJob::BatchUpdateItem;
41 use Koha::UI::Form::Builder::Item;
42 use Koha::UI::Table::Builder::Items;
43
44 my $input = CGI->new;
45 my $dbh = C4::Context->dbh;
46 my $error        = $input->param('error');
47 my @itemnumbers  = $input->multi_param('itemnumber');
48 my $biblionumber = $input->param('biblionumber');
49 my $op           = $input->param('op');
50 my $del          = $input->param('cud-del');
51 my $del_records  = $input->param('del_records');
52 my $src          = $input->param('src');
53 my $use_default_values = $input->param('use_default_values');
54 my $exclude_from_local_holds_priority = $input->param('exclude_from_local_holds_priority');
55 my $mark_items_returned = $input->param('mark_items_returned');
56
57 my $template_name;
58 my $template_flag;
59 if (!defined $op) {
60     $template_name = "tools/batchMod.tt";
61     $template_flag = { tools => '*' };
62     $op = q{};
63 } else {
64     $template_name = ($del) ? "tools/batchMod-del.tt" : "tools/batchMod-edit.tt";
65     $template_flag = ($del) ? { tools => 'items_batchdel' }   : { tools => 'items_batchmod' };
66 }
67
68 my ($template, $loggedinuser, $cookie)
69     = get_template_and_user({template_name => $template_name,
70                  query => $input,
71                  type => "intranet",
72                  flagsrequired => $template_flag,
73                  });
74
75 $template->param( searchid => scalar $input->param('searchid'), );
76
77 # Does the user have a restricted item edition permission?
78 my $patron = Koha::Patrons->find( $loggedinuser );
79 my $uid = $loggedinuser ? $patron->userid : undef;
80 my $restrictededition = $uid ? haspermission($uid,  {'tools' => 'items_batchmod_restricted'}) : undef;
81 # In case user is a superlibrarian, edition is not restricted
82 $restrictededition = 0 if ($restrictededition != 0 && C4::Context->IsSuperLibrarian());
83
84 my $nextop="";
85 my $display_items;
86
87 my @messages;
88
89 if ( $op eq "cud-action" ) {
90
91     if ($del) {
92         try {
93             my $params = {
94                 record_ids     => \@itemnumbers,
95                 delete_biblios => $del_records,
96             };
97             my $job_id =
98               Koha::BackgroundJob::BatchDeleteItem->new->enqueue($params);
99             $nextop = 'enqueued';
100             $template->param( job_id => $job_id, );
101         }
102         catch {
103             warn $_;
104             push @messages,
105               {
106                 type  => 'error',
107                 code  => 'cannot_enqueue_job',
108                 error => $_,
109               };
110             $template->param( view => 'errors' );
111         };
112     }
113
114     else {    # modification
115
116         my @item_columns = Koha::Items->columns;
117
118         my $new_item_data;
119         my ( $columns_with_regex );
120         my @subfields_to_blank = $input->multi_param('disable_input');
121         my @more_subfields = $input->multi_param("items.more_subfields_xml");
122         for my $item_column (@item_columns) {
123             my @attributes       = ($item_column);
124             my $cgi_param_prefix = 'items.';
125             if ( $item_column eq 'more_subfields_xml' ) {
126                 @attributes       = ();
127                 $cgi_param_prefix = 'items.more_subfields_xml_';
128                 for my $subfield (@more_subfields) {
129                     push @attributes, $subfield;
130                 }
131             }
132
133             for my $attr (@attributes) {
134
135                 my $cgi_var_name = $cgi_param_prefix
136                   . encode_utf8($attr)
137                   ;  # We need to deal correctly with encoding on subfield codes
138
139                 if ( grep { $cgi_var_name eq $_ } @subfields_to_blank ) {
140                     # Empty this column
141                     $new_item_data->{$attr} = undef;
142                 }
143                 elsif ( my $regex_search =
144                     $input->param( $cgi_var_name . '_regex_search' ) )
145                 {
146                     $columns_with_regex->{$attr} = {
147                         search => $regex_search,
148                         replace =>
149                           $input->param( $cgi_var_name . '_regex_replace' ),
150                         modifiers =>
151                           $input->param( $cgi_var_name . '_regex_modifiers' )
152                     };
153                 }
154                 else {
155                     my @v =
156                       grep { $_ ne "" } uniq $input->multi_param($cgi_var_name);
157
158                     next unless @v;
159
160                     $new_item_data->{$attr} = join '|', @v;
161                 }
162             }
163         }
164
165         my $params = {
166             record_ids                        => \@itemnumbers,
167             regex_mod                         => $columns_with_regex,
168             new_values                        => $new_item_data,
169             exclude_from_local_holds_priority => (
170                 defined $exclude_from_local_holds_priority
171                   && $exclude_from_local_holds_priority ne ""
172               )
173             ? $exclude_from_local_holds_priority
174             : undef,
175             mark_items_returned => (
176                 defined $mark_items_returned
177                   && $mark_items_returned ne ""
178                 )
179             ? $mark_items_returned : undef,
180
181         };
182         try {
183             my $job_id =
184               Koha::BackgroundJob::BatchUpdateItem->new->enqueue($params);
185             $nextop = 'enqueued';
186             $template->param( job_id => $job_id, );
187         }
188         catch {
189             push @messages,
190               {
191                 type  => 'error',
192                 code  => 'cannot_enqueue_job',
193                 error => $_,
194               };
195             $template->param( view => 'errors' );
196         };
197     }
198
199 }
200
201 $template->param(
202     messages => \@messages,
203 );
204 #
205 #-------------------------------------------------------------------------------
206 # build screen with existing items. and "new" one
207 #-------------------------------------------------------------------------------
208
209 if ($op eq "cud-show"){
210     my $filefh = $input->upload('uploadfile');
211     my $filecontent = $input->param('filecontent');
212     my ( @notfoundbarcodes, @notfounditemnumbers);
213
214     my $split_chars = C4::Context->preference('BarcodeSeparators');
215     if ($filefh){
216         binmode $filefh, ':encoding(UTF-8)';
217         my @contentlist;
218         while (my $content=<$filefh>){
219             $content =~ s/[\r\n]*$//;
220             push @contentlist, $content if $content;
221         }
222
223         if ($filecontent eq 'barcode_file') {
224             @contentlist = grep /\S/, ( map { split /[$split_chars]/ } @contentlist );
225             @contentlist = uniq @contentlist;
226             # Note: adding lc for case insensitivity
227             my %itemdata = map { lc($_->{barcode}) => $_->{itemnumber} } @{ Koha::Items->search({ barcode => { -in => \@contentlist } }, { columns => [ 'itemnumber', 'barcode' ] } )->unblessed };
228             @itemnumbers = map { exists $itemdata{lc $_} ? $itemdata{lc $_} : () } @contentlist;
229             @notfoundbarcodes = grep { !exists $itemdata{lc $_} } @contentlist;
230         }
231         elsif ( $filecontent eq 'itemid_file') {
232             @contentlist = uniq @contentlist;
233             my %itemdata = map { $_->{itemnumber} => 1 } @{ Koha::Items->search({ itemnumber => { -in => \@contentlist } }, { columns => [ 'itemnumber' ] } )->unblessed };
234             @itemnumbers = grep { exists $itemdata{$_} } @contentlist;
235             @notfounditemnumbers = grep { !exists $itemdata{$_} } @contentlist;
236         }
237     } else {
238         if (defined $biblionumber && !@itemnumbers){
239             my $biblio = Koha::Biblios->find($biblionumber);
240             @itemnumbers = $biblio ? $biblio->items->get_column('itemnumber') : ();
241         }
242         if ( my $list = $input->param('barcodelist') ) {
243             my @barcodelist = grep /\S/, ( split /[$split_chars]/, $list );
244             @barcodelist = uniq @barcodelist;
245
246             @barcodelist = map { barcodedecode( $_ ) } @barcodelist;
247
248             # Note: adding lc for case insensitivity
249             my %itemdata = map { lc($_->{barcode}) => $_->{itemnumber} } @{ Koha::Items->search({ barcode => { -in => \@barcodelist } }, { columns => [ 'itemnumber', 'barcode' ] } )->unblessed };
250             @itemnumbers = map { exists $itemdata{lc $_} ? $itemdata{lc $_} : () } @barcodelist;
251             @notfoundbarcodes = grep { !exists $itemdata{lc $_} } @barcodelist;
252         }
253     }
254
255     # Flag to tell the template there are valid results, hidden or not
256     if(scalar(@itemnumbers) > 0){ $template->param("itemresults" => 1); }
257     # Only display the items if there are no more than pref MaxItemsToProcessForBatchMod or MaxItemsToDisplayForBatchDel
258     my $max_display_items = $del
259         ? C4::Context->preference("MaxItemsToDisplayForBatchDel")
260         : C4::Context->preference("MaxItemsToDisplayForBatchMod");
261     $template->param("too_many_items_process" => scalar(@itemnumbers)) if !$del && scalar(@itemnumbers) > C4::Context->preference("MaxItemsToProcessForBatchMod");
262     if (scalar(@itemnumbers) <= ( $max_display_items // 1000 ) ) {
263         $display_items = 1;
264     } else {
265         $template->param("too_many_items_display" => scalar(@itemnumbers));
266         # Even if we do not display the items, we need the itemnumbers
267         $template->param(itemnumbers_array => \@itemnumbers);
268     }
269
270     # now, build the item form for entering a new item
271
272     # Getting list of subfields to keep when restricted batchmod edit is enabled
273     my @subfields_to_allow = $restrictededition ? split ' ', C4::Context->preference('SubfieldsToAllowForRestrictedBatchmod') : ();
274
275     my $subfields = Koha::UI::Form::Builder::Item->new->edit_form( # NOTE: We are not passing a biblionumber intentionally !
276         {
277             restricted_editition => $restrictededition,
278             (
279                 @subfields_to_allow
280                 ? ( subfields_to_allow => \@subfields_to_allow )
281                 : ()
282             ),
283             ignore_not_allowed_subfields => 1,
284             kohafields_to_ignore         => ['items.barcode'],
285             prefill_with_default_values  => $use_default_values,
286             branch_limit                 => C4::Context->userenv->{"branch"},
287             default_branches_empty       => 1,
288         }
289     );
290
291     # what's the next op ? it's what we are not in : an add if we're editing, otherwise, and edit.
292     $template->param(
293         subfields           => $subfields,
294         notfoundbarcodes    => \@notfoundbarcodes,
295         notfounditemnumbers => \@notfounditemnumbers
296     );
297     $nextop="cud-action";
298     $template->param( show => 1 );
299 } # -- End action="cud-show"
300
301 if ( $display_items ) {
302     my $items_table =
303       Koha::UI::Table::Builder::Items->new( { itemnumbers => \@itemnumbers } )
304       ->build_table( { patron => $patron } );;
305     $template->param(
306         items        => $items_table->{items},
307         item_header_loop => $items_table->{headers},
308     );
309 }
310
311 $template->param(
312     op  => $nextop,
313     del => $del,
314     ( $op ? ( $op => 1 ) : () ),
315     src          => $src,
316     biblionumber => $biblionumber,
317 );
318
319 output_html_with_http_headers $input, $cookie, $template->output;