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