Bug 34587: Add reports by data provider
Add the option to have a report by provider that rolls all usage up into one top-level figure to see how often that provider is being used a given period Signed-off-by: Jessica Zairo <jzairo@bywatersolutions.com> Signed-off-by: Michaela Sieber <michaela.sieber@kit.edu> Signed-off-by: Nick Clemens <nick@bywatersolutions.com> Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
This commit is contained in:
parent
ffbcf83b95
commit
e1583a334a
7 changed files with 297 additions and 24 deletions
|
@ -921,6 +921,61 @@ sub get_report_type_specific_fields {
|
|||
|
||||
}
|
||||
|
||||
=head3 test_connection
|
||||
|
||||
Tests the connection of the harvester to the SUSHI service and returns any alerts of planned SUSHI outages
|
||||
|
||||
=cut
|
||||
|
||||
sub test_connection {
|
||||
my ($self) = @_;
|
||||
|
||||
my $url = $self->service_url;
|
||||
$url .= '/status';
|
||||
$url .= '?customer_id=' . $self->customer_id;
|
||||
$url .= '&requestor_id=' . $self->requestor_id if $self->requestor_id;
|
||||
$url .= '&api_key=' . $self->api_key if $self->api_key;
|
||||
|
||||
my $request = HTTP::Request->new( 'GET' => $url );
|
||||
my $ua = LWP::UserAgent->new;
|
||||
my $response = $ua->simple_request($request);
|
||||
|
||||
my @result = decode_json( $response->decoded_content );
|
||||
if ( $result[0][0]->{Service_Active} ) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
=head3 erm_usage_titles
|
||||
|
||||
Method to embed erm_usage_titles to titles for report formatting
|
||||
|
||||
=cut
|
||||
|
||||
sub erm_usage_titles {
|
||||
my ($self) = @_;
|
||||
my $usage_title_rs = $self->_result->erm_usage_titles;
|
||||
return Koha::ERM::UsageTitles->_new_from_dbic($usage_title_rs);
|
||||
}
|
||||
|
||||
=head3 erm_usage_muses
|
||||
|
||||
Method to embed erm_usage_muses to titles for report formatting
|
||||
|
||||
=cut
|
||||
|
||||
sub erm_usage_muses {
|
||||
my ($self) = @_;
|
||||
my $usage_mus_rs = $self->_result->erm_usage_muses;
|
||||
return Koha::ERM::MonthlyUsages->_new_from_dbic($usage_mus_rs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
=head3 _type
|
||||
|
||||
=cut
|
||||
|
|
|
@ -359,4 +359,92 @@ sub test_connection {
|
|||
};
|
||||
}
|
||||
|
||||
=head3 providers_report
|
||||
|
||||
=cut
|
||||
|
||||
sub providers_report {
|
||||
my $c = shift->openapi->valid_input or return;
|
||||
|
||||
return try {
|
||||
|
||||
my $args = $c->validation->output;
|
||||
|
||||
my $usage_data_providers_set = Koha::ERM::UsageDataProviders->new;
|
||||
my $usage_data_providers = $c->objects->search( $usage_data_providers_set );
|
||||
|
||||
my @query_params_array;
|
||||
my $json = JSON->new;
|
||||
|
||||
if ( ref( $args->{q} ) eq 'ARRAY' ) {
|
||||
foreach my $q ( @{ $args->{q} } ) {
|
||||
push @query_params_array, $json->decode($q)
|
||||
if $q;
|
||||
}
|
||||
}
|
||||
|
||||
my $metric_types = $query_params_array[0][0]->{'erm_usage_titles.erm_usage_muses.metric_type'};
|
||||
|
||||
my @usage_data_provider_report_data;
|
||||
|
||||
for my $usage_data_provider ( @{ $usage_data_providers } ) {
|
||||
|
||||
# Split usage_data_providers into metric_types i.e. one table row per metric_type
|
||||
for my $metric_type ( @$metric_types ) {
|
||||
my @filtered_title_data;
|
||||
|
||||
for my $title ( @{ $usage_data_provider->{'erm_usage_titles'} }) {
|
||||
my $statistics = $title->{'erm_usage_muses'};
|
||||
my @filtered_statistics = grep { $metric_type eq $_->{metric_type} } @$statistics;
|
||||
|
||||
my %title_hash = (
|
||||
usage_data_provider_id => $title->{usage_data_provider_id},
|
||||
title_id => $title->{title_id},
|
||||
title => $title->{title},
|
||||
erm_usage_muses => \@filtered_statistics,
|
||||
online_issn => $title->{online_issn},
|
||||
print_issn => $title->{print_issn},
|
||||
title_doi => $title->{title_doi},
|
||||
title_uri => $title->{title_uri},
|
||||
metric_type => $metric_type,
|
||||
publisher => $title->{publisher},
|
||||
publisher_id => $title->{publisher_id},
|
||||
);
|
||||
|
||||
push @filtered_title_data, \%title_hash;
|
||||
}
|
||||
|
||||
|
||||
my %usage_data_provider_hash = (
|
||||
erm_usage_data_provider_id => $usage_data_provider->{erm_usage_data_provider_id},
|
||||
erm_usage_titles => \@filtered_title_data,
|
||||
aggregator => $usage_data_provider->{aggregator},
|
||||
api_key => $usage_data_provider->{api_key},
|
||||
begin_date => $usage_data_provider->{begin_date},
|
||||
customer_id => $usage_data_provider->{customer_id},
|
||||
description => $usage_data_provider->{description},
|
||||
end_date => $usage_data_provider->{end_date},
|
||||
method => $usage_data_provider->{method},
|
||||
name => $usage_data_provider->{name},
|
||||
report_release => $usage_data_provider->{report_release},
|
||||
report_types => $usage_data_provider->{report_types},
|
||||
requestor_email => $usage_data_provider->{requestor_email},
|
||||
requestor_id => $usage_data_provider->{requestor_id},
|
||||
requestor_name => $usage_data_provider->{requestor_name},
|
||||
service_type => $usage_data_provider->{service_type},
|
||||
service_url => $usage_data_provider->{service_url},
|
||||
metric_type => $metric_type
|
||||
);
|
||||
|
||||
push @usage_data_provider_report_data, \%usage_data_provider_hash;
|
||||
};
|
||||
};
|
||||
|
||||
return $c->render( status => 200, openapi => \@usage_data_provider_report_data );
|
||||
}
|
||||
catch {
|
||||
$c->unhandled_exception($_);
|
||||
};
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -85,11 +85,21 @@ properties:
|
|||
type:
|
||||
- string
|
||||
- "null"
|
||||
metric_type:
|
||||
description: metric type of the harvester when reporting
|
||||
type:
|
||||
- string
|
||||
- "null"
|
||||
counter_files:
|
||||
type: array
|
||||
description: counter files
|
||||
items:
|
||||
$ref: erm_counter_file.yaml
|
||||
erm_usage_titles:
|
||||
type: array
|
||||
description: usage titles
|
||||
items:
|
||||
$ref: erm_usage_title.yaml
|
||||
|
||||
additionalProperties: false
|
||||
required:
|
||||
|
|
|
@ -103,6 +103,7 @@
|
|||
type: string
|
||||
enum:
|
||||
- counter_files
|
||||
- erm_usage_titles.erm_usage_muses
|
||||
collectionFormat: csv
|
||||
- $ref: "../swagger.yaml#/parameters/match"
|
||||
- $ref: "../swagger.yaml#/parameters/order_by"
|
||||
|
@ -217,6 +218,9 @@
|
|||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- counter_files
|
||||
- erm_usage_titles.erm_usage_muses
|
||||
collectionFormat: csv
|
||||
responses:
|
||||
200:
|
||||
|
@ -416,7 +420,7 @@
|
|||
operationId: testUsageDataProviderHarvester
|
||||
tags:
|
||||
- usage data provider harvester
|
||||
summary: Run this data provider's harvester
|
||||
summary: Test this data provider's harvester
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
|
@ -445,6 +449,60 @@
|
|||
description: Under maintenance
|
||||
schema:
|
||||
$ref: "../swagger.yaml#/definitions/error"
|
||||
x-koha-authorization:
|
||||
permissions:
|
||||
erm: 1
|
||||
"/erm/usage_data_providers/report":
|
||||
get:
|
||||
x-mojo-to: ERM::UsageDataProviders#providers_report
|
||||
operationId: reportUsageDataProvider
|
||||
tags:
|
||||
- usage data provider report
|
||||
summary: Run a report for this data provider
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- $ref: "../swagger.yaml#/parameters/match"
|
||||
- $ref: "../swagger.yaml#/parameters/order_by"
|
||||
- $ref: "../swagger.yaml#/parameters/page"
|
||||
- $ref: "../swagger.yaml#/parameters/per_page"
|
||||
- $ref: "../swagger.yaml#/parameters/q_param"
|
||||
- $ref: "../swagger.yaml#/parameters/q_body"
|
||||
- $ref: "../swagger.yaml#/parameters/q_header"
|
||||
- name: x-koha-embed
|
||||
in: header
|
||||
required: false
|
||||
description: Embed list sent as a request header
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- counter_files
|
||||
- erm_usage_titles.erm_usage_muses
|
||||
responses:
|
||||
200:
|
||||
description: Successful report run
|
||||
schema:
|
||||
items:
|
||||
$ref: "../swagger.yaml#/definitions/erm_usage_data_provider"
|
||||
400:
|
||||
description: Bad request
|
||||
schema:
|
||||
$ref: "../swagger.yaml#/definitions/error"
|
||||
403:
|
||||
description: Access forbidden
|
||||
schema:
|
||||
$ref: "../swagger.yaml#/definitions/error"
|
||||
500:
|
||||
description: |-
|
||||
Internal server error. Possible `error_code` attribute values:
|
||||
* `internal_server_error`
|
||||
schema:
|
||||
$ref: "../swagger.yaml#/definitions/error"
|
||||
503:
|
||||
description: Under maintenance
|
||||
schema:
|
||||
$ref: "../swagger.yaml#/definitions/error"
|
||||
x-koha-authorization:
|
||||
permissions:
|
||||
erm: 1
|
|
@ -297,6 +297,8 @@ paths:
|
|||
$ref: "./paths/erm_usage_data_providers.yaml#/~1erm~1usage_data_providers~1{erm_usage_data_provider_id}~1run"
|
||||
"/erm/usage_data_providers/{erm_usage_data_provider_id}/test_connection":
|
||||
$ref: "./paths/erm_usage_data_providers.yaml#/~1erm~1usage_data_providers~1{erm_usage_data_provider_id}~1test_connection"
|
||||
"/erm/usage_data_providers/report":
|
||||
$ref: "./paths/erm_usage_data_providers.yaml#/~1erm~1usage_data_providers~1report"
|
||||
/erm/usage_titles:
|
||||
$ref: ./paths/erm_usage_titles.yaml#/~1erm~1usage_titles
|
||||
/erm/users:
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
value: 'metric_type',
|
||||
description: 'By metric type',
|
||||
},
|
||||
{
|
||||
value: 'usage_data_provider',
|
||||
description: 'By data provider totals',
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</li>
|
||||
|
@ -637,10 +641,24 @@ export default {
|
|||
|
||||
this.time_period_columns_builder = time_period_columns
|
||||
},
|
||||
buildMonthlyUrlQuery(query, time_period_columns, metric_type_report) {
|
||||
let url = metric_type_report
|
||||
? "/api/v1/erm/usage_titles/metric_types_report"
|
||||
: "/api/v1/erm/usage_titles/monthly_report"
|
||||
buildMonthlyUrlQuery(query, time_period_columns, data_display) {
|
||||
let url
|
||||
let prefix
|
||||
switch (data_display) {
|
||||
case "monthly":
|
||||
url = "/api/v1/erm/usage_titles/monthly_report"
|
||||
prefix = "erm_usage_muses"
|
||||
break
|
||||
case "metric_type":
|
||||
url = "/api/v1/erm/usage_titles/metric_types_report"
|
||||
prefix = "erm_usage_muses"
|
||||
break
|
||||
case "usage_data_provider":
|
||||
url = "/api/v1/erm/usage_data_providers/report"
|
||||
prefix = "erm_usage_titles.erm_usage_muses"
|
||||
break
|
||||
}
|
||||
|
||||
// Work out which years are included in the query
|
||||
const years = []
|
||||
const {
|
||||
|
@ -665,8 +683,8 @@ export default {
|
|||
const queryArray = years.map(year => {
|
||||
const queryByYear = {}
|
||||
|
||||
queryByYear[`erm_usage_muses.year`] = year
|
||||
queryByYear[`erm_usage_muses.report_type`] = report_type
|
||||
queryByYear[`${prefix}.year`] = year
|
||||
queryByYear[`${prefix}.report_type`] = report_type
|
||||
|
||||
// Find the months applicable to each year, ignoring months that have been de-selected
|
||||
const queryMonths = months[year]
|
||||
|
@ -674,21 +692,21 @@ export default {
|
|||
.map(month => {
|
||||
return month.value
|
||||
})
|
||||
queryByYear[`erm_usage_muses.month`] = queryMonths
|
||||
queryByYear[`${prefix}.month`] = queryMonths
|
||||
// Add any title query
|
||||
if (titles) {
|
||||
const title_ids = titles.map(title => {
|
||||
return title.title_id
|
||||
})
|
||||
queryByYear[`erm_usage_muses.title_id`] = title_ids
|
||||
queryByYear[`${prefix}.title_id`] = title_ids
|
||||
}
|
||||
// Add any metric types query
|
||||
if (metric_types) {
|
||||
queryByYear[`erm_usage_muses.metric_type`] = metric_types
|
||||
queryByYear[`${prefix}.metric_type`] = metric_types
|
||||
}
|
||||
// Add any data provider query
|
||||
if (usage_data_providers) {
|
||||
queryByYear[`erm_usage_muses.usage_data_provider_id`] =
|
||||
queryByYear[`${prefix}.usage_data_provider_id`] =
|
||||
usage_data_providers
|
||||
}
|
||||
|
||||
|
@ -889,19 +907,18 @@ export default {
|
|||
queryObject.metric_types = final_metric_types
|
||||
}
|
||||
|
||||
const metric_report_type =
|
||||
data_display === "metric_type" ? true : false
|
||||
const url = !data_display.includes("yearly")
|
||||
? this.buildMonthlyUrlQuery(
|
||||
queryObject,
|
||||
this.time_period_columns_builder,
|
||||
metric_report_type
|
||||
data_display
|
||||
)
|
||||
: this.buildYearlyUrlQuery(queryObject)
|
||||
const type = data_display
|
||||
const columns = this.defineColumns(
|
||||
this.title_property_column_options
|
||||
)
|
||||
const columns =
|
||||
data_display === "usage_data_provider"
|
||||
? []
|
||||
: this.defineColumns(this.title_property_column_options)
|
||||
const yearly_filter = data_display.includes("monthly")
|
||||
? this.yearly_filter_required
|
||||
: false
|
||||
|
|
|
@ -47,6 +47,20 @@ export default {
|
|||
this.report_type === "yearly"
|
||||
? ["erm_usage_yuses"]
|
||||
: ["erm_usage_muses"]
|
||||
switch (this.report_type) {
|
||||
case "monthly":
|
||||
this.embed = "erm_usage_muses"
|
||||
break
|
||||
case "yearly":
|
||||
this.embed = "erm_usage_yuses"
|
||||
break
|
||||
case "metric_type":
|
||||
this.embed = "erm_usage_muses"
|
||||
break
|
||||
case "usage_data_provider":
|
||||
this.embed = "erm_usage_titles.erm_usage_muses"
|
||||
break
|
||||
}
|
||||
|
||||
this.years = Object.keys(this.params.tp_columns)
|
||||
this.year = this.years[this.years.length - 1]
|
||||
|
@ -78,15 +92,16 @@ export default {
|
|||
const yearly_filter = params.yearly_filter
|
||||
const query = params.queryObject
|
||||
|
||||
const column_set = [
|
||||
{
|
||||
const column_set = [...columns]
|
||||
|
||||
report_type !== "usage_data_provider" &&
|
||||
column_set.unshift({
|
||||
title: __("Title"),
|
||||
data: "title",
|
||||
searchable: true,
|
||||
orderable: true,
|
||||
},
|
||||
...columns,
|
||||
]
|
||||
})
|
||||
|
||||
// Add metric type to each row
|
||||
if (report_type !== "metric_type") {
|
||||
column_set.push({
|
||||
|
@ -99,6 +114,36 @@ export default {
|
|||
})
|
||||
}
|
||||
|
||||
if (report_type === "usage_data_provider") {
|
||||
column_set.unshift({
|
||||
title: __("Data provider"),
|
||||
data: "name",
|
||||
searchable: true,
|
||||
orderable: true,
|
||||
})
|
||||
column_set.push({
|
||||
title: __("Period Total"),
|
||||
render: function (data, type, row, meta) {
|
||||
const sum = row.erm_usage_titles.reduce(
|
||||
(acc, title) => {
|
||||
const titleSum = title.erm_usage_muses.reduce(
|
||||
(acc, mus) => {
|
||||
return acc + mus.usage_count
|
||||
},
|
||||
0
|
||||
)
|
||||
return acc + titleSum
|
||||
},
|
||||
0
|
||||
)
|
||||
return sum
|
||||
},
|
||||
searchable: true,
|
||||
orderable: true,
|
||||
})
|
||||
return column_set
|
||||
}
|
||||
|
||||
// Add monthly columns
|
||||
if (yearly_filter) {
|
||||
months_data.forEach(month => {
|
||||
|
@ -307,8 +352,6 @@ export default {
|
|||
},
|
||||
watch: {
|
||||
table() {
|
||||
// table needs to be rendered before header can be created and
|
||||
// table is hidden by .hide-table until table header is created
|
||||
if (this.report_type !== "metric_type") {
|
||||
this.mergeTitleDataIntoOneLine(
|
||||
this.params.queryObject.metric_types.length
|
||||
|
|
Loading…
Reference in a new issue