]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Reporter.pm
forward porting: added method to check on an existing report with the given name...
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Reporter.pm
1 package OpenILS::Application::Reporter;
2 use base qw/OpenSRF::Application/;
3 use strict; use warnings;
4 use OpenSRF::Utils::Logger qw/$logger/;
5 use OpenILS::Utils::CStoreEditor qw/:funcs/;
6 use OpenILS::Utils::Fieldmapper;
7 use OpenILS::Application::AppUtils;
8 my $U = "OpenILS::Application::AppUtils";
9
10
11 __PACKAGE__->register_method(
12         api_name => 'open-ils.reporter.folder.create',
13         method => 'create_folder'
14 );
15
16 sub create_folder {
17         my( $self, $conn, $auth, $type, $folder ) = @_;
18
19         my $e = new_rstore_editor(xact=>1, authtoken=>$auth);
20         return $e->die_event unless $e->checkauth;
21         return $e->die_event unless $e->allowed('RUN_REPORTS');
22
23         return 0 if $folder->owner ne $e->requestor->id;
24
25         $folder->owner($e->requestor->id);
26         my $meth = "create_reporter_${type}_folder";
27         $e->$meth($folder) or return $e->die_event;
28         $e->commit;
29
30         return $folder->id;
31 }
32
33
34 __PACKAGE__->register_method(
35     api_name => 'open-ils.reporter.report.exists',
36     method => 'report_exists',
37     notes => q/
38         Returns 1 if a report with the given name and folder already exists.
39     /
40 );
41
42 sub report_exists {
43     my( $self, $conn, $auth, $report ) = @_;
44
45     my $e = new_rstore_editor(authtoken=>$auth);
46     return $e->event unless $e->checkauth;
47     return $e->event unless $e->allowed('RUN_REPORTS');
48
49     my $existing = $e->search_reporter_report(
50         {folder=>$report->folder, name=>$report->name});
51     return 1 if @$existing;
52     return 0;
53 }
54
55
56 __PACKAGE__->register_method(
57         api_name => 'open-ils.reporter.folder.visible.retrieve',
58         method => 'retrieve_visible_folders'
59 );
60
61 sub retrieve_visible_folders {
62         my( $self, $conn, $auth, $type ) = @_;
63         my $e = new_rstore_editor(authtoken=>$auth);
64         return $e->event unless $e->checkauth;
65         return $e->event unless $e->allowed('RUN_REPORTS');
66
67         my $class = 'rrf';
68         $class = 'rtf' if $type eq 'template';
69         $class = 'rof' if $type eq 'output';
70         my $flesh = {flesh => 1,flesh_fields => { $class => ['owner', 'share_with']}};
71
72         my $meth = "search_reporter_${type}_folder";
73         my $fs = $e->$meth( [{ owner => $e->requestor->id }, $flesh] );
74
75         my @orgs;
76         my $o = $U->storagereq(
77                 'open-ils.storage.actor.org_unit.full_path.atomic', $e->requestor->ws_ou);
78         push( @orgs, $_->id ) for @$o;
79
80         my $fs2 = $e->$meth(
81                 [
82                         {
83                                 shared => 't', 
84                                 share_with => \@orgs, 
85                                 owner => { '!=' => $e->requestor->id } 
86                         }, 
87                         $flesh
88                 ]
89         );
90         push( @$fs, @$fs2);
91         return $fs;
92 }
93
94
95
96 __PACKAGE__->register_method(
97         api_name => 'open-ils.reporter.folder_data.retrieve',
98         method => 'retrieve_folder_data'
99 );
100
101 sub retrieve_folder_data {
102         my( $self, $conn, $auth, $type, $folderid, $limit ) = @_;
103         my $e = new_rstore_editor(authtoken=>$auth);
104         return $e->event unless $e->checkauth;
105         return $e->event unless $e->allowed('RUN_REPORTS');
106         my $meth = "search_reporter_${type}";
107         my $class = 'rr';
108         $class = 'rt' if $type eq 'template';
109         my $flesh = {
110                 flesh => 1,
111                 flesh_fields => { $class => ['owner']}, 
112                 order_by => { $class => 'create_time DESC'} 
113         };
114         $flesh->{limit} = $limit if $limit;
115         return $e->$meth([{ folder => $folderid }, $flesh]); 
116 }
117
118 __PACKAGE__->register_method(
119         api_name => 'open-ils.reporter.schedule.retrieve_by_folder',
120         method => 'retrieve_schedules');
121 sub retrieve_schedules {
122         my( $self, $conn, $auth, $folderId, $limit, $complete ) = @_;
123         my $e = new_rstore_editor(authtoken=>$auth);
124         return $e->event unless $e->checkauth;
125         return $e->event unless $e->allowed('RUN_REPORTS');
126
127         my $search = { folder => $folderId };
128         my $query = [
129                 { folder => $folderId },
130                 { 
131                         order_by => { rs => 'run_time DESC' } ,
132                         flesh => 1,
133                         flesh_fields => { rs => ['report'] }
134                 }
135         ];
136
137         $query->[1]->{limit} = $limit if $limit;
138         $query->[0]->{complete_time} = undef unless $complete;
139         $query->[0]->{complete_time} = { '!=' => undef } if $complete;
140
141         return $e->search_reporter_schedule($query);
142 }
143
144 __PACKAGE__->register_method(
145         api_name => 'open-ils.reporter.schedule.retrieve',
146         method => 'retrieve_schedules');
147 sub retrieve_schedule {
148         my( $self, $conn, $auth, $sched_id ) = @_;
149         my $e = new_rstore_editor(authtoken=>$auth);
150         return $e->event unless $e->checkauth;
151         return $e->event unless $e->allowed('RUN_REPORTS');
152         my $s = $e->retrieve_reporter_schedule($sched_id)
153                 or return $e->event;
154         return $s;
155 }
156
157
158 __PACKAGE__->register_method(
159         api_name => 'open-ils.reporter.template.create',
160         method => 'create_template');
161 sub create_template {
162         my( $self, $conn, $auth, $template ) = @_;
163         my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
164         return $e->die_event unless $e->checkauth;
165         return $e->die_event unless $e->allowed('RUN_REPORTS');
166         $template->owner($e->requestor->id);
167
168         my $existing = $e->search_reporter_template( {owner=>$template->owner, 
169                         folder=>$template->folder, name=>$template->name},{idlist=>1});
170         return OpenILS::Event->new('REPORT_TEMPLATE_EXISTS') if @$existing;
171
172         my $tmpl = $e->create_reporter_template($template)
173                 or return $e->die_event;
174         $e->commit;
175         return $tmpl;
176 }
177
178
179
180         
181
182 __PACKAGE__->register_method(
183         api_name => 'open-ils.reporter.report.create',
184         method => 'create_report');
185 sub create_report {
186         my( $self, $conn, $auth, $report, $schedule ) = @_;
187         my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
188         return $e->die_event unless $e->checkauth;
189         return $e->die_event unless $e->allowed('RUN_REPORTS');
190         $report->owner($e->requestor->id);
191
192         my $existing = $e->search_reporter_report( {owner=>$report->owner, 
193                         folder=>$report->folder, name=>$report->name},{idlist=>1});
194         return OpenILS::Event->new('REPORT_REPORT_EXISTS') if @$existing;
195
196         my $rpt = $e->create_reporter_report($report)
197                 or return $e->die_event;
198         $schedule->report($rpt->id);
199         $schedule->runner($e->requestor->id);
200         $e->create_reporter_schedule($schedule) or return $e->die_event;
201         $e->commit;
202         return $rpt;
203 }
204
205
206 __PACKAGE__->register_method(
207         api_name => 'open-ils.scheduleer.schedule.create',
208         method => 'create_schedule');
209 sub create_schedule {
210         my( $self, $conn, $auth, $schedule ) = @_;
211         my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
212         return $e->die_event unless $e->checkauth;
213         return $e->die_event unless $e->allowed('RUN_REPORTS');
214         my $sched = $e->create_reporter_schedule($schedule)
215                 or return $e->die_event;
216         $e->commit;
217         return $sched;
218 }
219
220 __PACKAGE__->register_method(
221         api_name => 'open-ils.reporter.template.retrieve',
222         method => 'retrieve_template');
223 sub retrieve_template {
224         my( $self, $conn, $auth, $id ) = @_;
225         my $e = new_rstore_editor(authtoken=>$auth);
226         return $e->event unless $e->checkauth;
227         return $e->event unless $e->allowed('RUN_REPORTS');
228         my $t = $e->retrieve_reporter_template($id) 
229                 or return $e->event;
230         return $t;
231 }
232
233
234 __PACKAGE__->register_method(
235         api_name => 'open-ils.reporter.report.retrieve',
236         method => 'retrieve_report');
237 sub retrieve_report {
238         my( $self, $conn, $auth, $id ) = @_;
239         my $e = new_rstore_editor(authtoken=>$auth);
240         return $e->event unless $e->checkauth;
241         return $e->event unless $e->allowed('RUN_REPORTS');
242         my $r = $e->retrieve_reporter_report($id) 
243                 or return $e->event;
244         return $r;
245 }
246
247
248 __PACKAGE__->register_method(
249         api_name => 'open-ils.reporter.template.update',
250         method => 'update_template');
251 sub update_template {
252         my( $self, $conn, $auth, $tmpl ) = @_;
253         my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
254         return $e->die_event unless $e->checkauth;
255         return $e->die_event unless $e->allowed('RUN_REPORTS');
256         my $t = $e->retrieve_reporter_template($tmpl->id)
257                 or return $e->die_event;
258         return 0 if $t->owner ne $e->requestor->id;
259         $e->update_reporter_template($tmpl)
260                 or return $e->die_event;
261         $e->commit;
262         return 1;
263 }
264
265
266 __PACKAGE__->register_method(
267         api_name => 'open-ils.reporter.report.update',
268         method => 'update_report');
269 sub update_report {
270         my( $self, $conn, $auth, $report ) = @_;
271         my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
272         return $e->die_event unless $e->checkauth;
273         return $e->die_event unless $e->allowed('RUN_REPORTS');
274         my $r = $e->retrieve_reporter_report($report->id)
275                 or return $e->die_event;
276         if( $r->owner ne $e->requestor->id ) {
277                 $e->rollback;
278                 return 0;
279         }
280         $e->update_reporter_report($report)
281                 or return $e->die_event;
282         $e->commit;
283         return 1;
284 }
285
286
287 __PACKAGE__->register_method(
288         api_name => 'open-ils.reporter.schedule.update',
289         method => 'update_schedule');
290 sub update_schedule {
291         my( $self, $conn, $auth, $schedule ) = @_;
292         my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
293         return $e->die_event unless $e->checkauth;
294         return $e->die_event unless $e->allowed('RUN_REPORTS');
295         my $s = $e->retrieve_reporter_schedule($schedule->id)
296                 or return $e->die_event;
297         my $r = $e->retrieve_reporter_report($s->report)
298                 or return $e->die_event;
299         if( $r->owner ne $e->requestor->id ) {
300                 $e->rollback;
301                 return 0;
302         }
303         $e->update_reporter_schedule($schedule)
304                 or return $e->die_event;
305         $e->commit;
306         return 1;
307 }
308
309
310 __PACKAGE__->register_method(
311         api_name => 'open-ils.reporter.folder.update',
312         method => 'update_folder');
313 sub update_folder {
314         my( $self, $conn, $auth, $type, $folder ) = @_;
315         my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
316         return $e->die_event unless $e->checkauth;
317         return $e->die_event unless $e->allowed('RUN_REPORTS');
318         my $meth = "retrieve_reporter_${type}_folder";
319         my $f = $e->$meth($folder->id) or return $e->die_event;
320         return 0 if $f->owner ne $e->requestor->id;
321         $meth = "update_reporter_${type}_folder";
322         $e->$meth($folder) or return $e->die_event;
323         $e->commit;
324         return 1;
325 }
326
327
328 __PACKAGE__->register_method(
329         api_name => 'open-ils.reporter.folder.delete',
330         method => 'delete_folder');
331 sub delete_folder {
332         my( $self, $conn, $auth, $type, $folderId ) = @_;
333         my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
334         return $e->die_event unless $e->checkauth;
335         return $e->die_event unless $e->allowed('RUN_REPORTS');
336         my $meth = "retrieve_reporter_${type}_folder";
337         my $f = $e->$meth($folderId) or return $e->die_event;
338         return 0 if $f->owner ne $e->requestor->id;
339         $meth = "delete_reporter_${type}_folder";
340         $e->$meth($f) or return $e->die_event;
341         $e->commit;
342         return 1;
343 }
344
345
346 __PACKAGE__->register_method(
347         api_name => 'open-ils.reporter.template.delete',
348         method => 'delete_template');
349 sub delete_template {
350         my( $self, $conn, $auth, $templateId ) = @_;
351         my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
352         return $e->die_event unless $e->checkauth;
353         return $e->die_event unless $e->allowed('RUN_REPORTS');
354
355         my $t = $e->retrieve_reporter_template($templateId)
356                 or return $e->die_event;
357         return 0 if $t->owner ne $e->requestor->id;
358         $e->delete_reporter_template($t) or return $e->die_event;
359         $e->commit;
360         return 1;
361 }
362
363
364
365 __PACKAGE__->register_method(
366         api_name => 'open-ils.reporter.template.delete.cascade',
367         method => 'cascade_delete_template');
368
369 #__PACKAGE__->register_method(
370 #       api_name => 'open-ils.reporter.template.delete.cascade.force',
371 #       method => 'cascade_delete_template');
372
373 sub cascade_delete_template {
374         my( $self, $conn, $auth, $templateId ) = @_;
375
376         my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
377         return $e->die_event unless $e->checkauth;
378         return $e->die_event unless $e->allowed('RUN_REPORTS');
379
380     my $ret = cascade_delete_template_impl(
381         $e, $e->requestor->id, $templateId, ($self->api_name =~ /force/o) );
382     return $ret if ref $ret; # some fatal event occurred
383
384     $e->rollback if $ret == 0;
385     $e->commit if $ret > 0;
386     return $ret;
387 }
388
389
390 __PACKAGE__->register_method(
391         api_name => 'open-ils.reporter.report.delete.cascade',
392         method => 'cascade_delete_report');
393
394 #__PACKAGE__->register_method(
395 #       api_name => 'open-ils.reporter.report.delete.cascade.force',
396 #       method => 'cascade_delete_report');
397
398 sub cascade_delete_report {
399         my( $self, $conn, $auth, $reportId ) = @_;
400
401         my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
402         return $e->die_event unless $e->checkauth;
403         return $e->die_event unless $e->allowed('RUN_REPORTS');
404
405     my $ret = cascade_delete_report_impl($e, $e->requestor->id, $reportId);
406     return $ret if ref $ret; # some fatal event occurred
407
408     $e->rollback if $ret == 0;
409     $e->commit if $ret > 0;
410     return $ret;
411 }
412
413
414 # performs a cascading template delete
415 # returns 2 if all data was deleted
416 # returns 1 if some data was deleted
417 # returns 0 if no data was deleted
418 # returns event on error
419 sub cascade_delete_template_impl {
420     my( $e, $owner, $templateId ) = @_;
421
422     # fetch the template to delete
423     my $template = $e->search_reporter_template(
424         {id=>$templateId, owner=>$owner})->[0] or return 0;
425
426     # fetch he attached report IDs for this  owner
427     my $reports = $e->search_reporter_report(
428         {template=>$templateId, owner=>$owner},{idlist=>1});
429
430     # delete the attached reports
431     my $all_rpts_deleted = 1;
432     for my $r (@$reports) {
433         my $evt = cascade_delete_report_impl($e, $owner, $r);
434         return $evt if ref $evt;
435         $all_rpts_deleted = 0 unless $evt == 2;
436     }
437
438     # fetch all reports attached to this template that
439     # do not belong to $owner.  If there are any, we can't 
440     # delete the template
441     my $alt_reports = $e->search_reporter_report(
442         {template=>$templateId, owner=>{"!=" => $owner}},{idlist=>1});
443
444     # all_rpts_deleted will be false if a report has an 
445     # attached scheduled owned by a different user
446     return 1 if @$alt_reports or not $all_rpts_deleted;
447
448     $e->delete_reporter_template($template) 
449         or return $e->die_event;
450     return 2;
451 }
452
453 # performs a cascading report delete
454 # returns 2 if all data was deleted
455 # returns 1 if some data was deleted
456 # returns 0 if no data was deleted
457 # returns event on error
458 sub cascade_delete_report_impl {
459     my( $e, $owner, $reportId ) = @_;
460
461     # fetch the report to delete
462     my $report = $e->search_reporter_report(
463         {id=>$reportId, owner=>$owner})->[0] or return 0;
464
465     # fetch the attached schedule IDs for this owner
466     my $scheds = $e->search_reporter_schedule(
467         {report=>$reportId, runner=>$owner},{idlist=>1});
468
469     # delete the attached schedules
470     for my $sched (@$scheds) {
471         my $evt = delete_schedule_impl($e, $sched);
472         return $evt if $evt;
473     }
474
475     # fetch all schedules attached to this report that
476     # do not belong to $owner.  If there are any, we can't 
477     # delete the report
478     my $alt_scheds = $e->search_reporter_schedule(
479         {report=>$reportId, runner=>{"!=" => $owner}},{idlist=>1});
480
481     return 1 if @$alt_scheds;
482
483     $e->delete_reporter_report($report) 
484         or return $e->die_event;
485
486     return 2;
487 }
488
489
490 # deletes the requested schedule
491 # returns undef on success, event on error
492 sub delete_schedule_impl {
493     my( $e, $schedId ) = @_;
494     my $s = $e->retrieve_reporter_schedule($schedId)
495         or return $e->die_event;
496     $e->delete_reporter_schedule($s) or return $e->die_event;
497     return undef;
498 }
499
500
501
502
503 __PACKAGE__->register_method(
504         api_name => 'open-ils.reporter.report.delete',
505         method => 'delete_report');
506 sub delete_report {
507         my( $self, $conn, $auth, $reportId ) = @_;
508         my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
509         return $e->die_event unless $e->checkauth;
510         return $e->die_event unless $e->allowed('RUN_REPORTS');
511
512         my $t = $e->retrieve_reporter_report($reportId)
513                 or return $e->die_event;
514         return 0 if $t->owner ne $e->requestor->id;
515         $e->delete_reporter_report($t) or return $e->die_event;
516         $e->commit;
517         return 1;
518 }
519
520
521 __PACKAGE__->register_method(
522         api_name => 'open-ils.reporter.schedule.delete',
523         method => 'delete_schedule');
524 sub delete_schedule {
525         my( $self, $conn, $auth, $scheduleId ) = @_;
526         my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
527         return $e->die_event unless $e->checkauth;
528         return $e->die_event unless $e->allowed('RUN_REPORTS');
529
530         my $t = $e->retrieve_reporter_schedule($scheduleId)
531                 or return $e->die_event;
532         return 0 if $t->runner ne $e->requestor->id;
533         $e->delete_reporter_schedule($t) or return $e->die_event;
534         $e->commit;
535         return 1;
536 }
537
538
539 __PACKAGE__->register_method(
540         api_name => 'open-ils.reporter.template_has_reports',
541         method => 'has_reports');
542 sub has_reports {
543         my( $self, $conn, $auth, $templateId ) = @_;
544         my $e = new_rstore_editor(authtoken=>$auth);
545         return $e->die_event unless $e->checkauth;
546         return $e->die_event unless $e->allowed('RUN_REPORTS');
547         my $rpts = $e->search_reporter_report({template=>$templateId},{idlist=>1});
548         return 1 if @$rpts;
549         return 0;
550 }
551
552 __PACKAGE__->register_method(
553         api_name => 'open-ils.reporter.report_has_output',
554         method => 'has_output');
555 sub has_output {
556         my( $self, $conn, $auth, $reportId ) = @_;
557         my $e = new_rstore_editor(authtoken=>$auth);
558         return $e->die_event unless $e->checkauth;
559         return $e->die_event unless $e->allowed('RUN_REPORTS');
560         my $outs = $e->search_reporter_schedule({report=>$reportId},{idlist=>1});
561         return 1 if @$outs;
562         return 0;
563 }
564
565
566
567 __PACKAGE__->register_method(
568         method => 'org_full_path',
569         api_name => 'open-ils.reporter.org_unit.full_path');
570
571 sub org_full_path {
572         my( $self, $conn, $orgid ) = @_;
573         return $U->storagereq(
574                 'open-ils.storage.actor.org_unit.full_path.atomic', $orgid );
575 }
576
577
578
579
580 __PACKAGE__->register_method(
581         method => 'magic_fetch_all',
582         api_name => 'open-ils.reporter.magic_fetch');
583 sub magic_fetch_all {
584         my( $self, $conn, $auth, $args ) = @_;
585         my $e = new_editor(authtoken => $auth);
586         return $e->event unless $e->checkauth;
587         return $e->event unless $e->allowed('RUN_REPORTS');
588
589         my $hint = $$args{hint};
590         my $org_col = $$args{org_column};
591         my $orgs = $$args{org};
592
593 #       if ($orgs && !$$args{no_fetch}) {
594 #               ($orgs) = $self
595 #                               ->method_lookup( 'open-ils.reporter.org_unit.full_path' )
596 #                               ->run( @$orgs );
597 #               $orgs = [ map {$_->id} @$orgs ];
598 #       }
599
600         # Find the class the iplements the given hint
601         my ($class) = grep { 
602                 $Fieldmapper::fieldmap->{$_}{hint} eq $hint } Fieldmapper->classes;
603
604         return undef unless $class->Selector;
605
606         $class =~ s/Fieldmapper:://og;
607         $class =~ s/::/_/og;
608         
609         my $method;
610         my $margs;
611
612         if( $org_col ) {
613                 $method = "search_$class";
614                 $margs = { $org_col => $orgs };
615         } else {
616                 $method = "retrieve_all_$class";
617         }
618
619         $logger->info("reporter.magic_fetch => $method");
620
621         return $e->$method($margs);
622 }
623
624
625 1;