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');
24 return 0 if $folder->owner ne $e->requestor->id;
26 $folder->owner($e->requestor->id);
27 my $meth = "create_reporter_${type}_folder";
28 $e->$meth($folder) or return $e->die_event;
35 __PACKAGE__->register_method(
36 api_name => 'open-ils.reporter.report.exists',
37 method => 'report_exists',
39 Returns 1 if a report with the given name and folder already exists.
44 my( $self, $conn, $auth, $report ) = @_;
46 my $e = new_rstore_editor(authtoken=>$auth);
47 return $e->event unless $e->checkauth;
48 return $e->event unless $e->allowed('RUN_REPORTS');
50 my $existing = $e->search_reporter_report(
51 {folder=>$report->folder, name=>$report->name});
52 return 1 if @$existing;
57 __PACKAGE__->register_method(
58 api_name => 'open-ils.reporter.folder.visible.retrieve',
59 method => 'retrieve_visible_folders'
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');
69 $class = 'rtf' if $type eq 'template';
70 $class = 'rof' if $type eq 'output';
73 flesh_fields => { $class => ['owner', 'share_with']},
74 order_by => { $class => 'name ASC'}
77 my $meth = "search_reporter_${type}_folder";
78 my $fs = $e->$meth( [{ owner => $e->requestor->id }, $flesh] );
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;
90 owner => { '!=' => $e->requestor->id }
101 __PACKAGE__->register_method(
102 api_name => 'open-ils.reporter.folder_data.retrieve',
103 method => 'retrieve_folder_data'
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}";
113 $class = 'rt' if $type eq 'template';
116 flesh_fields => { $class => ['owner']},
117 order_by => { $class => 'create_time DESC'}
119 $flesh->{limit} = $limit if $limit;
120 return $e->$meth([{ folder => $folderid }, $flesh]);
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');
132 my $search = { folder => $folderId };
134 { folder => $folderId },
136 order_by => { rs => 'run_time DESC' } ,
138 flesh_fields => { rs => ['report'] }
142 $query->[1]->{limit} = $limit if $limit;
143 $query->[0]->{complete_time} = undef unless $complete;
144 $query->[0]->{complete_time} = { '!=' => undef } if $complete;
146 return $e->search_reporter_schedule($query);
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)
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);
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;
177 my $tmpl = $e->create_reporter_template($template)
178 or return $e->die_event;
187 __PACKAGE__->register_method(
188 api_name => 'open-ils.reporter.report.create',
189 method => '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);
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;
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;
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;
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)
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)
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;
271 __PACKAGE__->register_method(
272 api_name => 'open-ils.reporter.report.update',
273 method => '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 ) {
285 $e->update_reporter_report($report)
286 or return $e->die_event;
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 ) {
308 $e->update_reporter_schedule($schedule)
309 or return $e->die_event;
315 __PACKAGE__->register_method(
316 api_name => 'open-ils.reporter.folder.update',
317 method => '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;
333 __PACKAGE__->register_method(
334 api_name => 'open-ils.reporter.folder.delete',
335 method => '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;
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');
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;
370 __PACKAGE__->register_method(
371 api_name => 'open-ils.reporter.template.delete.cascade',
372 method => 'cascade_delete_template');
374 #__PACKAGE__->register_method(
375 # api_name => 'open-ils.reporter.template.delete.cascade.force',
376 # method => 'cascade_delete_template');
378 sub cascade_delete_template {
379 my( $self, $conn, $auth, $templateId ) = @_;
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');
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
389 $e->rollback if $ret == 0;
390 $e->commit if $ret > 0;
395 __PACKAGE__->register_method(
396 api_name => 'open-ils.reporter.report.delete.cascade',
397 method => 'cascade_delete_report');
399 #__PACKAGE__->register_method(
400 # api_name => 'open-ils.reporter.report.delete.cascade.force',
401 # method => 'cascade_delete_report');
403 sub cascade_delete_report {
404 my( $self, $conn, $auth, $reportId ) = @_;
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');
410 my $ret = cascade_delete_report_impl($e, $e->requestor->id, $reportId);
411 return $ret if ref $ret; # some fatal event occurred
413 $e->rollback if $ret == 0;
414 $e->commit if $ret > 0;
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 ) = @_;
427 # fetch the template to delete
428 my $template = $e->search_reporter_template(
429 {id=>$templateId, owner=>$owner})->[0] or return 0;
431 # fetch he attached report IDs for this owner
432 my $reports = $e->search_reporter_report(
433 {template=>$templateId, owner=>$owner},{idlist=>1});
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;
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});
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;
453 $e->delete_reporter_template($template)
454 or return $e->die_event;
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 ) = @_;
466 # fetch the report to delete
467 my $report = $e->search_reporter_report(
468 {id=>$reportId, owner=>$owner})->[0] or return 0;
470 # fetch the attached schedule IDs for this owner
471 my $scheds = $e->search_reporter_schedule(
472 {report=>$reportId, runner=>$owner},{idlist=>1});
474 # delete the attached schedules
475 for my $sched (@$scheds) {
476 my $evt = delete_schedule_impl($e, $sched);
480 # fetch all schedules attached to this report that
481 # do not belong to $owner. If there are any, we can't
483 my $alt_scheds = $e->search_reporter_schedule(
484 {report=>$reportId, runner=>{"!=" => $owner}},{idlist=>1});
486 return 1 if @$alt_scheds;
488 $e->delete_reporter_report($report)
489 or return $e->die_event;
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;
508 __PACKAGE__->register_method(
509 api_name => 'open-ils.reporter.report.delete',
510 method => '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');
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;
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');
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;
544 __PACKAGE__->register_method(
545 api_name => 'open-ils.reporter.template_has_reports',
546 method => '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});
557 __PACKAGE__->register_method(
558 api_name => 'open-ils.reporter.report_has_output',
559 method => '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});
572 __PACKAGE__->register_method(
573 method => 'org_full_path',
574 api_name => 'open-ils.reporter.org_unit.full_path');
577 my( $self, $conn, $orgid ) = @_;
578 return $U->storagereq(
579 'open-ils.storage.actor.org_unit.full_path.atomic', $orgid );
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');
594 my $hint = $$args{hint};
595 my $org_col = $$args{org_column};
596 my $orgs = $$args{org};
598 # if ($orgs && !$$args{no_fetch}) {
600 # ->method_lookup( 'open-ils.reporter.org_unit.full_path' )
602 # $orgs = [ map {$_->id} @$orgs ];
605 # Find the class the iplements the given hint
607 $Fieldmapper::fieldmap->{$_}{hint} eq $hint } Fieldmapper->classes;
609 return undef unless $class->Selector;
611 $class =~ s/Fieldmapper:://og;
618 $method = "search_$class";
619 $margs = { $org_col => $orgs };
621 $method = "retrieve_all_$class";
624 $logger->info("reporter.magic_fetch => $method");
626 return $e->$method($margs);