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