View | Details | Raw Unified | Return to bug 19316
Collapse All | Expand All

(-)a/Koha/BackgroundJob/BatchUpdateItem.pm (-17 / +17 lines)
Lines 92-132 sub process { Link Here
92
92
93
    $self->start;
93
    $self->start;
94
94
95
    my @record_ids = @{ $args->{record_ids} };
95
    my @record_ids                        = @{ $args->{record_ids} };
96
    my $regex_mod  = $args->{regex_mod};
96
    my $regex_mod                         = $args->{regex_mod};
97
    my $new_values = $args->{new_values};
97
    my $new_values                        = $args->{new_values};
98
    my $exclude_from_local_holds_priority =
98
    my $exclude_from_local_holds_priority = $args->{exclude_from_local_holds_priority};
99
      $args->{exclude_from_local_holds_priority};
99
    my $mark_items_returned               = $args->{mark_items_returned};
100
    my $mark_items_returned =
100
    my $sort1                             = $args->{sort1};
101
      $args->{mark_items_returned};
101
    my $sort2                             = $args->{sort2};
102
102
103
    my $report = {
103
    my $report = {
104
        total_records            => scalar @record_ids,
104
        total_records   => scalar @record_ids,
105
        modified_fields          => 0,
105
        modified_fields => 0,
106
    };
106
    };
107
107
108
    try {
108
    try {
109
        my ($results) = Koha::Items->search( { itemnumber => \@record_ids } )->batch_update(
109
        my ($results) = Koha::Items->search( { itemnumber => \@record_ids } )->batch_update(
110
            {   regex_mod                         => $regex_mod,
110
            {
111
                regex_mod                         => $regex_mod,
111
                new_values                        => $new_values,
112
                new_values                        => $new_values,
112
                exclude_from_local_holds_priority => $exclude_from_local_holds_priority,
113
                exclude_from_local_holds_priority => $exclude_from_local_holds_priority,
113
                mark_items_returned               => $mark_items_returned,
114
                mark_items_returned               => $mark_items_returned,
115
                sort1                             => $sort1,
116
                sort2                             => $sort2,
114
                callback                          => sub { $self->step; },
117
                callback                          => sub { $self->step; },
115
            }
118
            }
116
        );
119
        );
117
        $report->{modified_itemnumbers} = $results->{modified_itemnumbers};
120
        $report->{modified_itemnumbers} = $results->{modified_itemnumbers};
118
        $report->{modified_fields}      = $results->{modified_fields};
121
        $report->{modified_fields}      = $results->{modified_fields};
119
    }
122
    } catch {
120
    catch {
121
        warn $_;
123
        warn $_;
122
        die "Something terrible has happened!"
124
        die "Something terrible has happened!"
123
          if ( $_ =~ /Rollback failed/ );    # Rollback failed
125
            if ( $_ =~ /Rollback failed/ );    # Rollback failed
124
    };
126
    };
125
127
126
    my $data = $self->decoded_data;
128
    my $data = $self->decoded_data;
127
    $data->{report} = $report;
129
    $data->{report} = $report;
128
130
129
    $self->finish( $data );
131
    $self->finish($data);
130
}
132
}
131
133
132
=head3 enqueue
134
=head3 enqueue
Lines 167-175 sub additional_report { Link Here
167
    if ( scalar(@$itemnumbers) > C4::Context->preference('MaxItemsToDisplayForBatchMod') ) {
169
    if ( scalar(@$itemnumbers) > C4::Context->preference('MaxItemsToDisplayForBatchMod') ) {
168
        return { too_many_items_display => 1 };
170
        return { too_many_items_display => 1 };
169
    } else {
171
    } else {
170
        my $items_table =
172
        my $items_table = Koha::UI::Table::Builder::Items->new( { itemnumbers => $itemnumbers } )->build_table;
171
          Koha::UI::Table::Builder::Items->new( { itemnumbers => $itemnumbers } )
172
          ->build_table;
173
173
174
        return {
174
        return {
175
            items            => $items_table->{items},
175
            items            => $items_table->{items},
(-)a/Koha/Items.pm (-97 / +113 lines)
Lines 220-226 sub move_to_biblio { Link Here
220
220
221
=head3 batch_update
221
=head3 batch_update
222
222
223
    Koha::Items->search->batch_update
223
    Koha::Items->search->batch_update(
224
        {
224
        {
225
            new_values => {
225
            new_values => {
226
                itemnotes => $new_item_notes,
226
                itemnotes => $new_item_notes,
Lines 280-405 Callback function to call after an item has been modified Link Here
280
sub batch_update {
280
sub batch_update {
281
    my ( $self, $params ) = @_;
281
    my ( $self, $params ) = @_;
282
282
283
    my $regex_mod = $params->{regex_mod} || {};
283
    my $regex_mod                         = $params->{regex_mod}  || {};
284
    my $new_values = $params->{new_values} || {};
284
    my $new_values                        = $params->{new_values} || {};
285
    my $exclude_from_local_holds_priority = $params->{exclude_from_local_holds_priority};
285
    my $exclude_from_local_holds_priority = $params->{exclude_from_local_holds_priority};
286
    my $mark_items_returned = $params->{mark_items_returned};
286
    my $mark_items_returned               = $params->{mark_items_returned};
287
    my $callback = $params->{callback};
287
    my $sort1                             = $params->{sort1};
288
    my $sort2                             = $params->{sort2};
289
    my $callback                          = $params->{callback};
288
290
289
    my (@modified_itemnumbers, $modified_fields);
291
    my (@modified_itemnumbers, $modified_fields);
290
    my $i;
292
    my $i;
291
    my $schema = Koha::Database->new->schema;
293
    my $schema = Koha::Database->new->schema;
292
    while ( my $item = $self->next ) {
294
    while ( my $item = $self->next ) {
293
295
294
        try {$schema->txn_do(sub {
296
        try {
295
            my $modified_holds_priority = 0;
297
            $schema->txn_do(
296
            my $item_returned = 0;
298
                sub {
297
            if ( defined $exclude_from_local_holds_priority ) {
299
                    my $modified_holds_priority = 0;
298
                if(!defined $item->exclude_from_local_holds_priority || $item->exclude_from_local_holds_priority != $exclude_from_local_holds_priority) {
300
                    my $item_returned           = 0;
299
                    $item->exclude_from_local_holds_priority($exclude_from_local_holds_priority)->store;
301
                    my $sort_fields_modified    = 0;
300
                    $modified_holds_priority = 1;
302
                    if ( defined $exclude_from_local_holds_priority ) {
301
                }
303
                        if ( !defined $item->exclude_from_local_holds_priority
302
            }
304
                            || $item->exclude_from_local_holds_priority != $exclude_from_local_holds_priority )
305
                        {
306
                            $item->exclude_from_local_holds_priority($exclude_from_local_holds_priority)->store;
307
                            $modified_holds_priority = 1;
308
                        }
309
                    }
310
                    if ( defined $sort1 || defined $sort2 ) {
311
                        $item->sort1($sort1)->store if $sort1 ne "";
312
                        $sort_fields_modified++     if $sort1 ne "";
313
                        $item->sort2($sort2)->store if $sort2 ne "";
314
                        $sort_fields_modified++     if $sort2 ne "";
315
                    }
303
316
304
            my $modified = 0;
317
                    my $modified   = 0;
305
            my $new_values = {%$new_values};    # Don't modify the original
318
                    my $new_values = {%$new_values};    # Don't modify the original
306
319
307
            my $old_values = $item->unblessed;
320
                    my $old_values = $item->unblessed;
308
            if ( $item->more_subfields_xml ) {
321
                    if ( $item->more_subfields_xml ) {
309
                $old_values = {
322
                        $old_values = {
310
                    %$old_values,
323
                            %$old_values,
311
                    %{$item->additional_attributes->to_hashref},
324
                            %{ $item->additional_attributes->to_hashref },
312
                };
325
                        };
313
            }
326
                    }
327
328
                    for my $attr ( keys %$regex_mod ) {
329
                        my $old_value = $old_values->{$attr};
314
330
315
            for my $attr ( keys %$regex_mod ) {
331
                        next unless $old_value;
316
                my $old_value = $old_values->{$attr};
317
332
318
                next unless $old_value;
333
                        my $value = apply_regex(
334
                            {
335
                                %{ $regex_mod->{$attr} },
336
                                value => $old_value,
337
                            }
338
                        );
319
339
320
                my $value = apply_regex(
340
                        $new_values->{$attr} = $value;
321
                    {
322
                        %{ $regex_mod->{$attr} },
323
                        value => $old_value,
324
                    }
341
                    }
325
                );
326
342
327
                $new_values->{$attr} = $value;
343
                    for my $attribute ( keys %$new_values ) {
328
            }
344
                        next if $attribute eq 'more_subfields_xml';    # Already counted before
329
345
330
            for my $attribute ( keys %$new_values ) {
346
                        my $old = $old_values->{$attribute};
331
                next if $attribute eq 'more_subfields_xml'; # Already counted before
347
                        my $new = $new_values->{$attribute};
348
                        $modified++
349
                            if ( defined $old xor defined $new )
350
                            || ( defined $old && defined $new && $new ne $old );
351
                    }
332
352
333
                my $old = $old_values->{$attribute};
353
                    {    # Dealing with more_subfields_xml
334
                my $new = $new_values->{$attribute};
335
                $modified++
336
                  if ( defined $old xor defined $new )
337
                  || ( defined $old && defined $new && $new ne $old );
338
            }
339
354
340
            { # Dealing with more_subfields_xml
355
                        my $frameworkcode = $item->biblio->frameworkcode;
341
356
                        my $tagslib       = C4::Biblio::GetMarcStructure( 1, $frameworkcode, { unsafe => 1 } );
342
                my $frameworkcode = $item->biblio->frameworkcode;
357
                        my ( $itemtag, $itemsubfield ) = C4::Biblio::GetMarcFromKohaField("items.itemnumber");
343
                my $tagslib = C4::Biblio::GetMarcStructure( 1, $frameworkcode, { unsafe => 1 });
344
                my ( $itemtag, $itemsubfield ) = C4::Biblio::GetMarcFromKohaField( "items.itemnumber" );
345
346
                my @more_subfield_tags = map {
347
                    (
348
                             ref($_)
349
                          && %$_
350
                          && !$_->{kohafield}    # Get subfields that are not mapped
351
                      )
352
                      ? $_->{tagsubfield}
353
                      : ()
354
                } values %{ $tagslib->{$itemtag} };
355
356
                my $more_subfields_xml = Koha::Item::Attributes->new(
357
                    {
358
                        map {
359
                            exists $new_values->{$_} ? ( $_ => $new_values->{$_} )
360
                              : exists $old_values->{$_}
361
                              ? ( $_ => $old_values->{$_} )
362
                              : ()
363
                        } @more_subfield_tags
364
                    }
365
                )->to_marcxml($frameworkcode);
366
358
367
                $new_values->{more_subfields_xml} = $more_subfields_xml;
359
                        my @more_subfield_tags = map {
360
                            (
361
                                       ref($_)
362
                                    && %$_
363
                                    && !$_->{kohafield}    # Get subfields that are not mapped
364
                                )
365
                                ? $_->{tagsubfield}
366
                                : ()
367
                        } values %{ $tagslib->{$itemtag} };
368
368
369
                delete $new_values->{$_} for @more_subfield_tags; # Clean the hash
369
                        my $more_subfields_xml = Koha::Item::Attributes->new(
370
                            {
371
                                map {
372
                                          exists $new_values->{$_} ? ( $_ => $new_values->{$_} )
373
                                        : exists $old_values->{$_} ? ( $_ => $old_values->{$_} )
374
                                        : ()
375
                                } @more_subfield_tags
376
                            }
377
                        )->to_marcxml($frameworkcode);
370
378
371
            }
379
                        $new_values->{more_subfields_xml} = $more_subfields_xml;
372
380
373
            if ( $modified ) {
381
                        delete $new_values->{$_} for @more_subfield_tags;    # Clean the hash
374
                my $itemlost_pre = $item->itemlost;
375
                $item->set($new_values)->store({skip_record_index => 1});
376
382
377
                C4::Circulation::LostItem(
383
                    }
378
                    $item->itemnumber, 'batchmod', undef,
384
379
                    { skip_record_index => 1 }
385
                    if ($modified) {
380
                ) if $item->itemlost
386
                        my $itemlost_pre = $item->itemlost;
381
                      and not $itemlost_pre;
387
                        $item->set($new_values)->store( { skip_record_index => 1 } );
382
            }
388
383
            if ( $mark_items_returned ){
389
                        C4::Circulation::LostItem(
384
                my $issue = $item->checkout;
390
                            $item->itemnumber, 'batchmod', undef,
385
                if( $issue ){
391
                            { skip_record_index => 1 }
386
                        $item_returned = 1;
392
                            )
387
                        C4::Circulation::MarkIssueReturned(
393
                            if $item->itemlost
388
                        $issue->borrowernumber,
394
                            and not $itemlost_pre;
389
                        $item->itemnumber,
395
                    }
390
                        undef,
396
                    if ($mark_items_returned) {
391
                        $issue->patron->privacy,
397
                        my $issue = $item->checkout;
392
                        {
398
                        if ($issue) {
393
                            skip_record_index => 1,
399
                            $item_returned = 1;
394
                            skip_holds_queue  => 1,
400
                            C4::Circulation::MarkIssueReturned(
401
                                $issue->borrowernumber,
402
                                $item->itemnumber,
403
                                undef,
404
                                $issue->patron->privacy,
405
                                {
406
                                    skip_record_index => 1,
407
                                    skip_holds_queue  => 1,
408
                                }
409
                            );
395
                        }
410
                        }
396
                    );
411
                    }
397
                }
398
            }
399
412
400
            push @modified_itemnumbers, $item->itemnumber if $modified || $modified_holds_priority || $item_returned;
413
                    push @modified_itemnumbers, $item->itemnumber
401
            $modified_fields += $modified + $modified_holds_priority + $item_returned;
414
                        if $modified || $modified_holds_priority || $item_returned || $sort_fields_modified;
402
        })}
415
                    $modified_fields += $modified + $modified_holds_priority + $item_returned + $sort_fields_modified;
416
                }
417
            )
418
        }
403
        catch {
419
        catch {
404
            warn $_
420
            warn $_
405
        };
421
        };
(-)a/catalogue/updateitem.pl (-10 / +16 lines)
Lines 29-45 my $cgi= CGI->new; Link Here
29
29
30
checkauth($cgi, 0, {circulate => 'circulate_remaining_permissions'}, 'intranet');
30
checkauth($cgi, 0, {circulate => 'circulate_remaining_permissions'}, 'intranet');
31
31
32
my $op = $cgi->param('op') || "";
32
my $op                                = $cgi->param('op') || "";
33
my $biblionumber=$cgi->param('biblionumber');
33
my $biblionumber                      = $cgi->param('biblionumber');
34
my $itemnumber=$cgi->param('itemnumber');
34
my $itemnumber                        = $cgi->param('itemnumber');
35
my $biblioitemnumber=$cgi->param('biblioitemnumber');
35
my $biblioitemnumber                  = $cgi->param('biblioitemnumber');
36
my $itemlost=$cgi->param('itemlost');
36
my $itemlost                          = $cgi->param('itemlost');
37
my $itemnotes=$cgi->param('itemnotes');
37
my $itemnotes                         = $cgi->param('itemnotes');
38
my $itemnotes_nonpublic=$cgi->param('itemnotes_nonpublic');
38
my $itemnotes_nonpublic               = $cgi->param('itemnotes_nonpublic');
39
my $withdrawn=$cgi->param('withdrawn');
39
my $withdrawn                         = $cgi->param('withdrawn');
40
my $damaged=$cgi->param('damaged');
40
my $damaged                           = $cgi->param('damaged');
41
my $exclude_from_local_holds_priority = $cgi->param('exclude_from_local_holds_priority');
41
my $exclude_from_local_holds_priority = $cgi->param('exclude_from_local_holds_priority');
42
my $bookable = $cgi->param('bookable');
42
my $bookable                          = $cgi->param('bookable');
43
my $sort1                             = $cgi->param('sort1');
44
my $sort2                             = $cgi->param('sort2');
43
45
44
my $confirm=$cgi->param('confirm');
46
my $confirm=$cgi->param('confirm');
45
my $dbh = C4::Context->dbh;
47
my $dbh = C4::Context->dbh;
Lines 80-85 elsif ( $op eq "cud-set_public_note" ) { # i.e., itemnotes parameter passed from Link Here
80
    $item->bookable($bookable);
82
    $item->bookable($bookable);
81
} elsif ( $op eq "cud-set_damaged" && $damaged ne $item_data_hashref->{'damaged'}) {
83
} elsif ( $op eq "cud-set_damaged" && $damaged ne $item_data_hashref->{'damaged'}) {
82
    $item->damaged($damaged);
84
    $item->damaged($damaged);
85
} elsif ( $op eq "set_sort1" && $sort1 ne $item_data_hashref->{'sort1'} ) {
86
    $item->sort1($sort1);
87
} elsif ( $op eq "set_sort2" && $sort2 ne $item_data_hashref->{'sort2'} ) {
88
    $item->sort2($sort2);
83
} else {
89
} else {
84
    #nothings changed, so do nothing.
90
    #nothings changed, so do nothing.
85
    print $cgi->redirect("moredetail.pl?biblionumber=$biblionumber&itemnumber=$itemnumber#item$itemnumber");
91
    print $cgi->redirect("moredetail.pl?biblionumber=$biblionumber&itemnumber=$itemnumber#item$itemnumber");
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt (+32 lines)
Lines 378-383 Link Here
378
                                    </div> <!-- /.rows -->
378
                                    </div> <!-- /.rows -->
379
                            </div> <!-- /.listgroup -->
379
                            </div> <!-- /.listgroup -->
380
380
381
                            <div class="listgroup">
382
                                <h4>Sort fields</h4>
383
                                <div class="rows">
384
                                    <ol class="bibliodetails">
385
                                        <li>
386
                                            <span class="label">Sort 1:</span>
387
                                            [% IF ( CAN_user_editcatalogue_edit_items ) %]
388
                                                <form class="inline" action="updateitem.pl" method="post"><input type="hidden" name="biblionumber" value="[% ITEM_DAT.biblionumber | html %]" />
389
                                                    <input type="hidden" name="biblioitemnumber" value="[% ITEM_DAT.biblioitemnumber | html %]" /><input type="hidden" name="itemnumber" value="[% ITEM_DAT.itemnumber | html %]" />
390
                                                    <input type="hidden" name="op" value="set_sort1" />
391
                                                    <textarea name="sort1" rows="2" cols="30">[% ITEM_DAT.sort1 | html %]</textarea><input type="submit" name="submit" class="btn btn-primary btn-xs" value="Update" />
392
                                                </form>
393
                                            [% ELSE %]
394
                                                [% ITEM_DAT.sort1 | html %]
395
                                            [% END %]
396
                                        </li>
397
                                        <li>
398
                                            <span class="label">Sort 2:</span>
399
                                            [% IF ( CAN_user_editcatalogue_edit_items ) %]
400
                                                <form class="inline" action="updateitem.pl" method="post"><input type="hidden" name="biblionumber" value="[% ITEM_DAT.biblionumber | html %]" />
401
                                                    <input type="hidden" name="biblioitemnumber" value="[% ITEM_DAT.biblioitemnumber | html %]" /><input type="hidden" name="itemnumber" value="[% ITEM_DAT.itemnumber | html %]" />
402
                                                    <input type="hidden" name="op" value="set_sort2" />
403
                                                    <textarea name="sort2" rows="2" cols="30">[% ITEM_DAT.sort2 | html %]</textarea><input type="submit" name="submit" class="btn btn-primary btn-xs" value="Update" />
404
                                                </form>
405
                                            [% ELSE %]
406
                                                [% ITEM_DAT.sort2 | html %]
407
                                            [% END %]
408
                                        </li>
409
                                    </ol> <!-- /.bibliodetails -->
410
                                </div> <!-- /.rows -->
411
                            </div> <!-- /.listgroup -->
412
381
                            <div class="listgroup">
413
                            <div class="listgroup">
382
                                <h4>History</h4>
414
                                <h4>History</h4>
383
                                <div class="rows">
415
                                <div class="rows">
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batchMod-edit.tt (+12 lines)
Lines 218-223 Link Here
218
                                        </select>
218
                                        </select>
219
                                    </div>
219
                                    </div>
220
                                </li>
220
                                </li>
221
                                <li>
222
                                    <div class="subfield_line">
223
                                        <label for="sort1">Sort 1:</label>
224
                                        <input type="text" id="sort1" name="sort1" class="input_marceditor" maxlength="50" value="" />
225
                                    </div>
226
                                </li>
227
                                <li>
228
                                    <div class="subfield_line">
229
                                        <label for="sort1">Sort 2:</label>
230
                                        <input type="text" id="sort2" name="sort2" class="input_marceditor" maxlength="50" value="" />
231
                                    </div>
232
                                </li>
221
                            </ol>
233
                            </ol>
222
                        </fieldset>
234
                        </fieldset>
223
                        <fieldset class="rows">
235
                        <fieldset class="rows">
(-)a/tools/batchMod.pl (-13 / +15 lines)
Lines 41-58 use Koha::BackgroundJob::BatchUpdateItem; Link Here
41
use Koha::UI::Form::Builder::Item;
41
use Koha::UI::Form::Builder::Item;
42
use Koha::UI::Table::Builder::Items;
42
use Koha::UI::Table::Builder::Items;
43
43
44
my $input = CGI->new;
44
my $input                             = CGI->new;
45
my $dbh = C4::Context->dbh;
45
my $dbh                               = C4::Context->dbh;
46
my $error        = $input->param('error');
46
my $error                             = $input->param('error');
47
my @itemnumbers  = $input->multi_param('itemnumber');
47
my @itemnumbers                       = $input->multi_param('itemnumber');
48
my $biblionumber = $input->param('biblionumber');
48
my $biblionumber                      = $input->param('biblionumber');
49
my $op           = $input->param('op');
49
my $op                                = $input->param('op');
50
my $del          = $input->param('del');
50
my $del                               = $input->param('del');
51
my $del_records  = $input->param('del_records');
51
my $del_records                       = $input->param('del_records');
52
my $src          = $input->param('src');
52
my $src                               = $input->param('src');
53
my $use_default_values = $input->param('use_default_values');
53
my $use_default_values                = $input->param('use_default_values');
54
my $exclude_from_local_holds_priority = $input->param('exclude_from_local_holds_priority');
54
my $exclude_from_local_holds_priority = $input->param('exclude_from_local_holds_priority');
55
my $mark_items_returned = $input->param('mark_items_returned');
55
my $sort1                             = $input->param('sort1');
56
my $sort2                             = $input->param('sort2');
57
my $mark_items_returned               = $input->param('mark_items_returned');
56
58
57
my $template_name;
59
my $template_name;
58
my $template_flag;
60
my $template_flag;
Lines 177-183 if ( $op eq "cud-action" ) { Link Here
177
                  && $mark_items_returned ne ""
179
                  && $mark_items_returned ne ""
178
                )
180
                )
179
            ? $mark_items_returned : undef,
181
            ? $mark_items_returned : undef,
180
182
            sort1 => ( defined $sort1 && $sort1 ne "" ) ? $sort1 : undef,
183
            sort2 => ( defined $sort2 && $sort2 ne "" ) ? $sort2 : undef,
181
        };
184
        };
182
        try {
185
        try {
183
            my $job_id =
186
            my $job_id =
184
- 

Return to bug 19316