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.folder.visible.retrieve',
36 method => 'retrieve_visible_folders'
39 sub retrieve_visible_folders {
40 my( $self, $conn, $auth, $type ) = @_;
41 my $e = new_rstore_editor(authtoken=>$auth);
42 return $e->event unless $e->checkauth;
43 return $e->event unless $e->allowed('RUN_REPORTS');
46 $class = 'rtf' if $type eq 'template';
47 $class = 'rof' if $type eq 'output';
48 my $flesh = {flesh => 1,flesh_fields => { $class => ['owner', 'share_with']}};
50 my $meth = "search_reporter_${type}_folder";
51 my $fs = $e->$meth( [{ owner => $e->requestor->id }, $flesh] );
54 my $o = $U->storagereq(
55 'open-ils.storage.actor.org_unit.full_path.atomic', $e->requestor->ws_ou);
56 push( @orgs, $_->id ) for @$o;
63 owner => { '!=' => $e->requestor->id }
74 __PACKAGE__->register_method(
75 api_name => 'open-ils.reporter.folder_data.retrieve',
76 method => 'retrieve_folder_data'
79 sub retrieve_folder_data {
80 my( $self, $conn, $auth, $type, $folderid, $limit ) = @_;
81 my $e = new_rstore_editor(authtoken=>$auth);
82 return $e->event unless $e->checkauth;
83 return $e->event unless $e->allowed('RUN_REPORTS');
84 my $meth = "search_reporter_${type}";
86 $class = 'rt' if $type eq 'template';
89 flesh_fields => { $class => ['owner']},
90 order_by => { $class => 'create_time DESC'}
92 $flesh->{limit} = $limit if $limit;
93 return $e->$meth([{ folder => $folderid }, $flesh]);
96 __PACKAGE__->register_method(
97 api_name => 'open-ils.reporter.schedule.retrieve_by_folder',
98 method => 'retrieve_schedules');
99 sub retrieve_schedules {
100 my( $self, $conn, $auth, $folderId, $limit, $complete ) = @_;
101 my $e = new_rstore_editor(authtoken=>$auth);
102 return $e->event unless $e->checkauth;
103 return $e->event unless $e->allowed('RUN_REPORTS');
105 my $search = { folder => $folderId };
107 { folder => $folderId },
109 order_by => { rs => 'run_time DESC' } ,
111 flesh_fields => { rs => ['report'] }
115 $query->[1]->{limit} = $limit if $limit;
116 $query->[0]->{complete_time} = undef unless $complete;
117 $query->[0]->{complete_time} = { '!=' => undef } if $complete;
119 return $e->search_reporter_schedule($query);
122 __PACKAGE__->register_method(
123 api_name => 'open-ils.reporter.schedule.retrieve',
124 method => 'retrieve_schedules');
125 sub retrieve_schedule {
126 my( $self, $conn, $auth, $sched_id ) = @_;
127 my $e = new_rstore_editor(authtoken=>$auth);
128 return $e->event unless $e->checkauth;
129 return $e->event unless $e->allowed('RUN_REPORTS');
130 my $s = $e->retrieve_reporter_schedule($sched_id)
136 __PACKAGE__->register_method(
137 api_name => 'open-ils.reporter.template.create',
138 method => 'create_template');
139 sub create_template {
140 my( $self, $conn, $auth, $template ) = @_;
141 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
142 return $e->die_event unless $e->checkauth;
143 return $e->die_event unless $e->allowed('RUN_REPORTS');
144 $template->owner($e->requestor->id);
146 my $existing = $e->search_reporter_template( {owner=>$template->owner,
147 folder=>$template->folder, name=>$template->name},{idlist=>1});
148 return OpenILS::Event->new('REPORT_TEMPLATE_EXISTS') if @$existing;
150 my $tmpl = $e->create_reporter_template($template)
151 or return $e->die_event;
160 __PACKAGE__->register_method(
161 api_name => 'open-ils.reporter.report.create',
162 method => 'create_report');
164 my( $self, $conn, $auth, $report, $schedule ) = @_;
165 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
166 return $e->die_event unless $e->checkauth;
167 return $e->die_event unless $e->allowed('RUN_REPORTS');
168 $report->owner($e->requestor->id);
170 my $existing = $e->search_reporter_report( {owner=>$report->owner,
171 folder=>$report->folder, name=>$report->name},{idlist=>1});
172 return OpenILS::Event->new('REPORT_REPORT_EXISTS') if @$existing;
174 my $rpt = $e->create_reporter_report($report)
175 or return $e->die_event;
176 $schedule->report($rpt->id);
177 $schedule->runner($e->requestor->id);
178 $e->create_reporter_schedule($schedule) or return $e->die_event;
184 __PACKAGE__->register_method(
185 api_name => 'open-ils.scheduleer.schedule.create',
186 method => 'create_schedule');
187 sub create_schedule {
188 my( $self, $conn, $auth, $schedule ) = @_;
189 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
190 return $e->die_event unless $e->checkauth;
191 return $e->die_event unless $e->allowed('RUN_REPORTS');
192 my $sched = $e->create_reporter_schedule($schedule)
193 or return $e->die_event;
198 __PACKAGE__->register_method(
199 api_name => 'open-ils.reporter.template.retrieve',
200 method => 'retrieve_template');
201 sub retrieve_template {
202 my( $self, $conn, $auth, $id ) = @_;
203 my $e = new_rstore_editor(authtoken=>$auth);
204 return $e->event unless $e->checkauth;
205 return $e->event unless $e->allowed('RUN_REPORTS');
206 my $t = $e->retrieve_reporter_template($id)
212 __PACKAGE__->register_method(
213 api_name => 'open-ils.reporter.report.retrieve',
214 method => 'retrieve_report');
215 sub retrieve_report {
216 my( $self, $conn, $auth, $id ) = @_;
217 my $e = new_rstore_editor(authtoken=>$auth);
218 return $e->event unless $e->checkauth;
219 return $e->event unless $e->allowed('RUN_REPORTS');
220 my $r = $e->retrieve_reporter_report($id)
226 __PACKAGE__->register_method(
227 api_name => 'open-ils.reporter.template.update',
228 method => 'update_template');
229 sub update_template {
230 my( $self, $conn, $auth, $tmpl ) = @_;
231 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
232 return $e->die_event unless $e->checkauth;
233 return $e->die_event unless $e->allowed('RUN_REPORTS');
234 my $t = $e->retrieve_reporter_template($tmpl->id)
235 or return $e->die_event;
236 return 0 if $t->owner ne $e->requestor->id;
237 $e->update_reporter_template($tmpl)
238 or return $e->die_event;
244 __PACKAGE__->register_method(
245 api_name => 'open-ils.reporter.report.update',
246 method => 'update_report');
248 my( $self, $conn, $auth, $report ) = @_;
249 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
250 return $e->die_event unless $e->checkauth;
251 return $e->die_event unless $e->allowed('RUN_REPORTS');
252 my $r = $e->retrieve_reporter_report($report->id)
253 or return $e->die_event;
254 if( $r->owner ne $e->requestor->id ) {
258 $e->update_reporter_report($report)
259 or return $e->die_event;
265 __PACKAGE__->register_method(
266 api_name => 'open-ils.reporter.schedule.update',
267 method => 'update_schedule');
268 sub update_schedule {
269 my( $self, $conn, $auth, $schedule ) = @_;
270 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
271 return $e->die_event unless $e->checkauth;
272 return $e->die_event unless $e->allowed('RUN_REPORTS');
273 my $s = $e->retrieve_reporter_schedule($schedule->id)
274 or return $e->die_event;
275 my $r = $e->retrieve_reporter_report($s->report)
276 or return $e->die_event;
277 if( $r->owner ne $e->requestor->id ) {
281 $e->update_reporter_schedule($schedule)
282 or return $e->die_event;
288 __PACKAGE__->register_method(
289 api_name => 'open-ils.reporter.folder.update',
290 method => 'update_folder');
292 my( $self, $conn, $auth, $type, $folder ) = @_;
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 $meth = "retrieve_reporter_${type}_folder";
297 my $f = $e->$meth($folder->id) or return $e->die_event;
298 return 0 if $f->owner ne $e->requestor->id;
299 $meth = "update_reporter_${type}_folder";
300 $e->$meth($folder) or return $e->die_event;
306 __PACKAGE__->register_method(
307 api_name => 'open-ils.reporter.folder.delete',
308 method => 'delete_folder');
310 my( $self, $conn, $auth, $type, $folderId ) = @_;
311 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
312 return $e->die_event unless $e->checkauth;
313 return $e->die_event unless $e->allowed('RUN_REPORTS');
314 my $meth = "retrieve_reporter_${type}_folder";
315 my $f = $e->$meth($folderId) or return $e->die_event;
316 return 0 if $f->owner ne $e->requestor->id;
317 $meth = "delete_reporter_${type}_folder";
318 $e->$meth($f) or return $e->die_event;
324 __PACKAGE__->register_method(
325 api_name => 'open-ils.reporter.template.delete',
326 method => 'delete_template');
327 sub delete_template {
328 my( $self, $conn, $auth, $templateId ) = @_;
329 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
330 return $e->die_event unless $e->checkauth;
331 return $e->die_event unless $e->allowed('RUN_REPORTS');
333 my $t = $e->retrieve_reporter_template($templateId)
334 or return $e->die_event;
335 return 0 if $t->owner ne $e->requestor->id;
336 $e->delete_reporter_template($t) or return $e->die_event;
343 __PACKAGE__->register_method(
344 api_name => 'open-ils.reporter.template.delete.cascade',
345 method => 'cascade_delete_template');
347 #__PACKAGE__->register_method(
348 # api_name => 'open-ils.reporter.template.delete.cascade.force',
349 # method => 'cascade_delete_template');
351 sub cascade_delete_template {
352 my( $self, $conn, $auth, $templateId ) = @_;
354 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
355 return $e->die_event unless $e->checkauth;
356 return $e->die_event unless $e->allowed('RUN_REPORTS');
358 my $ret = cascade_delete_template_impl(
359 $e, $e->requestor->id, $templateId, ($self->api_name =~ /force/o) );
360 return $ret if ref $ret; # some fatal event occurred
362 $e->rollback if $ret == 0;
363 $e->commit if $ret > 0;
368 __PACKAGE__->register_method(
369 api_name => 'open-ils.reporter.report.delete.cascade',
370 method => 'cascade_delete_report');
372 #__PACKAGE__->register_method(
373 # api_name => 'open-ils.reporter.report.delete.cascade.force',
374 # method => 'cascade_delete_report');
376 sub cascade_delete_report {
377 my( $self, $conn, $auth, $reportId ) = @_;
379 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
380 return $e->die_event unless $e->checkauth;
381 return $e->die_event unless $e->allowed('RUN_REPORTS');
383 my $ret = cascade_delete_report_impl($e, $e->requestor->id, $reportId);
384 return $ret if ref $ret; # some fatal event occurred
386 $e->rollback if $ret == 0;
387 $e->commit if $ret > 0;
392 # performs a cascading template delete
393 # returns 2 if all data was deleted
394 # returns 1 if some data was deleted
395 # returns 0 if no data was deleted
396 # returns event on error
397 sub cascade_delete_template_impl {
398 my( $e, $owner, $templateId ) = @_;
400 # fetch the template to delete
401 my $template = $e->search_reporter_template(
402 {id=>$templateId, owner=>$owner})->[0] or return 0;
404 # fetch he attached report IDs for this owner
405 my $reports = $e->search_reporter_report(
406 {template=>$templateId, owner=>$owner},{idlist=>1});
408 # delete the attached reports
409 my $all_rpts_deleted = 1;
410 for my $r (@$reports) {
411 my $evt = cascade_delete_report_impl($e, $owner, $r);
412 return $evt if ref $evt;
413 $all_rpts_deleted = 0 unless $evt == 2;
416 # fetch all reports attached to this template that
417 # do not belong to $owner. If there are any, we can't
418 # delete the template
419 my $alt_reports = $e->search_reporter_report(
420 {template=>$templateId, owner=>{"!=" => $owner}},{idlist=>1});
422 # all_rpts_deleted will be false if a report has an
423 # attached scheduled owned by a different user
424 return 1 if @$alt_reports or not $all_rpts_deleted;
426 $e->delete_reporter_template($template)
427 or return $e->die_event;
431 # performs a cascading report delete
432 # returns 2 if all data was deleted
433 # returns 1 if some data was deleted
434 # returns 0 if no data was deleted
435 # returns event on error
436 sub cascade_delete_report_impl {
437 my( $e, $owner, $reportId ) = @_;
439 # fetch the report to delete
440 my $report = $e->search_reporter_report(
441 {id=>$reportId, owner=>$owner})->[0] or return 0;
443 # fetch the attached schedule IDs for this owner
444 my $scheds = $e->search_reporter_schedule(
445 {report=>$reportId, runner=>$owner},{idlist=>1});
447 # delete the attached schedules
448 for my $sched (@$scheds) {
449 my $evt = delete_schedule_impl($e, $sched);
453 # fetch all schedules attached to this report that
454 # do not belong to $owner. If there are any, we can't
456 my $alt_scheds = $e->search_reporter_schedule(
457 {report=>$reportId, runner=>{"!=" => $owner}},{idlist=>1});
459 return 1 if @$alt_scheds;
461 $e->delete_reporter_report($report)
462 or return $e->die_event;
468 # deletes the requested schedule
469 # returns undef on success, event on error
470 sub delete_schedule_impl {
471 my( $e, $schedId ) = @_;
472 my $s = $e->retrieve_reporter_schedule($schedId)
473 or return $e->die_event;
474 $e->delete_reporter_schedule($s) or return $e->die_event;
481 __PACKAGE__->register_method(
482 api_name => 'open-ils.reporter.report.delete',
483 method => 'delete_report');
485 my( $self, $conn, $auth, $reportId ) = @_;
486 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
487 return $e->die_event unless $e->checkauth;
488 return $e->die_event unless $e->allowed('RUN_REPORTS');
490 my $t = $e->retrieve_reporter_report($reportId)
491 or return $e->die_event;
492 return 0 if $t->owner ne $e->requestor->id;
493 $e->delete_reporter_report($t) or return $e->die_event;
499 __PACKAGE__->register_method(
500 api_name => 'open-ils.reporter.schedule.delete',
501 method => 'delete_schedule');
502 sub delete_schedule {
503 my( $self, $conn, $auth, $scheduleId ) = @_;
504 my $e = new_rstore_editor(authtoken=>$auth, xact=>1);
505 return $e->die_event unless $e->checkauth;
506 return $e->die_event unless $e->allowed('RUN_REPORTS');
508 my $t = $e->retrieve_reporter_schedule($scheduleId)
509 or return $e->die_event;
510 return 0 if $t->runner ne $e->requestor->id;
511 $e->delete_reporter_schedule($t) or return $e->die_event;
517 __PACKAGE__->register_method(
518 api_name => 'open-ils.reporter.template_has_reports',
519 method => 'has_reports');
521 my( $self, $conn, $auth, $templateId ) = @_;
522 my $e = new_rstore_editor(authtoken=>$auth);
523 return $e->die_event unless $e->checkauth;
524 return $e->die_event unless $e->allowed('RUN_REPORTS');
525 my $rpts = $e->search_reporter_report({template=>$templateId},{idlist=>1});
530 __PACKAGE__->register_method(
531 api_name => 'open-ils.reporter.report_has_output',
532 method => 'has_output');
534 my( $self, $conn, $auth, $reportId ) = @_;
535 my $e = new_rstore_editor(authtoken=>$auth);
536 return $e->die_event unless $e->checkauth;
537 return $e->die_event unless $e->allowed('RUN_REPORTS');
538 my $outs = $e->search_reporter_schedule({report=>$reportId},{idlist=>1});
545 __PACKAGE__->register_method(
546 method => 'org_full_path',
547 api_name => 'open-ils.reporter.org_unit.full_path');
550 my( $self, $conn, $orgid ) = @_;
551 return $U->storagereq(
552 'open-ils.storage.actor.org_unit.full_path.atomic', $orgid );
558 __PACKAGE__->register_method(
559 method => 'magic_fetch_all',
560 api_name => 'open-ils.reporter.magic_fetch');
561 sub magic_fetch_all {
562 my( $self, $conn, $auth, $args ) = @_;
563 my $e = new_editor(authtoken => $auth);
564 return $e->event unless $e->checkauth;
565 return $e->event unless $e->allowed('RUN_REPORTS');
567 my $hint = $$args{hint};
568 my $org_col = $$args{org_column};
569 my $orgs = $$args{org};
571 # if ($orgs && !$$args{no_fetch}) {
573 # ->method_lookup( 'open-ils.reporter.org_unit.full_path' )
575 # $orgs = [ map {$_->id} @$orgs ];
578 # Find the class the iplements the given hint
580 $Fieldmapper::fieldmap->{$_}{hint} eq $hint } Fieldmapper->classes;
582 return undef unless $class->Selector;
584 $class =~ s/Fieldmapper:://og;
591 $method = "search_$class";
592 $margs = { $org_col => $orgs };
594 $method = "retrieve_all_$class";
597 $logger->info("reporter.magic_fetch => $method");
599 return $e->$method($margs);