Skip to content
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

OCD-4516 - Build "developer attestations" report in PowerBI #1750

Merged
merged 17 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import gov.healthit.chpl.report.surveillance.CapCounts;
import gov.healthit.chpl.report.surveillance.NonconformityCounts;
import gov.healthit.chpl.report.surveillance.SurveillanceActivityCounts;
import gov.healthit.chpl.scheduler.job.report.attestation.AttestationReport;
import gov.healthit.chpl.scheduler.job.summarystatistics.data.CertificationBodyStatistic;
import gov.healthit.chpl.search.domain.ListingSearchResult;
import gov.healthit.chpl.util.SwaggerSecurityRequirement;
Expand Down Expand Up @@ -462,4 +463,14 @@ public ReportDataController(ReportDataManager reportDataManager, DeveloperSearch
return reportDataManager.getDirectReviewCounts();
}

@Operation(summary = "Retrieves the data used to generate the Attestations report.",
description = "Retrieves the data used to generate the Attestations report.",
security = {
@SecurityRequirement(name = SwaggerSecurityRequirement.API_KEY)
})
@RequestMapping(value = "/attestations", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
public @ResponseBody List<AttestationReport> getAttestationReports() {
return reportDataManager.getAttestationReports();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,13 @@
<KeyValuePair key="dd.span_id" value="%X{dd.span_id}" />
</JsonLayout>
</Console>
<Console name="attestationReportCreatorJobJson" target="SYSTEM_OUT">
<JsonLayout compact="true" eventEol="true" properties="true" stacktraceAsString="true">
<KeyValuePair key="service" value="attestationReportCreatorJob" />
<KeyValuePair key="dd.trace_id" value="%X{dd.trace_id}" />
<KeyValuePair key="dd.span_id" value="%X{dd.span_id}" />
</JsonLayout>
</Console>
<Console name="fixDatadogUrlUptimeAssertionsJobJson" target="SYSTEM_OUT">
<JsonLayout compact="true" eventEol="true" properties="true" stacktraceAsString="true">
<KeyValuePair key="service" value="fixDatadogUrlUptimeAssertionsJob" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,18 @@
interval="1" modulate="true" />
</Policies>
</RollingFile>
<RollingFile name="attestationReportCreatorJob"
fileName="${logDir}/scheduler/attestationReportCreatorJob.log"
filePattern="${logDir}/scheduler/history/attestationReportCreatorJob-%d{yyyy-MM-dd}.log"
filePermissions="rw-rw-r--">
<PatternLayout>
<Pattern>%d{ISO8601} %-5p (%t) [%C{1}(%M:%L)] %m%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy
interval="1" modulate="true" />
</Policies>
</RollingFile>
<RollingFile name="fixDatadogUrlUptimeAssertionsJob"
fileName="${logDir}/scheduler/fixDatadogUrlUptimeAssertionsJob.log"
filePattern="${logDir}/scheduler/history/fixDatadogUrlUptimeAssertionsJob-%d{yyyy-MM-dd}.log"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@
<Logger name="updatedSedFriendlyIdsJobLogger" level="INFO" additivity="false">
<AppenderRef ref="updatedSedFriendlyIdsJob" />
</Logger>
<Logger name="attestationReportCreatorJobLogger" level="INFO" additivity="false">
<AppenderRef ref="attestationReportCreatorJob" />
</Logger>
<Logger name="fixDatadogUrlUptimeAssertionsJobLogger" level="INFO" additivity="false">
<AppenderRef ref="fixDatadogUrlUptimeAssertionsJob" />
</Logger>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,10 @@
<AppenderRef ref="updatedSedFriendlyIdsJob" />
<AppenderRef ref="updatedSedFriendlyIdsJobJson" />
</Logger>
<Logger name="attestationReportCreatorJobLogger" level="INFO" additivity="false">
<AppenderRef ref="attestationReportCreatorJob" />
<AppenderRef ref="attestationReportCreatorJobJson" />
</Logger>
<Logger name="fixDatadogUrlUptimeAssertionsJobLogger" level="INFO" additivity="false">
<AppenderRef ref="fixDatadogUrlUptimeAssertionsJob" />
<AppenderRef ref="FixDatadogUrlUptimeAssertionsJobJson" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ apiCriteriaKeys=criterion.170_315_g_7,\

###### Attestations ######
attestationExceptionWindowInDays=5
attestationApprovalWindowInDays=30
####################################

###### Redis Connection Properties ######
Expand Down
9 changes: 9 additions & 0 deletions chpl/chpl-resources/src/main/resources/jobs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,15 @@
<recover>false</recover>
</job>

<job>
<name>attestationReportCreatorJob</name>
<group>systemJobs</group>
<description>Generate data for the Attestation Report (Power BI)</description>
<job-class>gov.healthit.chpl.scheduler.job.report.attestation.AttestationReportCreatorJob</job-class>
<durability>true</durability>
<recover>false</recover>
</job>

<job>
<name>fixDatadogUrlUptimeAssertionsJob</name>
<group>systemJobs</group>
Expand Down
10 changes: 10 additions & 0 deletions chpl/chpl-resources/src/main/resources/system-triggers.xml
Original file line number Diff line number Diff line change
Expand Up @@ -245,5 +245,15 @@
<cron-expression>0 30 6 * * ?</cron-expression> <!-- At 0630 UTC every day -->
</cron>
</trigger>
<trigger>
<cron>
<name>attestationReportCreator</name>
<group>AttestationReportCreatorJobTrigger</group>
<job-name>attestationReportCreatorJob</job-name>
<job-group>systemJobs</job-group>
<misfire-instruction>MISFIRE_INSTRUCTION_DO_NOTHING</misfire-instruction>
<cron-expression>0 30 10 * * ?</cron-expression> <!-- At 1030 UTC every day -->
</cron>
</trigger>
</schedule>
</job-scheduling-data>
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package gov.healthit.chpl.changerequest.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.stereotype.Repository;
Expand Down Expand Up @@ -47,4 +50,26 @@ public List<Developer> getDevelopersForCertificationBody(Long certificationBodyI
.map(item -> item.getDeveloper().toDomain())
.collect(Collectors.<Developer>toList());
}

public Map<Long, List<CertificationBody>> getCertificationBodiesForAllDeveloper() {
String hql = "SELECT main "
+ "FROM DeveloperCertificationBodyMapEntity main "
+ "JOIN FETCH main.developer dev "
+ "JOIN FETCH main.certificationBody cb "
+ "LEFT JOIN FETCH cb.address ";

List<DeveloperCertificationBodyMapEntity> entities = entityManager
.createQuery(hql, DeveloperCertificationBodyMapEntity.class)
.getResultList();

Map<Long, List<CertificationBody>> map = new HashMap<Long, List<CertificationBody>>();

entities.forEach(e -> {
if (!map.containsKey(e.getDeveloperId())) {
map.put(e.getDeveloperId(), new ArrayList<CertificationBody>());
}
map.get(e.getDeveloperId()).add(e.getCertificationBody().toDomain());
});
return map;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.stereotype.Component;

import gov.healthit.chpl.developer.search.DeveloperSearchResult;
import gov.healthit.chpl.report.attestation.AttestationReportService;
import gov.healthit.chpl.report.criteriaattribute.StandardListingReport;
import gov.healthit.chpl.report.criteriaattribute.StandardReport;
import gov.healthit.chpl.report.criteriaattribute.StandardReportService;
Expand All @@ -30,6 +31,7 @@
import gov.healthit.chpl.report.surveillance.NonconformityCounts;
import gov.healthit.chpl.report.surveillance.SurveillanceActivityCounts;
import gov.healthit.chpl.report.surveillance.SurveillanceReportsService;
import gov.healthit.chpl.scheduler.job.report.attestation.AttestationReport;
import gov.healthit.chpl.scheduler.job.summarystatistics.data.CertificationBodyStatistic;
import gov.healthit.chpl.search.domain.ListingSearchResult;
import lombok.Synchronized;
Expand All @@ -49,13 +51,15 @@ public class ReportDataManager {
private ServiceBaseUrlListReportService serviceBaseUrlListReportService;
private StandardReportService standardReportService;
private DirectReviewReportsService directReviewReportsService;
private AttestationReportService attestationReportService;
private ReportMetadataDAO reportMetadataDAO;

@Autowired
public ReportDataManager(CriteriaMigrationReportService criteriaMigrationReportService, DeveloperReportsService developerReportsService,
SurveillanceReportsService surveillanceReportsService, ProductReportsService productReportsService, ListingReportsService listingReportsService,
TestToolReportService testToolReportService, DirectReviewReportsService directReviewReportsService, ReportMetadataDAO reportMetadataDAO,
ServiceBaseUrlListReportService serviceBaseUrlListReportService, StandardReportService standardReportService) {
ServiceBaseUrlListReportService serviceBaseUrlListReportService, AttestationReportService attestationReportService,
StandardReportService standardReportService) {
this.criteriaMigrationReportService = criteriaMigrationReportService;
this.developerReportsService = developerReportsService;
this.surveillanceReportsService = surveillanceReportsService;
Expand All @@ -65,6 +69,7 @@ public ReportDataManager(CriteriaMigrationReportService criteriaMigrationReportS
this.serviceBaseUrlListReportService = serviceBaseUrlListReportService;
this.standardReportService = standardReportService;
this.directReviewReportsService = directReviewReportsService;
this.attestationReportService = attestationReportService;
this.reportMetadataDAO = reportMetadataDAO;
}

Expand Down Expand Up @@ -266,4 +271,10 @@ public List<StandardListingReport> getStandardListingReports() {
public DirectReviewCounts getDirectReviewCounts() {
return directReviewReportsService.getDirectReviewCounts();
}

@Synchronized("lock")
public List<AttestationReport> getAttestationReports() {
return attestationReportService.getAttestationReports();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package gov.healthit.chpl.report.attestation;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import gov.healthit.chpl.attestation.manager.AttestationPeriodService;
import gov.healthit.chpl.scheduler.job.report.attestation.AttestationReport;
import gov.healthit.chpl.scheduler.job.report.attestation.AttestationReportDAO;

@Component
public class AttestationReportService {

private AttestationReportDAO attestationReportDAO;
private AttestationPeriodService attestationPeriodService;

@Autowired
public AttestationReportService(AttestationReportDAO attestationReportDAO, AttestationPeriodService attestationPeriodService) {
this.attestationReportDAO = attestationReportDAO;
this.attestationPeriodService = attestationPeriodService;
}

@Transactional
public List<AttestationReport> getAttestationReports() {
return attestationReportDAO.getAttestationReportByAttestationPeriod(
attestationPeriodService.getMostRecentPastAttestationPeriod());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package gov.healthit.chpl.scheduler.job.report.attestation;

import java.time.LocalDate;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import gov.healthit.chpl.attestation.domain.AttestationPeriod;
import gov.healthit.chpl.domain.CertificationBody;
import gov.healthit.chpl.util.LocalDateDeserializer;
import gov.healthit.chpl.util.LocalDateSerializer;
import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class AttestationReport {
private Long id;

@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate reportDate;

private CertificationBody certificationBody;
private AttestationPeriod attestationPeriod;

@Builder.Default
private Long developerCount = 0L;

@Builder.Default
private Long approvedCount = 0L;

@Builder.Default
private Long pendingAcbActionCount = 0L;

@Builder.Default
private Long pendingDeveloperActionCount = 0L;

@Builder.Default
private Long noSubmissionCount = 0L;
}
Loading
Loading