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

(-)a/C4/Items.pm (-30 / +71 lines)
Lines 77-82 BEGIN { Link Here
77
        GetItemnumberFromBarcode
77
        GetItemnumberFromBarcode
78
        GetBarcodeFromItemnumber
78
        GetBarcodeFromItemnumber
79
        GetHiddenItemnumbers
79
        GetHiddenItemnumbers
80
        ItemSafeToDelete
80
        DelItemCheck
81
        DelItemCheck
81
    MoveItemFromBiblio
82
    MoveItemFromBiblio
82
    GetLatestAcquisitions
83
    GetLatestAcquisitions
Lines 2296-2359 sub MoveItemFromBiblio { Link Here
2296
    return;
2297
    return;
2297
}
2298
}
2298
2299
2299
=head2 DelItemCheck
2300
=head2 ItemSafeToDelete
2300
2301
2301
   DelItemCheck($dbh, $biblionumber, $itemnumber);
2302
   ItemSafeToDelete($dbh, $biblionumber, $itemnumber);
2302
2303
2303
Exported function (core API) for deleting an item record in Koha if there no current issue.
2304
Exported function (core API) for checking whether an item record is safe to delete.
2305
2306
returns 1 if the item is safe to delete, 
2307
2308
"book_on_loan" if the item is checked out,
2309
2310
"not_same_branch" if the item is blocked by independent branches,
2311
2312
"book_reserved" if the there are holds aganst the item, or
2313
2314
"linked_analytics" if the item has linked analytic records.
2304
2315
2305
=cut
2316
=cut
2306
2317
2307
sub DelItemCheck {
2318
sub ItemSafeToDelete {
2308
    my ( $dbh, $biblionumber, $itemnumber ) = @_;
2319
    my ( $dbh, $biblionumber, $itemnumber ) = @_;
2309
    my $error;
2320
    my $status;
2310
2311
        my $countanalytics=GetAnalyticsCount($itemnumber);
2312
2321
2322
    my $countanalytics = GetAnalyticsCount($itemnumber);
2313
2323
2314
    # check that there is no issue on this item before deletion.
2324
    # check that there is no issue on this item before deletion.
2315
    my $sth = $dbh->prepare(q{
2325
    my $sth = $dbh->prepare(
2326
        q{
2316
        SELECT COUNT(*) FROM issues
2327
        SELECT COUNT(*) FROM issues
2317
        WHERE itemnumber = ?
2328
        WHERE itemnumber = ?
2318
    });
2329
    }
2330
    );
2319
    $sth->execute($itemnumber);
2331
    $sth->execute($itemnumber);
2320
    my ($onloan) = $sth->fetchrow;
2332
    my ($onloan) = $sth->fetchrow;
2321
2333
2322
    my $item = GetItem($itemnumber);
2334
    my $item = GetItem($itemnumber);
2323
2335
2324
    if ($onloan){
2336
    if ($onloan) {
2325
        $error = "book_on_loan" 
2337
        $status = "book_on_loan";
2326
    }
2338
    }
2327
    elsif ( !C4::Context->IsSuperLibrarian()
2339
    elsif ( !C4::Context->IsSuperLibrarian()
2328
        and C4::Context->preference("IndependentBranches")
2340
        && C4::Context->preference("IndependentBranches")
2329
        and ( C4::Context->userenv->{branch} ne $item->{'homebranch'} ) )
2341
        && ( C4::Context->userenv->{branch} ne $item->{'homebranch'} ) )
2330
    {
2342
    {
2331
        $error = "not_same_branch";
2343
        $status = "not_same_branch";
2332
    }
2344
    }
2333
	else{
2345
    else {
2334
        # check it doesn't have a waiting reserve
2346
        # check it doesn't have a waiting reserve
2335
        $sth = $dbh->prepare(q{
2347
        $sth = $dbh->prepare(
2348
            q{
2336
            SELECT COUNT(*) FROM reserves
2349
            SELECT COUNT(*) FROM reserves
2337
            WHERE (found = 'W' OR found = 'T')
2350
            WHERE (found = 'W' OR found = 'T')
2338
            AND itemnumber = ?
2351
            AND itemnumber = ?
2339
        });
2352
        }
2353
        );
2340
        $sth->execute($itemnumber);
2354
        $sth->execute($itemnumber);
2341
        my ($reserve) = $sth->fetchrow;
2355
        my ($reserve) = $sth->fetchrow;
2342
        if ($reserve){
2356
        if ($reserve) {
2343
            $error = "book_reserved";
2357
            $status = "book_reserved";
2344
        } elsif ($countanalytics > 0){
2345
		$error = "linked_analytics";
2346
	} else {
2347
            DelItem(
2348
                {
2349
                    biblionumber => $biblionumber,
2350
                    itemnumber   => $itemnumber
2351
                }
2352
            );
2353
            return 1;
2354
        }
2358
        }
2359
        elsif ( $countanalytics > 0 ) {
2360
            $status = "linked_analytics";
2361
        }
2362
        else {
2363
            $status = 1;
2364
        }
2365
    }
2366
    return $status;
2367
}
2368
2369
=head2 DelItemCheck
2370
2371
   DelItemCheck($dbh, $biblionumber, $itemnumber);
2372
2373
Exported function (core API) for deleting an item record in Koha if there no current issue.
2374
2375
DelItemCheck wraps ItemSafeToDelete around DelItem.
2376
2377
It takes a database handle, biblionumber and itemnumber as arguments, and can optionally take a hashref with a 'do_not_commit' flag:
2378
2379
    DelItemCheck(  $dbh, $biblionumber, $itemnumber, { do_not_commit => 1 } );
2380
2381
This is done so that command line scripts calling DelItemCheck have the option of doing a 'dry-run'.
2382
=cut
2383
2384
sub DelItemCheck {
2385
    my ( $dbh, $biblionumber, $itemnumber, $options ) = @_;
2386
    my $commit = ( defined $options && $options->{do_not_commit} eq 1 ) ? 0 : 1;
2387
    my $status = ItemSafeToDelete( $dbh, $biblionumber, $itemnumber );
2388
2389
    if ( $status == 1 && $commit ) {
2390
        DelItem(
2391
            {
2392
                biblionumber => $biblionumber,
2393
                itemnumber   => $itemnumber
2394
            }
2395
        );
2355
    }
2396
    }
2356
    return $error;
2397
    return $status;
2357
}
2398
}
2358
2399
2359
=head2 _koha_modify_item
2400
=head2 _koha_modify_item
(-)a/t/db_dependent/Items_DelItemCheck.t (-1 / +146 lines)
Line 0 Link Here
0
- 
1
use Modern::Perl;
2
3
use MARC::Record;
4
use C4::Biblio;
5
use C4::Circulation;
6
use C4::Members;
7
use t::lib::Mocks;
8
9
10
use Test::More tests => 10;
11
12
*C4::Context::userenv = \&Mock_userenv;
13
14
BEGIN {
15
    use_ok('C4::Items');
16
}
17
18
my $dbh = C4::Context->dbh;
19
$dbh->{AutoCommit} = 0;
20
$dbh->{RaiseError} = 1;
21
22
my ( $biblionumber, $bibitemnum ) = get_biblio();
23
24
# book_on_loan
25
26
my ( $borrowernumber, $borrower ) = get_borrower();
27
my ( $itemnumber, $item )         = get_item( $biblionumber );
28
AddIssue( $borrower, 'i_dont_exist' );
29
30
is(
31
    ItemSafeToDelete($dbh, $biblionumber, $itemnumber),
32
    'book_on_loan',
33
    'ItemSafeToDelete reports item on loan',
34
);
35
36
is(
37
    DelItemCheck($dbh, $biblionumber, $itemnumber),
38
    'book_on_loan',
39
    'item that is on loan cannot be deleted',
40
);
41
42
AddReturn('i_dont_exist', 'CPL');
43
44
# book_reserved is tested in t/db_dependent/Reserves.t
45
46
# not_same_branch
47
t::lib::Mocks::mock_preference('IndependentBranches', 1); 
48
ModItem( { homebranch => 'FPL', holdingbranch => 'FPL' }, $biblionumber, $itemnumber );
49
50
is(
51
    ItemSafeToDelete($dbh, $biblionumber, $itemnumber),
52
    'not_same_branch',
53
    'ItemSafeToDelete reports IndependentBranches restriction',
54
);
55
56
is(
57
    DelItemCheck($dbh, $biblionumber, $itemnumber),
58
    'not_same_branch',
59
    'IndependentBranches prevents deletion at another branch',
60
);
61
62
ModItem( { homebranch => 'CPL', holdingbranch => 'CPL' }, $biblionumber, $itemnumber );
63
64
# linked_analytics
65
66
{ # codeblock to limit scope of $module->mock
67
68
    my $module = Test::MockModule->new('C4::Items');
69
    $module->mock( GetAnalyticsCount => sub { return 1 } );
70
71
    is(
72
        ItemSafeToDelete($dbh, $biblionumber, $itemnumber),
73
        'linked_analytics',
74
        'ItemSafeToDelete reports linked analytics',
75
    );
76
77
    is(
78
        DelItemCheck($dbh, $biblionumber, $itemnumber),
79
        'linked_analytics',
80
        'Linked analytics prevents deletion of item',
81
    );
82
83
}
84
85
is(
86
    ItemSafeToDelete($dbh, $biblionumber, $itemnumber),
87
    1,
88
    'ItemSafeToDelete shows item safe to delete'
89
);
90
91
DelItemCheck($dbh, $biblionumber, $itemnumber, { do_not_commit => 1 } );
92
93
my $testitem = GetItem( $itemnumber );
94
95
is( $testitem->{itemnumber} ,  $itemnumber,
96
    "DelItemCheck should not delete item if 'do_not_commit' is set"
97
);
98
99
DelItemCheck( $dbh, $biblionumber, $itemnumber );
100
101
$testitem = GetItem( $itemnumber );
102
103
is( $testitem->{itemnumber}, undef,
104
    "DelItemCheck should delete item if 'do_not_commit' not set"
105
);
106
107
# End of testing
108
109
# Helper methods to set up Biblio, Item, and Borrower.
110
sub get_biblio {
111
    my $bib = MARC::Record->new();
112
    $bib->append_fields(
113
        MARC::Field->new( '100', ' ', ' ', a => 'Moffat, Steven' ),
114
        MARC::Field->new( '245', ' ', ' ', a => 'Silence in the library' ),
115
    );
116
    my ( $bibnum, $bibitemnum ) = AddBiblio( $bib, '' );
117
    return ( $bibnum, $bibitemnum );
118
}
119
120
sub get_item {
121
    my $biblionumber = shift;
122
    my ( $item_bibnum, $item_bibitemnum, $itemnumber ) =
123
      AddItem( { homebranch => 'CPL', holdingbranch => 'CPL', barcode => 'i_dont_exist' }, $biblionumber );
124
    my $item = GetItem( $itemnumber );
125
    return ( $itemnumber, $item );
126
}
127
128
sub get_borrower {
129
    my $borrowernumber = AddMember(
130
        firstname =>  'my firstname',
131
        surname => 'my surname',
132
        categorycode => 'S',
133
        branchcode => 'CPL',
134
    );
135
136
    my $borrower = GetMember( borrowernumber => $borrowernumber );
137
    return ( $borrowernumber, $borrower );
138
}
139
140
# C4::Context->userenv
141
sub Mock_userenv {
142
        return { flags => 0, branch => 'CPL' };
143
}
144
145
$dbh->rollback;
146

Return to bug 14504