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

(-)a/Koha/Old/Biblio.pm (-2 / +46 lines)
Lines 154-171 sub to_api_mapping { Link Here
154
=head3 restore
154
=head3 restore
155
155
156
    my $biblio = $deleted_biblio->restore;
156
    my $biblio = $deleted_biblio->restore;
157
    my $biblio = $deleted_biblio->restore({
158
        patron      => $patron,
159
        item_ids    => \@item_ids,
160
        restore_all => 0
161
    });
157
162
158
Restores the deleted biblio record back to the biblio table along with
163
Restores the deleted biblio record back to the biblio table along with
159
its biblioitems and metadata. This removes the record from the deleted tables
164
its biblioitems and metadata. This removes the record from the deleted tables
160
and re-inserts it into the active tables. The biblio record will be reindexed
165
and re-inserts it into the active tables. The biblio record will be reindexed
161
after restoration.
166
after restoration.
162
167
168
Optional parameters:
169
  patron - Koha::Patron object. If provided, only items the patron can edit will be restored.
170
  item_ids - Arrayref of item IDs to restore. If not provided and restore_all is false,
171
             no items will be restored.
172
  restore_all - Boolean. If true and no item_ids provided, restore all items the patron
173
                has permission to edit.
174
163
Returns the newly restored Koha::Biblio object.
175
Returns the newly restored Koha::Biblio object.
164
176
165
=cut
177
=cut
166
178
167
sub restore {
179
sub restore {
168
    my ($self) = @_;
180
    my ( $self, $params ) = @_;
181
182
    $params //= {};
169
183
170
    my $biblio_data     = $self->unblessed;
184
    my $biblio_data     = $self->unblessed;
171
    my $biblioitem      = $self->biblioitem;
185
    my $biblioitem      = $self->biblioitem;
Lines 187-199 sub restore { Link Here
187
    $biblioitem->delete;
201
    $biblioitem->delete;
188
    $self->delete;
202
    $self->delete;
189
203
204
    my $patron      = $params->{patron};
205
    my $item_ids    = $params->{item_ids};
206
    my $restore_all = $params->{restore_all} // 0;
207
208
    my @restored_items;
209
    my @skipped_items;
210
211
    if ( $restore_all || $item_ids ) {
212
        my $deleted_items = $self->items;
213
        while ( my $deleted_item = $deleted_items->next ) {
214
            my $should_restore = 0;
215
216
            if ($item_ids) {
217
                $should_restore = grep { $_ == $deleted_item->itemnumber } @$item_ids;
218
            } elsif ($restore_all) {
219
                $should_restore = 1;
220
            }
221
222
            if ($should_restore) {
223
                if ( $patron && !$patron->can_edit_items_from( $deleted_item->homebranch ) ) {
224
                    push @skipped_items, $deleted_item->itemnumber;
225
                    next;
226
                }
227
228
                $deleted_item->restore;
229
                push @restored_items, $deleted_item->itemnumber;
230
            }
231
        }
232
    }
233
190
    my $indexer = Koha::SearchEngine::Indexer->new( { index => $Koha::SearchEngine::BIBLIOS_INDEX } );
234
    my $indexer = Koha::SearchEngine::Indexer->new( { index => $Koha::SearchEngine::BIBLIOS_INDEX } );
191
    $indexer->index_records( $new_biblio->biblionumber, "specialUpdate", "biblioserver" );
235
    $indexer->index_records( $new_biblio->biblionumber, "specialUpdate", "biblioserver" );
192
236
193
    logaction( "CATALOGUING", "RESTORE", $new_biblio->biblionumber, "biblio", undef, $new_biblio )
237
    logaction( "CATALOGUING", "RESTORE", $new_biblio->biblionumber, "biblio", undef, $new_biblio )
194
        if C4::Context->preference("CataloguingLog");
238
        if C4::Context->preference("CataloguingLog");
195
239
196
    return $new_biblio;
240
    return wantarray ? ( $new_biblio, \@restored_items, \@skipped_items ) : $new_biblio;
197
}
241
}
198
242
199
=head2 Internal methods
243
=head2 Internal methods
(-)a/Koha/REST/V1/DeletedBiblios.pm (-2 / +21 lines)
Lines 180-191 sub restore { Link Here
180
    return $c->render_resource_not_found("Bibliographic record")
180
    return $c->render_resource_not_found("Bibliographic record")
181
        unless $deleted_biblio;
181
        unless $deleted_biblio;
182
182
183
    my $body        = $c->req->json;
184
    my $item_ids    = $body->{item_ids};
185
    my $restore_all = $body->{restore_all} // 0;
186
183
    return try {
187
    return try {
184
        my $biblio = $deleted_biblio->restore;
188
        my $patron = $c->stash('koha.user');
189
190
        my ( $biblio, $restored_items, $skipped_items ) = $deleted_biblio->restore(
191
            {
192
                patron      => $patron,
193
                item_ids    => $item_ids,
194
                restore_all => $restore_all
195
            }
196
        );
197
198
        my $response = { biblio_id => $biblio->biblionumber };
199
200
        if ( $item_ids || $restore_all ) {
201
            $response->{restored_items} = $restored_items if @$restored_items;
202
            $response->{skipped_items}  = $skipped_items  if @$skipped_items;
203
        }
185
204
186
        return $c->render(
205
        return $c->render(
187
            status  => 200,
206
            status  => 200,
188
            openapi => { biblio_id => $biblio->biblionumber }
207
            openapi => $response
189
        );
208
        );
190
    } catch {
209
    } catch {
191
        $c->unhandled_exception($_);
210
        $c->unhandled_exception($_);
(-)a/Koha/REST/V1/DeletedItems.pm (+9 lines)
Lines 85-90 sub restore { Link Here
85
        unless $deleted_item;
85
        unless $deleted_item;
86
86
87
    return try {
87
    return try {
88
        my $patron = $c->stash('koha.user');
89
90
        unless ( $patron->can_edit_items_from( $deleted_item->homebranch ) ) {
91
            return $c->render(
92
                status  => 403,
93
                openapi => { error => "You do not have permission to restore items from this library." }
94
            );
95
        }
96
88
        my $item = $deleted_item->restore;
97
        my $item = $deleted_item->restore;
89
98
90
        return $c->render(
99
        return $c->render(
(-)a/api/v1/swagger/paths/deleted_biblios.yaml (+35 lines)
Lines 135-140 Link Here
135
    summary: Restore deleted biblio
135
    summary: Restore deleted biblio
136
    parameters:
136
    parameters:
137
      - $ref: "../swagger.yaml#/parameters/biblio_id_pp"
137
      - $ref: "../swagger.yaml#/parameters/biblio_id_pp"
138
      - name: body
139
        in: body
140
        description: Restore options for items
141
        required: false
142
        schema:
143
          type: object
144
          properties:
145
            item_ids:
146
              type: array
147
              description: Array of item IDs to restore with the biblio
148
              items:
149
                type: integer
150
            restore_all:
151
              type: boolean
152
              description: Restore all items the user has permission to edit
153
          additionalProperties: false
154
    consumes:
155
      - application/json
138
    produces:
156
    produces:
139
      - application/json
157
      - application/json
140
    responses:
158
    responses:
Lines 142-147 Link Here
142
        description: Biblio restored successfully
160
        description: Biblio restored successfully
143
        schema:
161
        schema:
144
          type: object
162
          type: object
163
          properties:
164
            biblio_id:
165
              type: integer
166
              description: The ID of the restored biblio
167
            restored_items:
168
              type: array
169
              description: List of item IDs that were successfully restored
170
              items:
171
                type: integer
172
            skipped_items:
173
              type: array
174
              description: List of item IDs that were skipped during restoration due to insufficient permissions
175
              items:
176
                type: integer
177
          required:
178
            - biblio_id
179
          additionalProperties: false
145
      "400":
180
      "400":
146
        description: Bad request
181
        description: Bad request
147
        schema:
182
        schema:
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/restore-records.tt (-8 / +35 lines)
Lines 190-195 Link Here
190
        }
190
        }
191
191
192
        $(document).ready(function () {
192
        $(document).ready(function () {
193
            var librariesWhereCanEdit = [% libraries_where_can_edit_json | $raw %];
194
            var canEditAnyLibrary = librariesWhereCanEdit.length === 0;
195
196
            function canEditItem(homebranch) {
197
                if (canEditAnyLibrary) {
198
                    return true;
199
                }
200
                return librariesWhereCanEdit.includes(homebranch);
201
            }
202
193
            var oneYearAgo = new Date();
203
            var oneYearAgo = new Date();
194
            oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);
204
            oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);
195
            var today = new Date();
205
            var today = new Date();
Lines 365-381 Link Here
365
                    {
375
                    {
366
                        data: function (row, type) {
376
                        data: function (row, type) {
367
                            if (type === "display") {
377
                            if (type === "display") {
368
                                return (
378
                                var canEdit = canEditItem(row.home_library_id);
369
                                    '<button class="btn btn-sm btn-default restore-item" data-item-id="' +
379
                                var disabled = canEdit ? '' : ' disabled';
380
                                var button = '<button class="btn btn-sm btn-default restore-item" data-item-id="' +
370
                                    row.item_id +
381
                                    row.item_id +
371
                                    '" data-barcode="' +
382
                                    '" data-barcode="' +
372
                                    $("<div/>")
383
                                    $("<div/>")
373
                                        .text(row.external_id || row.item_id)
384
                                        .text(row.external_id || row.item_id)
374
                                        .html() +
385
                                        .html() +
375
                                    '"><i class="fa fa-undo" aria-hidden="true"></i> ' +
386
                                    '"' + disabled + '><i class="fa fa-undo" aria-hidden="true"></i> ' +
376
                                    _("Restore") +
387
                                    _("Restore") +
377
                                    "</button>"
388
                                    "</button>";
378
                                );
389
390
                                if (!canEdit) {
391
                                    return '<span title="' + _("You do not have permission to restore items from this library") + '" style="cursor: not-allowed;">' + button + '</span>';
392
                                }
393
                                return button;
379
                            }
394
                            }
380
                            return "";
395
                            return "";
381
                        },
396
                        },
Lines 422-428 Link Here
422
                            {
437
                            {
423
                                data: function (row, type) {
438
                                data: function (row, type) {
424
                                    if (type === "display") {
439
                                    if (type === "display") {
425
                                        return '<input type="checkbox" class="item-checkbox" data-item-id="' + row.item_id + '">';
440
                                        var canEdit = canEditItem(row.home_library_id);
441
                                        var disabled = canEdit ? '' : ' disabled';
442
                                        var checkbox = '<input type="checkbox" class="item-checkbox" data-item-id="' + row.item_id + '"' + disabled + '>';
443
444
                                        if (!canEdit) {
445
                                            return '<span title="' + _("You do not have permission to restore items from this library") + '">' + checkbox + '</span>';
446
                                        }
447
                                        return checkbox;
426
                                    }
448
                                    }
427
                                    return "";
449
                                    return "";
428
                                },
450
                                },
Lines 462-468 Link Here
462
                                orderable: true,
484
                                orderable: true,
463
                                render: function (data, type, row) {
485
                                render: function (data, type, row) {
464
                                    if (type === "display") {
486
                                    if (type === "display") {
465
                                        return data ? $("<div/>").text(data).html() : "";
487
                                        var text = data ? $("<div/>").text(data).html() : "";
488
                                        var canEdit = canEditItem(data);
489
                                        if (!canEdit) {
490
                                            text += ' <span class="badge bg-warning text-dark">' + _("No permission") + '</span>';
491
                                        }
492
                                        return text;
466
                                    }
493
                                    }
467
                                    return data || "";
494
                                    return data || "";
468
                                },
495
                                },
Lines 570-576 Link Here
570
            // Select all items checkbox
597
            // Select all items checkbox
571
            $("#select-all-items").on("change", function () {
598
            $("#select-all-items").on("change", function () {
572
                var checked = $(this).prop("checked");
599
                var checked = $(this).prop("checked");
573
                $(".item-checkbox").prop("checked", checked);
600
                $(".item-checkbox:not(:disabled)").prop("checked", checked);
574
            });
601
            });
575
602
576
            // Restore biblio with items
603
            // Restore biblio with items
(-)a/tools/restore-records.pl (-2 / +10 lines)
Lines 17-26 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use CGI qw ( -utf8 );
20
use CGI  qw ( -utf8 );
21
use JSON qw( encode_json );
21
22
22
use C4::Auth   qw( get_template_and_user );
23
use C4::Auth   qw( get_template_and_user );
23
use C4::Output qw( output_html_with_http_headers );
24
use C4::Output qw( output_html_with_http_headers );
25
use Koha::Patrons;
24
26
25
my $input = CGI->new;
27
my $input = CGI->new;
26
28
Lines 33-36 my ( $template, $loggedinuser, $cookie ) = get_template_and_user( Link Here
33
    }
35
    }
34
);
36
);
35
37
38
my $patron                   = Koha::Patrons->find($loggedinuser);
39
my @libraries_where_can_edit = $patron->libraries_where_can_edit_items;
40
41
$template->param(
42
    libraries_where_can_edit_json => encode_json( \@libraries_where_can_edit ),
43
);
44
36
output_html_with_http_headers $input, $cookie, $template->output;
45
output_html_with_http_headers $input, $cookie, $template->output;
37
- 

Return to bug 17387