3 # Copyright 2020 Aleisha Amohia <aleisha@catalyst.net.nz>
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>.
24 use Koha::DateUtils qw( dt_from_string );
26 use C4::Stats qw( UpdateStats );
28 use base qw(Koha::Objects);
32 Koha::Recalls - Koha Recalls Object set class
40 my ( $recall, $due_interval, $due_date ) = Koha::Recalls->add_recall({
41 patron => $patron_object,
42 biblio => $biblio_object,
43 branchcode => $branchcode,
45 expirationdate => $expirationdate,
49 Add a new requested recall. We assume at this point that a recall is allowed to be placed on this item or biblio. We are past the checks and are now doing the recall.
50 Interface param is either OPAC or INTRANET
51 Send a RETURN_RECALLED_ITEM notice.
52 Add statistics and logs.
53 #FIXME: Add recallnotes and priority when staff-side recalls is added
58 my ( $self, $params ) = @_;
60 my $patron = $params->{patron};
61 my $biblio = $params->{biblio};
62 return if ( !defined($patron) or !defined($biblio) );
63 my $branchcode = $params->{branchcode};
64 $branchcode ||= $patron->branchcode;
65 my $item = $params->{item};
66 my $itemnumber = $item ? $item->itemnumber : undef;
67 my $expirationdate = $params->{expirationdate};
68 my $interface = $params->{interface};
70 if ( $expirationdate ){
71 my $now = dt_from_string;
72 $expirationdate = dt_from_string($expirationdate)->set({ hour => $now->hour, minute => $now->minute, second => $now->second });
75 my $recall_request = Koha::Recall->new({
76 borrowernumber => $patron->borrowernumber,
77 recalldate => dt_from_string(),
78 biblionumber => $biblio->biblionumber,
79 branchcode => $branchcode,
80 status => 'requested',
81 itemnumber => defined $itemnumber ? $itemnumber : undef,
82 expirationdate => $expirationdate,
83 item_level_recall => defined $itemnumber ? 1 : 0,
86 if (defined $recall_request->recall_id){ # successful recall
87 my $recall = Koha::Recalls->find( $recall_request->recall_id );
89 # get checkout and adjust due date based on circulation rules
90 my $checkout = $recall->checkout;
91 my $recall_due_date_interval = Koha::CirculationRules->get_effective_rule({
92 categorycode => $checkout->patron->categorycode,
93 itemtype => $checkout->item->effective_itemtype,
94 branchcode => $branchcode,
95 rule_name => 'recall_due_date_interval',
97 my $due_interval = defined $recall_due_date_interval ? $recall_due_date_interval->rule_value : 5;
98 my $timestamp = dt_from_string( $recall->timestamp );
99 my $due_date = $timestamp->add( days => $due_interval );
100 $checkout->update({ date_due => $due_date });
102 # get itemnumber of most relevant checkout if a biblio-level recall
103 unless ( $recall->item_level_recall ) { $itemnumber = $checkout->itemnumber; }
105 # send notice to user with recalled item checked out
106 my $letter = C4::Letters::GetPreparedLetter (
107 module => 'circulation',
108 letter_code => 'RETURN_RECALLED_ITEM',
109 branchcode => $recall->branchcode,
111 biblio => $biblio->biblionumber,
112 borrowers => $checkout->borrowernumber,
113 items => $itemnumber,
114 issues => $itemnumber,
118 C4::Message->enqueue( $letter, $checkout->patron->unblessed, 'email' );
120 $item = Koha::Items->find( $itemnumber );
121 # add to statistics table
123 branch => C4::Context->userenv->{'branch'},
125 itemnumber => $itemnumber,
126 borrowernumber => $recall->borrowernumber,
127 itemtype => $item->effective_itemtype,
128 ccode => $item->ccode,
132 C4::Log::logaction( 'RECALLS', 'CREATE', $recall->recall_id, "Recall requested by borrower #" . $recall->borrowernumber, $interface ) if ( C4::Context->preference('RecallsLog') );
134 return ( $recall, $due_interval, $due_date );
137 # unable to add recall
143 my $message = Koha::Recalls->move_recall({
144 recall_id = $recall_id,
146 item => $item_object,
147 borrowernumber => $borrowernumber,
150 A patron is attempting to check out an item that has been recalled by another patron.
151 If the recall is requested/overdue, they have the option of cancelling the recall.
152 If the recall is waiting, they also have the option of reverting the waiting status.
154 We can also fulfill the recall here if the recall is placed by this borrower.
156 recall_id = ID of the recall to perform the action on
157 action = either cancel or revert
158 item = item object that the patron is attempting to check out
159 borrowernumber = borrowernumber of the patron that is attemptig to check out
164 my ( $self, $params ) = @_;
166 my $recall_id = $params->{recall_id};
167 my $action = $params->{action};
168 return 'no recall_id provided' if ( !defined $recall_id );
169 my $item = $params->{item};
170 my $borrowernumber = $params->{borrowernumber};
172 my $message = 'no action provided';
174 if ( $action and $action eq 'cancel' ) {
175 my $recall = Koha::Recalls->find( $recall_id );
176 $recall->set_cancelled;
177 $message = 'cancelled';
178 } elsif ( $action and $action eq 'revert' ) {
179 my $recall = Koha::Recalls->find( $recall_id );
180 $recall->revert_waiting;
181 $message = 'reverted';
184 if ( $message eq 'no action provided' and $item and $item->biblionumber and $borrowernumber ) {
185 # move_recall was not called to revert or cancel, but was called to fulfill
186 my $recall = Koha::Recalls->search(
188 borrowernumber => $borrowernumber,
189 biblionumber => $item->biblionumber,
190 itemnumber => [ $item->itemnumber, undef ],
193 { order_by => { -asc => 'recalldate' } }
196 $recall->set_fulfilled;
197 $message = 'fulfilled';
204 =head2 Internal methods
219 return 'Koha::Recall';