]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/EventGroup.pm
Lp 1835035: Refactor auto_renewal back end code
[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_impl {
16     my $class = shift;
17     my @ids = @{shift()};
18     my $nochanges = shift;
19
20     $class = ref($class) || $class;
21
22     my $editor = new_editor(xact=>1);
23
24     my $self = bless {
25         environment => {},
26         events      => [
27             map {
28                 ref($_) ?
29                     do { $_->standalone(0); $_->editor($editor); $_ } :
30                     OpenILS::Application::Trigger::Event->new($_, $editor, $nochanges)
31             } @ids
32         ],
33         ids         => [ map { ref($_) ? $_->id : $_ } @ids ],
34         editor      => $editor
35     } => $class;
36
37
38     $self->editor->xact_commit; # flush out those updates
39     $self->editor->xact_begin;
40
41     return $self;
42 }
43
44 sub new_nochanges {
45     my $class = shift;
46     my @ids = @_;
47
48     return new_impl($class, \@ids, 1);
49 }
50
51 sub new {
52     my $class = shift;
53     my @ids = @_;
54
55     return new_impl($class, \@ids);
56 }
57
58 sub react {
59     my $self = shift;
60
61     return $self if (defined $self->reacted);
62
63     if ($self->valid) {
64         $self->update_state( 'reacting') || die 'Unable to update event group state';
65         $self->build_environment;
66
67         try {
68             my $env = $self->environment;
69             my $reactor = OpenILS::Application::Trigger::ModRunner::Reactor->new(
70                 $self->event->event_def->reactor,
71                 $env
72             );
73
74             $self->reacted( $reactor->run->final_result);
75
76             if ($env->{usr_message}{usr} && $env->{usr_message}{template}) {
77                 my $message_template_output =
78                     $reactor->pass('ProcessMessage')->run->final_result;
79
80                 if ($message_template_output) {
81                     my $usr_message = Fieldmapper::actor::usr_message->new;
82                     $usr_message->title( $env->{usr_message}{title} || $self->event->event_def->name );
83                     $usr_message->message( $message_template_output );
84                     $usr_message->usr( $env->{usr_message}{usr}->id );
85                     $usr_message->sending_lib( $env->{usr_message}{sending_lib}->id );
86
87                     if ($self->editor->xact_begin) {
88                         if ($self->editor->create_actor_usr_message( $usr_message )) {
89                             $self->editor->xact_commit;
90                         } else {
91                             $self->editor->xact_rollback;
92                         }
93                     }
94                 }
95             }
96
97         } otherwise {
98             $log->error("Event reacting failed with ". shift() );
99             $self->update_state( 'error' ) || die 'Unable to update event group state';
100         };
101
102         if (defined $self->reacted) {
103             $self->update_state( 'reacted' ) || die 'Unable to update event group state';
104         } else {
105             $self->update_state( 'error' ) || die 'Unable to update event group state';
106         }
107     } else {
108         $self->{reacted} = undef;
109     }
110     return $self;
111 }
112
113 sub validate {
114     my $self = shift;
115
116     return $self if (defined $self->valid);
117
118     $self->update_state( 'validating') || die 'Unable to update event group state';
119     $self->editor->xact_begin;
120
121     my @valid_events;
122     try {
123         for my $event ( @{ $self->events } ) {
124             $event->validate;
125             push @valid_events, $event if ($event->valid);
126         }
127         $self->valid(1) if (@valid_events);
128         $self->{events} = \@valid_events;
129         $self->{ids} = [ map { $_->id } @valid_events ];
130         $self->editor->xact_commit;
131     } otherwise {
132         $log->error("Event group validation failed with ". shift() );
133         $self->editor->xact_rollback;
134         $self->update_state( 'error' ) || die 'Unable to update event group state';
135     };
136
137     return $self;
138 }
139  
140 sub revalidate_test {
141     my $self = shift;
142
143     $self->editor->xact_begin;
144
145     my @valid_events;
146     try {
147         for my $event ( @{ $self->events } ) {
148             push @valid_events, $event->id if $event->revalidate_test;
149         }
150         $self->editor->xact_rollback;
151     } otherwise {
152         $log->error("Event group validation failed with ". shift());
153         $self->editor->xact_rollback;
154     };
155
156     return \@valid_events;
157 }
158  
159 sub cleanedup {
160     my $self = shift;
161     return undef unless (ref $self);
162
163     my $c = shift;
164     $self->{cleanedup} = $c if (defined $c);
165     return $self->{cleanedup};
166 }
167
168 sub reacted {
169     my $self = shift;
170     return undef unless (ref $self);
171
172     my $r = shift;
173     $self->{reacted} = $r if (defined $r);
174     return $self->{reacted};
175 }
176
177 sub valid {
178     my $self = shift;
179     return undef unless (ref $self);
180
181     my $v = shift;
182     $self->{valid} = $v if (defined $v);
183     return $self->{valid};
184 }
185
186 sub event {
187     my $self = shift;
188     return undef unless (ref $self);
189
190     return $self->{events}[0]->event;
191 }
192
193 sub events {
194     my $self = shift;
195     return undef unless (ref $self);
196
197     return $self->{events};
198 }
199
200 sub ids {
201     my $self = shift;
202     return undef unless (ref $self);
203
204     return $self->{ids};
205 }
206
207 sub environment {
208     my $self = shift;
209     return undef unless (ref $self);
210
211     my $e = shift;
212     $self->{environment} = $e if (defined $e);
213     return $self->{environment};
214 }
215
216 sub editor {
217     my $self = shift;
218     return undef unless (ref $self);
219
220     my $e = shift;
221     $self->{editor} = $e if (defined $e);
222     return $self->{editor};
223 }
224
225 sub unfind {
226     my $self = shift;
227     return undef unless (ref $self);
228
229     die 'Cannot unfind a reacted event group' if (defined $self->reacted);
230
231     $self->update_state( 'pending' ) || die 'Unable to update event group state';
232     $self->{events} = undef;
233     return $self;
234 }
235
236 sub update_state {
237     my $self = shift;
238     return undef unless ($self && ref $self);
239
240     my $state = shift;
241     return undef unless ($state);
242
243     my $fields = shift;
244
245     $self->editor->xact_begin || return undef;
246
247     my @oks;
248     my $ok;
249     my $last_updated;
250     for my $event ( @{ $self->events } ) {
251         my $e = $self->editor->retrieve_action_trigger_event( $event->id );
252         $e->start_time( 'now' ) unless $e->start_time;
253         $e->update_time( 'now' );
254         $e->update_process( $$ );
255         $e->state( $state );
256
257         $e->clear_start_time() if ($e->state eq 'pending');
258
259         $e->complete_time('now')
260             if ($e->state eq 'complete' && !$e->complete_time);
261
262         if ($fields && ref($fields)) {
263             $e->$_($$fields{$_}) for (keys %$fields);
264         }
265
266         my $ok = $self->editor->update_action_trigger_event( $e );
267         if ($ok) {
268             push @oks, $ok;
269             $last_updated = $e->id;
270         }
271     }
272
273     if (scalar(@oks) < scalar(@{ $self->ids })) {
274         $self->editor->xact_rollback;
275         return undef;
276     } 
277
278     my $updated = $self->editor->retrieve_action_trigger_event($last_updated);
279     $ok = $self->editor->xact_commit;
280
281     if ($ok) {
282         for my $event ( @{ $self->events } ) {
283             my $e = $event->event;
284             $e->start_time( $updated->start_time );
285             $e->update_time( $updated->update_time );
286             $e->update_process( $updated->update_process );
287             $e->state( $updated->state );
288         }
289     }
290
291     return $ok || undef;
292 }
293
294 sub findEvent {
295     my $self = shift;
296     my $member = shift;
297
298     $member = $member->id if (ref($member));
299
300     my @list = grep { $member == $_->id } @{ $self->events };
301
302     return shift(@list);
303 }
304
305 sub build_environment {
306     my $self = shift;
307     my $env = $self->environment;
308
309     $$env{EventProcessor} = $self;
310     $$env{target} = [];
311     $$env{event} = [];
312     $$env{user_data} = [];
313     for my $e ( @{ $self->events } ) {
314         for my $env_part ( keys %{ $e->environment } ) {
315             next if ($env_part eq 'EventProcessor');
316             if ($env_part eq 'target') {
317                 push @{ $$env{target} }, $e->environment->{target};
318             } elsif ($env_part eq 'event') {
319                 push @{ $$env{event} }, $e->environment->{event};
320             } elsif ($env_part eq 'user_data') {
321                 push @{ $$env{user_data} }, $e->environment->{user_data};
322             } else {
323                 $$env{$env_part} = $e->environment->{$env_part};
324             }
325         }
326     }
327
328     return $self;
329 }
330
331 1;