]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm
c88ec73c8753023c331a8f7d718e6cdd664f5c5e
[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 my $apputils = "OpenILS::Application::AppUtils";
11 my $holdcode = "OpenILS::Application::Circ::Holds";
12
13 my %scripts;                    # - circulation script filenames
14 my $standings;                  # - cached patron standings
15 my $group_tree;         # - cached permission group tree
16 my $script_libs;                # - any additional script libraries
17 my $copy_statuses;      # - copy status objects
18 my $copy_locations;     # - shelving locations
19
20 # ------------------------------------------------------------------------------
21 # Load the circ script from the config
22 # ------------------------------------------------------------------------------
23 sub initialize {
24
25         my $self = shift;
26         my $conf = OpenSRF::Utils::SettingsClient->new;
27         my @pfx = ( "apps", "open-ils.circ","app_settings", "scripts" );
28
29         my $p           = $conf->config_value(  @pfx, 'permission' );
30         my $d           = $conf->config_value(  @pfx, 'duration' );
31         my $f           = $conf->config_value(  @pfx, 'recurring_fines' );
32         my $m           = $conf->config_value(  @pfx, 'max_fines' );
33         my $pr  = $conf->config_value(  @pfx, 'permit_renew' );
34         my $ph  = $conf->config_value(  @pfx, 'permit_hold' );
35         my $lb  = $conf->config_value(  @pfx, 'script_lib' );
36
37         $logger->error( "Missing circ script(s)" ) 
38                 unless( $p and $d and $f and $m and $pr and $ph );
39
40         $scripts{circ_permit}                   = $p;
41         $scripts{circ_duration}                 = $d;
42         $scripts{circ_recurring_fines}= $f;
43         $scripts{circ_max_fines}                = $m;
44         $scripts{circ_renew_permit}     = $pr;
45         $scripts{hold_permit}                   = $ph;
46
47         $lb = [ $lb ] unless ref($lb);
48         $script_libs = $lb;
49
50         $logger->debug("Loaded rules scripts for circ: " .
51                 "circ permit : $p, circ duration :$d , circ recurring fines : $f, " .
52                 "circ max fines : $m, circ renew permit : $pr, permit hold: $ph");
53 }
54
55
56 # ------------------------------------------------------------------------------
57 # Loads the necessary circ objects and pushes them into the script environment
58 # Returns ( $data, $evt ).  if $evt is defined, then an
59 # unexpedted event occurred and should be dealt with / returned to the caller
60 # ------------------------------------------------------------------------------
61 sub create_circ_env {
62         my %params = @_;
63
64         my $barcode                     = $params{barcode};
65         my $patron                      = $params{patron};
66         my $fetch_summary = $params{fetch_patron_circ_summary};
67         my $fetch_cstatus       = $params{fetch_copy_statuses};
68         my $fetch_clocs = $params{fetch_copy_locations};
69
70         my ( $copy, $title, $evt );
71
72         if(!$standings) {
73                 $standings = $apputils->fetch_patron_standings();
74                 $group_tree = $apputils->fetch_permission_group_tree();
75         }
76
77         # XXX must decide if caching is "right"
78         my $cstatus = $apputils->fetch_copy_statuses if( $fetch_cstatus and !$copy_statuses );
79         my $clocs = $apputils->fetch_copy_locations if( $fetch_clocs and !$copy_locations);
80         my $summary = $apputils->fetch_patron_circ_summary($patron->id) if $fetch_summary;
81
82         ( $copy, $evt ) = $apputils->fetch_copy_by_barcode( $barcode );
83         return ( undef, $evt ) if $evt;
84
85         ( $title, $evt ) = $apputils->fetch_record_by_copy( $copy->id );
86         return ( undef, $evt ) if $evt;
87
88         _doctor_circ_objects( $patron, $title, $copy, $summary, $cstatus, $clocs );
89
90         my $runner = _build_circ_script_runner( $patron, $title, $copy, $summary );
91
92         return { 
93                 runner                  => $runner, 
94                 title                           => $title, 
95                 patron                  => $patron, 
96                 copy                            => $copy, 
97                 circ_summary    => $summary, 
98         };
99 }
100
101
102 # ------------------------------------------------------------------------------
103 # Patches up circ objects to make them easier to use from within the script
104 # environment
105 # ------------------------------------------------------------------------------
106 sub _doctor_circ_objects {
107         my( $patron, $title, $copy, $summary, $cstatus, $clocs ) = @_;
108
109         # set the patron standing to the standing name
110         for my $s (@$standings) {
111                 $patron->standing( $s->value ) if( $s->id eq $patron->standing);
112         }
113
114         # set the patron ptofile to the profile name
115         $patron->profile( _patron_get_profile( $patron, $group_tree ) );
116
117         # set the copy status to a status name
118         $copy->status( _get_copy_status_name( $copy, $cstatus ) );
119
120         # set the copy location to the location object
121         $copy->location( _get_copy_location( $copy, $clocs ) );
122
123 }
124
125 # recurse and find the patron profile name from the tree
126 # another option would be to grab the groups for the patron
127 # and cycle through those until the "profile" group has been found
128 sub _patron_get_profile { 
129         my( $patron, $group_tree ) = @_;
130         return $group_tree->name if ($group_tree->id eq $patron->profile);
131         for my $child (@{$group_tree->children}) {
132                 my $ret = _patron_get_profile( $patron, $child );
133                 return $ret if $ret;
134         }
135         return undef;
136 }
137
138 sub _get_copy_status_name {
139         my( $copy, $cstatus ) = @_;
140         for my $status (@$cstatus) {
141                 return $status->name if( $status->id eq $copy->status ) 
142         }
143         return undef;
144 }
145
146 sub _get_copy_location {
147         my( $copy, $locations ) = @_;
148         for my $loc (@$locations) {
149                 return $loc if $loc->id eq $copy->location;
150         }
151 }
152
153
154 # ------------------------------------------------------------------------------
155 # Constructs and shoves data into the script environment
156 # ------------------------------------------------------------------------------
157 sub _build_circ_script_runner {
158         my( $patron, $title, $copy, $summary ) = @_;
159
160         $logger->debug("Loading script environment for circulation");
161
162         my $runner = OpenILS::Utils::ScriptRunner->new( 
163                 type => 'js', libs => $script_libs );
164
165         $runner->insert( 'patron',              $patron );
166         $runner->insert( 'title',               $title );
167         $runner->insert( 'copy',                $copy );
168
169         # circ script result
170         $runner->insert( 'result', {} );
171         $runner->insert( 'result.event', 'SUCCESS' );
172
173         if($summary) {
174                 $runner->insert( 'patron_info', {} );
175                 $runner->insert( 'patron_info.items_out', $summary->[0] );
176                 $runner->insert( 'patron_info.fines', $summary->[1] );
177         }
178
179         _add_script_runner_methods( $runner );
180         return $runner;
181 }
182
183 sub _add_script_runner_methods {
184         my $runner = shift;     
185
186         $runner->context->function_set(
187                 'fetch_hold_by_copy', sub {
188                         my $copyid = shift;
189                         my $hold = $holdcode->fetch_open_hold_by_current_copy($copyid);
190                         $runner->insert( 'hold', $hold ) if $hold;
191                 }
192         );
193 }
194
195
196 # ------------------------------------------------------------------------------
197
198 __PACKAGE__->register_method(
199         method  => "permit_circ",
200         api_name        => "open-ils.circ.permit_checkout_",
201         notes           => <<"  NOTES");
202                 Determines if the given checkout can occur
203                 PARAMS( authtoken, barcode => bc, patron => pid, renew => t/f )
204                 Returns an event
205         NOTES
206
207 sub permit_circ {
208         my( $self, $client, $authtoken, %params ) = @_;
209         my $barcode             = $params{barcode};
210         my $patronid    = $params{patron};
211         my $isrenew             = $params{renew};
212         my ( $requestor, $patron, $env, $evt );
213
214         # check permisson of the requestor
215         ( $requestor, $patron, $evt ) = 
216                 $apputils->checkses_requestor( 
217                 $authtoken, $patronid, 'VIEW_PERMIT_CHECKOUT' );
218         return $evt if $evt;
219
220         # fetch and build the circulation environment
221         ( $env, $evt ) = create_circ_env( 
222                 barcode                                                 => $barcode, 
223                 patron                                                  => $patron, 
224                 fetch_patron_circ_summary       => 1,
225                 fetch_copy_statuses                     => 1, 
226                 fetch_copy_locations                    => 1, 
227                 );
228         return $evt if $evt;
229
230         # run the script
231         my $runner = $env->{runner};
232         $runner->load($scripts{circ_permit});
233         $runner->run or throw OpenSRF::EX::ERROR ("Circ Permit Script Died");
234
235         my $evtname = $runner->retrieve('result.event');
236         $logger->activity("Permit Circ for user $patronid and barcode $barcode returned event: $evtname");
237         return OpenILS::Event->new($evtname);
238 }
239
240
241 # ------------------------------------------------------------------------------
242
243 __PACKAGE__->register_method(
244         method  => "circulate",
245         api_name        => "open-ils.circ.checkout.barcode_",
246         notes           => <<"  NOTES");
247                 Checks out an item based on barcode
248                 PARAMS( authtoken, barcode => bc, patron => pid )
249         NOTES
250
251 sub circulate {
252         my( $self, $client, $authtoken, %params ) = @_;
253         my $barcode             = $params{barcode};
254         my $patronid    = $params{patron};
255 }
256
257
258 # ------------------------------------------------------------------------------
259
260 __PACKAGE__->register_method(
261         method  => "checkin",
262         api_name        => "open-ils.circ.checkin.barcode_",
263         notes           => <<"  NOTES");
264         PARAMS( authtoken, barcode => bc )
265         Checks in based on barcode
266         Returns an event object whose payload contains the record, circ, and copy
267         If the item needs to be routed, the event is a ROUTE_COPY event
268         with an additional 'route_to' variable set on the event
269         NOTES
270
271 sub checkin {
272         my( $self, $client, $authtoken, %params ) = @_;
273         my $barcode             = $params{barcode};
274 }
275
276 # ------------------------------------------------------------------------------
277
278 __PACKAGE__->register_method(
279         method  => "renew",
280         api_name        => "open-ils.circ.renew_",
281         notes           => <<"  NOTES");
282         PARAMS( authtoken, circ => circ_id );
283         open-ils.circ.renew(login_session, circ_object);
284         Renews the provided circulation.  login_session is the requestor of the
285         renewal and if the logged in user is not the same as circ->usr, then
286         the logged in user must have RENEW_CIRC permissions.
287         NOTES
288
289 sub renew {
290         my( $self, $client, $authtoken, %params ) = @_;
291         my $circ        = $params{circ};
292 }
293
294         
295
296
297 1;