Bug 25159: Implement diffs in action logs for holds
[koha.git] / Koha / ArticleRequest.pm
1 package Koha::ArticleRequest;
2
3 # Copyright ByWater Solutions 2015
4 #
5 # This file is part of Koha.
6 #
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.
11 #
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.
16 #
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>.
19
20 use Modern::Perl;
21
22 use Koha::Account::Lines;
23 use Koha::Database;
24 use Koha::Patrons;
25 use Koha::Biblios;
26 use Koha::Items;
27 use Koha::Libraries;
28 use Koha::DateUtils qw( dt_from_string );
29 use Koha::ArticleRequest::Status;
30 use Koha::Exceptions::ArticleRequest;
31
32 use base qw(Koha::Object);
33
34 =head1 NAME
35
36 Koha::ArticleRequest - Koha Article Request Object class
37
38 =head1 API
39
40 =head2 Class methods
41
42 =cut
43
44 =head3 request
45
46     $article_request->request;
47
48 Marks the article as requested. Send a notification if appropriate.
49
50 =cut
51
52 sub request {
53     my ($self) = @_;
54
55     Koha::Exceptions::ArticleRequest::LimitReached->throw(
56         error => 'Patron cannot request more articles for today'
57     ) unless $self->borrower->can_request_article;
58
59     $self->status(Koha::ArticleRequest::Status::Requested);
60
61     # Handle possible fees
62     my $debit = $self->borrower->add_article_request_fee_if_needed({ item_id => $self->itemnumber });
63     $self->debit_id( $debit->id )
64         if $debit;
65
66     $self->store();
67     $self->patron->update_lastseen('article');
68     $self->notify();
69     return $self;
70 }
71
72 =head3 set_pending
73
74     $article_request->set_pending;
75
76 Marks the article as pending. Send a notification if appropriate.
77
78 =cut
79
80 sub set_pending {
81     my ($self) = @_;
82
83     $self->status(Koha::ArticleRequest::Status::Pending);
84     $self->store();
85     $self->notify();
86     return $self;
87 }
88
89 =head3 process
90
91     $article_request->process;
92
93 Marks the article as in process. Send a notification if appropriate.
94
95 =cut
96
97 sub process {
98     my ($self) = @_;
99
100     $self->status(Koha::ArticleRequest::Status::Processing);
101     $self->store();
102     $self->notify();
103     return $self;
104 }
105
106 =head3 complete
107
108     $article_request->complete;
109
110 Marks the article as completed. Send a notification if appropriate.
111
112 =cut
113
114 sub complete {
115     my ($self) = @_;
116
117     $self->status(Koha::ArticleRequest::Status::Completed);
118     $self->store();
119     $self->notify();
120     return $self;
121 }
122
123 =head3 cancel
124
125     $article_request->cancel;
126
127 Marks the article as cancelled. Send a notification if appropriate.
128
129 =cut
130
131 sub cancel {
132     my ( $self, $params ) = @_;
133
134     my $cancellation_reason = $params->{cancellation_reason};
135     my $notes = $params->{notes};
136
137     $self->status(Koha::ArticleRequest::Status::Canceled);
138     $self->cancellation_reason($cancellation_reason) if $cancellation_reason;
139     $self->notes($notes) if $notes;
140     $self->store();
141     $self->notify();
142
143     my $debit = $self->debit;
144
145     if ( $debit ) {
146         # fees found, refund
147         my $account = $self->borrower->account;
148
149         my $total_reversible = $debit->debit_offsets->filter_by_reversible->total;
150         if ( $total_reversible ) {
151
152             $account->add_credit(
153                 {
154                     amount       => abs $total_reversible,
155                     interface    => C4::Context->interface,
156                     type         => 'REFUND',
157                 }
158             );
159         }
160
161         if ( $debit->amountoutstanding ) {
162             $debit->reduce({
163                 reduction_type => 'REFUND',
164                 amount         => $debit->amountoutstanding,
165                 interface      => C4::Context->interface,
166             })->discard_changes;
167         }
168     }
169
170     return $self;
171 }
172
173 =head3 biblio
174
175 Returns the Koha::Biblio object for this article request
176
177 =cut
178
179 sub biblio {
180     my ($self) = @_;
181
182     my $rs = $self->_result->biblionumber;
183     return unless $rs;
184     return Koha::Biblio->_new_from_dbic($rs);
185 }
186
187 =head3 debit
188
189     my $debit = $article_request->debit;
190
191 Returns the related Koha::Account::Line object for this article request
192
193 =cut
194
195 sub debit {
196     my ($self) = @_;
197
198     my $debit_rs = $self->_result->debit;
199     return unless $debit_rs;
200
201     return Koha::Account::Line->_new_from_dbic( $debit_rs );
202 }
203
204 =head3 item
205
206 Returns the Koha::Item object for this article request
207
208 =cut
209
210 sub item {
211     my ($self) = @_;
212     my $rs = $self->_result->itemnumber;
213     return unless $rs;
214     return Koha::Item->_new_from_dbic($rs);
215 }
216
217 =head3 borrower
218
219 Returns the Koha::Patron object for this article request
220
221 =cut
222
223 sub borrower {
224     my ($self) = @_;
225     my $rs = $self->_result->borrowernumber;
226     return unless $rs;
227     return Koha::Patron->_new_from_dbic($rs);
228 }
229
230 =head3 patron
231
232 Returns the Koha::Patron object for this article request
233
234 =cut
235
236 sub patron {
237     my ($self) = @_;
238     my $rs = $self->_result->borrowernumber;
239     return unless $rs;
240     return Koha::Patron->_new_from_dbic($rs);
241 }
242
243 =head3 branch
244
245 Returns the Koha::Library object for this article request
246
247 =cut
248
249 sub branch {
250     my ($self) = @_;
251     my $rs = $self->_result->branchcode;
252     return unless $rs;
253     return Koha::Library->_new_from_dbic($rs);
254 }
255
256 =head3 store
257
258 Override the default store behavior so that new opac requests
259 will have notifications sent.
260
261 =cut
262
263 sub store {
264     my ($self) = @_;
265
266     if ( !$self->in_storage ) {
267         $self->created_on( dt_from_string() );
268     }
269
270     return $self->SUPER::store;
271 }
272
273 =head2 Internal methods
274
275 =head3 notify
276
277     $self->notify();
278
279 internal method to be called when changing an article request status.
280 If a letter exists for the new status, it enqueues it.
281
282 =cut
283
284 sub notify {
285     my ($self) = @_;
286
287     my $status = $self->status;
288     my $reason = $self->notes;
289     if ( !defined $reason && $self->cancellation_reason ) {
290         my $av = Koha::AuthorisedValues->search(
291             {
292                 category            => 'AR_CANCELLATION',
293                 authorised_value    => $self->cancellation_reason
294             }
295         )->next;
296         $reason = $av->lib_opac ? $av->lib_opac : $av->lib if $av;
297     }
298
299     require C4::Letters;
300     if (
301         my $letter = C4::Letters::GetPreparedLetter(
302             module                 => 'circulation',
303             letter_code            => "AR_$status", # AR_REQUESTED, AR_PENDING, AR_PROCESSING, AR_COMPLETED, AR_CANCELED
304             message_transport_type => 'email',
305             lang                   => $self->borrower->lang,
306             tables                 => {
307                 article_requests => $self->id,
308                 borrowers        => $self->borrowernumber,
309                 biblio           => $self->biblionumber,
310                 biblioitems      => $self->biblionumber,
311                 items            => $self->itemnumber,
312                 branches         => $self->branchcode,
313             },
314             substitute => {
315                 reason => $reason,
316             },
317         )
318       )
319     {
320         C4::Letters::EnqueueLetter(
321             {
322                 letter                 => $letter,
323                 borrowernumber         => $self->borrowernumber,
324                 message_transport_type => 'email',
325             }
326         ) or warn "can't enqueue letter " . $letter->{code};
327     }
328 }
329
330 =head3 _type
331
332 =cut
333
334 sub _type {
335     return 'ArticleRequest';
336 }
337
338 =head1 AUTHOR
339
340 Kyle M Hall <kyle@bywatersolutions.com>
341
342 =cut
343
344 1;