diff --git a/src/main/java/org/broadinstitute/consent/http/db/DaaDAO.java b/src/main/java/org/broadinstitute/consent/http/db/DaaDAO.java index 19bcaf50e..e5695cb31 100644 --- a/src/main/java/org/broadinstitute/consent/http/db/DaaDAO.java +++ b/src/main/java/org/broadinstitute/consent/http/db/DaaDAO.java @@ -2,8 +2,10 @@ import java.time.Instant; import java.util.List; +import java.util.Map; import java.util.Set; import org.broadinstitute.consent.http.db.mapper.DaaAuditMapper; +import org.broadinstitute.consent.http.db.mapper.DaaDatasetReducer; import org.broadinstitute.consent.http.db.mapper.DaaMapper; import org.broadinstitute.consent.http.db.mapper.DataAccessAgreementReducer; import org.broadinstitute.consent.http.db.mapper.FileStorageObjectMapper; @@ -15,6 +17,7 @@ import org.jdbi.v3.sqlobject.customizer.Bind; import org.jdbi.v3.sqlobject.customizer.BindList; import org.jdbi.v3.sqlobject.customizer.BindList.EmptyHandling; +import org.jdbi.v3.sqlobject.statement.SqlBatch; import org.jdbi.v3.sqlobject.statement.SqlQuery; import org.jdbi.v3.sqlobject.statement.SqlUpdate; import org.jdbi.v3.sqlobject.statement.UseRowReducer; @@ -299,4 +302,32 @@ WHERE dataset.dataset_id IN () Set findDaaIdsByDatasetIds( @BindList(value = "datasetIds", onEmpty = EmptyHandling.NULL_STRING) List datasetIds); + + @SqlQuery( + """ + SELECT daa.daa_id, dataset.dataset_id + FROM data_access_agreement daa + INNER JOIN dac_daa ON daa.daa_id = dac_daa.daa_id + INNER JOIN dac ON dac.dac_id = dac_daa.dac_id + INNER JOIN dataset ON dataset.dac_id = dac.dac_id + WHERE dataset.dataset_id IN () + GROUP BY daa.daa_id, dataset.dataset_id + ORDER BY daa.daa_id + """) + @UseRowReducer(DaaDatasetReducer.class) + Map> mapDaaIdsToDatasetIds( + @BindList(value = "datasetIds", onEmpty = EmptyHandling.NULL_STRING) Set datasetIds); + + @SqlBatch( + """ + INSERT INTO dar_daa (dar_id, daa_id) VALUES (:darId, :daaId) + ON CONFLICT DO NOTHING + """) + void insertDarDAARelationship(@Bind("darId") Integer darId, @Bind("daaId") Set daaIds); + + @SqlUpdate( + """ + DELETE FROM dar_daa WHERE dar_id = :darId + """) + void deleteDarDAARelationship(@Bind("darId") Integer darId); } diff --git a/src/main/java/org/broadinstitute/consent/http/db/DataAccessRequestDAO.java b/src/main/java/org/broadinstitute/consent/http/db/DataAccessRequestDAO.java index e2e93287f..1129a9f6a 100644 --- a/src/main/java/org/broadinstitute/consent/http/db/DataAccessRequestDAO.java +++ b/src/main/java/org/broadinstitute/consent/http/db/DataAccessRequestDAO.java @@ -17,6 +17,7 @@ import org.jdbi.v3.sqlobject.customizer.BindBean; import org.jdbi.v3.sqlobject.customizer.BindList; import org.jdbi.v3.sqlobject.customizer.BindList.EmptyHandling; +import org.jdbi.v3.sqlobject.statement.GetGeneratedKeys; import org.jdbi.v3.sqlobject.statement.SqlBatch; import org.jdbi.v3.sqlobject.statement.SqlQuery; import org.jdbi.v3.sqlobject.statement.SqlUpdate; @@ -424,7 +425,8 @@ void insertDraftDataAccessRequest( VALUES (:collectionId, :referenceId, :userId, :createDate, :submissionDate, :updateDate, regexp_replace(:data, '\\\\u0000', '', 'g')::jsonb, :eraCommonsId) """) - void insertDataAccessRequest( + @GetGeneratedKeys + Integer insertDataAccessRequest( @Bind("collectionId") Integer collectionId, @Bind("referenceId") String referenceId, @Bind("userId") Integer userId, @@ -450,7 +452,8 @@ void insertDataAccessRequest( (parent_id, collection_id, reference_id, user_id, create_date, submission_date, update_date, data, era_commons_id) VALUES (:parentId, :collectionId, :referenceId, :userId, now(), now(), now(), regexp_replace(:data, '\\\\u0000', '', 'g')::jsonb, :eraCommonsId) """) - void insertProgressReport( + @GetGeneratedKeys + Integer insertProgressReport( @Bind("parentId") Integer parentId, @Bind("collectionId") Integer collectionId, @Bind("referenceId") String referenceId, diff --git a/src/main/java/org/broadinstitute/consent/http/db/mapper/DaaDatasetReducer.java b/src/main/java/org/broadinstitute/consent/http/db/mapper/DaaDatasetReducer.java new file mode 100644 index 000000000..46cf1ccc3 --- /dev/null +++ b/src/main/java/org/broadinstitute/consent/http/db/mapper/DaaDatasetReducer.java @@ -0,0 +1,31 @@ +package org.broadinstitute.consent.http.db.mapper; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Stream; +import org.jdbi.v3.core.result.RowReducer; +import org.jdbi.v3.core.result.RowView; + +public class DaaDatasetReducer + implements RowReducer>, Map.Entry>> { + + @Override + public Map> container() { + return new HashMap<>(); + } + + @Override + public void accumulate(Map> container, RowView rowView) { + int daaId = rowView.getColumn("daa_id", Integer.class); + Integer datasetId = rowView.getColumn("dataset_id", Integer.class); + container.computeIfAbsent(daaId, k -> new HashSet<>()).add(datasetId); + } + + @Override + public Stream>> stream(Map> container) { + return container.entrySet().stream(); + } +} diff --git a/src/main/java/org/broadinstitute/consent/http/models/DataAccessRequest.java b/src/main/java/org/broadinstitute/consent/http/models/DataAccessRequest.java index e8f0504a6..d0cd0f3d9 100644 --- a/src/main/java/org/broadinstitute/consent/http/models/DataAccessRequest.java +++ b/src/main/java/org/broadinstitute/consent/http/models/DataAccessRequest.java @@ -405,6 +405,11 @@ public static DataAccessRequest populateProgressReportFromJsonString( // object and not the original DAR. originalDataCopy.setReferenceId(referenceId); + // We need to set the new DAAs that were in place on the DAR because the DAAs may have been + // updated + // from the original DAR. + originalDataCopy.setDaaIds(newData.getDaaIds()); + newDar.setData(originalDataCopy); return newDar; } diff --git a/src/main/java/org/broadinstitute/consent/http/models/DataAccessRequestData.java b/src/main/java/org/broadinstitute/consent/http/models/DataAccessRequestData.java index 7fd7d8ed2..6416764b9 100644 --- a/src/main/java/org/broadinstitute/consent/http/models/DataAccessRequestData.java +++ b/src/main/java/org/broadinstitute/consent/http/models/DataAccessRequestData.java @@ -687,6 +687,9 @@ public void setPiEmail(String piEmail) { } public Set getDaaIds() { + if (Objects.isNull(daaIds)) { + daaIds = Collections.emptySet(); + } return daaIds; } diff --git a/src/main/java/org/broadinstitute/consent/http/resources/DaaResource.java b/src/main/java/org/broadinstitute/consent/http/resources/DaaResource.java index ee1bbd2f6..13fed0cc1 100644 --- a/src/main/java/org/broadinstitute/consent/http/resources/DaaResource.java +++ b/src/main/java/org/broadinstitute/consent/http/resources/DaaResource.java @@ -1,5 +1,7 @@ package org.broadinstitute.consent.http.resources; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; import com.google.inject.Inject; import io.dropwizard.auth.Auth; import jakarta.annotation.security.PermitAll; @@ -20,10 +22,12 @@ import jakarta.ws.rs.core.StreamingOutput; import jakarta.ws.rs.core.UriInfo; import java.io.InputStream; +import java.lang.reflect.Type; import java.net.URI; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Set; import org.broadinstitute.consent.http.enumeration.UserRoles; import org.broadinstitute.consent.http.models.Dac; import org.broadinstitute.consent.http.models.DataAccessAgreement; @@ -392,4 +396,18 @@ public Response sendNewDaaMessage( return createExceptionResponse(e); } } + + @POST + @RolesAllowed({ADMIN, CHAIRPERSON, MEMBER, SIGNINGOFFICIAL, RESEARCHER}) + @Path("datasets") + public Response findDaaForDatasets(@Auth DuosUser duosUser, String json) { + try { + Gson gson = new Gson(); + Type setType = new TypeToken>() {}.getType(); + Set set = gson.fromJson(json, setType); + return Response.ok(daaService.findDaaIdsByDatasetIds(set)).build(); + } catch (Exception e) { + return createExceptionResponse(e); + } + } } diff --git a/src/main/java/org/broadinstitute/consent/http/service/DaaService.java b/src/main/java/org/broadinstitute/consent/http/service/DaaService.java index e9e6d5474..66d8cb0ea 100644 --- a/src/main/java/org/broadinstitute/consent/http/service/DaaService.java +++ b/src/main/java/org/broadinstitute/consent/http/service/DaaService.java @@ -13,7 +13,9 @@ import java.io.InputStream; import java.util.Comparator; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.UUID; import org.apache.commons.lang3.StringUtils; import org.broadinstitute.consent.http.cloudstore.GCSService; @@ -221,4 +223,8 @@ public List findDAAsInJsonArray(String json, String arrayKe public List findByDarReferenceId(String referenceId) { return daaDAO.findByDarReferenceId(referenceId); } + + public Map> findDaaIdsByDatasetIds(Set datasetIds) { + return daaDAO.mapDaaIdsToDatasetIds(datasetIds); + } } diff --git a/src/main/java/org/broadinstitute/consent/http/service/DarCollectionService.java b/src/main/java/org/broadinstitute/consent/http/service/DarCollectionService.java index 109f9e3a9..a5fa42c7a 100644 --- a/src/main/java/org/broadinstitute/consent/http/service/DarCollectionService.java +++ b/src/main/java/org/broadinstitute/consent/http/service/DarCollectionService.java @@ -1232,8 +1232,10 @@ private void approveDataAccessRequestBySigningOfficial( dataAccessRequestDAO.updateDarApprovalSO(signingOfficial.getUserId(), dar.getReferenceId()); User researcher = userDAO.findUserById(dar.getUserId()); List datasetIds = dar.getDatasetIds(); - dacAutomationRuleService.triggerDACRuleSettings( - researcher, datasetIds, dar.getReferenceId(), request); + if (!dar.getIsCloseoutProgressReport() && !dar.getHasDMI()) { + dacAutomationRuleService.triggerDACRuleSettings( + researcher, datasetIds, dar.getReferenceId(), request); + } } private void validateSigningOfficialApproval(User signingOfficial, DataAccessRequest dar) { diff --git a/src/main/java/org/broadinstitute/consent/http/service/DataAccessRequestService.java b/src/main/java/org/broadinstitute/consent/http/service/DataAccessRequestService.java index 1fa0df441..a50794375 100644 --- a/src/main/java/org/broadinstitute/consent/http/service/DataAccessRequestService.java +++ b/src/main/java/org/broadinstitute/consent/http/service/DataAccessRequestService.java @@ -22,9 +22,11 @@ import java.util.Objects; import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; import org.apache.commons.validator.routines.EmailValidator; import org.broadinstitute.consent.http.configurations.ConsentConfiguration; import org.broadinstitute.consent.http.db.DAOContainer; +import org.broadinstitute.consent.http.db.DaaDAO; import org.broadinstitute.consent.http.db.DarCollectionDAO; import org.broadinstitute.consent.http.db.DataAccessRequestDAO; import org.broadinstitute.consent.http.db.DatasetDAO; @@ -74,6 +76,7 @@ public class DataAccessRequestService implements ConsentLogger { private static final String LAB_STAFF = "Lab staff"; private final CounterService counterService; private final DataAccessRequestDAO dataAccessRequestDAO; + private final DaaDAO daaDAO; private final DarCollectionDAO darCollectionDAO; private final ElectionDAO electionDAO; private final InstitutionService institutionService; @@ -109,6 +112,7 @@ public DataAccessRequestService( this.matchDAO = container.getMatchDAO(); this.voteDAO = container.getVoteDAO(); this.userDAO = container.getUserDAO(); + this.daaDAO = container.getDaaDAO(); this.dacService = dacService; this.dataAccessRequestServiceDAO = dataAccessRequestServiceDAO; this.ruleService = ruleService; @@ -235,26 +239,30 @@ public DataAccessRequest createDataAccessRequest( } String referenceId; List datasetIds = dataAccessRequest.getDatasetIds(); - + Integer darId; if (Objects.nonNull(existingDar)) { referenceId = dataAccessRequest.getReferenceId(); + darId = existingDar.getId(); dataAccessRequestDAO.updateDraftToSubmittedForCollection(collectionId, referenceId); dataAccessRequestDAO.updateDataByReferenceId( referenceId, user.getUserId(), now, now, darData, user.getEraCommonsId()); + daaDAO.deleteDarDAARelationship(darId); } else { referenceId = UUID.randomUUID().toString(); - dataAccessRequestDAO.insertDataAccessRequest( - collectionId, - referenceId, - user.getUserId(), - now, - now, - now, - darData, - user.getEraCommonsId()); - } + darId = + dataAccessRequestDAO.insertDataAccessRequest( + collectionId, + referenceId, + user.getUserId(), + now, + now, + now, + darData, + user.getEraCommonsId()); + } + daaDAO.insertDarDAARelationship(darId, dataAccessRequest.data.getDaaIds()); syncDataAccessRequestDatasets(datasetIds, referenceId); - boolean requiresSOApproval = flagIfSOApprovalIsNeeded(datasetIds, referenceId); + boolean requiresSOApproval = flagIfSOApprovalIsNeeded(user, datasetIds, referenceId); if (!requiresSOApproval) { ruleService.triggerDACRuleSettings(user, datasetIds, referenceId, request); } @@ -287,18 +295,23 @@ public DataAccessRequest createProgressReport( "Progress report can only be created for approved datasets in the parent DAR"); } try { - dataAccessRequestDAO.insertProgressReport( - progressReport.getParentId(), - progressReport.getCollectionId(), - referenceId, - user.getUserId(), - progressReport.getData(), - user.getEraCommonsId()); + Integer id = + dataAccessRequestDAO.insertProgressReport( + progressReport.getParentId(), + progressReport.getCollectionId(), + referenceId, + user.getUserId(), + progressReport.getData(), + user.getEraCommonsId()); + if (!progressReport.getIsCloseoutProgressReport()) { + daaDAO.insertDarDAARelationship(id, progressReport.getData().getDaaIds()); + } } catch (JdbiException e) { throw new BadRequestException( "Unable to create progress report for Data Access Request " + parentDar.getReferenceId()); } - + boolean userIsPreAuthedForDaas = + isUserPreAuthorizedForAllDaas(user, progressReport.getDatasetIds()); if (progressReport.getIsCloseoutProgressReport()) { try { User signingOfficialUser = @@ -312,11 +325,15 @@ public DataAccessRequest createProgressReport( } catch (TemplateException | IOException e) { throw new InternalServerErrorException(e); } + } else if (!userIsPreAuthedForDaas) { + dataAccessRequestDAO.updateRequiresSOApproval(true, referenceId); } syncDataAccessRequestDatasets(progressReportDatasetIds, referenceId); - if (!progressReport.getIsCloseoutProgressReport() && !progressReport.getHasDMI()) { + if (!progressReport.getIsCloseoutProgressReport() + && !progressReport.getHasDMI() + && userIsPreAuthedForDaas) { ruleService.triggerDACRuleSettings(user, progressReportDatasetIds, referenceId, request); } @@ -392,7 +409,7 @@ public void validateProgressReport( throw new BadRequestException( "Cannot create a progress report for a draft Data Access Request"); } - if (progressReport.getDatasetIds() == null || progressReport.getDatasetIds().isEmpty()) { + if (progressReport.getDatasetIds().isEmpty()) { throw new BadRequestException("At least one dataset is required"); } if (!Set.copyOf(parentDar.getDatasetIds()).containsAll(progressReport.getDatasetIds())) { @@ -421,6 +438,9 @@ public void validateProgressReport( "The selected signing official in the closeout was not found."); } } + if (!progressReport.getIsCloseoutProgressReport() && !progressReport.getHasDMI()) { + hasAcknowledgedRequiredDaas(progressReport); + } } @VisibleForTesting @@ -438,6 +458,29 @@ protected void validateCommonDarAndProgressReportElements(User user, DataAccessR userService.validateActiveERACredentials(user); } + @VisibleForTesting + protected void hasAcknowledgedRequiredDaas(DataAccessRequest dar) { + if (dar.getDatasetIds().isEmpty()) { + throw new BadRequestException("At least one dataset is required"); + } + + Set requiredDaas = daaDAO.findDaaIdsByDatasetIds(dar.getDatasetIds()); + + if (!(requiredDaas.containsAll(dar.getData().getDaaIds()) + && requiredDaas.size() == dar.getData().getDaaIds().size())) { + throw new BadRequestException("All of the DAAs required were not acknowledged."); + } + } + + private boolean isUserPreAuthorizedForAllDaas(User user, List datasetIds) { + Set datasetDaas = + daaDAO.findDaaIdsByDatasetIds(datasetIds).stream().collect(Collectors.toSet()); + + Set userDaas = user.getLibraryCard().getDaaIds().stream().collect(Collectors.toSet()); + + return userDaas.containsAll(datasetDaas); + } + public void validateDar(User user, DataAccessRequest dar) { validateCommonDarAndProgressReportElements(user, dar); @@ -450,6 +493,7 @@ public void validateDar(User user, DataAccessRequest dar) { validateNoKeyPersonnelDuplicates(dar.getData()); validatePersonnelInstitutionAndLibraryCardRequirements(user, dar.getData()); validateCountryOfOperation(dar.getData(), false); + hasAcknowledgedRequiredDaas(dar); } protected void validateCountryOfOperation(DataAccessRequestData darData, boolean skipPI) { @@ -736,11 +780,13 @@ public List findOpenElectionsByReferenceId(String referenceId) { return electionDAO.findOpenElectionsByReferenceIds(List.of(referenceId)); } - private boolean flagIfSOApprovalIsNeeded(List datasetIds, String referenceId) { + private boolean flagIfSOApprovalIsNeeded( + User user, List datasetIds, String referenceId) { if (!datasetDAO - .filterDatasetIdsByAutomationRuleType( - datasetIds, DACAutomationRuleType.REQUIRE_SO_DAR_APPROVAL.name()) - .isEmpty()) { + .filterDatasetIdsByAutomationRuleType( + datasetIds, DACAutomationRuleType.REQUIRE_SO_DAR_APPROVAL.name()) + .isEmpty() + || !isUserPreAuthorizedForAllDaas(user, datasetIds)) { dataAccessRequestDAO.updateRequiresSOApproval(true, referenceId); return true; } diff --git a/src/main/resources/assets/api-docs.yaml b/src/main/resources/assets/api-docs.yaml index ffc69ba62..13c290986 100644 --- a/src/main/resources/assets/api-docs.yaml +++ b/src/main/resources/assets/api-docs.yaml @@ -71,6 +71,8 @@ paths: $ref: 'paths/daaById.yaml' /api/daa/{dacId}/updated/{oldDaaId}/{newDaaName}: $ref: 'paths/daaUpdateByDacId.yaml' + /api/daa/datasets: + $ref: 'paths/daaDatasets.yaml' /api/dac: $ref: 'paths/dac.yaml' /api/dac/rules: diff --git a/src/main/resources/assets/paths/daaDatasets.yaml b/src/main/resources/assets/paths/daaDatasets.yaml new file mode 100644 index 000000000..9eb02f1ec --- /dev/null +++ b/src/main/resources/assets/paths/daaDatasets.yaml @@ -0,0 +1,36 @@ +post: + summary: Mapping between DAAs and Datasets + description: | + Provides insights into the datasets associated with each DAA. Useful to understand + which rules apply to each dataset in a multi-dataset/multi-dac DAR. + operationId: findDaaForDatasets + tags: + - DAA + requestBody: + description: A set of dataset IDs + content: + application/json: + schema: + type: array + items: + type: integer + responses: + 200: + content: + application/json: + schema: + type: object + additionalProperties: + type: array + items: + type: integer + example: + 100: [ 1, 2, 3 ] + 101: [ 5 ] + description: A Map of DAA to Datasets the DAA applies to. + 400: + description: Bad Request (malformed list of dataset ids) + 401: + description: Unauthenticated + 500: + description: Internal server error diff --git a/src/main/resources/changelog-master.xml b/src/main/resources/changelog-master.xml index e6e9fbce4..f3951040d 100644 --- a/src/main/resources/changelog-master.xml +++ b/src/main/resources/changelog-master.xml @@ -242,4 +242,5 @@ + diff --git a/src/main/resources/changesets/changelog-consent-2026-04-08-dar-daa.xml b/src/main/resources/changesets/changelog-consent-2026-04-08-dar-daa.xml new file mode 100644 index 000000000..c7829a109 --- /dev/null +++ b/src/main/resources/changesets/changelog-consent-2026-04-08-dar-daa.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + diff --git a/src/test/java/org/broadinstitute/consent/http/db/DaaDAOTest.java b/src/test/java/org/broadinstitute/consent/http/db/DaaDAOTest.java index 12536003b..42aaf1f24 100644 --- a/src/test/java/org/broadinstitute/consent/http/db/DaaDAOTest.java +++ b/src/test/java/org/broadinstitute/consent/http/db/DaaDAOTest.java @@ -1,5 +1,6 @@ package org.broadinstitute.consent.http.db; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -11,13 +12,16 @@ import java.time.Instant; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.UUID; import org.broadinstitute.consent.http.enumeration.AuditActions; import org.broadinstitute.consent.http.enumeration.FileCategory; import org.broadinstitute.consent.http.models.DaaAudit; import org.broadinstitute.consent.http.models.Dac; import org.broadinstitute.consent.http.models.DataAccessAgreement; import org.broadinstitute.consent.http.models.DataAccessRequest; +import org.broadinstitute.consent.http.models.DataAccessRequestData; import org.broadinstitute.consent.http.models.DataUseBuilder; import org.broadinstitute.consent.http.models.Dataset; import org.broadinstitute.consent.http.models.LibraryCard; @@ -373,7 +377,7 @@ void testFindByDarReferenceId() { } @Test - void testFindDaaIdsByDatasetIds() { + void testMapDaaIdsToDatasetIds() { Integer userId = createUserId(); Integer dacId = dacDAO.createDac(randomAlphabetic(5), randomAlphabetic(5), "", new Date()); Dataset dataset1 = createRandomDataset(userDAO.findUserById(userId), dacDAO.findById(dacId)); @@ -391,7 +395,118 @@ void testFindDaaIdsByDatasetIds() { } @Test - void testFindDaaIdsByDatasetIds_dacNotAssociated() { + void testFindDaaIdsWithDatasetIds() { + Integer userId = createUserId(); + Integer dacId1 = dacDAO.createDac("dac1", randomAlphabetic(5), "", new Date()); + Integer dacId2 = dacDAO.createDac("dac2", randomAlphabetic(5), "", new Date()); + Dataset dataset1 = createRandomDataset(userDAO.findUserById(userId), dacDAO.findById(dacId1)); + Dataset dataset2 = createRandomDataset(userDAO.findUserById(userId), dacDAO.findById(dacId2)); + Dataset dataset3 = createRandomDataset(userDAO.findUserById(userId), dacDAO.findById(dacId2)); + + Integer daa1 = daaDAO.createDaa(userId, Instant.now(), userId, Instant.now(), dacId1); + Integer daa2 = daaDAO.createDaa(userId, Instant.now(), userId, Instant.now(), dacId2); + + daaDAO.createDacDaaRelation(dacId1, daa1, userId); + daaDAO.createDacDaaRelation(dacId2, daa2, userId); + + Map> daaDatasetMap = + daaDAO.mapDaaIdsToDatasetIds( + Set.of(dataset1.getDatasetId(), dataset2.getDatasetId(), dataset3.getDatasetId())); + assertFalse(daaDatasetMap.isEmpty()); + assertEquals(2, daaDatasetMap.size()); + + Set daa1Datasets = daaDatasetMap.get(daa1); + assertEquals(1, daa1Datasets.size()); + assertTrue(daa1Datasets.contains(dataset1.getDatasetId())); + + Set daa2Datasets = daaDatasetMap.get(daa2); + assertEquals(2, daa2Datasets.size()); + assertTrue(daa2Datasets.contains(dataset2.getDatasetId())); + assertTrue(daa2Datasets.contains(dataset3.getDatasetId())); + } + + @Test + void testFindDaaIdsWithDatasetIds_No_IDs() { + Map> daaDatasetMap = daaDAO.mapDaaIdsToDatasetIds(Set.of()); + assertTrue(daaDatasetMap.isEmpty()); + } + + @Test + void testFindDaaIdsWithDatasetIds_No_Data() { + Map> daaDatasetMap = daaDAO.mapDaaIdsToDatasetIds(Set.of(1, 2, 3)); + assertTrue(daaDatasetMap.isEmpty()); + } + + @Test + void testStoreDarDAARelationshipForDar() { + Integer userId = createUserId(); + Integer dacId1 = dacDAO.createDac("dac1", randomAlphabetic(5), "", new Date()); + Integer dacId2 = dacDAO.createDac("dac2", randomAlphabetic(5), "", new Date()); + + Integer daa1 = daaDAO.createDaa(userId, Instant.now(), userId, Instant.now(), dacId1); + Integer daa2 = daaDAO.createDaa(userId, Instant.now(), userId, Instant.now(), dacId2); + + daaDAO.createDacDaaRelation(dacId1, daa1, userId); + daaDAO.createDacDaaRelation(dacId2, daa2, userId); + Date now = new Date(); + Integer darCollectionId = darCollectionDAO.insertDarCollection("ABC", userId, now); + Integer darId = + dataAccessRequestDAO.insertDataAccessRequest( + darCollectionId, + UUID.randomUUID().toString(), + userId, + now, + now, + now, + new DataAccessRequestData(), + "`"); + assertDoesNotThrow(() -> daaDAO.insertDarDAARelationship(darId, Set.of(daa1, daa2))); + } + + @Test + void testStoreDarDAARelationshipForPR() { + Integer userId = createUserId(); + Integer dacId1 = dacDAO.createDac("dac1", randomAlphabetic(5), "", new Date()); + Integer dacId2 = dacDAO.createDac("dac2", randomAlphabetic(5), "", new Date()); + + Integer daa1 = daaDAO.createDaa(userId, Instant.now(), userId, Instant.now(), dacId1); + Integer daa2 = daaDAO.createDaa(userId, Instant.now(), userId, Instant.now(), dacId2); + + daaDAO.createDacDaaRelation(dacId1, daa1, userId); + daaDAO.createDacDaaRelation(dacId2, daa2, userId); + Date now = new Date(); + Integer darCollectionId = darCollectionDAO.insertDarCollection("ABC", userId, now); + String darUUID = UUID.randomUUID().toString(); + Integer darId = + dataAccessRequestDAO.insertDataAccessRequest( + darCollectionId, darUUID, userId, now, now, now, new DataAccessRequestData(), "`"); + Integer prId = + dataAccessRequestDAO.insertProgressReport( + darId, + darCollectionId, + UUID.randomUUID().toString(), + userId, + new DataAccessRequestData(), + ""); + assertDoesNotThrow(() -> daaDAO.insertDarDAARelationship(prId, Set.of(daa1, daa2))); + assertEquals(2, getDarDaaCount(prId)); + + daaDAO.deleteDarDAARelationship(prId); + assertEquals(0, getDarDaaCount(prId)); + } + + private static Integer getDarDaaCount(Integer prId) { + return jdbi.withHandle( + handle -> + handle + .createQuery("SELECT count(*) FROM dar_daa WHERE dar_id = :prId") + .bind("prId", prId) + .mapTo(Integer.class) + .one()); + } + + @Test + void testMapDaaIdsToDatasetIds_dacNotAssociated() { Integer userId = createUserId(); Integer dacId = dacDAO.createDac(randomAlphabetic(5), randomAlphabetic(5), "", new Date()); Dataset dataset1 = createRandomDataset(userDAO.findUserById(userId), dacDAO.findById(dacId)); @@ -406,7 +521,7 @@ void testFindDaaIdsByDatasetIds_dacNotAssociated() { } @Test - void testFindDaaIdsByDatasetIds_datasetsNotAssociated() { + void testMapDaaIdsToDatasetIds_datasetsNotAssociated() { Integer userId = createUserId(); Integer dacId = dacDAO.createDac(randomAlphabetic(5), randomAlphabetic(5), "", new Date()); Dataset dataset1 = createRandomDataset(userDAO.findUserById(userId), dacDAO.findById(dacId)); diff --git a/src/test/java/org/broadinstitute/consent/http/models/DataAccessRequestDataTest.java b/src/test/java/org/broadinstitute/consent/http/models/DataAccessRequestDataTest.java index c0e75a0ec..6ade26345 100644 --- a/src/test/java/org/broadinstitute/consent/http/models/DataAccessRequestDataTest.java +++ b/src/test/java/org/broadinstitute/consent/http/models/DataAccessRequestDataTest.java @@ -6,6 +6,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import com.google.gson.Gson; import jakarta.ws.rs.BadRequestException; import java.util.List; import java.util.Set; @@ -642,7 +643,7 @@ void testGetSetCloseoutSupplement() { @Test void testGetSetDaaIds() { DataAccessRequestData data = new DataAccessRequestData(); - assertNull(data.getDaaIds()); + assertTrue(data.getDaaIds().isEmpty()); Set daaIds = Set.of(1, 2, 3); data.setDaaIds(daaIds); assertEquals(daaIds, data.getDaaIds()); @@ -653,4 +654,15 @@ void testGetDatasetIds_returnsEmptyListWhenNull() { DataAccessRequestData data = new DataAccessRequestData(); assertTrue(data.getDatasetIds().isEmpty()); } + + @Test + void testJsonSerializeDeserialize() { + DataAccessRequestData data = new DataAccessRequestData(); + Set daaIds = Set.of(1, 2, 3); + data.setDaaIds(daaIds); + Gson gson = new Gson(); + String json = gson.toJson(data); + DataAccessRequestData data2 = gson.fromJson(json, DataAccessRequestData.class); + assertEquals(data.getDaaIds(), data2.getDaaIds()); + } } diff --git a/src/test/java/org/broadinstitute/consent/http/resources/DaaResourceTest.java b/src/test/java/org/broadinstitute/consent/http/resources/DaaResourceTest.java index 20dbd8ae9..131cbcd0d 100644 --- a/src/test/java/org/broadinstitute/consent/http/resources/DaaResourceTest.java +++ b/src/test/java/org/broadinstitute/consent/http/resources/DaaResourceTest.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anySet; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -20,6 +21,7 @@ import java.io.IOException; import java.util.Collections; import java.util.List; +import java.util.Map; import org.apache.commons.io.IOUtils; import org.apache.http.HttpStatus; import org.broadinstitute.consent.http.AbstractTestHelper; @@ -1183,4 +1185,30 @@ void testRemoveDacFromDaaDoesNotExist() { assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatus()); } } + + @Test + void testFindDaaForDatasets() { + User authedUser = new User(); + DuosUser duosUser = new DuosUser(authUser, authedUser); + String testData = "[1, 2, 3]"; + when(daaService.findDaaIdsByDatasetIds(anySet())).thenReturn(Map.of()); + + resource = new DaaResource(daaService, dacService, userService, libraryCardService); + + try (Response response = resource.findDaaForDatasets(duosUser, testData)) { + assertEquals(HttpStatus.SC_OK, response.getStatus()); + } + } + + @Test + void testFindDaaForDatasets_BadRequest() { + User authedUser = new User(); + DuosUser duosUser = new DuosUser(authUser, authedUser); + String testData = "1"; + resource = new DaaResource(daaService, dacService, userService, libraryCardService); + + try (Response response = resource.findDaaForDatasets(duosUser, testData)) { + assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatus()); + } + } } diff --git a/src/test/java/org/broadinstitute/consent/http/service/DaaServiceTest.java b/src/test/java/org/broadinstitute/consent/http/service/DaaServiceTest.java index 64b25ca30..56fc37e12 100644 --- a/src/test/java/org/broadinstitute/consent/http/service/DaaServiceTest.java +++ b/src/test/java/org/broadinstitute/consent/http/service/DaaServiceTest.java @@ -7,6 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anySet; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -23,7 +24,9 @@ import java.io.InputStream; import java.sql.SQLException; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.Set; import org.broadinstitute.consent.http.AbstractTestHelper; import org.broadinstitute.consent.http.cloudstore.GCSService; import org.broadinstitute.consent.http.db.DaaDAO; @@ -463,4 +466,13 @@ void testFindByDarReferenceIdNoResults() { List daas = service.findByDarReferenceId(randomAlphabetic(5)); assertTrue(daas.isEmpty()); } + + @Test + void testFindDaaIdsByDatasetIds() { + initService(); + when(daaDAO.mapDaaIdsToDatasetIds(anySet())).thenReturn(Map.of()); + + Map> daaMap = service.findDaaIdsByDatasetIds(Set.of(1, 2, 3)); + assertTrue(daaMap.isEmpty()); + } } diff --git a/src/test/java/org/broadinstitute/consent/http/service/DarCollectionServiceTest.java b/src/test/java/org/broadinstitute/consent/http/service/DarCollectionServiceTest.java index c5524f917..f7620e469 100644 --- a/src/test/java/org/broadinstitute/consent/http/service/DarCollectionServiceTest.java +++ b/src/test/java/org/broadinstitute/consent/http/service/DarCollectionServiceTest.java @@ -13,6 +13,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -57,6 +58,7 @@ import org.broadinstitute.consent.http.models.DarCollectionSummary; import org.broadinstitute.consent.http.models.DataAccessRequest; import org.broadinstitute.consent.http.models.DataAccessRequestData; +import org.broadinstitute.consent.http.models.DataManagementIncident; import org.broadinstitute.consent.http.models.DataUseBuilder; import org.broadinstitute.consent.http.models.Dataset; import org.broadinstitute.consent.http.models.Election; @@ -650,6 +652,66 @@ void testApproveCollectionWithSORequired_Approving() { assertDoesNotThrow(() -> service.approveDarCollection(signingOfficial, collection, request)); } + @Test + void testApproveDarCollectionDMI() { + User user = new User(); + user.setEmail("email"); + user.setUserId(1); + User signingOfficial = new User(); + signingOfficial.setRoles(List.of(UserRoles.SigningOfficial())); + signingOfficial.setEmail("email2"); + signingOfficial.setUserId(2); + DataAccessRequest dar = new DataAccessRequest(); + dar.setReferenceId(UUID.randomUUID().toString()); + dar.setUserId(user.getUserId()); + dar.setCloseoutSigningOfficialApprovedUserId(signingOfficial.getUserId()); + DataAccessRequestData darData = new DataAccessRequestData(); + darData.setSigningOfficialEmail(signingOfficial.getEmail()); + darData.setDmi(new DataManagementIncident(List.of("one"), "my incident")); + dar.setData(darData); + dar.setRequiresSOApproval(true); + + DarCollection collection = new DarCollection(); + collection.addDar(dar); + + doNothing().when(dataAccessRequestDAO).updateDarApprovalSO(anyInt(), anyString()); + when(userDAO.findUserById(user.getUserId())).thenReturn(user); + service.approveDarCollection(signingOfficial, collection, request); + verify(dacAutomationRuleService, never()) + .triggerDACRuleSettings(any(), anyList(), anyString(), any()); + } + + @Test + void testApproveDarCollectionCloseout() { + User user = new User(); + user.setEmail("email"); + user.setUserId(1); + User signingOfficial = new User(); + signingOfficial.setRoles(List.of(UserRoles.SigningOfficial())); + signingOfficial.setEmail("email2"); + signingOfficial.setUserId(2); + DataAccessRequest dar = new DataAccessRequest(); + dar.setParentId(-1); + dar.setReferenceId(UUID.randomUUID().toString()); + dar.setUserId(user.getUserId()); + dar.setCloseoutSigningOfficialApprovedUserId(signingOfficial.getUserId()); + DataAccessRequestData darData = new DataAccessRequestData(); + darData.setSigningOfficialEmail(signingOfficial.getEmail()); + darData.setCloseoutSupplement( + new CloseoutSupplement(List.of("reasons"), "other text", signingOfficial.getUserId())); + dar.setData(darData); + dar.setRequiresSOApproval(true); + + DarCollection collection = new DarCollection(); + collection.addDar(dar); + + doNothing().when(dataAccessRequestDAO).updateDarApprovalSO(anyInt(), anyString()); + when(userDAO.findUserById(user.getUserId())).thenReturn(user); + service.approveDarCollection(signingOfficial, collection, request); + verify(dacAutomationRuleService, never()) + .triggerDACRuleSettings(any(), anyList(), anyString(), any()); + } + @Test void testApproveCollectionWithSORequired_Approving_NoSO_Email() { User user = new User(); diff --git a/src/test/java/org/broadinstitute/consent/http/service/DataAccessRequestServiceTest.java b/src/test/java/org/broadinstitute/consent/http/service/DataAccessRequestServiceTest.java index ac5b1d8c1..f7fb297a0 100644 --- a/src/test/java/org/broadinstitute/consent/http/service/DataAccessRequestServiceTest.java +++ b/src/test/java/org/broadinstitute/consent/http/service/DataAccessRequestServiceTest.java @@ -10,6 +10,7 @@ import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; @@ -38,6 +39,7 @@ import org.broadinstitute.consent.http.AbstractTestHelper; import org.broadinstitute.consent.http.configurations.ConsentConfiguration; import org.broadinstitute.consent.http.db.DAOContainer; +import org.broadinstitute.consent.http.db.DaaDAO; import org.broadinstitute.consent.http.db.DacDAO; import org.broadinstitute.consent.http.db.DarCollectionDAO; import org.broadinstitute.consent.http.db.DataAccessRequestDAO; @@ -58,6 +60,7 @@ import org.broadinstitute.consent.http.models.DarDataset; import org.broadinstitute.consent.http.models.DataAccessRequest; import org.broadinstitute.consent.http.models.DataAccessRequestData; +import org.broadinstitute.consent.http.models.DataManagementIncident; import org.broadinstitute.consent.http.models.Dataset; import org.broadinstitute.consent.http.models.Election; import org.broadinstitute.consent.http.models.Institution; @@ -94,6 +97,7 @@ class DataAccessRequestServiceTest extends AbstractTestHelper { @Mock private DacDAO dacDAO; @Mock private UserDAO userDAO; @Mock private DatasetDAO dataSetDAO; + @Mock private DaaDAO daaDAO; @Mock private ElectionDAO electionDAO; @Mock private EmailService emailService; @Mock private DacService dacService; @@ -168,6 +172,7 @@ void initService() { container.setElectionDAO(electionDAO); container.setVoteDAO(voteDAO); container.setMatchDAO(matchDAO); + container.setDaaDAO(daaDAO); serverUrl = config.getServicesConfiguration().getLocalURL(); service = new DataAccessRequestService( @@ -211,9 +216,41 @@ void testCreateDataAccessRequest_Create() { when(dataAccessRequestDAO.findByReferenceId(argThat(new LongerThanTwo()))).thenReturn(dar); when(darCollectionDAO.insertDarCollection(anyString(), anyInt(), any(Date.class))) .thenReturn(randomInt(1, 100)); - doNothing() - .when(dataAccessRequestDAO) - .insertDataAccessRequest( + when(dataAccessRequestDAO.insertDataAccessRequest( + anyInt(), + anyString(), + anyInt(), + any(Date.class), + any(Date.class), + any(Date.class), + any(DataAccessRequestData.class), + anyString())) + .thenReturn(1); + when(dataSetDAO.filterDatasetIdsByAutomationRuleType( + dar.getDatasetIds(), DACAutomationRuleType.REQUIRE_SO_DAR_APPROVAL.name())) + .thenReturn(List.of()); + when(daaDAO.findDaaIdsByDatasetIds(anyList())).thenReturn(Set.of()); + DataAccessRequest newDar = service.createDataAccessRequest(user, dar, request); + assertNotNull(newDar); + verify(dataAccessRequestDAO, never()).updateRequiresSOApproval(eq(true), anyString()); + } + + @Test + void testCreateDataAccessRequest_Create_Missing_DAAs() { + DataAccessRequest dar = generateDataAccessRequest(); + dar.addDatasetIds(List.of(1, 2, 3)); + dar.setCreateDate(new Timestamp(1000)); + dar.setReferenceId("id"); + User user = createUserWithPrerequisites(); + user.getLibraryCard().setDaaIds(List.of(2)); + dar.getData().setDaaIds(Set.of(1)); + when(institutionService.findInstitutionForEmail(any())).thenReturn(user.getInstitution()); + when(counterService.getNextDarSequence()).thenReturn(1); + when(dataAccessRequestDAO.findByReferenceId("id")).thenReturn(null); + when(dataAccessRequestDAO.findByReferenceId(argThat(new LongerThanTwo()))).thenReturn(dar); + when(darCollectionDAO.insertDarCollection(anyString(), anyInt(), any(Date.class))) + .thenReturn(randomInt(1, 100)); + when(dataAccessRequestDAO.insertDataAccessRequest( anyInt(), anyString(), anyInt(), @@ -221,12 +258,46 @@ void testCreateDataAccessRequest_Create() { any(Date.class), any(Date.class), any(DataAccessRequestData.class), - anyString()); + anyString())) + .thenReturn(1); when(dataSetDAO.filterDatasetIdsByAutomationRuleType( dar.getDatasetIds(), DACAutomationRuleType.REQUIRE_SO_DAR_APPROVAL.name())) - .thenReturn(dar.getDatasetIds()); + .thenReturn(List.of()); + when(daaDAO.findDaaIdsByDatasetIds(anyList())).thenReturn(Set.of(1)); DataAccessRequest newDar = service.createDataAccessRequest(user, dar, request); assertNotNull(newDar); + verify(dataAccessRequestDAO).updateRequiresSOApproval(eq(true), anyString()); + } + + @Test + void testCreateDataAccessRequest_Create_SO_Approval_Required_By_Rule() { + DataAccessRequest dar = generateDataAccessRequest(); + dar.addDatasetIds(List.of(1, 2, 3)); + dar.setCreateDate(new Timestamp(1000)); + dar.setReferenceId("id"); + User user = createUserWithPrerequisites(); + when(institutionService.findInstitutionForEmail(any())).thenReturn(user.getInstitution()); + when(counterService.getNextDarSequence()).thenReturn(1); + when(dataAccessRequestDAO.findByReferenceId("id")).thenReturn(null); + when(dataAccessRequestDAO.findByReferenceId(argThat(new LongerThanTwo()))).thenReturn(dar); + when(darCollectionDAO.insertDarCollection(anyString(), anyInt(), any(Date.class))) + .thenReturn(randomInt(1, 100)); + when(dataAccessRequestDAO.insertDataAccessRequest( + anyInt(), + anyString(), + anyInt(), + any(Date.class), + any(Date.class), + any(Date.class), + any(DataAccessRequestData.class), + anyString())) + .thenReturn(1); + when(dataSetDAO.filterDatasetIdsByAutomationRuleType( + dar.getDatasetIds(), DACAutomationRuleType.REQUIRE_SO_DAR_APPROVAL.name())) + .thenReturn(List.of(1, 2, 3)); + DataAccessRequest newDar = service.createDataAccessRequest(user, dar, request); + assertNotNull(newDar); + verify(dataAccessRequestDAO).updateRequiresSOApproval(eq(true), anyString()); } @Test @@ -307,6 +378,73 @@ void createProgressReport() { .insertAllDarDatasets(argThat(new DarDatasetMatcher(progressReport))); } + @Test + void createProgressReportDmi() { + DataAccessRequest parentDar = generateDataAccessRequest(); + DataAccessRequest progressReport = generateProgressReport(); + progressReport.setParentId(parentDar.getId()); + progressReport.setCollectionId(parentDar.getCollectionId()); + progressReport.getData().setDmi(new DataManagementIncident(List.of("incident 1"), "A bad day")); + parentDar.setSubmissionDate(Timestamp.from(Instant.now())); + User user = createUserWithPrerequisites(); + parentDar.setUserId(user.getUserId()); + when(dataAccessRequestDAO.findByReferenceId(progressReport.getReferenceId())) + .thenReturn(progressReport); + when(dataAccessRequestDAO.findDatasetApprovalsByDar(parentDar.getReferenceId())) + .thenReturn(Set.copyOf(progressReport.getDatasetIds())); + when(daaDAO.findDaaIdsByDatasetIds(progressReport.getDatasetIds())).thenReturn(Set.of(1)); + DataAccessRequest newDar = + service.createProgressReport(user, progressReport, parentDar, request); + assertNotNull(newDar); + verify(dataAccessRequestDAO) + .insertProgressReport( + parentDar.getId(), + progressReport.getCollectionId(), + progressReport.getReferenceId(), + user.getUserId(), + progressReport.getData(), + user.getEraCommonsId()); + verify(ruleService, never()) + .triggerDACRuleSettings( + user, progressReport.getDatasetIds(), progressReport.getReferenceId(), request); + verify(dataAccessRequestDAO) + .insertAllDarDatasets(argThat(new DarDatasetMatcher(progressReport))); + } + + @Test + void createProgressReportNotPreAuthed() { + DataAccessRequest parentDar = generateDataAccessRequest(); + DataAccessRequest progressReport = generateProgressReport(); + progressReport.setParentId(parentDar.getId()); + progressReport.setCollectionId(parentDar.getCollectionId()); + progressReport.getData().setDaaIds(Set.of(1)); + parentDar.setSubmissionDate(Timestamp.from(Instant.now())); + User user = createUserWithPrerequisites(); + user.getLibraryCard().setDaaIds(List.of(2)); + parentDar.setUserId(user.getUserId()); + when(dataAccessRequestDAO.findByReferenceId(progressReport.getReferenceId())) + .thenReturn(progressReport); + when(dataAccessRequestDAO.findDatasetApprovalsByDar(parentDar.getReferenceId())) + .thenReturn(Set.copyOf(progressReport.getDatasetIds())); + when(daaDAO.findDaaIdsByDatasetIds(progressReport.getDatasetIds())).thenReturn(Set.of(1)); + DataAccessRequest newDar = + service.createProgressReport(user, progressReport, parentDar, request); + assertNotNull(newDar); + verify(dataAccessRequestDAO) + .insertProgressReport( + parentDar.getId(), + progressReport.getCollectionId(), + progressReport.getReferenceId(), + user.getUserId(), + progressReport.getData(), + user.getEraCommonsId()); + verify(ruleService, never()) + .triggerDACRuleSettings( + user, progressReport.getDatasetIds(), progressReport.getReferenceId(), request); + verify(dataAccessRequestDAO) + .insertAllDarDatasets(argThat(new DarDatasetMatcher(progressReport))); + } + @Test void createCloseoutProgressReport() throws TemplateException, IOException { User user = createUserWithPrerequisites(); @@ -351,6 +489,7 @@ void createCloseoutProgressReport() throws TemplateException, IOException { verify(ruleService, never()).triggerDACRuleSettings(any(), any(), any(), any()); verify(dataAccessRequestDAO) .insertAllDarDatasets(argThat(new DarDatasetMatcher(progressReport))); + verify(dataAccessRequestDAO, never()).updateRequiresSOApproval(eq(true), anyString()); } @Test @@ -880,6 +1019,71 @@ void testGetUsersApprovedForDataset() { assertEquals(List.of(dar1, dar2), service.getApprovedDARsForDataset(d)); } + @Test + void testHasAcknowledgedRequiredDaas() { + Dataset d = new Dataset(); + d.setDatasetId(10); + Integer daaId = 1; + DataAccessRequest dar = new DataAccessRequest(); + dar.setDatasetIds(List.of(d.getDatasetId())); + DataAccessRequestData darData = new DataAccessRequestData(); + darData.setDaaIds(Set.of(daaId)); + dar.setData(darData); + when(daaDAO.findDaaIdsByDatasetIds(List.of(d.getDatasetId()))).thenReturn(Set.of(daaId)); + + assertDoesNotThrow(() -> service.hasAcknowledgedRequiredDaas(dar)); + } + + @Test + void testHasAcknowledgedRequiredDaas_No_DAA_Submitted() { + Dataset d = new Dataset(); + d.setDatasetId(10); + Integer daaId = 1; + DataAccessRequest dar = new DataAccessRequest(); + dar.setDatasetIds(List.of(d.getDatasetId())); + DataAccessRequestData darData = new DataAccessRequestData(); + darData.setDaaIds(Set.of()); + dar.setData(darData); + when(daaDAO.findDaaIdsByDatasetIds(List.of(d.getDatasetId()))).thenReturn(Set.of(daaId)); + + assertThrows(BadRequestException.class, () -> service.hasAcknowledgedRequiredDaas(dar)); + } + + @Test + void testHasRequiredDaas_No_DAA_Acknowledged_Required() { + Dataset d = new Dataset(); + d.setDatasetId(10); + Integer daaId = 1; + DataAccessRequest dar = new DataAccessRequest(); + dar.setDatasetIds(List.of(d.getDatasetId())); + DataAccessRequestData darData = new DataAccessRequestData(); + darData.setDaaIds(Set.of(daaId)); + dar.setData(darData); + when(daaDAO.findDaaIdsByDatasetIds(List.of(d.getDatasetId()))).thenReturn(Set.of()); + + assertThrows(BadRequestException.class, () -> service.hasAcknowledgedRequiredDaas(dar)); + } + + @Test + void testHasAcknowledgedRequiredDaas_No_Datasets() { + DataAccessRequest dar = new DataAccessRequest(); + assertThrows(BadRequestException.class, () -> service.hasAcknowledgedRequiredDaas(dar)); + } + + @Test + void testHasRequiredDaas_No_DAA_Submitted_OR_Acknowledged_Required_Allowed() { + Dataset d = new Dataset(); + d.setDatasetId(10); + DataAccessRequest dar = new DataAccessRequest(); + dar.setDatasetIds(List.of(d.getDatasetId())); + DataAccessRequestData darData = new DataAccessRequestData(); + darData.setDaaIds(Set.of()); + dar.setData(darData); + when(daaDAO.findDaaIdsByDatasetIds(List.of(d.getDatasetId()))).thenReturn(Set.of()); + + assertDoesNotThrow(() -> service.hasAcknowledgedRequiredDaas(dar)); + } + @Test void testInsertDraftDataAccessRequest() { User user = new User();