Skip to content

Commit

Permalink
Merge branch 'OCD-4817' into qa
Browse files Browse the repository at this point in the history
  • Loading branch information
kekey1 committed Mar 4, 2025
2 parents 3793c19 + 86a4fe1 commit 3747814
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1961,7 +1961,7 @@
" pm.expect(pm.response.text()).to.include(\"Standards Version Advancement Process 170.204(a)(1) is not valid for criteria 170.315 (b)(6)\");\r",
"});\r",
"pm.test(\"expect to see an error for invalid Test Functionality ID and name\", function () {\r",
" pm.expect(pm.response.text()).to.include(\"Certification 170.315 (g)(8) contains invalid Functionality Tested ID '45'.\");\r",
" pm.expect(pm.response.text()).to.include(\"In Criteria 170.315 (g)(8), Functionality Tested (g)(4)(i)(B) is for Criteria 170.315 (g)(4) and is not valid for Criteria 170.315 (g)(8). The invalid Functionality Tested has been removed.\");\r",
"});\r",
"pm.test(\"expect to see an error for invalid Test Standard ID\", function () {\r",
" pm.expect(pm.response.text()).to.include(\"Criteria 170.315 (b)(6) contains a test standard ID '2021' which does not exist for edition 2015\");\r",
Expand Down
3 changes: 2 additions & 1 deletion chpl/chpl-resources/src/main/resources/errors.properties
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ listing.criteria.additionalSoftwareHasNameAndListingData=Additional Software for
listing.criteria.invalidHasAdditionalSoftware=Criteria %s contains an invalid value '%s' for Additional Software.
listing.criteria.noAdditionalSoftwareMismatch=Criteria %s indicates additional software should be present but none was found.
listing.criteria.hasAdditionalSoftwareMismatch=Criteria %s indicates additional software should not be present but some was found.
listing.criteria.additionalSoftwareRequiresGrouping=Criterion %s has multiple additional software entries. A "grouping" value must be provided to indicate how the additional software must be combined (e.g. software A and B or software C).

#test tool errors
listing.criteria.badTestTool=Could not process Test Tool '%s'.
Expand Down Expand Up @@ -309,7 +310,7 @@ listing.criteria.invalidFunctionalityTested=Certification %s contains invalid Fu
listing.criteria.invalidFunctionalityTestedId=Certification %s contains invalid Functionality Tested ID '%s'.
listing.criteria.missingFunctionalityTestedName=There was no Functionality Tested name found for certification criteria %s.
listing.criteria.functionalityTestedCriterionMismatch=In Criteria %s, Functionality Tested %s is for Criteria %s and is not valid for Criteria %s. The invalid Functionality Tested has been removed.
listing.criteria.functionalityTestedNotFoundAndRemoved=Criteria %s contains an invalid Functionality Tested '%s'. It has been removed from the pending listing.
listing.criteria.functionalityTestedNotFoundAndRemoved=Criteria %s contains an invalid Functionality Tested '%s'. It has been removed.
listing.criteria.functionalityTestedPermissionError=Current user does not have permission to add/remove Functionality Tested '%s' for Criteria '%s'.
listing.criteria.functionalityTestedUnavailable=The functionality tested %s on the criterion %s is unavailable for this listing.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ private void addAccessibilityStandards(String[][] csvDataMatrix, List<CertifiedP
csvDataMatrix[0][col++] = "1";
for (int i = 0; i < accStds.size(); i++) {
CertifiedProductAccessibilityStandard accStd = accStds.get(i);
csvDataMatrix[i][col++] = accStd.getAccessibilityStandardName();
csvDataMatrix[i][col] = accStd.getAccessibilityStandardName();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public boolean matches(CertificationResultAdditionalSoftware other) {
} else if (!StringUtils.isEmpty(this.getName()) && !StringUtils.isEmpty(other.getName())
&& this.getName().equalsIgnoreCase(other.getName())
&& ((StringUtils.isEmpty(this.getVersion()) && StringUtils.isEmpty(other.getVersion()))
|| this.getVersion().equalsIgnoreCase(other.getVersion()))) {
|| StringUtils.equals(this.getVersion(), other.getVersion()))) {
result = true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
import gov.healthit.chpl.util.ErrorMessageUtil;
import gov.healthit.chpl.util.Util;
import gov.healthit.chpl.util.ValidationUtils;
import gov.healthit.chpl.validation.listing.reviewer.Reviewer;

@Component("listingUploadAdditionalSoftwareFrameworkReviewer")
public class AdditionalSoftwareReviewer {
@Component("listingUploadAdditionalSoftwareReviewer")
public class AdditionalSoftwareReviewer implements Reviewer {
private CertificationResultRules certResultRules;
private ValidationUtils validationUtils;
private ErrorMessageUtil msgUtil;
Expand All @@ -41,6 +42,7 @@ private void review(CertifiedProductSearchDetails listing, CertificationResult c
reviewAdditionalSoftwareListMatchesAdditionalSoftwareBoolean(listing, certResult);
reviewAdditionalSoftwareHasEitherNameOrListing(listing, certResult);
reviewAdditionalSoftwareListingsAreValid(listing, certResult);
reviewAdditionalSoftwareGroupingsPresent(listing, certResult);
}

private void reviewCriteriaCanHaveAdditionalSoftware(CertifiedProductSearchDetails listing, CertificationResult certResult) {
Expand Down Expand Up @@ -96,4 +98,17 @@ private void reviewAdditionalSoftwareListingsAreValid(CertifiedProductSearchDeta
Util.formatCriteriaNumber(certResult.getCriterion()))));
}
}

private void reviewAdditionalSoftwareGroupingsPresent(CertifiedProductSearchDetails listing, CertificationResult certResult) {
if (!CollectionUtils.isEmpty(certResult.getAdditionalSoftware())
&& certResult.getAdditionalSoftware().size() > 1) {
long additionalSoftwareWithoutGroupings = certResult.getAdditionalSoftware().stream()
.filter(additionalSoftware -> StringUtils.isEmpty(additionalSoftware.getGrouping()))
.count();
if (additionalSoftwareWithoutGroupings > 0) {
listing.addDataErrorMessage(msgUtil.getMessage("listing.criteria.additionalSoftwareRequiresGrouping",
Util.formatCriteriaNumber(certResult.getCriterion())));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class CertificationResultReviewer {
public CertificationResultReviewer(@Qualifier("listingUploadUnavailableCriteriaReviewer") UnavailableCriteriaReviewer unavailableCriteriaReviewer,
@Qualifier("listingUploadCriteriaReviewer") CriteriaReviewer criteriaReviewer,
@Qualifier("listingUploadPrivacyAndSecurityFrameworkReviewer") PrivacyAndSecurityFrameworkReviewer privacyAndSecurityFrameworkReviewer,
@Qualifier("listingUploadAdditionalSoftwareFrameworkReviewer") AdditionalSoftwareReviewer additionalSoftwareReviewer,
@Qualifier("listingUploadAdditionalSoftwareReviewer") AdditionalSoftwareReviewer additionalSoftwareReviewer,
@Qualifier("gapAllowedReviewer") GapAllowedReviewer gapAllowedReviewer,
@Qualifier("listingUploadTestToolReviewer") TestToolReviewer testToolReviewer,
@Qualifier("listingUploadTestDataReviewer") TestDataReviewer testDataReviewer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@
import gov.healthit.chpl.util.ErrorMessageUtil;
import gov.healthit.chpl.util.Util;
import gov.healthit.chpl.util.ValidationUtils;
import gov.healthit.chpl.validation.listing.reviewer.Reviewer;

@Component("listingUploadFunctionalityTestedReviewer")
public class FunctionalityTestedReviewer {
public class FunctionalityTestedReviewer implements Reviewer {
private CertificationResultRules certResultRules;
private ValidationUtils validationUtils;
private FunctionalityTestedDAO functionalityTestedDao;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@

import gov.healthit.chpl.upload.listing.validation.reviewer.AccessibilityStandardReviewer;
import gov.healthit.chpl.upload.listing.validation.reviewer.AdditionalSoftwareCodeReviewer;
import gov.healthit.chpl.upload.listing.validation.reviewer.AdditionalSoftwareReviewer;
import gov.healthit.chpl.upload.listing.validation.reviewer.ChplNumberFormatReviewer;
import gov.healthit.chpl.upload.listing.validation.reviewer.CqmResultReviewer;
import gov.healthit.chpl.upload.listing.validation.reviewer.FunctionalityTestedReviewer;
import gov.healthit.chpl.upload.listing.validation.reviewer.IcsCodeReviewer;
import gov.healthit.chpl.upload.listing.validation.reviewer.PrivacyAndSecurityFrameworkReviewer;
import gov.healthit.chpl.upload.listing.validation.reviewer.QmsStandardReviewer;
Expand Down Expand Up @@ -46,7 +48,6 @@
import gov.healthit.chpl.validation.listing.reviewer.UnavailableCriteriaReviewer;
import gov.healthit.chpl.validation.listing.reviewer.UnsupportedCharacterReviewer;
import gov.healthit.chpl.validation.listing.reviewer.UrlReviewer;
import gov.healthit.chpl.validation.listing.reviewer.ValidDataReviewer;
import gov.healthit.chpl.validation.listing.reviewer.edition2015.CodeSetAsOfTodayReviewer;
import gov.healthit.chpl.validation.listing.reviewer.edition2015.FunctionalityTestedAllowedByCriteriaReviewer;
import gov.healthit.chpl.validation.listing.reviewer.edition2015.FunctionalityTestedAllowedByRoleReviewer;
Expand Down Expand Up @@ -99,8 +100,8 @@ public class Edition2015ListingValidator extends Validator {
private TestingLabReviewer testingLabReviewer;

@Autowired
@Qualifier("validDataReviewer")
private ValidDataReviewer validDataReviewer;
@Qualifier("listingUploadAdditionalSoftwareReviewer")
private AdditionalSoftwareReviewer additionalSoftwareReviewer;

@Autowired
@Qualifier("sedG32015Reviewer")
Expand Down Expand Up @@ -146,9 +147,13 @@ public class Edition2015ListingValidator extends Validator {
@Qualifier("urlReviewer")
private UrlReviewer urlReviewer;

@Autowired
@Qualifier("listingUploadFunctionalityTestedReviewer")
private FunctionalityTestedReviewer functionalityTestedReviewer;

@Autowired
@Qualifier("functionalityTestedAllowedByCriteriaReviewer")
private FunctionalityTestedAllowedByCriteriaReviewer functionalityTestedReviewer;
private FunctionalityTestedAllowedByCriteriaReviewer functionalityTestedAllowedByCriteriaReviewer;

@Autowired
@Qualifier("duplicateDataReviewer")
Expand Down Expand Up @@ -277,7 +282,7 @@ public synchronized List<Reviewer> getReviewers() {
reviewers.add(requiredAndRelatedCriteriaReviewer);
reviewers.add(unavailableCriteriaReviewer);
reviewers.add(testingLabReviewer);
reviewers.add(validDataReviewer);
reviewers.add(additionalSoftwareReviewer);
reviewers.add(sedG3Reviewer);
reviewers.add(sedReviewer);
reviewers.add(ucdProcessReviewer);
Expand All @@ -292,6 +297,7 @@ public synchronized List<Reviewer> getReviewers() {
reviewers.add(ttReviewer);
reviewers.add(urlReviewer);
reviewers.add(functionalityTestedReviewer);
reviewers.add(functionalityTestedAllowedByCriteriaReviewer);
reviewers.add(standardReviewer);
reviewers.add(invalidCriteriaCombinationReviewer);
reviewers.add(cqmResultReviewer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import gov.healthit.chpl.domain.CertifiedProductSearchDetails;
import gov.healthit.chpl.validation.listing.reviewer.ComparisonReviewer;
import gov.healthit.chpl.validation.listing.reviewer.Reviewer;
import jakarta.transaction.Transactional;
import lombok.extern.log4j.Log4j2;

@Log4j2
Expand All @@ -17,6 +18,7 @@ public abstract class Validator {
public abstract List<ComparisonReviewer> getComparisonReviewers();
public abstract List<ComparisonReviewer> getComparisonReviewersToAlwaysCheck();

@Transactional
public synchronized void validate(CertifiedProductSearchDetails listing) {
if (CollectionUtils.isEmpty(listing.getCertificationEvents()) || listing.isCertificateActive()) {
for (Reviewer reviewer : getReviewers()) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class AdditionalSoftwareReviewerTest {
private static final String NO_ADDITIONAL_SOFTWARE_BUT_SHOULD = "Criteria %s contains no additional software but it is expected.";
private static final String ADDITIONAL_SOFTWARE_INVALID = "No CHPL product was found matching additional software %s for %s.";
private static final String ADDITIONAL_SOFTWARE_BOTH_FIELDS_HAVE_DATA = "Additional Software for %s has both a listing and software name/version specified. Only one is expected.";
private static final String ADDITIONAL_SOFTWARE_REQUIRES_GROUPING = "Criteria %s requires groupings on additional software.";

private CertificationResultRules certResultRules;
private ErrorMessageUtil msgUtil;
Expand All @@ -53,6 +54,10 @@ public void before() throws EntityRetrievalException {
Mockito.when(msgUtil.getMessage(ArgumentMatchers.eq("listing.criteria.invalidAdditionalSoftware"),
ArgumentMatchers.anyString(), ArgumentMatchers.anyString()))
.thenAnswer(i -> String.format(ADDITIONAL_SOFTWARE_INVALID, i.getArgument(1), i.getArgument(2)));
Mockito.when(msgUtil.getMessage(ArgumentMatchers.eq("listing.criteria.additionalSoftwareRequiresGrouping"),
ArgumentMatchers.anyString()))
.thenAnswer(i -> String.format(ADDITIONAL_SOFTWARE_REQUIRES_GROUPING, i.getArgument(1), ""));

reviewer = new AdditionalSoftwareReviewer(certResultRules,
new ValidationUtils(Mockito.mock(CertificationCriterionService.class)),
msgUtil);
Expand Down Expand Up @@ -543,6 +548,36 @@ public void review_additionalSoftwareBothChplIdAndVersionWithDataRemovedCriteria
assertEquals(0, listing.getErrorMessages().size());
}

@Test
public void review_additionalSoftwareMultipleWithoutGrouping_hasError() {
Mockito.when(certResultRules.hasCertOption(ArgumentMatchers.anyLong(), ArgumentMatchers.eq(CertificationResultRules.ADDITIONAL_SOFTWARE)))
.thenReturn(true);

List<CertificationResultAdditionalSoftware> additionalSoftware = new ArrayList<CertificationResultAdditionalSoftware>();
additionalSoftware.add(CertificationResultAdditionalSoftware.builder()
.name("test")
.build());
additionalSoftware.add(CertificationResultAdditionalSoftware.builder()
.name("test2")
.build());
CertifiedProductSearchDetails listing = CertifiedProductSearchDetails.builder()
.certificationResult(CertificationResult.builder()
.criterion(CertificationCriterion.builder()
.id(1L)
.number("170.315 (a)(1)")
.build())
.success(true)
.additionalSoftware(additionalSoftware)
.build())
.build();
reviewer.review(listing);

assertEquals(0, listing.getWarningMessages().size());
assertEquals(1, listing.getErrorMessages().size());
assertTrue(listing.getErrorMessages().contains(
String.format(ADDITIONAL_SOFTWARE_REQUIRES_GROUPING, "170.315 (a)(1)")));
}

@Test
public void review_additionalSoftwareValidName_noError() {
Mockito.when(certResultRules.hasCertOption(ArgumentMatchers.anyLong(), ArgumentMatchers.eq(CertificationResultRules.ADDITIONAL_SOFTWARE)))
Expand All @@ -567,4 +602,33 @@ public void review_additionalSoftwareValidName_noError() {
assertEquals(0, listing.getWarningMessages().size());
assertEquals(0, listing.getErrorMessages().size());
}

public void review_additionalSoftwareValidNamesWithMultipleAndGrouping_noError() {
Mockito.when(certResultRules.hasCertOption(ArgumentMatchers.anyLong(), ArgumentMatchers.eq(CertificationResultRules.ADDITIONAL_SOFTWARE)))
.thenReturn(true);

List<CertificationResultAdditionalSoftware> additionalSoftware = new ArrayList<CertificationResultAdditionalSoftware>();
additionalSoftware.add(CertificationResultAdditionalSoftware.builder()
.name("test")
.grouping("a")
.build());
additionalSoftware.add(CertificationResultAdditionalSoftware.builder()
.name("test2")
.grouping("a")
.build());
CertifiedProductSearchDetails listing = CertifiedProductSearchDetails.builder()
.certificationResult(CertificationResult.builder()
.criterion(CertificationCriterion.builder()
.id(1L)
.number("170.315 (a)(1)")
.build())
.success(true)
.additionalSoftware(additionalSoftware)
.build())
.build();
reviewer.review(listing);

assertEquals(0, listing.getWarningMessages().size());
assertEquals(0, listing.getErrorMessages().size());
}
}

0 comments on commit 3747814

Please sign in to comment.