1 package OpenILS::Application::Reporter;
2 use base qw/OpenSRF::Application/;
3 use strict; use warnings;
4 use OpenSRF::Utils::Logger qw/$logger/;
5 use OpenILS::Utils::CStoreEditor qw/:funcs/;
6 use OpenILS::Utils::Fieldmapper;
7 use OpenILS::Application::AppUtils;
8 my $U = "OpenILS::Application::AppUtils";
11 __PACKAGE__->register_method(
12 api_name => 'open-ils.reporter.folder.create',
13 method => 'create_folder'
17 my( $self, $conn, $auth, $type, $folder ) = @_;
19 my $e = new_rstore_editor(xact=>1, authtoken=>$auth);
20 return $e->die_event unless $e->checkauth;
21 return $e->die_event unless $e->allowed('RUN_REPORTS');
23 return 0 if $folder->owner ne $e->requestor->id;
25 $folder->owner($e->requestor->id);
26 my $meth = "create_reporter_${type}_folder";
27 $e->$meth($folder) or return $e->die_event;
34 __PACKAGE__->register_method(
35 api_name => 'open-ils.reporter.report.exists',
36 method => 'report_exists',
38 Returns 1 if a report with the given name and folder already exists.
43 my( $self, $conn, $auth, $report ) = @_;
45 my $e = new_rstore_editor(authtoken=>$auth);
46 return $e->event unless $e->checkauth;
47 return $e->event unless $e->allowed('RUN_REPORTS');
49 my $existing = $e->search_reporter_report(
50 {folder=>$report->folder, name=>$report->name});
51 return 1 if @$existing;
56 __PACKAGE__->register_method(
57 api_name => 'open-ils.reporter.folder.visible.retrieve',
58 method => 'retrieve_visible_folders'
61 sub retrieve_visible_folders {
62 my( $self, $conn, $auth, $type ) = @_;
63 my $e = new_rstore_editor(authtoken=>$auth);
64 return $e->event unless $e->checkauth;
65 return $e->event unless $e->allowed('RUN_REPORTS');
68 $class = 'rtf' if $type eq 'template';
69 $class = 'rof' if $type eq 'output';
70 my $flesh = {flesh => 1,flesh_fields => { $class => ['owner', 'share_with']}};
72 my $meth = "search_reporter_${type}_folder";
73 my $fs = $e->$meth( [{ owner => $e->requestor->id }, $flesh] );
76 my $o = $U->storagereq(
77 'open-ils.storage.actor.org_unit.full_path.atomic', $e->requestor->ws_ou);
78 push( @orgs, $_->id ) for @$o;
85 owner => { '!=' => $e->requestor->id }
96 __PACKAGE__->register_method(
97 api_name => 'open-ils.reporter.folder_data.retrieve',
98 method => 'retrieve_folder_data'
101 sub retrieve_folder_data {
102 my( $self, $conn, $auth, $type, $folderid, $limit ) = @_;
103 my $e = new_rstore_editor(authtoken=>$auth);
104 return $e->event unless $e->checkauth;
105 return $e->event unless $e->allowed('RUN_REPORTS');
106 my $meth = "search_reporter_${type}";
108 $class = 'rt' if $type eq 'template';
111 flesh_fields => { $class => ['owner']},
112 order_by => { $class => 'create_time DESC'}
114 $flesh->{limit} = $limit if $limit;
115 return $e->$meth([{ folder => $folderid }, $flesh]);
118 __PACKAGE__->register_method(
119 api_name => 'open-ils.reporter.schedule.retrieve_by_folder',
120 method => 'retrieve_schedules');
121 sub retrieve_schedules {
122 my( $self, $conn, $auth, $folderId, $limit, $complete ) = @_;
123 my $e = new_rstore_editor(authtoken=>$auth);
124 return $e->event unless $e->checkauth;
125 return $e->event unless $e->allowed('RUN_REPORTS');
127 my $search = { folder => $folderId };
129 { folder => $folderId },
131 order_by => { rs => 'run_time DESC' } ,
133 flesh_fields => { rs => ['report'] }
137 $query->[1]->{limit} = $limit if $limit;
138 $query->[0]->{complete_time} = undef unless $complete;
139 $query->[0]->{complete_time} = { '!=' => undef } if $complete;
141 return $e->search_reporter_schedule($query);
144 __PACKAGE__->register_method(
145 api_name => 'open-ils.reporter.schedule.retrieve',
146 method => 'retrieve_schedules');
147 sub retrieve_schedule {
148 my( $self, $conn, $auth, $sched_id ) = @_;
149 my $e = new_rstore_editor(authtoken=>$auth);
150 return $e->event unless $e->checkauth;
151 return $e->event unless $e->allowed('RUN_REPORTS');
152 my $s = $e->retrieve_reporter_schedule($sched_id)
158 __PACKAGE__->register_method(
159 api_name => 'open-ils.reporter.template.create',
160 method => 'create_template');
161 sub create_template {
162 my( $self, $conn, $auth, $template ) = @_;
163 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
164 return $e->die_event unless $e->checkauth;
165 return $e->die_event unless $e->allowed('RUN_REPORTS');
166 $template->owner($e->requestor->id);
168 my $existing = $e->search_reporter_template( {owner=>$template->owner,
169 folder=>$template->folder, name=>$template->name},{idlist=>1});
170 return OpenILS::Event->new('REPORT_TEMPLATE_EXISTS') if @$existing;
172 my $tmpl = $e->create_reporter_template($template)
173 or return $e->die_event;
182 __PACKAGE__->register_method(
183 api_name => 'open-ils.reporter.report.create',
184 method => 'create_report');
186 my( $self, $conn, $auth, $report, $schedule ) = @_;
187 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
188 return $e->die_event unless $e->checkauth;
189 return $e->die_event unless $e->allowed('RUN_REPORTS');
190 $report->owner($e->requestor->id);
192 my $existing = $e->search_reporter_report( {owner=>$report->owner,
193 folder=>$report->folder, name=>$report->name},{idlist=>1});
194 return OpenILS::Event->new('REPORT_REPORT_EXISTS') if @$existing;
196 my $rpt = $e->create_reporter_report($report)
197 or return $e->die_event;
198 $schedule->report($rpt->id);
199 $schedule->runner($e->requestor->id);
200 $e->create_reporter_schedule($schedule) or return $e->die_event;
206 __PACKAGE__->register_method(
207 api_name => 'open-ils.scheduleer.schedule.create',
208 method => 'create_schedule');
209 sub create_schedule {
210 my( $self, $conn, $auth, $schedule ) = @_;
211 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
212 return $e->die_event unless $e->checkauth;
213 return $e->die_event unless $e->allowed('RUN_REPORTS');
214 my $sched = $e->create_reporter_schedule($schedule)
215 or return $e->die_event;
220 __PACKAGE__->register_method(
221 api_name => 'open-ils.reporter.template.retrieve',
222 method => 'retrieve_template');
223 sub retrieve_template {
224 my( $self, $conn, $auth, $id ) = @_;
225 my $e = new_rstore_editor(authtoken=>$auth);
226 return $e->event unless $e->checkauth;
227 return $e->event unless $e->allowed('RUN_REPORTS');
228 my $t = $e->retrieve_reporter_template($id)
234 __PACKAGE__->register_method(
235 api_name => 'open-ils.reporter.report.retrieve',
236 method => 'retrieve_report');
237 sub retrieve_report {
238 my( $self, $conn, $auth, $id ) = @_;
239 my $e = new_rstore_editor(authtoken=>$auth);
240 return $e->event unless $e->checkauth;
241 return $e->event unless $e->allowed('RUN_REPORTS');
242 my $r = $e->retrieve_reporter_report($id)
248 __PACKAGE__->register_method(
249 api_name => 'open-ils.reporter.template.update',
250 method => 'update_template');
251 sub update_template {
252 my( $self, $conn, $auth, $tmpl ) = @_;
253 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
254 return $e->die_event unless $e->checkauth;
255 return $e->die_event unless $e->allowed('RUN_REPORTS');
256 my $t = $e->retrieve_reporter_template($tmpl->id)
257 or return $e->die_event;
258 return 0 if $t->owner ne $e->requestor->id;
259 $e->update_reporter_template($tmpl)
260 or return $e->die_event;
266 __PACKAGE__->register_method(
267 api_name => 'open-ils.reporter.report.update',
268 method => 'update_report');
270 my( $self, $conn, $auth, $report ) = @_;
271 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
272 return $e->die_event unless $e->checkauth;
273 return $e->die_event unless $e->allowed('RUN_REPORTS');
274 my $r = $e->retrieve_reporter_report($report->id)
275 or return $e->die_event;
276 if( $r->owner ne $e->requestor->id ) {
280 $e->update_reporter_report($report)
281 or return $e->die_event;
287 __PACKAGE__->register_method(
288 api_name => 'open-ils.reporter.schedule.update',
289 method => 'update_schedule');
290 sub update_schedule {
291 my( $self, $conn, $auth, $schedule ) = @_;
292 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
293 return $e->die_event unless $e->checkauth;
294 return $e->die_event unless $e->allowed('RUN_REPORTS');
295 my $s = $e->retrieve_reporter_schedule($schedule->id)
296 or return $e->die_event;
297 my $r = $e->retrieve_reporter_report($s->report)
298 or return $e->die_event;
299 if( $r->owner ne $e->requestor->id ) {
303 $e->update_reporter_schedule($schedule)
304 or return $e->die_event;
310 __PACKAGE__->register_method(
311 api_name => 'open-ils.reporter.folder.update',
312 method => 'update_folder');
314 my( $self, $conn, $auth, $type, $folder ) = @_;
315 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
316 return $e->die_event unless $e->checkauth;
317 return $e->die_event unless $e->allowed('RUN_REPORTS');
318 my $meth = "retrieve_reporter_${type}_folder";
319 my $f = $e->$meth($folder->id) or return $e->die_event;
320 return 0 if $f->owner ne $e->requestor->id;
321 $meth = "update_reporter_${type}_folder";
322 $e->$meth($folder) or return $e->die_event;
328 __PACKAGE__->register_method(
329 api_name => 'open-ils.reporter.folder.delete',
330 method => 'delete_folder');
332 my( $self, $conn, $auth, $type, $folderId ) = @_;
333 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
334 return $e->die_event unless $e->checkauth;
335 return $e->die_event unless $e->allowed('RUN_REPORTS');
336 my $meth = "retrieve_reporter_${type}_folder";
337 my $f = $e->$meth($folderId) or return $e->die_event;
338 return 0 if $f->owner ne $e->requestor->id;
339 $meth = "delete_reporter_${type}_folder";
340 $e->$meth($f) or return $e->die_event;
346 __PACKAGE__->register_method(
347 api_name => 'open-ils.reporter.template.delete',
348 method => 'delete_template');
349 sub delete_template {
350 my( $self, $conn, $auth, $templateId ) = @_;
351 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
352 return $e->die_event unless $e->checkauth;
353 return $e->die_event unless $e->allowed('RUN_REPORTS');
355 my $t = $e->retrieve_reporter_template($templateId)
356 or return $e->die_event;
357 return 0 if $t->owner ne $e->requestor->id;
358 $e->delete_reporter_template($t) or return $e->die_event;
365 __PACKAGE__->register_method(
366 api_name => 'open-ils.reporter.template.delete.cascade',
367 method => 'cascade_delete_template');
369 #__PACKAGE__->register_method(
370 # api_name => 'open-ils.reporter.template.delete.cascade.force',
371 # method => 'cascade_delete_template');
373 sub cascade_delete_template {
374 my( $self, $conn, $auth, $templateId ) = @_;
376 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
377 return $e->die_event unless $e->checkauth;
378 return $e->die_event unless $e->allowed('RUN_REPORTS');
380 my $ret = cascade_delete_template_impl(
381 $e, $e->requestor->id, $templateId, ($self->api_name =~ /force/o) );
382 return $ret if ref $ret; # some fatal event occurred
384 $e->rollback if $ret == 0;
385 $e->commit if $ret > 0;
390 __PACKAGE__->register_method(
391 api_name => 'open-ils.reporter.report.delete.cascade',
392 method => 'cascade_delete_report');
394 #__PACKAGE__->register_method(
395 # api_name => 'open-ils.reporter.report.delete.cascade.force',
396 # method => 'cascade_delete_report');
398 sub cascade_delete_report {
399 my( $self, $conn, $auth, $reportId ) = @_;
401 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
402 return $e->die_event unless $e->checkauth;
403 return $e->die_event unless $e->allowed('RUN_REPORTS');
405 my $ret = cascade_delete_report_impl($e, $e->requestor->id, $reportId);
406 return $ret if ref $ret; # some fatal event occurred
408 $e->rollback if $ret == 0;
409 $e->commit if $ret > 0;
414 # performs a cascading template delete
415 # returns 2 if all data was deleted
416 # returns 1 if some data was deleted
417 # returns 0 if no data was deleted
418 # returns event on error
419 sub cascade_delete_template_impl {
420 my( $e, $owner, $templateId ) = @_;
422 # fetch the template to delete
423 my $template = $e->search_reporter_template(
424 {id=>$templateId, owner=>$owner})->[0] or return 0;
426 # fetch he attached report IDs for this owner
427 my $reports = $e->search_reporter_report(
428 {template=>$templateId, owner=>$owner},{idlist=>1});
430 # delete the attached reports
431 my $all_rpts_deleted = 1;
432 for my $r (@$reports) {
433 my $evt = cascade_delete_report_impl($e, $owner, $r);
434 return $evt if ref $evt;
435 $all_rpts_deleted = 0 unless $evt == 2;
438 # fetch all reports attached to this template that
439 # do not belong to $owner. If there are any, we can't
440 # delete the template
441 my $alt_reports = $e->search_reporter_report(
442 {template=>$templateId, owner=>{"!=" => $owner}},{idlist=>1});
444 # all_rpts_deleted will be false if a report has an
445 # attached scheduled owned by a different user
446 return 1 if @$alt_reports or not $all_rpts_deleted;
448 $e->delete_reporter_template($template)
449 or return $e->die_event;
453 # performs a cascading report delete
454 # returns 2 if all data was deleted
455 # returns 1 if some data was deleted
456 # returns 0 if no data was deleted
457 # returns event on error
458 sub cascade_delete_report_impl {
459 my( $e, $owner, $reportId ) = @_;
461 # fetch the report to delete
462 my $report = $e->search_reporter_report(
463 {id=>$reportId, owner=>$owner})->[0] or return 0;
465 # fetch the attached schedule IDs for this owner
466 my $scheds = $e->search_reporter_schedule(
467 {report=>$reportId, runner=>$owner},{idlist=>1});
469 # delete the attached schedules
470 for my $sched (@$scheds) {
471 my $evt = delete_schedule_impl($e, $sched);
475 # fetch all schedules attached to this report that
476 # do not belong to $owner. If there are any, we can't
478 my $alt_scheds = $e->search_reporter_schedule(
479 {report=>$reportId, runner=>{"!=" => $owner}},{idlist=>1});
481 return 1 if @$alt_scheds;
483 $e->delete_reporter_report($report)
484 or return $e->die_event;
490 # deletes the requested schedule
491 # returns undef on success, event on error
492 sub delete_schedule_impl {
493 my( $e, $schedId ) = @_;
494 my $s = $e->retrieve_reporter_schedule($schedId)
495 or return $e->die_event;
496 $e->delete_reporter_schedule($s) or return $e->die_event;
503 __PACKAGE__->register_method(
504 api_name => 'open-ils.reporter.report.delete',
505 method => 'delete_report');
507 my( $self, $conn, $auth, $reportId ) = @_;
508 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
509 return $e->die_event unless $e->checkauth;
510 return $e->die_event unless $e->allowed('RUN_REPORTS');
512 my $t = $e->retrieve_reporter_report($reportId)
513 or return $e->die_event;
514 return 0 if $t->owner ne $e->requestor->id;
515 $e->delete_reporter_report($t) or return $e->die_event;
521 __PACKAGE__->register_method(
522 api_name => 'open-ils.reporter.schedule.delete',
523 method => 'delete_schedule');
524 sub delete_schedule {
525 my( $self, $conn, $auth, $scheduleId ) = @_;
526 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
527 return $e->die_event unless $e->checkauth;
528 return $e->die_event unless $e->allowed('RUN_REPORTS');
530 my $t = $e->retrieve_reporter_schedule($scheduleId)
531 or return $e->die_event;
532 return 0 if $t->runner ne $e->requestor->id;
533 $e->delete_reporter_schedule($t) or return $e->die_event;
539 __PACKAGE__->register_method(
540 api_name => 'open-ils.reporter.template_has_reports',
541 method => 'has_reports');
543 my( $self, $conn, $auth, $templateId ) = @_;
544 my $e = new_rstore_editor(authtoken=>$auth);
545 return $e->die_event unless $e->checkauth;
546 return $e->die_event unless $e->allowed('RUN_REPORTS');
547 my $rpts = $e->search_reporter_report({template=>$templateId},{idlist=>1});
552 __PACKAGE__->register_method(
553 api_name => 'open-ils.reporter.report_has_output',
554 method => 'has_output');
556 my( $self, $conn, $auth, $reportId ) = @_;
557 my $e = new_rstore_editor(authtoken=>$auth);
558 return $e->die_event unless $e->checkauth;
559 return $e->die_event unless $e->allowed('RUN_REPORTS');
560 my $outs = $e->search_reporter_schedule({report=>$reportId},{idlist=>1});
567 __PACKAGE__->register_method(
568 method => 'org_full_path',
569 api_name => 'open-ils.reporter.org_unit.full_path');
572 my( $self, $conn, $orgid ) = @_;
573 return $U->storagereq(
574 'open-ils.storage.actor.org_unit.full_path.atomic', $orgid );
580 __PACKAGE__->register_method(
581 method => 'magic_fetch_all',
582 api_name => 'open-ils.reporter.magic_fetch');
583 sub magic_fetch_all {
584 my( $self, $conn, $auth, $args ) = @_;
585 my $e = new_editor(authtoken => $auth);
586 return $e->event unless $e->checkauth;
587 return $e->event unless $e->allowed('RUN_REPORTS');
589 my $hint = $$args{hint};
590 my $org_col = $$args{org_column};
591 my $orgs = $$args{org};
593 # if ($orgs && !$$args{no_fetch}) {
595 # ->method_lookup( 'open-ils.reporter.org_unit.full_path' )
597 # $orgs = [ map {$_->id} @$orgs ];
600 # Find the class the iplements the given hint
602 $Fieldmapper::fieldmap->{$_}{hint} eq $hint } Fieldmapper->classes;
604 return undef unless $class->Selector;
606 $class =~ s/Fieldmapper:://og;
613 $method = "search_$class";
614 $margs = { $org_col => $orgs };
616 $method = "retrieve_all_$class";
619 $logger->info("reporter.magic_fetch => $method");
621 return $e->$method($margs);