Make Evergreen Perl modules installable via Module::Build to match OpenSRF
[working/Evergreen.git] / Open-ILS / src / perlmods / lib / OpenILS / Application / Trigger / EventGroup.pm
1 package OpenILS::Application::Trigger::EventGroup;
2 use strict; use warnings;
3 use OpenILS::Application::Trigger::Event;
4 use base 'OpenILS::Application::Trigger::Event';
5 use OpenSRF::EX qw/:try/;
6
7 use OpenSRF::Utils::Logger qw/$logger/;
8
9 use OpenILS::Utils::Fieldmapper;
10 use OpenILS::Utils::CStoreEditor q/:funcs/;
11 use OpenILS::Application::Trigger::ModRunner;
12
13 my $log = 'OpenSRF::Utils::Logger';
14
15 sub new {
16     my $class = shift;
17     my @ids = @_;
18     $class = ref($class) || $class;
19
20     my $editor = new_editor(xact=>1);
21
22     my $self = bless {
23         environment => {},
24         events      => [
25             map {
26                 ref($_) ?
27                     do { $_->standalone(0); $_->editor($editor); $_ } :
28                     OpenILS::Application::Trigger::Event->new($_, $editor)
29             } @ids
30         ],
31         ids         => [ map { ref($_) ? $_->id : $_ } @ids ],
32         editor      => $editor
33     } => $class;
34
35
36     $self->editor->xact_commit; # flush out those updates
37     $self->editor->xact_begin;
38
39     return $self;
40 }
41
42 sub react {
43     my $self = shift;
44
45     return $self if (defined $self->reacted);
46
47     if ($self->valid) {
48         $self->update_state( 'reacting') || die 'Unable to update event group state';
49         $self->build_environment;
50
51         try {
52             $self->reacted(
53                 OpenILS::Application::Trigger::ModRunner::Reactor
54                     ->new( $self->event->event_def->reactor, $self->environment )
55                     ->run
56                     ->final_result
57             );
58         } otherwise {
59             $log->error("Event reacting failed with ". shift() );
60             $self->update_state( 'error' ) || die 'Unable to update event group state';
61         };
62
63         if (defined $self->reacted) {
64             $self->update_state( 'reacted' ) || die 'Unable to update event group state';
65         } else {
66             $self->update_state( 'error' ) || die 'Unable to update event group state';
67         }
68     } else {
69         $self->{reacted} = undef;
70     }
71     return $self;
72 }
73
74 sub validate {
75     my $self = shift;
76
77     return $self if (defined $self->valid);
78
79     $self->update_state( 'validating') || die 'Unable to update event group state';
80     $self->editor->xact_begin;
81
82     my @valid_events;
83     try {
84         for my $event ( @{ $self->events } ) {
85             $event->validate;
86             push @valid_events, $event if ($event->valid);
87         }
88         $self->valid(1) if (@valid_events);
89         $self->{events} = \@valid_events;
90         $self->{ids} = [ map { $_->id } @valid_events ];
91         $self->editor->xact_commit;
92     } otherwise {
93         $log->error("Event group validation failed with ". shift() );
94         $self->editor->xact_rollback;
95         $self->update_state( 'error' ) || die 'Unable to update event group state';
96     };
97
98     return $self;
99 }
100  
101 sub cleanedup {
102     my $self = shift;
103     return undef unless (ref $self);
104
105     my $c = shift;
106     $self->{cleanedup} = $c if (defined $c);
107     return $self->{cleanedup};
108 }
109
110 sub reacted {
111     my $self = shift;
112     return undef unless (ref $self);
113
114     my $r = shift;
115     $self->{reacted} = $r if (defined $r);
116     return $self->{reacted};
117 }
118
119 sub valid {
120     my $self = shift;
121     return undef unless (ref $self);
122
123     my $v = shift;
124     $self->{valid} = $v if (defined $v);
125     return $self->{valid};
126 }
127
128 sub event {
129     my $self = shift;
130     return undef unless (ref $self);
131
132     return $self->{events}[0]->event;
133 }
134
135 sub events {
136     my $self = shift;
137     return undef unless (ref $self);
138
139     return $self->{events};
140 }
141
142 sub ids {
143     my $self = shift;
144     return undef unless (ref $self);
145
146     return $self->{ids};
147 }
148
149 sub environment {
150     my $self = shift;
151     return undef unless (ref $self);
152
153     my $e = shift;
154     $self->{environment} = $e if (defined $e);
155     return $self->{environment};
156 }
157
158 sub editor {
159     my $self = shift;
160     return undef unless (ref $self);
161
162     my $e = shift;
163     $self->{editor} = $e if (defined $e);
164     return $self->{editor};
165 }
166
167 sub unfind {
168     my $self = shift;
169     return undef unless (ref $self);
170
171     die 'Cannot unfind a reacted event group' if (defined $self->reacted);
172
173     $self->update_state( 'pending' ) || die 'Unable to update event group state';
174     $self->{events} = undef;
175     return $self;
176 }
177
178 sub update_state {
179     my $self = shift;
180     return undef unless ($self && ref $self);
181
182     my $state = shift;
183     return undef unless ($state);
184
185     my $fields = shift;
186
187     $self->editor->xact_begin || return undef;
188
189     my @oks;
190     my $ok;
191     my $last_updated;
192     for my $event ( @{ $self->events } ) {
193         my $e = $self->editor->retrieve_action_trigger_event( $event->id );
194         $e->start_time( 'now' ) unless $e->start_time;
195         $e->update_time( 'now' );
196         $e->update_process( $$ );
197         $e->state( $state );
198
199         $e->clear_start_time() if ($e->state eq 'pending');
200
201         if ($fields && ref($fields)) {
202             $e->$_($$fields{$_}) for (keys %$fields);
203         }
204
205         my $ok = $self->editor->update_action_trigger_event( $e );
206         if ($ok) {
207             push @oks, $ok;
208             $last_updated = $e->id;
209         }
210     }
211
212     if (scalar(@oks) < scalar(@{ $self->ids })) {
213         $self->editor->xact_rollback;
214         return undef;
215     } 
216
217     my $updated = $self->editor->retrieve_action_trigger_event($last_updated);
218     $ok = $self->editor->xact_commit;
219
220     if ($ok) {
221         for my $event ( @{ $self->events } ) {
222             my $e = $event->event;
223             $e->start_time( $updated->start_time );
224             $e->update_time( $updated->update_time );
225             $e->update_process( $updated->update_process );
226             $e->state( $updated->state );
227         }
228     }
229
230     return $ok || undef;
231 }
232
233 sub findEvent {
234     my $self = shift;
235     my $member = shift;
236
237     $member = $member->id if (ref($member));
238
239     my @list = grep { $member == $_->id } @{ $self->events };
240
241     return shift(@list);
242 }
243
244 sub build_environment {
245     my $self = shift;
246     my $env = $self->environment;
247
248     $$env{EventProcessor} = $self;
249     $$env{target} = [];
250     $$env{event} = [];
251     $$env{user_data} = [];
252     for my $e ( @{ $self->events } ) {
253         for my $env_part ( keys %{ $e->environment } ) {
254             next if ($env_part eq 'EventProcessor');
255             if ($env_part eq 'target') {
256                 push @{ $$env{target} }, $e->environment->{target};
257             } elsif ($env_part eq 'event') {
258                 push @{ $$env{event} }, $e->environment->{event};
259             } elsif ($env_part eq 'user_data') {
260                 push @{ $$env{user_data} }, $e->environment->{user_data};
261             } else {
262                 $$env{$env_part} = $e->environment->{$env_part};
263             }
264         }
265     }
266
267     return $self;
268 }
269
270 1;