]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Circ/ScriptBuilder.pm
attempting to remove a big leak
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Circ / ScriptBuilder.pm
1 package OpenILS::Application::Circ::ScriptBuilder;
2 use strict; use warnings;
3 use OpenILS::Utils::ScriptRunner;
4 use OpenILS::Utils::CStoreEditor qw/:funcs/;
5 use OpenILS::Application::AppUtils;
6 use OpenILS::Application::Actor;
7 use OpenSRF::Utils::Logger qw/$logger/;
8 use Scalar::Util qw/weaken/;
9 my $U = "OpenILS::Application::AppUtils";
10 use Data::Dumper;
11
12 my $evt = "environment";
13 my @COPY_STATUSES;
14 my @COPY_LOCATIONS;
15 my %GROUP_SET;
16 my $GROUP_TREE;
17 my $ORG_TREE;
18 my @ORG_LIST;
19
20
21
22 # -----------------------------------------------------------------------
23 # Possible Args:
24 #  copy
25 #  copy_id
26 #  copy_barcode
27 #
28 #  patron
29 #  patron_id
30 #  patron_barcode
31 #
32 #  fetch_patron_circ_info - load info on items out, overdues, and fines.
33 #
34 #  _direct - this is a hash of key/value pairs to shove directly into the 
35 #  script runner.  Use this to cover data not covered by this module
36 # -----------------------------------------------------------------------
37 sub build {
38         my( $class, $args ) = @_;
39
40         my $evt;
41         my @evts;
42
43         my $editor = $$args{editor} || new_editor();
44
45         $args->{_direct} = {} unless $args->{_direct};
46         
47         $evt = fetch_bib_data($editor, $args);
48         push(@evts, $evt) if $evt;
49         $evt = fetch_user_data($editor, $args);
50         push(@evts, $evt) if $evt;
51
52         if(@evts) {
53                 my @e;
54                 push( @e, $_->{textcode} ) for @evts;
55                 $logger->info("script_builder: some events occurred: @e");
56                 $logger->debug("script_builder: some events occurred: " . Dumper(\@evts));
57                 $args->{_events} = \@evts;
58         }
59
60         return build_runner($editor, $args);
61 }
62
63
64 sub build_runner {
65         my $editor      = shift;
66         my $ctx         = shift;
67
68         my $runner = OpenILS::Utils::ScriptRunner->new;
69
70         my $gt = $GROUP_TREE;
71         weaken($gt); # just to be safe
72         $runner->insert( "$evt.groupTree",      $gt, 1);
73
74
75         $runner->insert( "$evt.patron",         $ctx->{patron}, 1);
76         $runner->insert( "$evt.copy",                   $ctx->{copy}, 1);
77         $runner->insert( "$evt.volume",         $ctx->{volume}, 1);
78         $runner->insert( "$evt.title",          $ctx->{title}, 1);
79         $runner->insert( "$evt.requestor",      $ctx->{requestor}, 1);
80         $runner->insert( "$evt.titleDescriptor", $ctx->{titleDescriptor}, 1);
81
82         $runner->insert( "$evt.patronItemsOut", $ctx->{patronItemsOut}, 1 );
83         $runner->insert( "$evt.patronOverdueCount", $ctx->{patronOverdue}, 1 );
84         $runner->insert( "$evt.patronFines", $ctx->{patronFines}, 1 );
85
86         $runner->insert("$evt.$_", $ctx->{_direct}->{$_}) for keys %{$ctx->{_direct}};
87
88         if(!$ORG_TREE) {
89                 $ORG_TREE = $editor->search_actor_org_unit(
90                         [
91                                 {"parent_ou" => undef },
92                                 {
93                                         flesh                           => 2,
94                                         flesh_fields    => { aou =>  ['children'] },
95                                         order_by                        => { aou => 'name'}
96                                 }
97                         ]
98                 )->[0];
99                 flatten_org_tree($ORG_TREE);
100         }
101         #insert_org_methods( $editor, $ctx );
102
103         $runner->insert( "$evt.orgList", $ORG_TREE, 1 );
104
105         $ctx->{runner} = $runner;
106
107         return $runner;
108 }
109
110 sub fetch_bib_data {
111         my $e = shift;
112         my $ctx = shift;
113
114         if(!$ctx->{copy}) {
115
116                 if($ctx->{copy_id}) {
117                         $ctx->{copy} = $e->retrieve_asset_copy($ctx->{copy_id})
118                                 or return $e->event;
119
120                 } elsif( $ctx->{copy_barcode} ) {
121
122                         my $cps = $e->search_asset_copy({barcode => $ctx->{copy_barcode}});
123                         return $e->event unless @$cps;
124                         $ctx->{copy} = $$cps[0];
125                 }
126         }
127
128         return undef unless my $copy = $ctx->{copy};
129
130         # --------------------------------------------------------------------
131         # Fetch/Cache the copy status and location objects
132         # --------------------------------------------------------------------
133         if(!@COPY_STATUSES) {
134                 my $s = $e->retrieve_all_config_copy_status();
135                 @COPY_STATUSES = @$s;
136                 $s = $e->retrieve_all_asset_copy_location();
137                 @COPY_LOCATIONS = @$s;
138         }
139
140         # Flesh the status and location
141         $copy->status( 
142                 grep { $_->id == $copy->status } @COPY_STATUSES ) 
143                 unless ref $copy->status;
144
145         $copy->location( 
146                 grep { $_->id == $copy->location } @COPY_LOCATIONS ) 
147                 unless ref $copy->location;
148
149         $copy->circ_lib( 
150                 $e->retrieve_actor_org_unit($copy->circ_lib)) 
151                 unless ref $copy->circ_lib;
152
153         $ctx->{volume} = $e->retrieve_asset_call_number(
154                 $ctx->{copy}->call_number) or return $e->event;
155
156         $ctx->{title} = $e->retrieve_biblio_record_entry(
157                 $ctx->{volume}->record) or return $e->event;
158
159         if(!$ctx->{titleDescriptor}) {
160                 $ctx->{titleDescriptor} = $e->search_metabib_record_descriptor( 
161                         { record => $ctx->{title}->id }) or return $e->event;
162
163                 $ctx->{titleDescriptor} = $ctx->{titleDescriptor}->[0];
164         }
165
166         #insert_copy_method();  
167
168         return undef;
169 }
170
171
172
173 sub fetch_user_data {
174         my( $e, $ctx ) = @_;
175         
176         if(!$ctx->{patron}) {
177
178                 if( $ctx->{patron_id} ) {
179                         $ctx->{patron} = $e->retrieve_actor_user($ctx->{patron_id});
180
181                 } elsif( $ctx->{patron_barcode} ) {
182
183                         my $card = $e->search_actor_card( 
184                                 { barcode => $ctx->{patron_barcode} } ) or return $e->event;
185
186                         $ctx->{patron} = $e->search_actor_user( 
187                                 { card => $card->[0]->id }) or return $e->event;
188                         $ctx->{patron} = $ctx->{patron}->[0];
189                 }
190         }
191
192         return undef unless my $patron = $ctx->{patron};
193
194         $patron->home_ou( 
195                 $e->retrieve_actor_org_unit($patron->home_ou) ) 
196                 unless ref $patron->home_ou;
197
198         $patron->home_ou->ou_type(
199                 $patron->home_ou->ou_type->id) 
200                 if ref $patron->home_ou->ou_type;
201
202         if(!%GROUP_SET) {
203                 $GROUP_TREE = $e->search_permission_grp_tree(
204                         [
205                                 { parent => undef }, 
206                                 { 
207                                         flesh => 100,
208                                         flesh_fields => { pgt => ['children'] }
209                                 } 
210                         ]
211                 )->[0];
212
213                 flatten_groups($GROUP_TREE);
214         }
215
216         $patron->profile( $GROUP_SET{$patron->profile} )
217                 unless ref $patron->profile;
218
219         $patron->card($e->retrieve_actor_card($patron->card));
220
221         $ctx->{requestor} = $ctx->{requestor} || $e->requestor;
222
223         # this could alter the requestor object within the editor..
224         #if( my $req = $ctx->{requestor} ) {
225         #       $req->home_ou( $e->retrieve_actor_org_unit($requestor->home_ou) );      
226         #       $req->ws_ou( $e->retrieve_actor_org_unit($requestor->ws_ou) );  
227         #}
228
229         if( $ctx->{fetch_patron_circ_info} ) {
230
231                 my $circ_counts = 
232                         OpenILS::Application::Actor::_checked_out(1, $e, $patron->id);
233
234                 $ctx->{patronOverdue} = $circ_counts->{overdue} || 0;
235                 $ctx->{patronItemsOut} = $ctx->{patronOverdue} + $circ_counts->{out};
236
237                 # Grab the fines
238                 my $fxacts = $e->search_money_open_billable_transaction_summary(
239                         { usr => $patron->id, balance_owed => { ">" => 0 } });
240
241                 my $fines = 0;
242                 $fines += $_->balance_owed for @$fxacts;
243                 $ctx->{patronFines} = $fines;
244
245                 $logger->debug("script_builder: patron fines determined to be $fines");
246                 $logger->debug("script_builder: patron overdue count is " . $ctx->{patronOverdue});
247         }
248
249         return undef;
250 }
251
252
253 sub flatten_groups {
254         my $tree = shift;
255         return undef unless $tree;
256         $GROUP_SET{$tree->id} = $tree;
257         if( $tree->children ) {
258                 flatten_groups($_) for @{$tree->children};
259         }
260 }
261
262 sub flatten_org_tree {
263         my $tree = shift;
264         return undef unless $tree;
265         push( @ORG_LIST, $tree );
266         if( $tree->children ) {
267                 flatten_org_tree($_) for @{$tree->children};
268         }
269 }
270
271
272
273 sub insert_org_methods {
274         my ( $editor, $ctx ) = @_;
275         my $runner = $ctx->{runner};
276
277         if(!$ORG_TREE) {
278                 $ORG_TREE = $editor->search_actor_org_unit(
279                         [
280                                 {"parent_ou" => undef },
281                                 {
282                                         flesh                           => 2,
283                                         flesh_fields    => { aou =>  ['children'] },
284                                         order_by                        => { aou => 'name'}
285                                 }
286                         ]
287                 )->[0];
288                 flatten_org_tree($ORG_TREE);
289         }
290
291         my $r = $runner;
292         weaken($r);
293
294         $runner->insert(__OILS_FUNC_isOrgDescendent  => 
295                 sub {
296                         my( $write_key, $sname, $id ) = @_;
297                         my ($parent)    = grep { $_->shortname eq $sname } @ORG_LIST;
298                         my ($child)             = grep { $_->id == $id } @ORG_LIST;
299                         my $val = is_org_descendent( $parent, $child );
300                         $r->insert($write_key, $val);
301                         return $val;
302                 }
303         );
304 }
305
306
307 sub is_org_descendent {
308         my( $parent, $child ) = @_;
309         return 0 unless $parent and $child;
310         do {
311                 return 1 if $parent->id == $child->id;
312         } while( ($child) = grep { $_->id == $child->parent_ou } @ORG_LIST );
313         return 0;
314 }
315
316
317
318 #       if( $ctx->{copy} ) {
319 #               
320 #               # allows a script to fetch a hold that is currently targeting the
321 #               # copy in question
322 #               $runner->insert_method( 'environment.copy', '__OILS_FUNC_fetch_hold', sub {
323 #                               my $key = shift;
324 #                               my $hold = $holdcode->fetch_related_holds($ctx->{copy}->id);
325 #                               $hold = undef unless $hold;
326 #                               $runner->insert( $key, $hold, 1 );
327 #                       }
328 #               );
329 #       }
330
331
332
333 1;