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

(-)a/Koha/Hold.pm (+29 lines)
Lines 30-35 use Koha::Patrons; Link Here
30
use Koha::Biblios;
30
use Koha::Biblios;
31
use Koha::Items;
31
use Koha::Items;
32
use Koha::Libraries;
32
use Koha::Libraries;
33
use Koha::Calendar;
33
34
34
use base qw(Koha::Object);
35
use base qw(Koha::Object);
35
36
Lines 43-48 Koha::Hold - Koha Hold object class Link Here
43
44
44
=cut
45
=cut
45
46
47
=head3 age
48
49
returns the number of days since a hold was placed, optionally
50
using the calendar
51
52
my $age = $hold->age( $use_calendar );
53
54
=cut
55
56
sub age {
57
    my ( $self, $use_calendar ) = @_;
58
59
    my $today = DateTime->now(time_zone => C4::Context->tz );
60
    my $age;
61
62
    if ( $use_calendar ) {
63
        my $calendar = Koha::Calendar->new( branchcode => $self->branchcode );
64
        $age = $calendar->days_between( dt_from_string( $self->reservedate ), $today );
65
    }
66
    else {
67
        $age = $today->delta_days( dt_from_string( $self->reservedate ) );
68
    }
69
70
    $age = $age->in_units( 'days' );
71
72
    return $age;
73
}
74
46
=head3 suspend_hold
75
=head3 suspend_hold
47
76
48
my $hold = $hold->suspend_hold( $suspend_until_dt );
77
my $hold = $hold->suspend_hold( $suspend_until_dt );
(-)a/Koha/Holds.pm (-2 / +14 lines)
Lines 39-52 Koha::Holds - Koha Hold object set class Link Here
39
39
40
=head3 waiting
40
=head3 waiting
41
41
42
Returns a set of holds that are waiting from an existing set
42
returns a set of holds that are waiting from an existing set
43
43
44
=cut
44
=cut
45
45
46
sub waiting {
46
sub waiting {
47
    my ( $self ) = @_;
47
    my ( $self ) = @_;
48
48
49
    return $self->search( { found => 'W' } );
49
    return $self->search( { found => 'w' } );
50
}
51
52
=head3 unfilled
53
54
returns a set of holds that are unfilled from an existing set
55
56
=cut
57
58
sub unfilled {
59
    my ( $self ) = @_;
60
61
    return $self->search( { found => undef } );
50
}
62
}
51
63
52
=head3 forced_hold_level
64
=head3 forced_hold_level
(-)a/misc/cronjobs/holds/cancel_unfilled_holds.pl (+151 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
#
4
# This file is part of Koha.
5
#
6
# Koha is free software; you can redistribute it and/or modify it
7
# under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 3 of the License, or
9
# (at your option) any later version.
10
#
11
# Koha is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with Koha; if not, see <http://www.gnu.org/licenses>.
18
19
use Modern::Perl;
20
21
BEGIN {
22
    # find Koha's Perl modules
23
    # test carefully before changing this
24
    use FindBin;
25
    eval { require "$FindBin::Bin/../kohalib.pl" };
26
}
27
28
use Getopt::Long;
29
use Pod::Usage;
30
31
use C4::Reserves;
32
use C4::Log;
33
use Koha::Holds;
34
use Koha::Calendar;
35
use Koha::DateUtils;
36
use Koha::Libraries;
37
38
cronlogaction();
39
40
=head1 NAME
41
42
cancel_waiting_holds.pl
43
44
=head1 SYNOPSIS
45
46
cancel_waiting_holds.pl
47
    [-days][-library][-holidays]
48
49
 Options:
50
    -help                       brief help
51
    -days                       cancel holds waiting this many days
52
    -library                    [repeatable] limit to specified branch(es)
53
    -holidays                   skip holidays when calculating days waiting
54
    -v                          verbose
55
56
head1 OPTIONS
57
58
=over 8
59
60
=item B<-help>
61
62
Print brief help and exit.
63
64
=item B<-man>
65
66
Print full documentation and exit.
67
68
=item B<-days>
69
70
Specify the number of days waiting upon which to cancel holds.
71
72
=item B<-library>
73
74
Repeatable option to specify which branchcode(s) to cancel holds for.
75
76
=item B<-holidays>
77
78
This switch specifies whether to count holidays as days waiting. Default is no.
79
80
=back
81
82
=cut
83
84
my $help = 0;
85
my $days;
86
my @branchcodes;
87
my $use_calendar = 0;
88
my $verbose      = 0;
89
my $confirm      = 0;
90
91
GetOptions(
92
    'help|?'    => \$help,
93
    'days=s'    => \$days,
94
    'library=s' => \@branchcodes,
95
    'holidays'  => \$use_calendar,
96
    'v'         => \$verbose,
97
    'confirm'   => \$confirm,
98
) or pod2usage(1);
99
pod2usage(1) if $help;
100
101
unless ( defined $days ) {
102
    pod2usage(
103
        {
104
            -exitval => 1,
105
            -msg =>
106
qq{\nError: You must specify a value for days waiting to cancel holds.\n},
107
        }
108
    );
109
}
110
warn "Running in test mode, no actions will be taken" unless ($confirm);
111
112
$verbose and warn "Looking for unfilled holds placed $days or more days ago\n";
113
114
unless ( scalar @branchcodes > 0 ) {
115
    my $branches = Koha::Libraries->search->get_column('branchcode');
116
    while ( my $branch = $branches->next ) {
117
        push @branchcodes, $branch->branchcode;
118
    }
119
}
120
$verbose and warn "Running for branch(es): " . join( "|", @branchcodes ) . "\n";
121
122
foreach my $branch (@branchcodes) {
123
124
    my $holds =
125
      Koha::Holds->search( { branchcode => $branch } )->unfilled();
126
127
    while ( my $hold = $holds->next ) {
128
129
        my $age = $hold->age( $use_calendar );
130
131
        $verbose
132
          and warn "Hold #"
133
          . $hold->reserve_id
134
          . " has been unfilled for $age day(s)\n";
135
136
        if ( $age >= $days ) {
137
            my $action = $confirm ? "Cancelling " : "Would have cancelled ";
138
            $verbose
139
              and warn $action
140
              . "reserve_id: "
141
              . $hold->reserve_id
142
              . " for borrower: "
143
              . $hold->borrowernumber
144
              . " on biblio: "
145
              . $hold->biblionumber . "\n";
146
            CancelReserve( { reserve_id => $hold->reserve_id } ) if $confirm;
147
        }
148
149
    }
150
151
}
(-)a/t/db_dependent/Hold.t (-1 / +9 lines)
Lines 22-34 use C4::Context; Link Here
22
use C4::Biblio qw( AddBiblio );
22
use C4::Biblio qw( AddBiblio );
23
use Koha::Database;
23
use Koha::Database;
24
use Koha::Libraries;
24
use Koha::Libraries;
25
use C4::Calendar;
25
use Koha::Patrons;
26
use Koha::Patrons;
26
use Koha::Holds;
27
use Koha::Holds;
27
use Koha::Item;
28
use Koha::Item;
28
use Koha::DateUtils;
29
use Koha::DateUtils;
29
use t::lib::TestBuilder;
30
use t::lib::TestBuilder;
30
31
31
use Test::More tests => 33;
32
use Test::More tests => 35;
32
use Test::Warn;
33
use Test::Warn;
33
34
34
use_ok('Koha::Hold');
35
use_ok('Koha::Hold');
Lines 66-71 my $hold = Koha::Hold->new( Link Here
66
    {
67
    {
67
        biblionumber   => $biblionumber,
68
        biblionumber   => $biblionumber,
68
        itemnumber     => $item->id(),
69
        itemnumber     => $item->id(),
70
        reservedate    => '2017-01-01',
69
        waitingdate    => '2000-01-01',
71
        waitingdate    => '2000-01-01',
70
        borrowernumber => $borrower->{borrowernumber},
72
        borrowernumber => $borrower->{borrowernumber},
71
        branchcode     => $branches[1]->{branchcode},
73
        branchcode     => $branches[1]->{branchcode},
Lines 74-79 my $hold = Koha::Hold->new( Link Here
74
);
76
);
75
$hold->store();
77
$hold->store();
76
78
79
my $b1_cal = C4::Calendar->new( branchcode => $branches[1]->{branchcode} );
80
$b1_cal->insert_single_holiday( day => 02, month => 01, year => 2017, title => "Morty Day", description => "Rick" ); #Add a holiday
81
my $today = DateTime->now(time_zone => C4::Context->tz );
82
is( $hold->age(), $today->delta_days( dt_from_string( '2017-01-01' ) )->in_units( 'days')  , "Age of hold is days from reservedate to now if calendar ignored");
83
is( $hold->age(1), $today->delta_days( dt_from_string( '2017-01-01' ) )->in_units( 'days' ) - 1 , "Age of hold is days from reservedate to now minus 1 if calendar used");
84
77
is( $hold->suspend, 0, "Hold is not suspended" );
85
is( $hold->suspend, 0, "Hold is not suspended" );
78
$hold->suspend_hold();
86
$hold->suspend_hold();
79
is( $hold->suspend, 1, "Hold is suspended" );
87
is( $hold->suspend, 1, "Hold is suspended" );
(-)a/t/db_dependent/Holds.t (-2 / +2 lines)
Lines 7-13 use t::lib::TestBuilder; Link Here
7
7
8
use C4::Context;
8
use C4::Context;
9
9
10
use Test::More tests => 61;
10
use Test::More tests => 62;
11
use MARC::Record;
11
use MARC::Record;
12
use C4::Biblio;
12
use C4::Biblio;
13
use C4::Items;
13
use C4::Items;
Lines 114-119 ok( $hold_branch == $hold->branch(), "branch method returns stashed branch" ); Link Here
114
my $hold_found = $hold->found();
114
my $hold_found = $hold->found();
115
$hold->set({ found => 'W'})->store();
115
$hold->set({ found => 'W'})->store();
116
is( Koha::Holds->waiting()->count(), 1, "Koha::Holds->waiting returns waiting holds" );
116
is( Koha::Holds->waiting()->count(), 1, "Koha::Holds->waiting returns waiting holds" );
117
is( Koha::Holds->unfilled()->count(), 4, "Koha::Holds->unfilled returns unfilled holds" );
117
118
118
my ( $reserve ) = GetReservesFromBorrowernumber($borrowernumbers[0]);
119
my ( $reserve ) = GetReservesFromBorrowernumber($borrowernumbers[0]);
119
ok( $reserve->{'borrowernumber'} eq $borrowernumbers[0], "Test GetReservesFromBorrowernumber()");
120
ok( $reserve->{'borrowernumber'} eq $borrowernumbers[0], "Test GetReservesFromBorrowernumber()");
120
- 

Return to bug 16187