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

(-)a/C4/Acquisition.pm (-2 / +2 lines)
Lines 1926-1934 sub DelOrder { Link Here
1926
    my $order = Koha::Acquisition::Orders->find($ordernumber);
1926
    my $order = Koha::Acquisition::Orders->find($ordernumber);
1927
    my $items = $order->items;
1927
    my $items = $order->items;
1928
    while ( my $item = $items->next ) { # Should be moved to Koha::Acquisition::Order->delete
1928
    while ( my $item = $items->next ) { # Should be moved to Koha::Acquisition::Order->delete
1929
        my $delcheck = C4::Items::DelItemCheck( $bibnum, $item->itemnumber );
1929
        my $delcheck = $item->safe_delete;
1930
1930
1931
        if($delcheck != 1) {
1931
        if($delcheck ne '1') {
1932
            $error->{'delitem'} = 1;
1932
            $error->{'delitem'} = 1;
1933
        }
1933
        }
1934
    }
1934
    }
(-)a/C4/ImportBatch.pm (-2 / +3 lines)
Lines 910-917 sub BatchRevertItems { Link Here
910
    $sth->bind_param(1, $import_record_id);
910
    $sth->bind_param(1, $import_record_id);
911
    $sth->execute();
911
    $sth->execute();
912
    while (my $row = $sth->fetchrow_hashref()) {
912
    while (my $row = $sth->fetchrow_hashref()) {
913
        my $error = DelItemCheck( $biblionumber, $row->{'itemnumber'});
913
        my $item = Koha::Items->find($row->{itemnumber});
914
        if ($error == 1){
914
        my $error = $item->safe_delete;
915
        if ($error eq '1'){
915
            my $updsth = $dbh->prepare("UPDATE import_items SET status = ? WHERE import_items_id = ?");
916
            my $updsth = $dbh->prepare("UPDATE import_items SET status = ? WHERE import_items_id = ?");
916
            $updsth->bind_param(1, 'reverted');
917
            $updsth->bind_param(1, 'reverted');
917
            $updsth->bind_param(2, $row->{'import_items_id'});
918
            $updsth->bind_param(2, $row->{'import_items_id'});
(-)a/C4/Items.pm (-87 lines)
Lines 39-46 BEGIN { Link Here
39
        GetHostItemsInfo
39
        GetHostItemsInfo
40
        get_hostitemnumbers_of
40
        get_hostitemnumbers_of
41
        GetHiddenItemnumbers
41
        GetHiddenItemnumbers
42
        ItemSafeToDelete
43
        DelItemCheck
44
        MoveItemFromBiblio
42
        MoveItemFromBiblio
45
        CartToShelf
43
        CartToShelf
46
        GetAnalyticsCount
44
        GetAnalyticsCount
Lines 1367-1457 sub MoveItemFromBiblio { Link Here
1367
    return;
1365
    return;
1368
}
1366
}
1369
1367
1370
=head2 ItemSafeToDelete
1371
1372
   ItemSafeToDelete( $biblionumber, $itemnumber);
1373
1374
Exported function (core API) for checking whether an item record is safe to delete.
1375
1376
returns 1 if the item is safe to delete,
1377
1378
"book_on_loan" if the item is checked out,
1379
1380
"not_same_branch" if the item is blocked by independent branches,
1381
1382
"book_reserved" if the there are holds aganst the item, or
1383
1384
"linked_analytics" if the item has linked analytic records.
1385
1386
=cut
1387
1388
sub ItemSafeToDelete {
1389
    my ( $biblionumber, $itemnumber ) = @_;
1390
    my $status;
1391
    my $dbh = C4::Context->dbh;
1392
1393
    my $error;
1394
1395
    my $countanalytics = GetAnalyticsCount($itemnumber);
1396
1397
    my $item = Koha::Items->find($itemnumber) or return;
1398
1399
    if ($item->checkout) {
1400
        $status = "book_on_loan";
1401
    }
1402
    elsif ( defined C4::Context->userenv
1403
        and !C4::Context->IsSuperLibrarian()
1404
        and C4::Context->preference("IndependentBranches")
1405
        and ( C4::Context->userenv->{branch} ne $item->homebranch ) )
1406
    {
1407
        $status = "not_same_branch";
1408
    }
1409
    else {
1410
        # check it doesn't have a waiting reserve
1411
        my $sth = $dbh->prepare(
1412
            q{
1413
            SELECT COUNT(*) FROM reserves
1414
            WHERE (found = 'W' OR found = 'T')
1415
            AND itemnumber = ?
1416
        }
1417
        );
1418
        $sth->execute($itemnumber);
1419
        my ($reserve) = $sth->fetchrow;
1420
        if ($reserve) {
1421
            $status = "book_reserved";
1422
        }
1423
        elsif ( $countanalytics > 0 ) {
1424
            $status = "linked_analytics";
1425
        }
1426
        else {
1427
            $status = 1;
1428
        }
1429
    }
1430
    return $status;
1431
}
1432
1433
=head2 DelItemCheck
1434
1435
   DelItemCheck( $biblionumber, $itemnumber);
1436
1437
Exported function (core API) for deleting an item record in Koha if there no current issue.
1438
1439
DelItemCheck wraps ItemSafeToDelete around DelItem.
1440
1441
=cut
1442
1443
sub DelItemCheck {
1444
    my ( $biblionumber, $itemnumber ) = @_;
1445
    my $status = ItemSafeToDelete( $biblionumber, $itemnumber );
1446
1447
    if ( $status == 1 ) {
1448
        my $item = Koha::Items->find($itemnumber);
1449
        $item->move_to_deleted;
1450
        $item->delete;
1451
    }
1452
    return $status;
1453
}
1454
1455
sub _mod_item_dates { # date formatting for date fields in item hash
1368
sub _mod_item_dates { # date formatting for date fields in item hash
1456
    my ( $item ) = @_;
1369
    my ( $item ) = @_;
1457
    return if !$item || ref($item) ne 'HASH';
1370
    return if !$item || ref($item) ne 'HASH';
(-)a/Koha/Item.pm (+60 lines)
Lines 176-181 sub delete { Link Here
176
    return $self->SUPER::delete;
176
    return $self->SUPER::delete;
177
}
177
}
178
178
179
=head3 safe_delete
180
181
=cut
182
183
sub safe_delete {
184
    my ($self) = @_;
185
186
    my $safe_to_delete = $self->safe_to_delete;
187
    return $safe_to_delete unless $safe_to_delete eq '1';
188
189
    $self->move_to_deleted;
190
191
    return $self->delete;
192
}
193
194
=head3 safe_to_delete
195
196
returns 1 if the item is safe to delete,
197
198
"book_on_loan" if the item is checked out,
199
200
"not_same_branch" if the item is blocked by independent branches,
201
202
"book_reserved" if the there are holds aganst the item, or
203
204
"linked_analytics" if the item has linked analytic records.
205
206
=cut
207
208
sub safe_to_delete {
209
    my ($self) = @_;
210
211
    return "book_on_loan" if $self->checkout;
212
213
    return "not_same_branch"
214
      if defined C4::Context->userenv
215
      and !C4::Context->IsSuperLibrarian()
216
      and C4::Context->preference("IndependentBranches")
217
      and ( C4::Context->userenv->{branch} ne $self->homebranch );
218
219
    # check it doesn't have a waiting reserve
220
    return "book_reserved"
221
      if $self->holds->search( { found => [ 'W', 'T' ] } )->count;
222
223
    return "linked_analytics"
224
      if C4::Items::GetAnalyticsCount( $self->itemnumber ) > 0;
225
226
    return 1;
227
}
228
179
=head3 move_to_deleted
229
=head3 move_to_deleted
180
230
181
my $is_moved = $item->move_to_deleted;
231
my $is_moved = $item->move_to_deleted;
Lines 546-551 sub current_holds { Link Here
546
    return Koha::Holds->_new_from_dbic($hold_rs);
596
    return Koha::Holds->_new_from_dbic($hold_rs);
547
}
597
}
548
598
599
=head3 holds
600
601
=cut
602
603
sub holds {
604
    my ( $self ) = @_;
605
    my $hold_rs = $self->_result->reserves->search;
606
    return Koha::Holds->_new_from_dbic($hold_rs);
607
}
608
549
=head3 stockrotationitem
609
=head3 stockrotationitem
550
610
551
  my $sritem = Koha::Item->stockrotationitem;
611
  my $sritem = Koha::Item->stockrotationitem;
(-)a/cataloguing/additem.pl (-6 / +7 lines)
Lines 669-676 if ($op eq "additem") { Link Here
669
} elsif ($op eq "delitem") {
669
} elsif ($op eq "delitem") {
670
#-------------------------------------------------------------------------------
670
#-------------------------------------------------------------------------------
671
    # check that there is no issue on this item before deletion.
671
    # check that there is no issue on this item before deletion.
672
    $error = &DelItemCheck( $biblionumber,$itemnumber);
672
    my $item = Koha::Items->find($itemnumber);
673
    if($error == 1){
673
    $error = $item->safe_to_delete;
674
    if($error ne '1'){
674
        print $input->redirect("additem.pl?biblionumber=$biblionumber&frameworkcode=$frameworkcode&searchid=$searchid");
675
        print $input->redirect("additem.pl?biblionumber=$biblionumber&frameworkcode=$frameworkcode&searchid=$searchid");
675
    }else{
676
    }else{
676
        push @errors,$error;
677
        push @errors,$error;
Lines 679-688 if ($op eq "additem") { Link Here
679
#-------------------------------------------------------------------------------
680
#-------------------------------------------------------------------------------
680
} elsif ($op eq "delallitems") {
681
} elsif ($op eq "delallitems") {
681
#-------------------------------------------------------------------------------
682
#-------------------------------------------------------------------------------
682
    my @itemnumbers = Koha::Items->search({ biblionumber => $biblionumber })->get_column('itemnumber');
683
    my $items = Koha::Items->search({ biblionumber => $biblionumber });
683
    foreach my $itemnumber ( @itemnumbers ) {
684
    while ( my $item = $items->next ) {
684
        $error = C4::Items::DelItemCheck( $biblionumber, $itemnumber );
685
        $error = $item->safe_delete;
685
        next if $error == 1; # Means ok
686
        next if $error eq '1'; # Means ok
686
        push @errors,$error;
687
        push @errors,$error;
687
    }
688
    }
688
    if ( @errors ) {
689
    if ( @errors ) {
(-)a/misc/cronjobs/delete_items.pl (-4 / +6 lines)
Lines 54-71 my $where_clause = ' where ' . join ( " and ", @where ); Link Here
54
54
55
verbose "Where statement: $where_clause";
55
verbose "Where statement: $where_clause";
56
56
57
# FIXME Use Koha::Items instead
57
$GLOBAL->{sth}->{target_items} = $dbh->prepare( $query->{target_items} . $where_clause  );
58
$GLOBAL->{sth}->{target_items} = $dbh->prepare( $query->{target_items} . $where_clause  );
58
$GLOBAL->{sth}->{target_items}->execute();
59
$GLOBAL->{sth}->{target_items}->execute();
59
60
60
DELITEM: while ( my $item = $GLOBAL->{sth}->{target_items}->fetchrow_hashref() ) {
61
DELITEM: while ( my $item = $GLOBAL->{sth}->{target_items}->fetchrow_hashref() ) {
61
62
62
    my $status = C4::Items::ItemSafeToDelete( $item->{biblionumber}, $item->{itemnumber} );
63
    my $item_object = Koha::Items->find($item->{itemnumber});
63
    if( $status eq '1' )  {
64
    my $safe_to_delete = $item_object->safe_to_delete;
64
        C4::Items::DelItemCheck( $item->{biblionumber}, $item->{itemnumber} )
65
    if( $safe_to_delete eq '1' )  {
66
        $item->safe_delete
65
            if $OPTIONS->{flags}->{commit};
67
            if $OPTIONS->{flags}->{commit};
66
        verbose "Deleting '$item->{itemnumber}'";
68
        verbose "Deleting '$item->{itemnumber}'";
67
    } else {
69
    } else {
68
        verbose "Item '$item->{itemnumber}' not deletd: $status";
70
        verbose "Item '$item->{itemnumber}' not deleted: $safe_to_delete";
69
    }
71
    }
70
}
72
}
71
73
(-)a/misc/cronjobs/delete_records_via_leader.pl (-1 / +1 lines)
Lines 99-105 foreach my $m (@metadatas) { Link Here
99
        foreach my $item ( @items ) {
99
        foreach my $item ( @items ) {
100
            my $itemnumber = $item->itemnumber();
100
            my $itemnumber = $item->itemnumber();
101
101
102
            my $error = $test ? "Test mode enabled" : DelItemCheck( $biblionumber, $itemnumber );
102
            my $error = $test ? "Test mode enabled" : $item->safe_delete;
103
            $error = undef if $error eq '1';
103
            $error = undef if $error eq '1';
104
104
105
            if ($error) {
105
            if ($error) {
(-)a/t/db_dependent/Circulation/IsItemIssued.t (-2 / +2 lines)
Lines 68-74 AddIssue($borrower, $item->barcode); Link Here
68
is ( IsItemIssued( $item->itemnumber ), 1, "item is now on loan" );
68
is ( IsItemIssued( $item->itemnumber ), 1, "item is now on loan" );
69
69
70
is(
70
is(
71
    DelItemCheck( $biblionumber, $item->itemnumber),
71
    $item->safe_delete,
72
    'book_on_loan',
72
    'book_on_loan',
73
    'item that is on loan cannot be deleted',
73
    'item that is on loan cannot be deleted',
74
);
74
);
Lines 77-83 AddReturn($item->barcode, $library->{branchcode}); Link Here
77
is ( IsItemIssued( $item->itemnumber ), 0, "item has been returned" );
77
is ( IsItemIssued( $item->itemnumber ), 0, "item has been returned" );
78
78
79
is(
79
is(
80
    DelItemCheck( $biblionumber, $item->itemnumber),
80
    $item->safe_delete,
81
    1,
81
    1,
82
    'item that is not on loan can be deleted',
82
    'item that is not on loan can be deleted',
83
);
83
);
(-)a/t/db_dependent/Items_DelItemCheck.t (-13 / +13 lines)
Lines 98-110 my $item = $builder->build_object( Link Here
98
AddIssue( $patron, $item->barcode );
98
AddIssue( $patron, $item->barcode );
99
99
100
is(
100
is(
101
    ItemSafeToDelete( $biblio->{biblionumber}, $item->itemnumber ),
101
    $item->safe_to_delete,
102
    'book_on_loan',
102
    'book_on_loan',
103
    'ItemSafeToDelete reports item on loan',
103
    'Koha::Item->safe_to_delete reports item on loan',
104
);
104
);
105
105
106
is(
106
is(
107
    DelItemCheck( $biblio->{biblionumber}, $item->itemnumber ),
107
    $item->safe_delete,
108
    'book_on_loan',
108
    'book_on_loan',
109
    'item that is on loan cannot be deleted',
109
    'item that is on loan cannot be deleted',
110
);
110
);
Lines 118-130 t::lib::Mocks::mock_preference('IndependentBranches', 1); Link Here
118
$item->set( { homebranch => $branch2->{branchcode}, holdingbranch => $branch2->{branchcode} })->store;
118
$item->set( { homebranch => $branch2->{branchcode}, holdingbranch => $branch2->{branchcode} })->store;
119
119
120
is(
120
is(
121
    ItemSafeToDelete( $biblio->{biblionumber}, $item->itemnumber ),
121
    $item->safe_to_delete,
122
    'not_same_branch',
122
    'not_same_branch',
123
    'ItemSafeToDelete reports IndependentBranches restriction',
123
    'Koha::Item->safe_to_delete reports IndependentBranches restriction',
124
);
124
);
125
125
126
is(
126
is(
127
    DelItemCheck( $biblio->{biblionumber}, $item->itemnumber ),
127
    $item->safe_delete,
128
    'not_same_branch',
128
    'not_same_branch',
129
    'IndependentBranches prevents deletion at another branch',
129
    'IndependentBranches prevents deletion at another branch',
130
);
130
);
Lines 139-151 $item->set( { homebranch => $branch->{branchcode}, holdingbranch => $branch->{br Link Here
139
    $module->mock( GetAnalyticsCount => sub { return 1 } );
139
    $module->mock( GetAnalyticsCount => sub { return 1 } );
140
140
141
    is(
141
    is(
142
        ItemSafeToDelete( $biblio->{biblionumber}, $item->itemnumber ),
142
        $item->safe_to_delete,
143
        'linked_analytics',
143
        'linked_analytics',
144
        'ItemSafeToDelete reports linked analytics',
144
        'Koha::Item->safe_to_delete reports linked analytics',
145
    );
145
    );
146
146
147
    is(
147
    is(
148
        DelItemCheck( $biblio->{biblionumber}, $item->itemnumber ),
148
        $item->safe_delete,
149
        'linked_analytics',
149
        'linked_analytics',
150
        'Linked analytics prevents deletion of item',
150
        'Linked analytics prevents deletion of item',
151
    );
151
    );
Lines 153-169 $item->set( { homebranch => $branch->{branchcode}, holdingbranch => $branch->{br Link Here
153
}
153
}
154
154
155
is(
155
is(
156
    ItemSafeToDelete( $biblio->{biblionumber}, $item->itemnumber ),
156
    $item->safe_to_delete,
157
    1,
157
    1,
158
    'ItemSafeToDelete shows item safe to delete'
158
    'Koha::Item->safe_to_delete shows item safe to delete'
159
);
159
);
160
160
161
DelItemCheck( $biblio->{biblionumber}, $item->itemnumber );
161
$item->safe_delete,
162
162
163
my $test_item = Koha::Items->find( $item->itemnumber );
163
my $test_item = Koha::Items->find( $item->itemnumber );
164
164
165
is( $test_item, undef,
165
is( $test_item, undef,
166
    "DelItemCheck should delete item if ItemSafeToDelete returns true"
166
    "Koha::Item->safe_delete should delete item if safe_to_delete returns true"
167
);
167
);
168
168
169
$schema->storage->txn_rollback;
169
$schema->storage->txn_rollback;
(-)a/t/db_dependent/Reserves.t (-2 / +2 lines)
Lines 404-411 is($new_count, $hold_notice_count + 1, 'patron not notified a second time (bug 1 Link Here
404
404
405
# avoiding the not_same_branch error
405
# avoiding the not_same_branch error
406
t::lib::Mocks::mock_preference('IndependentBranches', 0);
406
t::lib::Mocks::mock_preference('IndependentBranches', 0);
407
my $item = Koha::Items->find($itemnumber);
407
is(
408
is(
408
    DelItemCheck( $bibnum, $itemnumber),
409
    $item->safe_delete,
409
    'book_reserved',
410
    'book_reserved',
410
    'item that is captured to fill a hold cannot be deleted',
411
    'item that is captured to fill a hold cannot be deleted',
411
);
412
);
Lines 431-437 AddReserve( Link Here
431
    }
432
    }
432
);
433
);
433
434
434
my $item = Koha::Items->find( $itemnumber );
435
$holds = $item->current_holds;
435
$holds = $item->current_holds;
436
my $dtf = Koha::Database->new->schema->storage->datetime_parser;
436
my $dtf = Koha::Database->new->schema->storage->datetime_parser;
437
my $future_holds = $holds->search({ reservedate => { '>' => $dtf->format_date( dt_from_string ) } } );
437
my $future_holds = $holds->search({ reservedate => { '>' => $dtf->format_date( dt_from_string ) } } );
(-)a/tools/batchMod.pl (-4 / +4 lines)
Lines 186-196 if ($op eq "action") { Link Here
186
	foreach my $itemnumber(@itemnumbers){
186
	foreach my $itemnumber(@itemnumbers){
187
187
188
		$job->progress($i) if $runinbackground;
188
		$job->progress($i) if $runinbackground;
189
        my $itemdata = Koha::Items->find($itemnumber);
189
        my $item = Koha::Items->find($itemnumber);
190
        next unless $itemdata; # Should have been tested earlier, but just in case...
190
        next unless $item; # Should have been tested earlier, but just in case...
191
        $itemdata = $itemdata->unblessed;
191
        my $itemdata = $item->unblessed;
192
        if ( $del ){
192
        if ( $del ){
193
            my $return = DelItemCheck( $itemdata->{'biblionumber'}, $itemdata->{'itemnumber'});
193
            my $return = $item->safe_delete;
194
			if ($return == 1) {
194
			if ($return == 1) {
195
			    $deleted_items++;
195
			    $deleted_items++;
196
			} else {
196
			} else {
(-)a/tools/batch_delete_records.pl (-5 / +4 lines)
Lines 175-184 if ( $op eq 'form' ) { Link Here
175
            }
175
            }
176
176
177
            # Delete items
177
            # Delete items
178
            my @itemnumbers = Koha::Items->search({ biblionumber => $biblionumber })->get_column('itemnumber');
178
            my $items = Koha::Items->search({ biblionumber => $biblionumber });
179
            ITEMNUMBER: for my $itemnumber ( @itemnumbers ) {
179
            while ( my $item = $items->next ) {
180
                my $error = eval { C4::Items::DelItemCheck( $biblionumber, $itemnumber ) };
180
                my $error = eval { $item->safe_delete };
181
                if ( $error != 1 or $@ ) {
181
                if ( $error ne '1' or $@ ) {
182
                    push @messages, {
182
                    push @messages, {
183
                        type => 'error',
183
                        type => 'error',
184
                        code => 'item_not_deleted',
184
                        code => 'item_not_deleted',
185
- 

Return to bug 23463