1 # ---------------------------------------------------------------
2 # Copyright (C) 2005 Georgia Public Library Service
3 # Bill Erickson <highfalutin@gmail.com>
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 # ---------------------------------------------------------------
17 package OpenILS::Application::Circ::Holds;
18 use base qw/OpenSRF::Application/;
19 use strict; use warnings;
20 use OpenILS::Application::AppUtils;
21 my $apputils = "OpenILS::Application::AppUtils";
27 __PACKAGE__->register_method(
28 method => "create_hold",
29 api_name => "open-ils.circ.holds.create",
31 Create a new hold for an item. From a permissions perspective,
32 the login session is used as the 'requestor' of the hold.
33 The hold recipient is determined by the 'usr' setting within
36 First we verify the requestion has holds request permissions.
37 Then we verify that the recipient is allowed to make the given hold.
38 If not, we see if the requestor has "override" capabilities. If not,
39 a permission exception is returned. If permissions allow, we cycle
40 through the set of holds objects and create.
42 If the recipient does not have permission to place multiple holds
43 on a single title and said operation is attempted, a permission
48 my( $self, $client, $login_session, @holds) = @_;
50 if(!@holds){return 0;}
51 my $user = $apputils->check_user_session($login_session);
55 if(ref($holds[0]) eq 'ARRAY') {
57 } else { $holds = [ @holds ]; }
59 warn "Iterating over holds requests...\n";
61 for my $hold (@$holds) {
64 my $type = $hold->hold_type;
67 warn "Hold to create: " . Dumper($hold) . "\n";
70 if($user->id ne $hold->usr) {
76 #enforce the fact that the login is the one requesting the hold
77 $hold->requestor($user->id);
81 # see if the requestor even has permission to request
82 if($hold->requestor ne $hold->usr) {
83 $perm = _check_request_holds_perm($type, $user->id, $user->home_ou);
84 if($perm) { return $perm; }
87 $perm = _check_holds_perm($type, $hold->usr, $recipient->home_ou);
89 #if there is a requestor, see if the requestor has override privelages
90 if($hold->requestor ne $hold->usr) {
91 $perm = _check_request_holds_override($user->id, $user->home_ou);
92 if($perm) {return $perm;}
99 #my $session = $apputils->start_db_session();
100 my $session = OpenSRF::AppSession->create("open-ils.storage");
101 my $method = "open-ils.storage.direct.action.hold_request.create";
102 warn "Sending hold request to storage... $method \n";
104 my $req = $session->request( $method, $hold );
106 my $resp = $req->gather(1);
107 $session->disconnect();
108 if(!$resp) { return OpenILS::EX->new("UNKNOWN")->ex(); }
109 # $apputils->commit_db_session($session);
115 # makes sure that a user has permission to place the type of requested hold
116 # returns the Perm exception if not allowed, returns undef if all is well
117 sub _check_holds_perm {
118 my($type, $user_id, $org_id) = @_;
121 if($apputils->check_user_perms($user_id, $org_id, "MR_HOLDS")) {
122 return OpenILS::Perm->new("MR_HOLDS");
125 } elsif ($type eq "T") {
126 if($apputils->check_user_perms($user_id, $org_id, "TITLE_HOLDS")) {
127 return OpenILS::Perm->new("TITLE_HOLDS");
130 } elsif($type eq "V") {
131 if($apputils->check_user_perms($user_id, $org_id, "VOLUME_HOLDS")) {
132 return OpenILS::Perm->new("VOLUME_HOLDS");
135 } elsif($type eq "C") {
136 if($apputils->check_user_perms($user_id, $org_id, "COPY_HOLDS")) {
137 return OpenILS::Perm->new("COPY_HOLDS");
144 # tests if the given user is allowed to place holds on another's behalf
145 sub _check_request_holds_perm {
148 if($apputils->check_user_perms($user_id, $org_id, "REQUEST_HOLDS")) {
149 return OpenILS::Perm->new("REQUEST_HOLDS");
153 sub _check_request_holds_override {
156 if($apputils->check_user_perms($user_id, $org_id, "REQUEST_HOLDS_OVERRIDE")) {
157 return OpenILS::Perm->new("REQUEST_HOLDS_OVERRIDE");
162 __PACKAGE__->register_method(
163 method => "retrieve_holds",
164 api_name => "open-ils.circ.holds.retrieve",
166 Retrieves all the holds for the specified user id. The login session
167 is the requestor and if the requestor is different from the user, then
168 the requestor must have VIEW_HOLDS permissions.
173 my($self, $client, $login_session, $user_id) = @_;
175 my $user = $apputils->check_user_session($login_session);
177 if($user->id ne $user_id) {
178 if($apputils->check_user_perms($user->id, $user->home_ou, "VIEW_HOLDS")) {
179 return OpenILS::Perm->new("VIEW_HOLDS");
183 my $session = OpenSRF::AppSession->create("open-ils.storage");
184 my $req = $session->request(
185 "open-ils.storage.direct.action.hold_request.search.atomic",
186 "usr" => $user_id , { order_by => "request_time" });
188 my $h = $req->gather(1);
189 $session->disconnect();
194 __PACKAGE__->register_method(
195 method => "cancel_hold",
196 api_name => "open-ils.circ.hold.cancel",
198 Cancels the specified hold. The login session
199 is the requestor and if the requestor is different from the usr field
200 on the hold, the requestor must have CANCEL_HOLDS permissions.
201 the hold may be either the hold object or the hold id
205 my($self, $client, $login_session, $hold) = @_;
207 my $user = $apputils->check_user_session($login_session);
209 my $session = OpenSRF::AppSession->create("open-ils.storage");
212 $hold = $session->request(
213 "open-ils.storage.direct.action.hold_request.retrieve", $hold)->gather(1);
216 if($user->id ne $hold->usr) {
217 if($apputils->check_user_perms($user->id, $user->home_ou, "CANCEL_HOLDS")) {
218 return OpenILS::Perm->new("CANCEL_HOLDS");
223 warn "Cancelling hold: " . Dumper($hold) . "\n";
225 my $req = $session->request(
226 "open-ils.storage.direct.action.hold_request.delete",
228 my $h = $req->gather(1);
230 warn "[$h] returned from hold_request delete\n";
231 $session->disconnect();
236 __PACKAGE__->register_method(
237 method => "update_hold",
238 api_name => "open-ils.circ.hold.update",
240 Updates the specified hold. The login session
241 is the requestor and if the requestor is different from the usr field
242 on the hold, the requestor must have UPDATE_HOLDS permissions.
246 my($self, $client, $login_session, $hold) = @_;
248 my $user = $apputils->check_user_session($login_session);
250 if($user->id ne $hold->usr) {
251 if($apputils->check_user_perms($user->id, $user->home_ou, "UPDATE_HOLDS")) {
252 return OpenILS::Perm->new("UPDATE_HOLDS");
257 warn "Updating hold: " . Dumper($hold) . "\n";
259 my $session = OpenSRF::AppSession->create("open-ils.storage");
260 my $req = $session->request(
261 "open-ils.storage.direct.action.hold_request.update", $hold );
262 my $h = $req->gather(1);
264 warn "[$h] returned from hold_request update\n";
265 $session->disconnect();
270 __PACKAGE__->register_method(
271 method => "retrieve_hold_status",
272 api_name => "open-ils.circ.hold.status.retrieve",
274 Calculates the current status of the hold.
275 the requestor must have VIEW_HOLDS permissions if the hold is for a user
276 other than the requestor.
277 Returns -1 on error (for now)
278 Returns 1 for 'waiting for copy to become available'
279 Returns 2 for 'waiting for copy capture'
280 Returns 3 for 'in transit'
281 Returns 4 for 'arrived'
284 sub retrieve_hold_status {
285 my($self, $client, $login_session, $hold_id) = @_;
287 my $user = $apputils->check_user_session($login_session);
289 my $session = OpenSRF::AppSession->create("open-ils.storage");
291 my $hold = $session->request(
292 "open-ils.storage.direct.action.hold_request.retrieve", $hold_id )->gather(1);
293 return -1 unless $hold; # should be an exception
296 if($user->id ne $hold->usr) {
297 if($apputils->check_user_perms($user->id, $user->home_ou, "VIEW_HOLDS")) {
298 return OpenILS::Perm->new("VIEW_HOLDS");
302 return 1 unless (defined($hold->current_copy));
304 #return 2 unless (defined($hold->capture_time));
306 my $copy = $session->request(
307 "open-ils.storage.direct.asset.copy.retrieve", $hold->current_copy )->gather(1);
308 return 1 unless $copy; # should be an exception
311 warn "Hold Copy in status check: " . Dumper($copy) . "\n\n";
313 return 4 if ($hold->capture_time and $copy->circ_lib eq $hold->pickup_lib);
315 my $transit = _fetch_hold_transit($session, $hold->id);
316 return 4 if(ref($transit) and defined($transit->dest_recv_time) );
318 return 3 if defined($hold->capture_time);
324 sub _fetch_hold_transit {
327 return $session->request(
328 "open-ils.storage.direct.action.hold_transit_copy.search.hold",
329 $holdid )->gather(1);