1 package Koha::StockRotationItem;
3 # Copyright PTFS Europe 2016
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
23 use DateTime::Duration;
25 use Koha::DateUtils qw/dt_from_string/;
26 use Koha::Item::Transfer;
28 use Koha::StockRotationStage;
31 use base qw(Koha::Object);
35 StockRotationItem - Koha StockRotationItem Object class
39 StockRotationItem class used primarily by stockrotation .pls and the stock
44 Standard Koha::Objects definitions, and additional methods.
57 return 'Stockrotationitem';
62 my $item = Koha::StockRotationItem->itemnumber;
64 Returns the item associated with the current stock rotation item.
70 my $rs = $self->_result->itemnumber;
71 return Koha::Item->_new_from_dbic( $rs );
76 my $stage = Koha::StockRotationItem->stage;
78 Returns the stage associated with the current stock rotation item.
84 my $rs = $self->_result->stage;
85 return Koha::StockRotationStage->_new_from_dbic( $rs );
88 =head3 needs_repatriating
90 1|0 = $item->needs_repatriating;
92 Return 1 if this item is currently not at the library it should be at
93 according to our stockrotation plan.
97 sub needs_repatriating {
99 my ( $item, $stage ) = ( $self->itemnumber, $self->stage );
100 if ( $self->itemnumber->get_transfer ) {
101 return 0; # We're in transit.
102 } elsif ( $item->holdingbranch ne $stage->branchcode_id
103 || $item->homebranch ne $stage->branchcode_id ) {
104 return 1; # We're not where we should be.
106 return 0; # We're at home.
110 =head3 needs_advancing
112 1|0 = $item->needs_advancing;
114 Return 1 if this item is ready to be moved on to the next stage in its rota.
118 sub needs_advancing {
120 return 0 if $self->itemnumber->get_transfer; # intransfer: don't advance.
121 return 1 if $self->fresh; # Just on rota: advance.
122 my $completed = $self->itemnumber->_result->branchtransfers->search(
123 { 'reason' => "StockrotationAdvance" },
124 { order_by => { -desc => 'datearrived' } }
126 # Do maths on whether we need to be moved on.
127 if ( $completed->count ) {
128 my $arrival = dt_from_string(
129 $completed->next->datearrived, 'iso'
131 my $duration = DateTime::Duration
132 ->new( days => $self->stage->duration );
133 if ( $arrival + $duration le dt_from_string() ) {
139 warn "We have no historical branch transfer for itemnumber " . $self->itemnumber->itemnumber . "; This should not have happened!";
145 1|0 = $sritem->repatriate
147 Put this item into branch transfer with 'StockrotationRepatriation' comment, so
148 that it may return to it's stage.branch to continue its rota as normal.
150 Note: Stockrotation falls outside of the normal branch transfer limits and so we
151 pass 'ignore_limits' in the call to request_transfer.
156 my ( $self, $msg ) = @_;
158 # Create the transfer.
160 $self->itemnumber->request_transfer(
162 to => $self->stage->branchcode,
163 reason => "StockrotationRepatriation",
170 # Ensure the homebranch is still in sync with the rota stage
171 $self->itemnumber->homebranch( $self->stage->branchcode_id )->store;
173 return defined($transfer) ? 1 : 0;
178 1|0 = $sritem->advance;
180 Put this item into branch transfer with 'StockrotationAdvance' comment, to
181 transfer it to the next stage in its rota.
183 If this is the last stage in the rota and this rota is cyclical, we return to
184 the first stage. If it is not cyclical, then we delete this
187 If this item is 'indemand', and advance is invoked, we disable 'indemand' and
188 advance the item as per usual.
190 Note: Stockrotation falls outside of the normal branch transfer limits and so we
191 pass 'ignore_limits' in the call to request_transfer.
197 my $item = $self->itemnumber;
198 my $current_branch = $item->holdingbranch;
201 # Find and interpret our stage
202 my $stage = $self->stage;
204 if ( $self->indemand && !$self->fresh ) {
205 $self->indemand(0)->store; # De-activate indemand
210 if ( $self->fresh ) {
211 $new_stage = $self->stage->first_sibling || $self->stage;
212 $self->fresh(0)->store; # Reset fresh
215 elsif ( !$stage->last_sibling ) {
217 if ( $stage->rota->cyclical ) {
219 $stage->first_sibling || $stage; # Revert to first stage.
222 $self->delete; # StockRotationItem is done.
227 $new_stage = $self->stage->next_sibling; # Just advance
231 # Update stage and record transfer
232 $self->stage_id( $new_stage->stage_id )->store; # Set new stage
233 $item->homebranch( $new_stage->branchcode_id )->store; # Update homebranch
235 $item->request_transfer(
237 to => $new_stage->branchcode,
238 reason => "StockrotationAdvance",
239 ignore_limits => 1 # Ignore transfer limits
244 if ( $_->isa('Koha::Exceptions::Item::Transfer::Found') ) {
246 my $found_transfer = $_->transfer;
247 if ( $found_transfer->in_transit
248 || $found_transfer->reason eq 'Reserve' )
250 return $item->request_transfer(
252 to => $new_stage->branchcode,
253 reason => "StockrotationAdvance",
259 return $item->request_transfer(
261 to => $new_stage->branchcode,
262 reason => "StockrotationAdvance",
266 ); # Replace transfer
273 if $item->holdingbranch eq $new_stage->branchcode_id; # Already at branch
280 my $report = $item->investigate;
282 Return the base set of information, namely this individual item's report, for
283 generating stockrotation reports about this stockrotationitem.
290 title => $self->itemnumber->_result->biblioitem
291 ->biblionumber->title,
292 author => $self->itemnumber->_result->biblioitem
293 ->biblionumber->author,
294 callnumber => $self->itemnumber->itemcallnumber,
295 location => $self->itemnumber->location,
296 onloan => $self->itemnumber->onloan,
297 barcode => $self->itemnumber->barcode,
298 itemnumber => $self->itemnumber_id,
299 branch => $self->itemnumber->_result->holdingbranch,
303 if ( $self->fresh ) {
304 $reason = 'initiation';
305 } elsif ( $self->needs_repatriating ) {
306 $reason = 'repatriation';
307 } elsif ( $self->needs_advancing ) {
308 $reason = 'advancement';
309 $reason = 'in-demand' if $self->indemand;
311 $reason = 'not-ready';
313 $item_report->{reason} = $reason;
322 Alex Sassmannshausen <alex.sassmannshausen@ptfs-europe.com>