-
Notifications
You must be signed in to change notification settings - Fork 2
DT-2957: Update the API call for getting DAR details for a dataset ID #2822
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 19 commits
2c40a8c
c425a4f
309976c
8067534
61bc0ee
c9b4531
1687f4b
ac7bd25
5e04126
bde9e91
eeb65b4
f94eee2
50aff79
ced1193
9d72fed
b35ebc9
efa62d0
3e6e83f
3e394f6
5b2b966
a87c6f1
a6ccb67
a5b174b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -101,6 +101,49 @@ AND dar.collection_id NOT IN ( | |
| """) | ||
| List<DataAccessRequest> findApprovedDARsByDatasetId(@Bind("datasetId") Integer datasetId); | ||
|
|
||
| /** | ||
| * This query finds DARs submitted on dar-dataset combinations where the most recent vote is true | ||
| * similar to {@link #findApprovedDARsByDatasetId(Integer datasetId) findApprovedDARsByDatasetId}. | ||
| * The primary difference is that we want to include expired DARs to show in dataset usage | ||
| * metrics. | ||
| * | ||
| * @param datasetId The dataset id | ||
| * @return List of approved DARs for the dataset | ||
| */ | ||
| @UseRowReducer(DataAccessRequestReducer.class) | ||
| @SqlQuery( | ||
| """ | ||
| SELECT dar.id, dar.reference_id, dar.collection_id, dar.parent_id, dar.user_id, | ||
| dar.create_date, dar.submission_date, dar.update_date, dar.data, dar.era_commons_id, | ||
| dar.approving_so_id, dar.approving_so_timestamp, dar.requires_so_approval, | ||
| dar.closeout_so_approval_timestamp, dar.closeout_approving_so_id, | ||
| dd.dataset_id, collection.dar_code | ||
| FROM data_access_request dar | ||
| LEFT JOIN dar_collection collection on collection.collection_id = dar.collection_id | ||
| INNER JOIN dar_dataset dd ON dd.reference_id = dar.reference_id | ||
| INNER JOIN ( | ||
| SELECT DISTINCT e.reference_id, e.dataset_id, LAST_VALUE(v.vote) | ||
| OVER( | ||
| PARTITION BY e.reference_id, e.dataset_id | ||
| ORDER BY v.create_date | ||
| RANGE BETWEEN | ||
| UNBOUNDED PRECEDING AND | ||
| UNBOUNDED FOLLOWING | ||
| ) last_vote | ||
| FROM election e | ||
| INNER JOIN vote v ON e.election_id = v.election_id AND v.vote IS NOT NULL | ||
| AND LOWER(e.election_type) = 'dataaccess' | ||
| AND LOWER(v.type) IN ('final', 'radar_approve')) final_access_vote ON final_access_vote.reference_id = dar.reference_id AND final_access_vote.dataset_id = dd.dataset_id | ||
| WHERE dd.dataset_id = :datasetId | ||
| AND dar.submission_date IS NOT NULL | ||
| AND final_access_vote.last_vote = TRUE | ||
| AND (LOWER(dar.data->>'status') != 'archived' OR dar.data->>'status' IS NULL) | ||
| -- Exclude DARs that have a closeoutSupplement | ||
| AND data ->> 'closeoutSupplement' IS NULL | ||
| """) | ||
| List<DataAccessRequest> findSummaryMetricApprovedDARsByDatasetIdIncludesExpired( | ||
| @Bind("datasetId") Integer datasetId); | ||
|
|
||
| /** | ||
| * This query finds dataset ids on dar-dataset combinations where the most recent vote is true. | ||
| * This includes datasets that are a part of expired DARs, UNLIKE findApprovedDARsByDatasetId. The | ||
|
|
@@ -305,11 +348,6 @@ void updateDataByReferenceId( | |
| """) | ||
| void deleteByReferenceId(@Bind("referenceId") String referenceId); | ||
|
|
||
| @SqlUpdate("DELETE FROM data_access_request WHERE reference_id IN (<referenceIds>)") | ||
| void deleteByReferenceIds( | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Drive-by fix: unused |
||
| @BindList(value = "referenceIds", onEmpty = EmptyHandling.NULL_STRING) | ||
| List<String> referenceIds); | ||
|
|
||
| @SqlUpdate( | ||
| """ | ||
| UPDATE data_access_request | ||
|
|
@@ -494,16 +532,6 @@ INSERT INTO dar_dataset (reference_id, dataset_id) | |
| """) | ||
| void deleteDARDatasetRelationByReferenceId(@Bind("referenceId") String referenceId); | ||
|
|
||
| /** | ||
| * Delete rows which have a referenceId that is in the list referenceIds | ||
| * | ||
| * @param referenceIds List<String> | ||
| */ | ||
| @SqlUpdate("DELETE FROM dar_dataset WHERE reference_id in (<referenceIds>)") | ||
| void deleteDARDatasetRelationByReferenceIds( | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Drive-by fix: unused |
||
| @BindList(value = "referenceIds", onEmpty = EmptyHandling.NULL_STRING) | ||
| List<String> referenceIds); | ||
|
|
||
| /** | ||
| * Returns all dataset_ids that match any of the referenceIds inside the "referenceIds" list | ||
| * | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,36 @@ | ||||||||||||||||||||||||||||||
| package org.broadinstitute.consent.http.models; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| import java.sql.Timestamp; | ||||||||||||||||||||||||||||||
| import java.time.LocalDateTime; | ||||||||||||||||||||||||||||||
| import java.time.ZoneId; | ||||||||||||||||||||||||||||||
| import java.time.ZonedDateTime; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| public record DarMetricsSummary( | ||||||||||||||||||||||||||||||
| Timestamp updateDate, | ||||||||||||||||||||||||||||||
| String projectTitle, | ||||||||||||||||||||||||||||||
| String darCode, | ||||||||||||||||||||||||||||||
| String nonTechRus, | ||||||||||||||||||||||||||||||
| String referenceId, | ||||||||||||||||||||||||||||||
| Boolean expired) { | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| public DarMetricsSummary(DataAccessRequest dar) { | ||||||||||||||||||||||||||||||
| this( | ||||||||||||||||||||||||||||||
| dar != null ? dar.getUpdateDate() : null, | ||||||||||||||||||||||||||||||
| dar != null && dar.getData() != null ? dar.getData().getProjectTitle() : null, | ||||||||||||||||||||||||||||||
| dar != null ? dar.getDarCode() : null, | ||||||||||||||||||||||||||||||
| dar != null && dar.getData() != null ? dar.getData().getNonTechRus() : null, | ||||||||||||||||||||||||||||||
| dar != null ? dar.getReferenceId() : null, | ||||||||||||||||||||||||||||||
| computeExpired(dar)); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| private static Boolean computeExpired(DataAccessRequest dar) { | ||||||||||||||||||||||||||||||
rushtong marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||
| // If the DAR or its submission date is null, we consider it expired for metrics purposes | ||||||||||||||||||||||||||||||
| if (dar == null || dar.getSubmissionDate() == null) { | ||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| LocalDateTime oneYearAgo = LocalDateTime.now().minusYears(1); | ||||||||||||||||||||||||||||||
| ZonedDateTime zonedDateTime = oneYearAgo.atZone(ZoneId.systemDefault()); | ||||||||||||||||||||||||||||||
| Timestamp lastYear = Timestamp.from(zonedDateTime.toInstant()); | ||||||||||||||||||||||||||||||
| return dar.getSubmissionDate().before(lastYear); | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
| // If the DAR or its submission date is null, we consider it expired for metrics purposes | |
| if (dar == null || dar.getSubmissionDate() == null) { | |
| return true; | |
| } | |
| LocalDateTime oneYearAgo = LocalDateTime.now().minusYears(1); | |
| ZonedDateTime zonedDateTime = oneYearAgo.atZone(ZoneId.systemDefault()); | |
| Timestamp lastYear = Timestamp.from(zonedDateTime.toInstant()); | |
| return dar.getSubmissionDate().before(lastYear); | |
| // If the DAR is null, we consider it expired for metrics purposes. | |
| // Otherwise, rely on the expiration logic defined in DataAccessRequest. | |
| if (dar == null) { | |
| return true; | |
| } | |
| return dar.getExpired(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In short, we are doing this but with one additional check to ensure that submission date isn't also null.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,20 @@ | ||
| package org.broadinstitute.consent.http.resources; | ||
|
|
||
| import com.google.inject.Inject; | ||
| import io.dropwizard.auth.Auth; | ||
| import jakarta.annotation.security.PermitAll; | ||
| import jakarta.ws.rs.GET; | ||
| import jakarta.ws.rs.Path; | ||
| import jakarta.ws.rs.PathParam; | ||
| import jakarta.ws.rs.Produces; | ||
| import jakarta.ws.rs.core.Response; | ||
| import java.util.List; | ||
| import org.broadinstitute.consent.http.models.DarMetricsSummary; | ||
| import org.broadinstitute.consent.http.models.DatasetMetrics; | ||
| import org.broadinstitute.consent.http.models.DuosUser; | ||
| import org.broadinstitute.consent.http.service.MetricsService; | ||
|
|
||
| @Path("/metrics") | ||
| @Path("{api : (api/)?}metrics") | ||
| public class MetricsResource extends Resource { | ||
|
|
||
| private final MetricsService metricsService; | ||
|
|
@@ -19,6 +24,12 @@ public MetricsResource(MetricsService metricsService) { | |
| this.metricsService = metricsService; | ||
| } | ||
|
|
||
| /** | ||
| * @deprecated | ||
| * @param datasetId the id of the dataset for which to generate metrics | ||
| * @return Response containing DatasetMetrics for the given datasetId | ||
| */ | ||
| @Deprecated(forRemoval = true, since = "2026-02-23") | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will be removed when the front end is updated to use the |
||
| @GET | ||
| @Path("/dataset/{datasetId}") | ||
| @Produces("application/json") | ||
|
|
@@ -30,4 +41,19 @@ public Response getDatasetMetricsData(@PathParam("datasetId") Integer datasetId) | |
| return createExceptionResponse(e); | ||
| } | ||
| } | ||
|
|
||
| @SuppressWarnings("unused") | ||
| @GET | ||
| @Path("/dar-summaries/{datasetId}") | ||
| @Produces("application/json") | ||
| @PermitAll | ||
| public Response getDarSummaryData( | ||
| @Auth DuosUser user, @PathParam("datasetId") Integer datasetId) { | ||
| try { | ||
| List<DarMetricsSummary> summaries = metricsService.generateDarSummaries(datasetId); | ||
| return Response.ok().entity(summaries).build(); | ||
| } catch (Exception e) { | ||
| return createExceptionResponse(e); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,115 +1,40 @@ | ||
| package org.broadinstitute.consent.http.service; | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||
| import com.google.inject.Inject; | ||
| import jakarta.ws.rs.NotFoundException; | ||
| import java.sql.Timestamp; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
| import java.util.function.Function; | ||
| import java.util.stream.Collectors; | ||
| import org.broadinstitute.consent.http.db.DarCollectionDAO; | ||
| import org.broadinstitute.consent.http.db.DataAccessRequestDAO; | ||
| import org.broadinstitute.consent.http.db.DatasetDAO; | ||
| import org.broadinstitute.consent.http.db.ElectionDAO; | ||
| import org.broadinstitute.consent.http.models.DarCollection; | ||
| import org.broadinstitute.consent.http.models.DarMetricsSummary; | ||
| import org.broadinstitute.consent.http.models.DataAccessRequest; | ||
| import org.broadinstitute.consent.http.models.Dataset; | ||
| import org.broadinstitute.consent.http.models.DatasetMetrics; | ||
| import org.broadinstitute.consent.http.models.Election; | ||
|
|
||
| public class MetricsService { | ||
|
|
||
| private final DatasetDAO dataSetDAO; | ||
| private final DataAccessRequestDAO darDAO; | ||
| private final DarCollectionDAO darCollectionDAO; | ||
| private final ElectionDAO electionDAO; | ||
|
|
||
| @Inject | ||
| public MetricsService( | ||
| DatasetDAO dataSetDAO, | ||
| DataAccessRequestDAO darDAO, | ||
| DarCollectionDAO darCollectionDAO, | ||
| ElectionDAO electionDAO) { | ||
| public MetricsService(DatasetDAO dataSetDAO, DataAccessRequestDAO darDAO) { | ||
| this.dataSetDAO = dataSetDAO; | ||
| this.darDAO = darDAO; | ||
| this.darCollectionDAO = darCollectionDAO; | ||
| this.electionDAO = electionDAO; | ||
| } | ||
|
|
||
| public static class DarMetricsSummary { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extracted to the models package. |
||
|
|
||
| final Timestamp updateDate; | ||
| @JsonProperty final String projectTitle; | ||
| @JsonProperty final String darCode; | ||
| @JsonProperty final String nonTechRus; | ||
| @JsonProperty final String referenceId; | ||
|
|
||
| public DarMetricsSummary(DataAccessRequest dar, String darCode) { | ||
| if (dar != null && dar.data != null) { | ||
| this.updateDate = dar.getUpdateDate(); | ||
| this.projectTitle = dar.data.getProjectTitle(); | ||
| this.darCode = darCode; | ||
| this.nonTechRus = dar.data.getNonTechRus(); | ||
| this.referenceId = dar.getReferenceId(); | ||
| } else { | ||
| this.updateDate = null; | ||
| this.projectTitle = null; | ||
| this.darCode = null; | ||
| this.nonTechRus = null; | ||
| this.referenceId = null; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public DatasetMetrics generateDatasetMetrics(Integer datasetId) { | ||
|
|
||
| DatasetMetrics metrics = new DatasetMetrics(); | ||
| List<DarMetricsSummary> darMetricsSummaries = generateDarSummaries(datasetId); | ||
| metrics.setDars(darMetricsSummaries); | ||
| return metrics; | ||
| } | ||
|
|
||
| // get datasetDTO with properties and data use restrictions | ||
| public List<DarMetricsSummary> generateDarSummaries(Integer datasetId) { | ||
| Dataset dataset = dataSetDAO.findDatasetById(datasetId); | ||
| if (dataset == null) { | ||
| throw new NotFoundException("Dataset with specified ID does not exist."); | ||
| } | ||
|
|
||
| // find dars with the given datasetId in their list of datasetIds, datasetId is a String so it | ||
| // can be converted to jsonb in query | ||
| // convert all dars into smaller objects that only contain the information needed | ||
| List<DataAccessRequest> dars = darDAO.findApprovedDARsByDatasetId(datasetId); | ||
| List<Integer> darCollectionIds = dars.stream().map(DataAccessRequest::getCollectionId).toList(); | ||
| List<DarCollection> darCollections = | ||
| darCollectionIds.isEmpty() | ||
| ? List.of() | ||
| : darCollectionDAO.findDARCollectionByCollectionIds(darCollectionIds); | ||
| Map<Integer, DarCollection> collectionMap = | ||
| darCollections.stream() | ||
| .collect(Collectors.toMap(DarCollection::getDarCollectionId, Function.identity())); | ||
|
|
||
| List<DarMetricsSummary> darInfo = | ||
| dars.stream() | ||
| .map( | ||
| dar -> { | ||
| DarCollection collection = collectionMap.get(dar.getCollectionId()); | ||
| String darCode = Objects.nonNull(collection) ? collection.getDarCode() : null; | ||
| return new DarMetricsSummary(dar, darCode); | ||
| }) | ||
| .collect(Collectors.toList()); | ||
|
|
||
| // if there are associated dars, find associated access elections so we know how many and which | ||
| // dars are approved/denied | ||
| List<String> referenceIds = | ||
| dars.stream().map(dar -> (dar.referenceId)).collect(Collectors.toList()); | ||
| if (!referenceIds.isEmpty()) { | ||
| List<Election> elections = | ||
| electionDAO.findLastElectionsByReferenceIdsAndType(referenceIds, "DataAccess"); | ||
| metrics.setElections(elections); | ||
| } else { | ||
| metrics.setElections(Collections.emptyList()); | ||
| } | ||
| metrics.setDataset(dataset); | ||
| metrics.setDars(darInfo); | ||
| return metrics; | ||
| List<DataAccessRequest> dars = | ||
| darDAO.findSummaryMetricApprovedDARsByDatasetIdIncludesExpired(datasetId); | ||
| return dars.stream().map(DarMetricsSummary::new).toList(); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.