]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm
updated circ code to run with updated script runner
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Circ / Circulate.pm
1 package OpenILS::Application::Circ::Circulate;
2 use base 'OpenSRF::Application';
3 use strict; use warnings;
4 use OpenSRF::EX qw(:try);
5 use Data::Dumper;
6 use OpenSRF::Utils::Logger qw(:logger);
7 use OpenILS::Utils::ScriptRunner;
8 use OpenILS::Application::AppUtils;
9 use OpenILS::Application::Circ::Holds;
10 $Data::Dumper::Indent = 0;
11 my $apputils = "OpenILS::Application::AppUtils";
12 my $holdcode = "OpenILS::Application::Circ::Holds";
13
14 my %scripts;                    # - circulation script filenames
15 my $standings;                  # - cached patron standings
16 my $group_tree;         # - cached permission group tree
17 my $script_libs;                # - any additional script libraries
18 my $copy_statuses;      # - copy status objects
19 my $copy_locations;     # - shelving locations
20
21 my $cur_copy;
22 my $cur_patron;
23 my $cur_title;
24 my $cur_standings;
25
26 my %contexts;                   # - Script runner contexts
27
28 # ------------------------------------------------------------------------------
29 # Load the circ script from the config
30 # ------------------------------------------------------------------------------
31 sub initialize {
32
33         my $self = shift;
34         my $conf = OpenSRF::Utils::SettingsClient->new;
35         my @pfx = ( "apps", "open-ils.circ","app_settings", "scripts" );
36
37         my $p           = $conf->config_value(  @pfx, 'permission' );
38         my $d           = $conf->config_value(  @pfx, 'duration' );
39         my $f           = $conf->config_value(  @pfx, 'recurring_fines' );
40         my $m           = $conf->config_value(  @pfx, 'max_fines' );
41         my $pr  = $conf->config_value(  @pfx, 'permit_renew' );
42         my $ph  = $conf->config_value(  @pfx, 'permit_hold' );
43         my $lb  = $conf->config_value(  'apps', 'open-ils.circ', 'app_settings', 'script_path' );
44
45         $logger->error( "Missing circ script(s)" ) 
46                 unless( $p and $d and $f and $m and $pr and $ph );
47
48         $scripts{circ_permit}                   = $p;
49         $scripts{circ_duration}                 = $d;
50         $scripts{circ_recurring_fines}= $f;
51         $scripts{circ_max_fines}                = $m;
52         $scripts{circ_renew_permit}     = $pr;
53         $scripts{hold_permit}                   = $ph;
54
55         $lb = [ $lb ] unless ref($lb);
56         $script_libs = $lb;
57
58         $logger->debug("Loaded rules scripts for circ: " .
59                 "circ permit : $p, circ duration :$d , circ recurring fines : $f, " .
60                 "circ max fines : $m, circ renew permit : $pr, permit hold: $ph");
61 }
62
63
64 # ------------------------------------------------------------------------------
65 # Loads the necessary circ objects and pushes them into the script environment
66 # Returns ( $data, $evt ).  if $evt is defined, then an
67 # unexpedted event occurred and should be dealt with / returned to the caller
68 # ------------------------------------------------------------------------------
69 sub create_circ_env {
70         my %params = @_;
71
72         my $barcode                     = $params{barcode};
73         my $patron                      = $params{patron};
74         my $fetch_summary = $params{fetch_patron_circ_summary};
75         my $fetch_cstatus       = $params{fetch_copy_statuses};
76         my $fetch_clocs = $params{fetch_copy_locations};
77
78         my ( $copy, $title, $evt );
79
80         if(!$cur_standings) {
81                 $cur_standings = $apputils->fetch_patron_standings();
82                 $group_tree = $apputils->fetch_permission_group_tree();
83         }
84
85         my $cstatus             = $apputils->fetch_copy_statuses if( $fetch_cstatus and !$copy_statuses );
86         my $clocs               = $apputils->fetch_copy_locations if( $fetch_clocs and !$copy_locations);
87         my $summary             = $apputils->fetch_patron_circ_summary($patron->id) if $fetch_summary;
88
89         ( $copy, $evt ) = $apputils->fetch_copy_by_barcode( $barcode );
90         return ( undef, $evt ) if $evt;
91
92         ( $title, $evt ) = $apputils->fetch_record_by_copy( $copy->id );
93         return ( undef, $evt ) if $evt;
94
95         _doctor_circ_objects( $patron, $title, $copy, $summary, $cstatus, $clocs );
96
97         my $runner = _build_circ_script_runner( $patron, $title, $copy, $summary, $params{type} );
98
99         $cur_patron = $patron;
100         $cur_copy       = $copy;
101         $cur_title      = $title;
102
103         return { 
104                 runner                  => $runner, 
105                 title                           => $title, 
106                 patron                  => $patron, 
107                 copy                            => $copy, 
108                 circ_summary    => $summary, 
109         };
110 }
111
112
113 # ------------------------------------------------------------------------------
114 # Patches up circ objects to make them easier to use from within the script
115 # environment
116 # ------------------------------------------------------------------------------
117 sub _doctor_circ_objects {
118         my( $patron, $title, $copy, $summary, $cstatus, $clocs ) = @_;
119
120         # set the patron standing to the standing name
121         for my $s (@$cur_standings) {
122                 $patron->standing( $s->value ) if( $s->id eq $patron->standing);
123         }
124
125         # set the patron ptofile to the profile name
126         $patron->profile( _patron_get_profile( $patron, $group_tree ) );
127
128         # set the copy status to a status name
129         $copy->status( _get_copy_status_name( $copy, $cstatus ) );
130
131         # set the copy location to the location object
132         $copy->location( _get_copy_location( $copy, $clocs ) );
133
134 }
135
136 # recurse and find the patron profile name from the tree
137 # another option would be to grab the groups for the patron
138 # and cycle through those until the "profile" group has been found
139 sub _patron_get_profile { 
140         my( $patron, $group_tree ) = @_;
141         return $group_tree->name if ($group_tree->id eq $patron->profile);
142         for my $child (@{$group_tree->children}) {
143                 my $ret = _patron_get_profile( $patron, $child );
144                 return $ret if $ret;
145         }
146         return undef;
147 }
148
149 sub _get_copy_status_name {
150         my( $copy, $cstatus ) = @_;
151         for my $status (@$cstatus) {
152                 return $status->name if( $status->id eq $copy->status ) 
153         }
154         return undef;
155 }
156
157 sub _get_copy_location {
158         my( $copy, $locations ) = @_;
159         for my $loc (@$locations) {
160                 return $loc if $loc->id eq $copy->location;
161         }
162 }
163
164
165 # ------------------------------------------------------------------------------
166 # Constructs and shoves data into the script environment
167 # ------------------------------------------------------------------------------
168 sub _build_circ_script_runner {
169         my( $patron, $title, $copy, $summary, $type ) = @_;
170
171         $logger->debug("Loading script environment for circulation");
172
173         my $runner;
174         if( $runner = $contexts{$type} ) {
175                 $runner->refresh_context;
176         } else {
177                 $runner = OpenILS::Utils::ScriptRunner->new unless $runner;
178                 $contexts{$type} = $runner;
179         }
180
181         for(@$script_libs) {
182                 $logger->debug("Loading circ script lib path $_");
183                 $runner->add_path( $_ );
184         }
185
186         $runner->insert( 'patron',              $patron );
187         $runner->insert( 'title',               $title );
188         $runner->insert( 'copy',                $copy );
189
190         # circ script result
191         $runner->insert( 'result', {} );
192         $runner->insert( 'result.event', 'SUCCESS' );
193
194         if($summary) {
195                 $runner->insert( 'patron_info', {} );
196                 $runner->insert( 'patron_info.items_out', $summary->[0] );
197                 $runner->insert( 'patron_info.fines', $summary->[1] );
198         }
199
200         _add_script_runner_methods( $runner );
201         return $runner;
202 }
203
204 sub _add_script_runner_methods {
205         my $runner = shift;     
206
207         $runner->insert_method( 'copy', '__OILS_FUNC_fetch_hold', sub {
208                         my $key = shift;
209                         my $hold = $holdcode->fetch_open_hold_by_current_copy($cur_copy->id);
210                         $hold = undef unless $hold;
211                         $runner->insert( $key, $hold );
212                 }
213         );
214
215 #       $runner->insert_method( 'patron', '__OILS_FUNC_get_standing', sub {
216 #                       my $key = shift;
217 #                       my $standing = "";
218 #                       for my $s (@$cur_standings) {
219 #                               $standing = $s->value if ( $s->id eq $cur_patron->standing );
220 #                       }
221 #                       $runner->insert( $key, $standing );
222 #               }
223 #       );
224
225
226 }
227
228 =head blah
229 sub _insert_event {
230         my $runner = shift;
231         my $evt = shift;
232         $runner->insert('result.event', $evt->{textcode} );
233 }
234
235 sub _add_script_methods {
236         my $runner = shift;
237
238         $runner->insert( 'fetch_patron', sub {
239                         my ( $key, $id ) = @_;  
240                         my ( $user, $evt ) = $apputils->fetch_user($id);
241                         _insert_event( $runner, $evt ) if $evt;
242                         $runner->insert( $key, $user );
243                 }
244         );
245
246         $runner->insert( 'fetch_copy_by_barcode', sub {
247                         my( $key, $barcode ) = @_;
248                         my( $copy, $evt ) = $apputils->fetch_copy_by_barcode( $barcode );
249                         _insert_event( $runner, $evt ) if $evt;
250                         $runner->insert( $key, $copy );
251                 }
252         );
253
254         $runner->insert( 'fetch_copy_statuses', sub {
255                 my $key = shift;
256                 $runner->insert( $key, $apputils->fetch_copy_statuses ); 
257         });
258
259         $runner->insert( 'fetch_copy_locations', sub {
260                 my $key = shift;
261                 $runner->insert( $key, $apputils->fetch_copy_locations ); });
262
263         $runner->insert( 'fetch_patron_circ_summary', sub {
264                 my( $key, $patron_id ) = @_;
265                 $runner->insert( $key, $apputils->fetch_patron_circ_summary($patron_id)); });
266
267         $runner->insert( 'fetch_group_tree', sub { 
268                 my $key = shift;
269                 $runner->insert( $key, $apputils->fetch_permission_group_tree ); });
270
271         $runner->insert( 'fetch_patron_standings', sub { 
272                 my $key = shift;
273                 $runner->insert( $key, $apputils->fetch_patron_standings ); } );
274 }
275
276
277 sub _build_script_runner {
278         my %params = @_;
279
280         my $runner = OpenILS::Utils::ScriptRunner->new( 
281                 type => 'js', libs => $script_libs );
282         
283         # return status event
284         $runner->insert( 'result', {} );
285         $runner->insert( 'result.event', 'SUCCESS' );
286
287         $runner->insert('env.patron_id', $params{patron_id} ) if defined $params{patron_id};
288         $runner->insert('env.copy_barcode', $params{copy_barcode} ) if defined $params{copy_barcode};
289
290         $runner->insert( 'arr', [ 1, 5, 10 ] );
291
292
293         return $runner;
294 }
295
296 =cut
297
298
299 # ------------------------------------------------------------------------------
300
301 __PACKAGE__->register_method(
302         method  => "permit_circ",
303         api_name        => "open-ils.circ.permit_checkout_",
304         notes           => <<"  NOTES");
305                 Determines if the given checkout can occur
306                 PARAMS( authtoken, barcode => bc, patron => pid, renew => t/f )
307                 Returns an event
308         NOTES
309
310 sub permit_circ {
311         my( $self, $client, $authtoken, %params ) = @_;
312
313         my $barcode             = $params{barcode};
314         my $patronid    = $params{patron};
315         my $isrenew             = $params{renew};
316         my ( $requestor, $patron, $env, $evt );
317
318
319         # check permisson of the requestor
320         ( $requestor, $patron, $evt ) = 
321                 $apputils->checkses_requestor( 
322                 $authtoken, $patronid, 'VIEW_PERMIT_CHECKOUT' );
323         return $evt if $evt;
324
325         $logger->info("Checking circulation permission for staff: " . $requestor->id .
326                 ", patron " . $patron->id . ", and barcode $barcode" );
327
328         # fetch and build the circulation environment
329         ( $env, $evt ) = create_circ_env( 
330                 barcode                                                 => $barcode, 
331                 patron                                                  => $patron, 
332                 type                                                            => 'permit',
333                 fetch_patron_circ_summary       => 1,
334                 fetch_copy_statuses                     => 1, 
335                 fetch_copy_locations                    => 1, 
336                 );
337         return $evt if $evt;
338
339         # run the script
340         my $runner = $env->{runner};
341
342 #       my $runner = _build_script_runner( patron_id => $patronid, copy_barcode => $barcode );
343 #       _add_script_methods( $runner );
344
345         $runner->load($scripts{circ_permit});
346         $runner->run or throw OpenSRF::EX::ERROR ("Circ Permit Script Died: $@");
347
348         my $evtname = $runner->retrieve('result.event');
349         $logger->activity("Permit Circ for user $patronid and barcode $barcode returned event: $evtname");
350         return OpenILS::Event->new($evtname);
351 }
352
353
354 # ------------------------------------------------------------------------------
355
356 __PACKAGE__->register_method(
357         method  => "circulate",
358         api_name        => "open-ils.circ.checkout.barcode_",
359         notes           => <<"  NOTES");
360                 Checks out an item based on barcode
361                 PARAMS( authtoken, barcode => bc, patron => pid )
362         NOTES
363
364 sub circulate {
365         my( $self, $client, $authtoken, %params ) = @_;
366         my $barcode             = $params{barcode};
367         my $patronid    = $params{patron};
368 }
369
370
371 # ------------------------------------------------------------------------------
372
373 __PACKAGE__->register_method(
374         method  => "checkin",
375         api_name        => "open-ils.circ.checkin.barcode_",
376         notes           => <<"  NOTES");
377         PARAMS( authtoken, barcode => bc )
378         Checks in based on barcode
379         Returns an event object whose payload contains the record, circ, and copy
380         If the item needs to be routed, the event is a ROUTE_COPY event
381         with an additional 'route_to' variable set on the event
382         NOTES
383
384 sub checkin {
385         my( $self, $client, $authtoken, %params ) = @_;
386         my $barcode             = $params{barcode};
387 }
388
389 # ------------------------------------------------------------------------------
390
391 __PACKAGE__->register_method(
392         method  => "renew",
393         api_name        => "open-ils.circ.renew_",
394         notes           => <<"  NOTES");
395         PARAMS( authtoken, circ => circ_id );
396         open-ils.circ.renew(login_session, circ_object);
397         Renews the provided circulation.  login_session is the requestor of the
398         renewal and if the logged in user is not the same as circ->usr, then
399         the logged in user must have RENEW_CIRC permissions.
400         NOTES
401
402 sub renew {
403         my( $self, $client, $authtoken, %params ) = @_;
404         my $circ        = $params{circ};
405 }
406
407         
408
409
410 1;