Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
import org.springframework.web.bind.annotation.RestController;

import gov.healthit.chpl.report.ReportDataManager;
import gov.healthit.chpl.report.realworldtesting.RealWorldTestingSummaryReport;
import gov.healthit.chpl.report.realworldtesting.RealWorldTestingSummaryByAcbReport;
import gov.healthit.chpl.report.realworldtesting.RealWorldTestingSummaryByDeveloperReport;
import gov.healthit.chpl.util.LogMethodUsage;
import gov.healthit.chpl.util.SwaggerSecurityRequirement;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -30,25 +31,36 @@ public RealWorldTestingReportController(ReportDataManager reportDataManager) {
this.reportDataManager = reportDataManager;
}

@Operation(summary = "Retrieves the data used to generate the Real World Testing Plans report.",
description = "Retrieves the data used to generate the Real World Testing Plans report.",
@Operation(summary = "Retrieves the data used to generate the Real World Testing Plans summary by ONC-ACB report.",
description = "Retrieves the data used to generate the Real World Testing Plans summary by ONC-ACB report.",
security = {
@SecurityRequirement(name = SwaggerSecurityRequirement.API_KEY)
})
@LogMethodUsage
@RequestMapping(value = "/plans", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
public @ResponseBody List<RealWorldTestingSummaryReport> getRealWorldTestingPlanReports() {
return reportDataManager.getRealWorldTestingReportDataService().getRealWorldTestingPlanSummaryReports();
public @ResponseBody List<RealWorldTestingSummaryByAcbReport> getRealWorldTestingPlanSummaryByAcbReports() {
return reportDataManager.getRealWorldTestingReportDataService().getRealWorldTestingPlanSummaryByAcbReports();
}

@Operation(summary = "Retrieves the data used to generate the Real World Testing Results report.",
description = "Retrieves the data used to generate the Real World Testing Results report.",
@Operation(summary = "Retrieves the data used to generate the Real World Testing Results summary by ONC-ACB report.",
description = "Retrieves the data used to generate the Real World Testing Results summary by ONC-ACB report.",
security = {
@SecurityRequirement(name = SwaggerSecurityRequirement.API_KEY)
})
@LogMethodUsage
@RequestMapping(value = "/results", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
public @ResponseBody List<RealWorldTestingSummaryReport> getRealWorldTestingResultsReports() {
return reportDataManager.getRealWorldTestingReportDataService().getRealWorldTestingResultsSummaryReports();
public @ResponseBody List<RealWorldTestingSummaryByAcbReport> getRealWorldTestingResultsSummaryByAcbReports() {
return reportDataManager.getRealWorldTestingReportDataService().getRealWorldTestingResultsSummaryByAcbReports();
}

@Operation(summary = "Retrieves the data used to generate the Real World Testing Results summary by Developer report.",
description = "Retrieves the data used to generate the Real World Testing Results summary by Developer report.",
security = {
@SecurityRequirement(name = SwaggerSecurityRequirement.API_KEY)
})
@LogMethodUsage
@RequestMapping(value = "/results-summary-by-developer", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
public @ResponseBody List<RealWorldTestingSummaryByDeveloperReport> getRealWorldTestingResultsSummaryByDeveloperReports() {
return reportDataManager.getRealWorldTestingReportDataService().getRealWorldTestingResultsSummaryByDeveloperReports();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ rwtPlanDueDate=12/15
rwtResultsStartDayOfYear=01/01
# Date when the Results is considered late - Format is MM/DD
rwtResultsDueDate=03/15
#Date when we stop gathering summary data about RWT results submissions, used in charts
rwtResultsDataGatheringEndDate=07/15

#Criteria that make a listing eligible for rwt
realWorldTestingCriteriaKeys={2021: 'criterion.170_315_b_1_old,\
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,13 @@ public LocalDate getResultsLateDate(Integer rwtEligYear) {
return LocalDate.parse(mmddyyyy, formatter);
}

public LocalDate getResultsDataGatheringStopDate(Integer rwtEligYear) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy");
String mmdd = env.getProperty("rwtResultsDataGatheringEndDate");
String mmddyyyy = mmdd + "/" + String.valueOf(rwtEligYear + 1);
return LocalDate.parse(mmddyyyy, formatter);
}

private boolean isWithdrawn(RealWorldTestingReport record) {
String statusName = record.getCurrentStatus();
return withdrawnStatuses.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "real_world_testing_plan_summary_report")
public class RealWorldTestingPlanSummaryReportEntity extends EntityAudit {
@Table(name = "real_world_testing_plan_summary_by_acb_report")
public class RealWorldTestingPlanSummaryByAcbReportEntity extends EntityAudit {
private static final long serialVersionUID = -1208758504334058893L;

@Id
Expand All @@ -52,8 +52,8 @@ public class RealWorldTestingPlanSummaryReportEntity extends EntityAudit {
@Column(name = "requires_check_count")
private Long requiresCheckCount;

public RealWorldTestingSummaryReport toDomain() {
return RealWorldTestingSummaryReport.builder()
public RealWorldTestingSummaryByAcbReport toDomain() {
return RealWorldTestingSummaryByAcbReport.builder()
.id(id)
.realWorldTestingYear(realWorldTestingYear)
.certificationBody(certificationBody.toDomain())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
@Component
public class RealWorldTestingPlanSummaryReportDao extends BaseDAOImpl {

public void save(RealWorldTestingSummaryReport realWorldTestingSummaryReport) throws EntityRetrievalException {
RealWorldTestingPlanSummaryReportEntity entity = getEntityByCheckedDateAndAcb(realWorldTestingSummaryReport.getCheckedDate(),
public void save(RealWorldTestingSummaryByAcbReport realWorldTestingSummaryReport) throws EntityRetrievalException {
RealWorldTestingPlanSummaryByAcbReportEntity entity = getEntityByCheckedDateAndAcb(realWorldTestingSummaryReport.getCheckedDate(),
realWorldTestingSummaryReport.getCertificationBody().getId());
if (entity == null) {
entity = RealWorldTestingPlanSummaryReportEntity.builder()
entity = RealWorldTestingPlanSummaryByAcbReportEntity.builder()
.realWorldTestingYear(realWorldTestingSummaryReport.getRealWorldTestingYear())
.certificationBody(CertificationBodyEntity.builder()
.id(realWorldTestingSummaryReport.getCertificationBody().getId())
Expand All @@ -36,33 +36,33 @@ public void save(RealWorldTestingSummaryReport realWorldTestingSummaryReport) th
}
}

public Optional<Long> getMaxRealWorldTestingYear() {
public Optional<Long> getMaxRealWorldTestingYearForAcbSummary() {
return Optional.ofNullable(entityManager.createQuery(
"select MAX(rwtpsr.realWorldTestingYear) "
+ "from RealWorldTestingPlanSummaryReportEntity rwtpsr "
+ "from RealWorldTestingPlanSummaryByAcbReportEntity rwtpsr "
+ "where (NOT deleted = true)", Long.class)
.getSingleResult());

}

public List<RealWorldTestingSummaryReport> getRealWorldTestingReportsByTestingYear(Long realWorldTestingYear) {
return getEntitiesByRealWorldTestingYear(realWorldTestingYear).stream()
public List<RealWorldTestingSummaryByAcbReport> getRealWorldTestingSummaryByAcbReportsByTestingYear(Long realWorldTestingYear) {
return getAcbSummaryEntitiesByRealWorldTestingYear(realWorldTestingYear).stream()
.map(entity -> entity.toDomain())
.toList();
}

private RealWorldTestingPlanSummaryReportEntity getEntityByCheckedDateAndAcb(LocalDate checkedDate, Long certificationBodyId) throws EntityRetrievalException {
private RealWorldTestingPlanSummaryByAcbReportEntity getEntityByCheckedDateAndAcb(LocalDate checkedDate, Long certificationBodyId) throws EntityRetrievalException {
Query query = entityManager.createQuery(
"from RealWorldTestingPlanSummaryReportEntity rwtps "
"from RealWorldTestingPlanSummaryByAcbReportEntity rwtps "
+ "where (NOT deleted = true) "
+ "and checkedDate = :checkedDate "
+ "and rwtps.certificationBody.id = :certificationBodyId", RealWorldTestingPlanSummaryReportEntity.class);
+ "and rwtps.certificationBody.id = :certificationBodyId", RealWorldTestingPlanSummaryByAcbReportEntity.class);
query.setParameter("checkedDate", checkedDate);
query.setParameter("certificationBodyId", certificationBodyId);
List<RealWorldTestingPlanSummaryReportEntity> result = query.getResultList();
List<RealWorldTestingPlanSummaryByAcbReportEntity> result = query.getResultList();

if (result.size() > 1) {
throw new EntityRetrievalException("Data error. Duplicate checked_date in real_world_testing_plan_summary_report table.");
throw new EntityRetrievalException("Data error. Duplicate checked_date in real_world_testing_plan_summary_by_acb_report table.");
}

if (result.size() > 0) {
Expand All @@ -71,13 +71,21 @@ private RealWorldTestingPlanSummaryReportEntity getEntityByCheckedDateAndAcb(Loc
return null;
}

private List<RealWorldTestingPlanSummaryReportEntity> getEntitiesByRealWorldTestingYear(Long testingYear) {
private List<RealWorldTestingPlanSummaryByAcbReportEntity> getAcbSummaryEntitiesByRealWorldTestingYear(Long testingYear) {
return entityManager.createQuery(
"from RealWorldTestingPlanSummaryReportEntity rwtps "
"from RealWorldTestingPlanSummaryByAcbReportEntity rwtps "
+ "where (NOT deleted = true) "
+ "and rwtps.realWorldTestingYear = :realWorldTestingYear", RealWorldTestingPlanSummaryReportEntity.class)
+ "and rwtps.realWorldTestingYear = :realWorldTestingYear", RealWorldTestingPlanSummaryByAcbReportEntity.class)
.setParameter("realWorldTestingYear", testingYear)
.getResultList();
}

public Optional<Long> getMaxRealWorldTestingYearForDeveloperSummary() {
return Optional.ofNullable(entityManager.createQuery(
"select MAX(rwtpsr.realWorldTestingYear) "
+ "from RealWorldTestingPlanSummaryByDeveloperReportEntity rwtpsr "
+ "where (NOT deleted = true)", Long.class)
.getSingleResult());

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,30 @@ public RealWorldTestingReportDataService(RealWorldTestingPlanSummaryReportDao re
}

@Transactional
public List<RealWorldTestingSummaryReport> getRealWorldTestingPlanSummaryReports() {
Optional<Long> rwtYear = realWorldTestingPlanSummaryReportDao.getMaxRealWorldTestingYear();
public List<RealWorldTestingSummaryByAcbReport> getRealWorldTestingPlanSummaryByAcbReports() {
Optional<Long> rwtYear = realWorldTestingPlanSummaryReportDao.getMaxRealWorldTestingYearForAcbSummary();
if (rwtYear.isPresent()) {
return realWorldTestingPlanSummaryReportDao.getRealWorldTestingReportsByTestingYear(rwtYear.get());
return realWorldTestingPlanSummaryReportDao.getRealWorldTestingSummaryByAcbReportsByTestingYear(rwtYear.get());
} else {
return List.of();
}
}

@Transactional
public List<RealWorldTestingSummaryReport> getRealWorldTestingResultsSummaryReports() {
Optional<Long> rwtYear = realWorldTestingResultsSummaryReportDao.getMaxRealWorldTestingYear();
public List<RealWorldTestingSummaryByAcbReport> getRealWorldTestingResultsSummaryByAcbReports() {
Optional<Long> rwtYear = realWorldTestingResultsSummaryReportDao.getMaxRealWorldTestingYearForAcbSummary();
if (rwtYear.isPresent()) {
return realWorldTestingResultsSummaryReportDao.getRealWorldTestingReportsByTestingYear(rwtYear.get());
return realWorldTestingResultsSummaryReportDao.getRealWorldTestingSummaryByAcbReportsByTestingYear(rwtYear.get());
} else {
return List.of();
}
}

@Transactional
public List<RealWorldTestingSummaryByDeveloperReport> getRealWorldTestingResultsSummaryByDeveloperReports() {
Optional<Long> rwtYear = realWorldTestingResultsSummaryReportDao.getMaxRealWorldTestingYearForDeveloperSummary();
if (rwtYear.isPresent()) {
return realWorldTestingResultsSummaryReportDao.getRealWorldTestingSummaryByDeveloperReportsByTestingYear(rwtYear.get());
} else {
return List.of();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "real_world_testing_results_summary_report")
public class RealWorldTestingResultsSummaryReportEntity extends EntityAudit {
@Table(name = "real_world_testing_results_summary_by_acb_report")
public class RealWorldTestingResultsSummaryByAcbReportEntity extends EntityAudit {
private static final long serialVersionUID = 4976557989831765742L;

@Id
Expand All @@ -52,8 +52,8 @@ public class RealWorldTestingResultsSummaryReportEntity extends EntityAudit {
@Column(name = "requires_check_count")
private Long requiresCheckCount;

public RealWorldTestingSummaryReport toDomain() {
return RealWorldTestingSummaryReport.builder()
public RealWorldTestingSummaryByAcbReport toDomain() {
return RealWorldTestingSummaryByAcbReport.builder()
.id(id)
.realWorldTestingYear(realWorldTestingYear)
.certificationBody(certificationBody.toDomain())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package gov.healthit.chpl.report.realworldtesting;

import java.time.LocalDate;

import gov.healthit.chpl.entity.EntityAudit;
import gov.healthit.chpl.entity.developer.DeveloperEntitySimple;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.SuperBuilder;

@Getter
@Setter
@ToString
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "real_world_testing_results_summary_by_developer_report")
public class RealWorldTestingResultsSummaryByDeveloperReportEntity extends EntityAudit {
private static final long serialVersionUID = -1208758504334058121L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;

@Column(name = "real_world_testing_year")
private Long realWorldTestingYear;

@OneToOne(optional = true, fetch = FetchType.LAZY)
@JoinColumn(name = "developer_id")
private DeveloperEntitySimple developer;

@Column(name = "checked_date")
private LocalDate checkedDate;

@Column(name = "checked_count")
private Long checkedCount;

@Column(name = "requires_check_count")
private Long requiresCheckCount;

public RealWorldTestingSummaryByDeveloperReport toDomain() {
return RealWorldTestingSummaryByDeveloperReport.builder()
.id(id)
.realWorldTestingYear(realWorldTestingYear)
.developerId(developer != null ? developer.getId() : null)
.developerName(developer != null ? developer.getName() : null)
.checkedDate(checkedDate)
.checkedCount(checkedCount)
.requiresCheckCount(requiresCheckCount)
.build();
}
}
Loading
Loading