1 package OpenILS::Application::AppUtils;
2 use strict; use warnings;
3 use base qw/OpenSRF::Application/;
4 use OpenSRF::Utils::Cache;
5 use OpenSRF::EX qw(:try);
7 use OpenSRF::Utils::Logger;
8 use OpenILS::Utils::ModsParser;
10 my $logger = "OpenSRF::Utils::Logger";
13 my $cache_client = "OpenSRF::Utils::Cache";
15 # ---------------------------------------------------------------------------
16 # Pile of utilty methods used accross applications.
17 # ---------------------------------------------------------------------------
20 # ---------------------------------------------------------------------------
21 # on sucess, returns the created session, on failure throws ERROR exception
22 # ---------------------------------------------------------------------------
23 sub start_db_session {
26 my $session = OpenSRF::AppSession->connect( "open-ils.storage" );
27 my $trans_req = $session->request( "open-ils.storage.transaction.begin" );
29 my $trans_resp = $trans_req->recv();
30 if(ref($trans_resp) and UNIVERSAL::isa($trans_resp,"Error")) { throw $trans_resp; }
31 if( ! $trans_resp->content() ) {
33 ("Unable to Begin Transaction with database" );
40 # returns undef if user has all of the perms provided
41 # returns the first failed perm on failure
42 sub check_user_perms {
43 my($self, $user_id, $org_id, @perm_types ) = @_;
45 $logger->debug("Checking perms with user : $user_id , org: $org_id, @perm_types");
47 throw OpenSRF::EX::ERROR ("Invalid call to check_user_perms()")
48 unless( defined($user_id) and defined($org_id) and @perm_types);
50 my $session = OpenSRF::AppSession->create("open-ils.storage");
51 for my $type (@perm_types) {
52 my $req = $session->request(
53 "open-ils.storage.permission.user_has_perm",
54 $user_id, $type, $org_id );
55 my $resp = $req->gather(1);
57 $session->disconnect();
62 $session->disconnect();
66 # checks the list of user perms. The first one that fails returns a new
67 # OpenILS::Perm object of that type. Returns undef if all perms are allowed
69 my( $self, $user_id, $org_id, @perm_types ) = @_;
70 my $t = $self->check_user_perms( $user_id, $org_id, @perm_types );
71 return OpenILS::Event->new('PERM_FAILURE', ilsperm => $t, ilspermloc => $org_id ) if $t;
77 # ---------------------------------------------------------------------------
78 # commits and destroys the session
79 # ---------------------------------------------------------------------------
80 sub commit_db_session {
81 my( $self, $session ) = @_;
83 my $req = $session->request( "open-ils.storage.transaction.commit" );
84 my $resp = $req->recv();
87 throw OpenSRF::EX::ERROR ("Unable to commit db session");
90 if(UNIVERSAL::isa($resp,"Error")) {
91 throw $resp ($resp->stringify);
95 throw OpenSRF::EX::ERROR ("Unable to commit db session");
99 $session->disconnect();
103 sub rollback_db_session {
104 my( $self, $session ) = @_;
106 my $req = $session->request("open-ils.storage.transaction.rollback");
107 my $resp = $req->recv();
108 if(UNIVERSAL::isa($resp,"Error")) { throw $resp; }
111 $session->disconnect();
116 # returns undef it the event is not an ILS event
117 # returns the event code otherwise
119 my( $self, $evt ) = @_;
120 return $evt->{ilsevent} if( ref($evt) eq 'HASH' and defined($evt->{ilsevent})) ;
124 # ---------------------------------------------------------------------------
125 # Checks to see if a user is logged in. Returns the user record on success,
126 # throws an exception on error.
127 # ---------------------------------------------------------------------------
128 sub check_user_session {
130 my( $self, $user_session ) = @_;
132 my $content = $self->simplereq(
134 'open-ils.auth.session.retrieve', $user_session );
137 if(! $content or $self->event_code($content)) {
138 throw OpenSRF::EX::ERROR
139 ("Session [$user_session] cannot be authenticated" );
142 $logger->debug("Fetch user session $user_session found user " . $content->id );
147 # generic simple request returning a scalar value
149 my($self, $service, $method, @params) = @_;
150 return $self->simple_scalar_request($service, $method, @params);
154 sub simple_scalar_request {
155 my($self, $service, $method, @params) = @_;
157 my $session = OpenSRF::AppSession->create( $service );
158 my $request = $session->request( $method, @params );
159 my $response = $request->recv(30);
161 $request->wait_complete;
163 if(!$request->complete) {
164 throw OpenSRF::EX::ERROR ("Call to $service for method $method with params @params" .
165 "\n did not complete successfully");
169 warn "No response from $service for method $method with params @params";
172 if(UNIVERSAL::isa($response,"Error")) {
173 throw $response ("Call to $service for method $method with params @params" .
174 "\n failed with exception: " . $response->stringify );
180 $session->disconnect();
184 if($response) { $value = $response->content; }
185 else { $value = undef; }
196 my $org_typelist = undef;
197 my $org_typelist_hash = {};
202 if($tree) { return $tree; }
204 # see if it's in the cache
205 $tree = $cache_client->new()->get_cache('_orgtree');
206 if($tree) { return $tree; }
209 warn "Retrieving Org Tree\n";
210 $orglist = $self->simple_scalar_request(
212 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
215 if( ! $org_typelist ) {
216 warn "Retrieving org types\n";
217 $org_typelist = $self->simple_scalar_request(
219 "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
220 $self->build_org_type($org_typelist);
223 $tree = $self->build_org_tree($orglist,1);
224 $cache_client->new()->put_cache('_orgtree', $tree);
229 my $slimtree = undef;
230 sub get_slim_org_tree {
233 if($slimtree) { return $slimtree; }
235 # see if it's in the cache
236 $slimtree = $cache_client->new()->get_cache('slimorgtree');
237 if($slimtree) { return $slimtree; }
240 warn "Retrieving Org Tree\n";
241 $orglist = $self->simple_scalar_request(
243 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
246 $slimtree = $self->build_org_tree($orglist);
247 $cache_client->new->put_cache('slimorgtree', $slimtree);
254 my($self, $org_typelist) = @_;
255 for my $type (@$org_typelist) {
256 $org_typelist_hash->{$type->id()} = $type;
264 my( $self, $orglist, $add_types ) = @_;
266 return $orglist unless (
267 ref($orglist) and @$orglist > 1 );
270 $a->ou_type <=> $b->ou_type ||
271 $a->name cmp $b->name } @$orglist;
273 for my $org (@list) {
277 if(!ref($org->ou_type()) and $add_types) {
278 $org->ou_type( $org_typelist_hash->{$org->ou_type()});
281 next unless (defined($org->parent_ou));
283 my ($parent) = grep { $_->id == $org->parent_ou } @list;
285 $parent->children([]) unless defined($parent->children);
286 push( @{$parent->children}, $org );
294 my( $self, $userid ) = @_;
297 $logger->debug("Fetching user $userid from storage");
299 $user = $self->simplereq(
301 'open-ils.storage.direct.actor.user.retrieve', $userid );
304 $logger->info("User $userid not found in the db");
305 $evt = OpenILS::Event->new('USER_NOT_FOUND');
308 return ($user, $evt);
312 my( $self, $session ) = @_;
313 my $user; my $evt; my $e;
315 $logger->debug("Checking user session $session");
318 $user = $self->check_user_session($session);
319 } catch Error with { $e = 1; };
321 if( $e or !$user ) { $evt = OpenILS::Event->new('NO_SESSION'); }
322 return ( $user, $evt );
326 # verifiese the session and checks the permissions agains the
327 # session user and the user's home_ou as the org id
329 my( $self, $session, @perms ) = @_;
330 my $user; my $evt; my $e;
331 $logger->debug("Checking user session $session and perms @perms");
332 ($user, $evt) = $self->checkses($session);
333 return (undef, $evt) if $evt;
334 $evt = $self->check_perms($user->id, $user->home_ou, @perms);
335 return ($user, $evt) if $evt;
340 my( $self, $staffobj, $userid, @perms ) = @_;
342 $userid = $staffobj->id unless defined $userid;
344 $logger->debug("checkrequestor(): requestor => " . $staffobj->id . ", target => $userid");
346 if( $userid ne $staffobj->id ) {
347 ($user, $evt) = $self->fetch_user($userid);
348 return (undef, $evt) if $evt;
349 $evt = $self->check_perms( $staffobj->id, $user->home_ou, @perms );
355 return ($user, $evt);
358 sub checkses_requestor {
359 my( $self, $authtoken, $targetid, @perms ) = @_;
360 my( $requestor, $target, $evt );
362 ($requestor, $evt) = $self->checkses($authtoken);
363 return (undef, undef, $evt) if $evt;
365 ($target, $evt) = $self->checkrequestor( $requestor, $targetid, @perms );
366 return( $requestor, $target, $evt);
370 my( $self, $copyid ) = @_;
373 $logger->debug("Fetching copy $copyid from storage");
375 $copy = $self->simplereq(
377 'open-ils.storage.direct.asset.copy.retrieve', $copyid );
379 if(!$copy) { $evt = OpenILS::Event->new('COPY_NOT_FOUND'); }
381 return( $copy, $evt );
385 # retrieves a circ object by id
386 sub fetch_circulation {
387 my( $self, $circid ) = @_;
390 $logger->debug("Fetching circ $circid from storage");
392 $circ = $self->simplereq(
394 "open-ils.storage.direct.action.circulation.retrieve", $circid );
397 $evt = OpenILS::Event->new('CIRCULATION_NOT_FOUND', circid => $circid );
400 return ( $circ, $evt );
403 sub fetch_record_by_copy {
404 my( $self, $copyid ) = @_;
407 $logger->debug("Fetching record by copy $copyid from storage");
409 $record = $self->simplereq(
411 'open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy', $copyid );
414 $evt = OpenILS::Event->new('BIBLIO_RECORD_NOT_FOUND');
417 return ($record, $evt);
420 # turns a record object into an mvr (mods) object
422 my( $self, $record ) = @_;
423 my $u = OpenILS::Utils::ModsParser->new();
424 $u->start_mods_batch( $record->marc );
425 my $mods = $u->finish_mods_batch();
426 $mods->doc_id($record->id);
431 my( $self, $holdid ) = @_;
434 $logger->debug("Fetching hold $holdid from storage");
436 $hold = $self->simplereq(
438 'open-ils.storage.direct.action.hold_request.retrieve', $holdid);
440 $evt = OpenILS::Event->new('HOLD_NOT_FOUND', holdid => $holdid) unless $hold;
442 return ($hold, $evt);
446 sub fetch_hold_transit_by_hold {
447 my( $self, $holdid ) = @_;
448 my( $transit, $evt );
450 $logger->debug("Fetching transit by hold $holdid from storage");
452 $transit = $self->simplereq(
454 'open-ils.storage.direct.action.hold_transit_copy.search.hold', $holdid );
456 $evt = OpenILS::Event->new('TRANSIT_NOT_FOUND', holdid => $holdid) unless $transit;
458 return ($transit, $evt );
462 sub fetch_copy_by_barcode {
463 my( $self, $barcode ) = @_;
466 $logger->debug("Fetching copy by barcode $barcode from storage");
468 $copy = $self->simplereq( 'open-ils.storage',
469 'open-ils.storage.direct.asset.copy.search.barcode', $barcode );
471 $evt = OpenILS::Event->new('COPY_NOT_FOUND', barcode => $barcode) unless $copy;
473 return ($copy, $evt);
476 sub fetch_open_billable_transaction {
477 my( $self, $transid ) = @_;
478 my( $transaction, $evt );
480 $logger->debug("Fetching open billable transaction $transid from storage");
482 $transaction = $self->simplereq(
484 'open-ils.storage.direct.money.open_billable_transaction_summary.retrieve', $transid);
486 $evt = OpenILS::Event->new(
487 'TRANSACTION_NOT_FOUND', transid => $transid ) unless $transaction;
489 return ($transaction, $evt);
495 $buckets{'biblio'} = 'biblio_record_entry_bucket';
496 $buckets{'callnumber'} = 'call_number_bucket';
497 $buckets{'copy'} = 'copy_bucket';
498 $buckets{'user'} = 'user_bucket';
500 sub fetch_container {
501 my( $self, $id, $type ) = @_;
504 $logger->debug("Fetching container $id with type $type");
506 my $meth = $buckets{$type};
507 $bucket = $self->simplereq(
509 "open-ils.storage.direct.container.$meth.retrieve", $id );
511 $evt = OpenILS::Event->new(
512 'CONTAINER_NOT_FOUND', container => $id,
513 container_type => $type ) unless $bucket;
515 return ($bucket, $evt);
519 sub fetch_container_item {
520 my( $self, $id, $type ) = @_;
523 $logger->debug("Fetching container item $id with type $type");
525 my $meth = $buckets{$type} . "_item";
527 $bucket = $self->simplereq(
529 "open-ils.storage.direct.container.$meth.retrieve", $id );
531 $evt = OpenILS::Event->new(
532 'CONTAINER_ITEM_NOT_FOUND', itemid => $id,
533 container_type => $type ) unless $bucket;
535 return ($bucket, $evt);
539 sub fetch_patron_standings {
541 $logger->debug("Fetching patron standings");
542 return $self->simplereq(
544 'open-ils.storage.direct.config.standing.retrieve.all.atomic');
548 sub fetch_permission_group_tree {
550 $logger->debug("Fetching patron profiles");
551 return $self->simplereq(
553 'open-ils.actor.groups.tree.retrieve' );
557 sub fetch_patron_circ_summary {
558 my( $self, $userid ) = @_;
559 $logger->debug("Fetching patron summary for $userid");
560 my $summary = $self->simplereq(
562 "open-ils.storage.action.circulation.patron_summary", $userid );
566 $summary->[1] ||= 0.0;
573 sub fetch_copy_statuses {
575 $logger->debug("Fetching copy statuses");
576 return $self->simplereq(
578 'open-ils.storage.direct.config.copy_status.retrieve.all.atomic' );
581 sub fetch_copy_locations {
583 return $self->simplereq(
585 'open-ils.storage.direct.asset.copy_location.retrieve.all.atomic');
588 sub fetch_callnumber {
589 my( $self, $id ) = @_;
591 $logger->debug("Fetching callnumber $id");
593 my $cn = $self->simplereq(
595 'open-ils.storage.direct.asset.call_number.retrieve', $id );
596 $evt = OpenILS::Event->new( 'VOLUME_NOT_FOUND', id => $id ) unless $cn;
598 return ( $cn, $evt );
602 my( $self, $id ) = @_;
603 $logger->debug("Fetching org unit $id");
606 my $org = $self->simplereq(
608 'open-ils.storage.direct.actor.org_unit.retrieve', $id );
609 $evt = OpenILS::Event->new( 'ORG_UNIT_NOT_FOUND', id => $id ) unless $org;
615 my( $self, $type, $id ) = @_;
617 $logger->debug("Fetching $type stat cat: $id");
618 $cat = $self->simplereq(
620 "open-ils.storage.direct.$type.stat_cat.retrieve", $id );
621 $evt = OpenILS::Event->new( 'STAT_CAT_NOT_FOUND', id => $id ) unless $cat;
622 return ( $cat, $evt );
625 sub fetch_stat_cat_entry {
626 my( $self, $type, $id ) = @_;
628 $logger->debug("Fetching $type stat cat entry: $id");
629 $entry = $self->simplereq(
631 "open-ils.storage.direct.$type.stat_cat_entry.retrieve", $id );
632 $evt = OpenILS::Event->new( 'STAT_CAT_ENTRY_NOT_FOUND', id => $id ) unless $entry;
633 return ( $entry, $evt );
638 my( $self, $org_tree, $orgid ) = @_;
639 return $org_tree if ( $org_tree->id eq $orgid );
640 return undef unless ref($org_tree->children);
641 for my $c (@{$org_tree->children}) {
642 my $o = $self->find_org($c, $orgid);