From 675fd78e952c3b339a9e4ea42d40e19176476d67 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Sat, 12 Aug 2017 11:08:30 -0400 Subject: [PATCH] LP#1694577 Report templates search API & paging Adds new API call open-ils.reporter.search.templates allowing search of reporter template names and/or descriptions. Searching is case-insensitive, any order, with left-anchored words. Searching can be for specific folders or all folders visible to the calling user. Adds paging support (limit / offset) for retriving templates, reports, and outputs. Signed-off-by: Bill Erickson Signed-off-by: Galen Charlton Signed-off-by: Jason Etheridge --- .../perlmods/lib/OpenILS/Application/Reporter.pm | 108 ++++++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Reporter.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Reporter.pm index 897fb224ae..6d55157fa8 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Reporter.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Reporter.pm @@ -109,7 +109,7 @@ __PACKAGE__->register_method( ); sub retrieve_folder_data { - my( $self, $conn, $auth, $type, $folderid, $limit ) = @_; + my( $self, $conn, $auth, $type, $folderid, $limit, $offset ) = @_; my $e = new_rstore_editor(authtoken=>$auth); return $e->event unless $e->checkauth; if($type eq 'output') { @@ -126,6 +126,7 @@ sub retrieve_folder_data { order_by => { $class => 'create_time DESC'} }; $flesh->{limit} = $limit if $limit; + $flesh->{offset} = $offset if $offset; return $e->$meth([{ folder => $folderid }, $flesh]); } @@ -674,5 +675,110 @@ sub magic_fetch_all { return $e->$method($margs); } +__PACKAGE__->register_method( + method => 'search_templates', + api_name => 'open-ils.reporter.search.templates', + stream => 1 +); + +sub search_templates { + my ($self, $client, $auth, $query_args) = @_; + + my $limit = $query_args->{limit} || 100; + my $offset = $query_args->{offset} || 0; + my $folder = $query_args->{folder}; + my $fields = $query_args->{fields} || ['name','description']; + my $query_string = $query_args->{query}; + + return undef unless $query_string; + + my $e = new_rstore_editor(authtoken => $auth); + return $e->event unless $e->checkauth; + + my ($visible_folders) = $self + ->method_lookup('open-ils.reporter.folder.visible.retrieve') + ->run($auth, 'template'); + + my @visible_folder_ids = map { $_->id } @$visible_folders; + + return undef unless @$visible_folders; + + my $query = { + select => {rt => ['id']}, + from => 'rt', + where => { + folder => \@visible_folder_ids, + '-and' => [] + }, + limit => $limit, + offset => $offset + }; + + if ($folder) { # search request for specific folder + sub-folders + my ($root_folder) = grep { $_->id == $folder} @$visible_folders; + + return OpenILS::Event->new('BAD_PARAMS', + desc => q/Cannot search requested folder/) unless $root_folder; + + # find all folders that are descendants of the selected folder. + my @ffilter; + my $finder; + $finder = sub { + my $node = shift; + return unless $node; + push(@ffilter, $node->id); + my @children = grep { $_->parent == $node->id } @$visible_folders; + $finder->($_) for @children; + }; + + $finder->($root_folder); + $query->{where}->{folder} = \@ffilter; + } + + $query_string =~ s/^\s+|\s+$//gm; # remove open/trailing spaces + my @query_parts = split(/ +/, $query_string); + + # Compile the query parts and searched fields down to a JSON-query + # structure like this. Note that single-field searches have no + # nested -or's. + # where => { + # -and => [ + # {-or => [ + # {$field1 => {~* => $value1}}, + # {$field2 => {~* => $value1}} + # }, + # {-or => [ + # {$field1 => {~* => $value2}}, + # {$field2 => {~* => $value2}} + # } + # ] + #} + for my $part (@query_parts) { + my $subq; + + if (@$fields > 1) { + $subq = {'-or' => []}; + for my $field (@$fields) { + push(@{$subq->{'-or'}}, {$field => {'~*' => "(^| )$part"}}); + } + } else { + $subq = {$fields->[0] => {'~*' => "(^| )$part"}}; + } + + push(@{$query->{where}->{'-and'}}, $subq); + } + + my $template_ids = $e->json_query($query); + + # Flesh template owner for consistency with retrieve_folder_data + my $flesh = {flesh => 1, flesh_fields => {rt => ['owner']}}; + + $client->respond($e->retrieve_reporter_template([$_->{id}, $flesh])) + for @$template_ids; + + return; +} + + 1; -- 2.11.0