94c561c2180bf62b2e3055a461ac6aa372f8d296
[working/Evergreen.git] / Open-ILS / src / perlmods / lib / OpenILS / Utils / Penalty.pm
1 package OpenILS::Utils::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::Application::AppUtils;
9 use OpenSRF::Utils::Logger qw(:logger);
10 use OpenILS::Utils::CStoreEditor qw/:funcs/;
11 use OpenILS::Utils::Fieldmapper;
12 use OpenILS::Const qw/:const/;
13 my $U = "OpenILS::Application::AppUtils";
14
15
16 # calculate and update the well-known penalties
17 sub calculate_penalties {
18     my($class, $e, $user_id, $context_org) = @_;
19
20     my $commit = 0;
21     unless($e) {
22         $e = new_editor(xact =>1);
23         $commit = 1;
24     }
25
26     my $penalties = $e->json_query({from => ['actor.calculate_system_penalties',$user_id, $context_org]});
27
28     my $user = $e->retrieve_actor_user( $user_id );
29     my @existing_penalties = grep { defined $_->{id} } @$penalties;
30     my @wanted_penalties = grep { !defined $_->{id} } @$penalties;
31     my @trigger_events;
32
33     my %csp;
34     for my $pen_obj (@wanted_penalties) {
35
36         my $pen = Fieldmapper::actor::user_standing_penalty->new;
37         $pen->$_($pen_obj->{$_}) for keys %$pen_obj;
38
39         # let's see if this penalty is accounted for already
40         my ($existing) = grep { 
41                 $_->{org_unit} == $pen_obj->{org_unit} and
42                 $_->{standing_penalty} == $pen_obj->{standing_penalty}
43             } @existing_penalties;
44
45         if($existing) { 
46             # we have one of these already.  Leave it be, but remove it from the 
47             # existing set so it's not deleted in the subsequent loop
48             @existing_penalties = grep { $_->{id} ne $existing->{id} }  @existing_penalties;
49
50         } else {
51
52             # this is a new penalty
53             $e->create_actor_user_standing_penalty($pen) or return $e->die_event;
54
55             my $csp_obj = $csp{$pen->standing_penalty} || 
56                 $e->retrieve_config_standing_penalty( $pen->standing_penalty );
57
58             # cache for later
59             $csp{$pen->standing_penalty} = $csp_obj;
60
61             push(@trigger_events, ['penalty.' . $csp_obj->name, $pen, $pen->org_unit]);
62         }
63     }
64
65     # at this point, any penalties remaining in the existing 
66     # penalty set are unaccounted for and should be removed
67     for my $pen_obj (@existing_penalties) {
68         my $pen = Fieldmapper::actor::user_standing_penalty->new;
69         $pen->$_($pen_obj->{$_}) for keys %$pen_obj;
70         $e->delete_actor_user_standing_penalty($pen) or return $e->die_event;
71     }
72
73     $e->commit if $commit;
74
75     $U->create_events_for_hook($$_[0], $$_[1], $$_[2]) for @trigger_events;
76     return undef;
77 }
78
79 # any penalties whose block_list has an item from @fatal_mask will be sorted
80 # into the fatal_penalties set.  Others will be sorted into the info_penalties set
81 sub retrieve_penalties {
82     my($class, $e, $user_id, $context_org, @fatal_mask) = @_;
83
84     my(@info, @fatal);
85     my $penalties = $class->retrieve_usr_penalties($e, $user_id, $context_org);
86
87     for my $p (@$penalties) {
88         my $pushed = 0;
89         if($p->standing_penalty->block_list) {
90             for my $m (@fatal_mask) {
91                 if($p->standing_penalty->block_list =~ /$m/) {
92                     push(@fatal, $p->standing_penalty);
93                     $pushed = 1;
94                     last;
95                 }
96             }
97         }
98         push(@info, $p->standing_penalty) unless $pushed;
99     }
100
101     return {fatal_penalties => \@fatal, info_penalties => \@info};
102 }
103
104
105 # Returns a list of actor_user_standing_penalty objects
106 sub retrieve_usr_penalties {
107     my($class, $e, $user_id, $context_org) = @_;
108
109     return $e->search_actor_user_standing_penalty([
110         {
111             usr => $user_id, 
112             org_unit => $U->get_org_full_path($context_org),
113             '-or' => [
114                 {stop_date => undef},
115                 {stop_date => {'>' => 'now'}}
116             ],
117         },
118         {flesh => 1, flesh_fields => {ausp => ['standing_penalty']}}
119     ]);
120 }
121
122 1;
123
124