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