Lines 46-56
This script converts holds to recalls when a record has a set minimum number of
Link Here
|
46 |
|
46 |
|
47 |
If a record is found to have the specified minimum number of holds, the script will find the oldest hold and convert it to a recall, as long as it would be a legal recall. |
47 |
If a record is found to have the specified minimum number of holds, the script will find the oldest hold and convert it to a recall, as long as it would be a legal recall. |
48 |
|
48 |
|
49 |
This script uses the ConvertedSelectedHoldsToRecalls system preference. |
49 |
This script uses the ConvertSelectedHoldsToRecalls system preference. |
50 |
|
50 |
|
51 |
When ConvertedSelectedHoldsToRecalls is set to 'oldest', this script will only convert the single oldest hold. Once converted, the script will move on to the next record, it will not continue to convert holds on this record. |
51 |
When ConvertSelectedHoldsToRecalls is set to 'oldest', this script will only convert the single oldest hold. Once converted, the script will move on to the next record, it will not continue to convert holds on this record. |
52 |
|
52 |
|
53 |
When ConvertedSelectedHoldsToRecalls is set to 'recallable', this script will convert reserves one-by-one, oldest first, until all recallable items have been recalled. |
53 |
When ConvertSelectedHoldsToRecalls is set to 'recallable', this script will convert reserves one-by-one, oldest first, until all recallable items have been recalled. |
54 |
|
54 |
|
55 |
Options: |
55 |
Options: |
56 |
-v verbose |
56 |
-v verbose |
Lines 76-121
my $min = 5;
Link Here
|
76 |
my $verbose; |
76 |
my $verbose; |
77 |
|
77 |
|
78 |
GetOptions( |
78 |
GetOptions( |
79 |
'min|m=i' => \$min, |
79 |
'min|m=i' => \$min, |
80 |
'verbose|v' => \$verbose |
80 |
'verbose|v' => \$verbose |
81 |
) or pod2usage(1); |
81 |
) or pod2usage(1); |
82 |
|
82 |
|
83 |
# get holds where there is more than $min holds on one biblio |
83 |
# get holds where there is more than $min holds on one biblio |
84 |
my @bib_holds = Koha::Holds->search({}, { |
84 |
my @bib_holds = Koha::Holds->search( |
85 |
select => [ |
85 |
{}, |
86 |
'biblionumber', |
86 |
{ |
87 |
{ count => 'biblionumber', -as => 'bibcount' } |
87 |
select => [ |
88 |
], |
88 |
'biblionumber', |
89 |
group_by => 'biblionumber', |
89 |
{ count => 'biblionumber', -as => 'bibcount' } |
90 |
having => { 'bibcount' => { '>=', $min } }, |
90 |
], |
91 |
})->as_list; |
91 |
group_by => 'biblionumber', |
|
|
92 |
having => { 'bibcount' => { '>=', $min } }, |
93 |
} |
94 |
)->as_list; |
92 |
|
95 |
|
93 |
my $count = 0; |
96 |
my $count = 0; |
94 |
foreach my $bib ( @bib_holds ) { |
97 |
foreach my $bib (@bib_holds) { |
95 |
$bib = $bib->unblessed; |
98 |
$bib = $bib->unblessed; |
|
|
99 |
|
96 |
# If there are $min or more holds on the same record, we can begin converting holds |
100 |
# If there are $min or more holds on the same record, we can begin converting holds |
97 |
if ( $bib->{bibcount} >= $min ) { |
101 |
if ( $bib->{bibcount} >= $min ) { |
98 |
|
102 |
|
99 |
# Get all holds on this biblio |
103 |
# Get all holds on this biblio |
100 |
my @holds = Koha::Holds->search({ biblionumber => $bib->{biblionumber}, found => undef }, { order_by => { -asc => 'reservedate' } })->as_list; |
104 |
my @holds = Koha::Holds->search( |
|
|
105 |
{ biblionumber => $bib->{biblionumber}, found => undef }, |
106 |
{ order_by => { -asc => 'reservedate' } } |
107 |
)->as_list; |
101 |
|
108 |
|
102 |
if ( C4::Context->preference('ConvertedSelectedHoldsToRecalls') eq 'oldest' ) { |
109 |
if ( C4::Context->preference('ConvertSelectedHoldsToRecalls') eq 'oldest' ) { |
103 |
|
110 |
|
104 |
my $hold_to_convert = $holds[0]; |
111 |
my $hold_to_convert = $holds[0]; |
105 |
my $itemnumber_to_allocate = can_convert( $hold_to_convert ); |
112 |
my $itemnumber_to_allocate = can_convert($hold_to_convert); |
106 |
if ( $itemnumber_to_allocate ) { |
113 |
if ($itemnumber_to_allocate) { |
107 |
my $item_to_allocate = Koha::Items->find( $itemnumber_to_allocate ); |
114 |
my $item_to_allocate = Koha::Items->find($itemnumber_to_allocate); |
108 |
do_convert( $hold_to_convert, $item_to_allocate ); |
115 |
do_convert( $hold_to_convert, $item_to_allocate ); |
109 |
report( $hold_to_convert, ++$count ); |
116 |
report( $hold_to_convert, ++$count ); |
110 |
} |
117 |
} |
111 |
|
118 |
|
112 |
} elsif ( C4::Context->preference('ConvertedSelectedHoldsToRecalls') eq 'recallable' ) { |
119 |
} elsif ( C4::Context->preference('ConvertSelectedHoldsToRecalls') eq 'recallable' ) { |
113 |
|
120 |
|
114 |
my $this_record_holds_converted = 0; |
121 |
my $this_record_holds_converted = 0; |
115 |
|
122 |
|
116 |
my @items = Koha::Items->search({ biblionumber => $bib->{biblionumber} })->as_list; |
123 |
my @items = Koha::Items->search( { biblionumber => $bib->{biblionumber} } )->as_list; |
117 |
foreach my $item ( @items ) { |
124 |
foreach my $item (@items) { |
118 |
my $hold_to_convert = $holds[ $this_record_holds_converted ]; |
125 |
my $hold_to_convert = $holds[$this_record_holds_converted]; |
119 |
|
126 |
|
120 |
if ( !$hold_to_convert ) { |
127 |
if ( !$hold_to_convert ) { |
121 |
last; |
128 |
last; |
Lines 123-130
foreach my $bib ( @bib_holds ) {
Link Here
|
123 |
|
130 |
|
124 |
my $itemnumber_to_allocate = can_convert( $hold_to_convert, $item ); |
131 |
my $itemnumber_to_allocate = can_convert( $hold_to_convert, $item ); |
125 |
|
132 |
|
126 |
if ( $itemnumber_to_allocate ) { |
133 |
if ($itemnumber_to_allocate) { |
127 |
my $item_to_allocate = $itemnumber_to_allocate == $item->id ? $item : Koha::Items->find( $itemnumber_to_allocate ); |
134 |
my $item_to_allocate = |
|
|
135 |
$itemnumber_to_allocate == $item->id ? $item : Koha::Items->find($itemnumber_to_allocate); |
128 |
do_convert( $hold_to_convert, $item_to_allocate ); |
136 |
do_convert( $hold_to_convert, $item_to_allocate ); |
129 |
report( $hold_to_convert, ++$count ); |
137 |
report( $hold_to_convert, ++$count ); |
130 |
$this_record_holds_converted++; |
138 |
$this_record_holds_converted++; |
Lines 144-175
sub can_convert {
Link Here
|
144 |
if ( $hold->item_level_hold ) { |
152 |
if ( $hold->item_level_hold ) { |
145 |
|
153 |
|
146 |
if ( $item and $item->id == $hold->itemnumber ) { |
154 |
if ( $item and $item->id == $hold->itemnumber ) { |
|
|
155 |
|
147 |
# item-level reserve, on this specific item |
156 |
# item-level reserve, on this specific item |
148 |
if ( $item->can_be_recalled({ patron => $patron, hold_convert => 1 }) ) { |
157 |
if ( $item->can_be_recalled( { patron => $patron, hold_convert => 1 } ) ) { |
149 |
return $item->id; |
158 |
return $item->id; |
150 |
} |
159 |
} |
151 |
} else { |
160 |
} else { |
|
|
161 |
|
152 |
# item-level reserve but not on this item |
162 |
# item-level reserve but not on this item |
153 |
# so check if intended item can be allocated for the recall |
163 |
# so check if intended item can be allocated for the recall |
154 |
$item = Koha::Items->find( $hold->itemnumber ); |
164 |
$item = Koha::Items->find( $hold->itemnumber ); |
155 |
if ( $item and $item->can_be_recalled({ patron => $patron, hold_convert => 1 }) ) { |
165 |
if ( $item and $item->can_be_recalled( { patron => $patron, hold_convert => 1 } ) ) { |
156 |
return $item->id; |
166 |
return $item->id; |
157 |
} |
167 |
} |
158 |
} |
168 |
} |
159 |
|
169 |
|
160 |
} else { |
170 |
} else { |
|
|
171 |
|
161 |
# bib-level reserve |
172 |
# bib-level reserve |
162 |
|
173 |
|
163 |
if ( $item and $item->can_be_recalled({ patron => $patron, hold_convert => 1 }) and Koha::Recalls->filter_by_current->search({ item_id => $item->id })->count < 1 ) { |
174 |
if ( C4::Context->preference('ConvertSelectedHoldsToRecalls') eq 'oldest' ) { |
164 |
# this item may be able to fill the recall |
175 |
if ( $item |
165 |
return $item->id; |
176 |
and $item->can_be_recalled( { patron => $patron, hold_convert => 1 } ) |
|
|
177 |
and Koha::Recalls->filter_by_current->search( { item_id => $item->id } )->count < 1 ) |
178 |
{ |
179 |
# this item may be able to fill the recall |
180 |
return $item->id; |
181 |
} |
166 |
} |
182 |
} |
167 |
|
183 |
|
168 |
# don't have a specific item to allocate for this recall |
184 |
# don't have a specific item to allocate for this recall |
169 |
# so get an eligible item that's not already recalled |
185 |
# so get an eligible item that's not already recalled |
170 |
foreach my $i ( $biblio->items->as_list ) { |
186 |
foreach my $i ( $biblio->items->as_list ) { |
171 |
if ( Koha::Recalls->filter_by_current->search({ item_id => $i->id })->count < 1 ) { |
187 |
if ( Koha::Recalls->filter_by_current->search( { item_id => $i->id } )->count < 1 ) { |
172 |
if ( $i and $i->can_be_recalled({ patron => $patron, hold_convert => 1 }) ) { |
188 |
if ( $i and $i->can_be_recalled( { patron => $patron, hold_convert => 1 } ) ) { |
173 |
return $i->id; |
189 |
return $i->id; |
174 |
} |
190 |
} |
175 |
} |
191 |
} |
Lines 189-211
sub do_convert {
Link Here
|
189 |
my $patron = Koha::Patrons->find( $hold->borrowernumber ); |
205 |
my $patron = Koha::Patrons->find( $hold->borrowernumber ); |
190 |
my $biblio = Koha::Biblios->find( $hold->biblionumber ); |
206 |
my $biblio = Koha::Biblios->find( $hold->biblionumber ); |
191 |
|
207 |
|
192 |
my ( $recall, $due_interval, $due_date ) = Koha::Recalls->add_recall({ |
208 |
my ( $recall, $due_interval, $due_date ) = Koha::Recalls->add_recall( |
193 |
patron => $patron, |
209 |
{ |
194 |
biblio => $biblio, |
210 |
patron => $patron, |
195 |
branchcode => $hold->branchcode, |
211 |
biblio => $biblio, |
196 |
item => $item, |
212 |
branchcode => $hold->branchcode, |
197 |
expirationdate => $hold->patron_expiration_date ? $hold->patron_expiration_date : $hold->expirationdate, |
213 |
item => $item, |
198 |
interface => 'commandline', |
214 |
expirationdate => $hold->patron_expiration_date ? $hold->patron_expiration_date : $hold->expirationdate, |
199 |
}); |
215 |
interface => 'commandline', |
200 |
$hold->cancel({ cancellation_reason => 'RECALLED' }); |
216 |
} |
|
|
217 |
); |
218 |
$hold->cancel( { cancellation_reason => 'RECALLED' } ); |
201 |
} |
219 |
} |
202 |
|
220 |
|
203 |
sub report { |
221 |
sub report { |
204 |
my $hold = shift; |
222 |
my $hold = shift; |
205 |
my $count = shift; |
223 |
my $count = shift; |
206 |
|
224 |
|
207 |
if ( $verbose ) { |
225 |
if ($verbose) { |
208 |
my $hold_id = $hold->reserve_id; |
226 |
my $hold_id = $hold->reserve_id; |
209 |
my $biblionumber = $hold->biblionumber; |
227 |
my $biblionumber = $hold->biblionumber; |
210 |
print "$count. Hold converted to recall (reserve_id: $hold_id, biblionumber: $biblionumber).\n"; |
228 |
print "$count. Hold converted to recall (reserve_id: $hold_id, biblionumber: $biblionumber).\n"; |
211 |
} |
229 |
} |
212 |
- |
|
|