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';
71 my $flesh = {flesh => 1,flesh_fields => { $class => ['owner', 'share_with']}};
73 my $meth = "search_reporter_${type}_folder";
74 my $fs = $e->$meth( [{ owner => $e->requestor->id }, $flesh] );
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;
86 owner => { '!=' => $e->requestor->id }
97 __PACKAGE__->register_method(
98 api_name => 'open-ils.reporter.folder_data.retrieve',
99 method => 'retrieve_folder_data'
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}";
109 $class = 'rt' if $type eq 'template';
112 flesh_fields => { $class => ['owner']},
113 order_by => { $class => 'create_time DESC'}
115 $flesh->{limit} = $limit if $limit;
116 return $e->$meth([{ folder => $folderid }, $flesh]);
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');
128 my $search = { folder => $folderId };
130 { folder => $folderId },
132 order_by => { rs => 'run_time DESC' } ,
134 flesh_fields => { rs => ['report'] }
138 $query->[1]->{limit} = $limit if $limit;
139 $query->[0]->{complete_time} = undef unless $complete;
140 $query->[0]->{complete_time} = { '!=' => undef } if $complete;
142 return $e->search_reporter_schedule($query);
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)
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);
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;
173 my $tmpl = $e->create_reporter_template($template)
174 or return $e->die_event;
183 __PACKAGE__->register_method(
184 api_name => 'open-ils.reporter.report.create',
185 method => '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);
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;
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;
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;
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)
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)
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;
267 __PACKAGE__->register_method(
268 api_name => 'open-ils.reporter.report.update',
269 method => '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 ) {
281 $e->update_reporter_report($report)
282 or return $e->die_event;
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 ) {
304 $e->update_reporter_schedule($schedule)
305 or return $e->die_event;
311 __PACKAGE__->register_method(
312 api_name => 'open-ils.reporter.folder.update',
313 method => '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;
329 __PACKAGE__->register_method(
330 api_name => 'open-ils.reporter.folder.delete',
331 method => '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;
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');
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;
366 __PACKAGE__->register_method(
367 api_name => 'open-ils.reporter.template.delete.cascade',
368 method => 'cascade_delete_template');
370 #__PACKAGE__->register_method(
371 # api_name => 'open-ils.reporter.template.delete.cascade.force',
372 # method => 'cascade_delete_template');
374 sub cascade_delete_template {
375 my( $self, $conn, $auth, $templateId ) = @_;
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');
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
385 $e->rollback if $ret == 0;
386 $e->commit if $ret > 0;
391 __PACKAGE__->register_method(
392 api_name => 'open-ils.reporter.report.delete.cascade',
393 method => 'cascade_delete_report');
395 #__PACKAGE__->register_method(
396 # api_name => 'open-ils.reporter.report.delete.cascade.force',
397 # method => 'cascade_delete_report');
399 sub cascade_delete_report {
400 my( $self, $conn, $auth, $reportId ) = @_;
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');
406 my $ret = cascade_delete_report_impl($e, $e->requestor->id, $reportId);
407 return $ret if ref $ret; # some fatal event occurred
409 $e->rollback if $ret == 0;
410 $e->commit if $ret > 0;
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 ) = @_;
423 # fetch the template to delete
424 my $template = $e->search_reporter_template(
425 {id=>$templateId, owner=>$owner})->[0] or return 0;
427 # fetch he attached report IDs for this owner
428 my $reports = $e->search_reporter_report(
429 {template=>$templateId, owner=>$owner},{idlist=>1});
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;
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});
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;
449 $e->delete_reporter_template($template)
450 or return $e->die_event;
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 ) = @_;
462 # fetch the report to delete
463 my $report = $e->search_reporter_report(
464 {id=>$reportId, owner=>$owner})->[0] or return 0;
466 # fetch the attached schedule IDs for this owner
467 my $scheds = $e->search_reporter_schedule(
468 {report=>$reportId, runner=>$owner},{idlist=>1});
470 # delete the attached schedules
471 for my $sched (@$scheds) {
472 my $evt = delete_schedule_impl($e, $sched);
476 # fetch all schedules attached to this report that
477 # do not belong to $owner. If there are any, we can't
479 my $alt_scheds = $e->search_reporter_schedule(
480 {report=>$reportId, runner=>{"!=" => $owner}},{idlist=>1});
482 return 1 if @$alt_scheds;
484 $e->delete_reporter_report($report)
485 or return $e->die_event;
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;
504 __PACKAGE__->register_method(
505 api_name => 'open-ils.reporter.report.delete',
506 method => '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');
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;
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');
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;
540 __PACKAGE__->register_method(
541 api_name => 'open-ils.reporter.template_has_reports',
542 method => '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});
553 __PACKAGE__->register_method(
554 api_name => 'open-ils.reporter.report_has_output',
555 method => '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});
568 __PACKAGE__->register_method(
569 method => 'org_full_path',
570 api_name => 'open-ils.reporter.org_unit.full_path');
573 my( $self, $conn, $orgid ) = @_;
574 return $U->storagereq(
575 'open-ils.storage.actor.org_unit.full_path.atomic', $orgid );
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');
590 my $hint = $$args{hint};
591 my $org_col = $$args{org_column};
592 my $orgs = $$args{org};
594 # if ($orgs && !$$args{no_fetch}) {
596 # ->method_lookup( 'open-ils.reporter.org_unit.full_path' )
598 # $orgs = [ map {$_->id} @$orgs ];
601 # Find the class the iplements the given hint
603 $Fieldmapper::fieldmap->{$_}{hint} eq $hint } Fieldmapper->classes;
605 return undef unless $class->Selector;
607 $class =~ s/Fieldmapper:://og;
614 $method = "search_$class";
615 $margs = { $org_col => $orgs };
617 $method = "retrieve_all_$class";
620 $logger->info("reporter.magic_fetch => $method");
622 return $e->$method($margs);