]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Penalty.pm
adding penalty server - basically works
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Penalty.pm
1 package OpenILS::Application::Penalty;
2 use strict; use warnings;
3 use DateTime;
4 use Data::Dumper;
5 use OpenSRF::EX qw(:try);
6 use OpenSRF::Utils::Cache;
7 use OpenSRF::Utils qw/:datetime/;
8 use OpenILS::Utils::ScriptRunner;
9 use OpenSRF::Utils::SettingsClient;
10 use OpenILS::Application::AppUtils;
11 use OpenSRF::Utils::Logger qw(:logger);
12 use base 'OpenSRF::Application';
13
14 my $U = "OpenILS::Application::AppUtils";
15 my $script;
16 my $path;
17 my $libs;
18 my $runner;
19 my %groups; # - user groups
20
21 my $fatal_key = 'result.fatalEvents';
22 my $info_key = 'result.infoEvents';
23
24
25 # --------------------------------------------------------------
26 # Loads the config info
27 # --------------------------------------------------------------
28 sub initialize {
29
30         my $conf = OpenSRF::Utils::SettingsClient->new;
31         my @pfx  = ( "apps", "open-ils.penalty","app_settings" );
32         $path           = $conf->config_value( @pfx, 'script_path');
33         $script = $conf->config_value( @pfx, 'patron_penalty' );
34
35         if(!($path and $script)) {
36                 $logger->error("Penalty server config missing script and/or script path");
37                 return 0;
38         }
39
40         $logger->info("penalty: Loading patron penalty script $script with path $path");
41 }
42
43
44 # --------------------------------------------------------------
45 # Builds the script runner and shoves data into the script 
46 # context
47 # --------------------------------------------------------------
48 sub build_runner {
49
50         my %args = @_;
51         my $patron = $args{patron};
52         my $patron_summary = $args{patron_summary};
53
54         my $pgroup = find_profile($patron);
55         $patron->profile( $pgroup );
56
57         if($runner) {
58                 $runner->refresh_context if $runner;
59
60         } else {
61                 $runner = OpenILS::Utils::ScriptRunner->new unless $runner;
62                 $runner->add_path( $_ );
63         }
64
65         $runner->insert( 'environment.patron',  $patron, 1);
66         $runner->insert( $fatal_key, [] );
67         $runner->insert( $info_key, [] );
68         $runner->insert( 'environment.patronItemsOut', $patron_summary->[0] );
69         $runner->insert( 'environment.patronFines', $patron_summary->[1] );
70
71         return $runner;
72 }
73
74
75 sub find_profile {
76         my $patron = shift;
77
78         if(!%groups) {
79                 my $groups = $U->storagereq(
80                         'open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic');
81                 %groups = map { $_->id => $_ } @$groups;
82         }
83
84         return $groups{$patron->profile};
85 }
86
87
88
89 __PACKAGE__->register_method (
90         method   => 'patron_penalty',
91         api_name         => 'open-ils.penalty.patron_penalty.calculate',
92         signature => q/
93                 Calculates the patron's standing penalties
94                 @param authtoken The login session key
95                 @params args An object of named params including:
96                         patronid The id of the patron
97                         update True if this call should update the database
98                         background True if this call should return immediately,
99                                 then go on to process the penalties.  This flag
100                                 works only in conjunction with the 'update' flag.
101                 @return An object with keys 'fatal_penalties' and 
102                 'info_penalties' who are themeselves arrays of 0 or 
103                 more penalties.  Returns event on error.
104         /
105 );
106
107 # --------------------------------------------------------------
108 # modes: 
109 #  - update 
110 #  - background : modifier to 'update' which says to return 
111 #               immediately then continue processing.  If this flag is set
112 #               then the caller will get no penalty info and will never 
113 #               know for sure if the call even succeeded. 
114 # --------------------------------------------------------------
115 sub patron_penalty {
116         my( $self, $conn, $authtoken, $args ) = @_;
117         
118         my( $requestor, $patron, $evt );
119
120         $conn->respond_complete(1) if $$args{background};
121
122         ( $patron, $evt ) = $U->fetch_user($$args{patronid});
123         return $evt if $evt;
124
125         ( $requestor, $evt ) = $U->checkses($authtoken);
126         return $evt if $evt;
127
128         $evt = $U->check_perms( $requestor->id,  $patron->home_ou, 'VIEW_USER');
129         return $evt if $evt;
130
131         # - fetch the circulation summary info for the user
132         my $summary = $U->fetch_patron_circ_summary($patron->id);
133
134         # - build the script runner
135         my $runner = build_runner( 
136                 patron                  => $patron, 
137                 patron_summary => $summary 
138                 );
139
140         # - Load up the script and run it
141         $runner->add_path($path);
142         $runner->load($script);
143         $runner->run or throw OpenSRF::EX::ERROR ("Patron Penalty Script Died: $@");
144
145         # array items are returned as a comma-separated list of strings
146         my @fatals = split( /,/, $runner->retrieve($fatal_key) );
147         my @infos = split( /,/, $runner->retrieve($info_key) );
148         my $all = [ @fatals, @infos ];
149
150         $logger->info("penalty: script returned fatal events [@fatals] and info events [@infos]");
151
152         # - update the penalty info in the db if necessary
153         $evt = update_patron_penalties( 
154                 patron    => $patron, 
155                 penalties => $all, 
156                 requestor => $requestor ) if $$args{update};
157
158         return $evt if $evt;
159
160         return { fatal_penalties => \@fatals, info_penalties => \@infos };
161 }
162
163 # --------------------------------------------------------------
164 # Removes existing penalties for the patron that are not passed 
165 # into this function.  Creates new penalty entries for the 
166 # provided penalties that don't already exist;
167 # --------------------------------------------------------------
168 sub update_patron_penalties {
169
170         my %args      = @_;
171         my $patron    = $args{patron};
172         my $penalties = $args{penalties};
173         my $requestor = $args{requestor};
174
175         my $session   = $U->start_db_session();
176
177         # - fetch the current penalties
178         my $existing = $session->request(
179                 'open-ils.storage.direct.actor.'.
180                 'user_standing_penalty.search.usr.atomic', $patron->id )->gather(1);
181
182         my @deleted;
183         my $reqid = $requestor->id;
184         my $patronid = $patron->id;
185
186         # If an existing penalty is not in the newly generated 
187         # list of penalties, remove it from the DB
188         for my $e (@$existing) {
189                 if( ! grep { $_ eq $e->penalty_type } @$penalties ) {
190
191                         $logger->activity("user $reqid removing user penalty ".
192                                 $e->penalty_type . " from user $patronid");
193
194                         my $s = $session->request(
195                                 'open-ils.storage.direct.actor.user_standing_penalty.delete', $e->id )->gather(1);
196                         return $U->DB_UPDATE_FAILED($e) unless defined($s);
197                 }
198         }
199
200         # Add penalties that previously didn't exist
201         for my $p (@$penalties) {
202                 if( ! grep { $_->penalty_type eq $p } @$existing ) {
203
204                         $logger->activity("user $reqid adding user penalty $p to user $patronid");
205
206                         my $newp = Fieldmapper::actor::user_standing_penalty->new;
207                         $newp->penalty_type( $p );
208                         $newp->usr( $patronid );
209
210                         my $s = $session->request(
211                                 'open-ils.storage.direct.actor.user_standing_penalty.create', $newp )->gather(1);
212                         return $U->DB_UPDATE_FAILED($p) unless $s;
213                 }
214         }
215         
216         $U->commit_db_session($session);
217         return undef;
218 }
219
220
221
222
223
224 1;