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";
12 __PACKAGE__->register_method(
13 api_name => 'open-ils.reporter.folder.create',
14 method => 'create_folder'
18 my( $self, $conn, $auth, $type, $folder ) = @_;
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'));
25 return 0 if $folder->owner ne $e->requestor->id;
27 $folder->owner($e->requestor->id);
28 my $meth = "create_reporter_${type}_folder";
29 $e->$meth($folder) or return $e->die_event;
36 __PACKAGE__->register_method(
37 api_name => 'open-ils.reporter.report.exists',
38 method => 'report_exists',
40 Returns 1 if a report with the given name and folder already exists.
45 my( $self, $conn, $auth, $report ) = @_;
47 my $e = new_rstore_editor(authtoken=>$auth);
48 return $e->event unless $e->checkauth;
49 return $e->event unless $e->allowed('RUN_REPORTS');
51 my $existing = $e->search_reporter_report(
52 {folder=>$report->folder, name=>$report->name});
53 return 1 if @$existing;
58 __PACKAGE__->register_method(
59 api_name => 'open-ils.reporter.folder.visible.retrieve',
60 method => 'retrieve_visible_folders'
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']);
70 return $e->event unless $e->allowed('RUN_REPORTS');
74 $class = 'rtf' if $type eq 'template';
75 $class = 'rof' if $type eq 'output';
78 flesh_fields => { $class => ['owner', 'share_with']},
79 order_by => { $class => 'name ASC'}
82 my $meth = "search_reporter_${type}_folder";
83 my $fs = $e->$meth( [{ owner => $e->requestor->id }, $flesh] );
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;
95 owner => { '!=' => $e->requestor->id }
106 __PACKAGE__->register_method(
107 api_name => 'open-ils.reporter.folder_data.retrieve',
108 method => 'retrieve_folder_data'
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']);
118 return $e->event unless $e->allowed('RUN_REPORTS');
120 my $meth = "search_reporter_${type}";
122 $class = 'rt' if $type eq 'template';
125 flesh_fields => { $class => ['owner']},
126 order_by => { $class => 'create_time DESC'}
128 $flesh->{limit} = $limit if $limit;
129 return $e->$meth([{ folder => $folderid }, $flesh]);
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']);
141 my $search = { folder => $folderId };
143 { folder => $folderId },
145 order_by => { rs => 'run_time DESC' } ,
147 flesh_fields => { rs => ['report'] }
151 $query->[1]->{limit} = $limit if $limit;
152 $query->[0]->{complete_time} = undef unless $complete;
153 $query->[0]->{complete_time} = { '!=' => undef } if $complete;
155 return $e->search_reporter_schedule($query);
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)
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);
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;
187 my $tmpl = $e->create_reporter_template($template)
188 or return $e->die_event;
197 __PACKAGE__->register_method(
198 api_name => 'open-ils.reporter.report.create',
199 method => '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);
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;
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;
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;
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)
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)
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;
282 __PACKAGE__->register_method(
283 api_name => 'open-ils.reporter.report.update',
284 method => '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 ) {
296 $e->update_reporter_report($report)
297 or return $e->die_event;
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 ) {
319 $e->update_reporter_schedule($schedule)
320 or return $e->die_event;
326 __PACKAGE__->register_method(
327 api_name => 'open-ils.reporter.folder.update',
328 method => '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;
344 __PACKAGE__->register_method(
345 api_name => 'open-ils.reporter.folder.delete',
346 method => '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;
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');
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;
381 __PACKAGE__->register_method(
382 api_name => 'open-ils.reporter.template.delete.cascade',
383 method => 'cascade_delete_template');
385 #__PACKAGE__->register_method(
386 # api_name => 'open-ils.reporter.template.delete.cascade.force',
387 # method => 'cascade_delete_template');
389 sub cascade_delete_template {
390 my( $self, $conn, $auth, $templateId ) = @_;
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');
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
400 $e->rollback if $ret == 0;
401 $e->commit if $ret > 0;
406 __PACKAGE__->register_method(
407 api_name => 'open-ils.reporter.report.delete.cascade',
408 method => 'cascade_delete_report');
410 #__PACKAGE__->register_method(
411 # api_name => 'open-ils.reporter.report.delete.cascade.force',
412 # method => 'cascade_delete_report');
414 sub cascade_delete_report {
415 my( $self, $conn, $auth, $reportId ) = @_;
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');
421 my $ret = cascade_delete_report_impl($e, $e->requestor->id, $reportId);
422 return $ret if ref $ret; # some fatal event occurred
424 $e->rollback if $ret == 0;
425 $e->commit if $ret > 0;
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 ) = @_;
438 # fetch the template to delete
439 my $template = $e->search_reporter_template(
440 {id=>$templateId, owner=>$owner})->[0] or return 0;
442 # fetch he attached report IDs for this owner
443 my $reports = $e->search_reporter_report(
444 {template=>$templateId, owner=>$owner},{idlist=>1});
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;
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});
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;
464 $e->delete_reporter_template($template)
465 or return $e->die_event;
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 ) = @_;
477 # fetch the report to delete
478 my $report = $e->search_reporter_report(
479 {id=>$reportId, owner=>$owner})->[0] or return 0;
481 # fetch the attached schedule IDs for this owner
482 my $scheds = $e->search_reporter_schedule(
483 {report=>$reportId, runner=>$owner},{idlist=>1});
485 # delete the attached schedules
486 for my $sched (@$scheds) {
487 my $evt = delete_schedule_impl($e, $sched);
491 # fetch all schedules attached to this report that
492 # do not belong to $owner. If there are any, we can't
494 my $alt_scheds = $e->search_reporter_schedule(
495 {report=>$reportId, runner=>{"!=" => $owner}},{idlist=>1});
497 return 1 if @$alt_scheds;
499 $e->delete_reporter_report($report)
500 or return $e->die_event;
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;
519 __PACKAGE__->register_method(
520 api_name => 'open-ils.reporter.report.delete',
521 method => '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');
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;
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');
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;
555 __PACKAGE__->register_method(
556 api_name => 'open-ils.reporter.template_has_reports',
557 method => '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});
568 __PACKAGE__->register_method(
569 api_name => 'open-ils.reporter.report_has_output',
570 method => '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});
583 __PACKAGE__->register_method(
584 method => 'org_full_path',
585 api_name => 'open-ils.reporter.org_unit.full_path');
588 my( $self, $conn, $orgid ) = @_;
589 return $U->storagereq(
590 'open-ils.storage.actor.org_unit.full_path.atomic', $orgid );
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');
605 my $hint = $$args{hint};
606 my $org_col = $$args{org_column};
607 my $orgs = $$args{org};
609 # if ($orgs && !$$args{no_fetch}) {
611 # ->method_lookup( 'open-ils.reporter.org_unit.full_path' )
613 # $orgs = [ map {$_->id} @$orgs ];
616 # Find the class the iplements the given hint
618 $Fieldmapper::fieldmap->{$_}{hint} eq $hint } Fieldmapper->classes;
620 return undef unless $class->Selector;
622 $class =~ s/Fieldmapper:://og;
629 $method = "search_$class";
630 $margs = { $org_col => $orgs };
632 $method = "retrieve_all_$class";
635 $logger->info("reporter.magic_fetch => $method");
637 return $e->$method($margs);