Summary Table

Categories Total Count
PII 0
URL 0
DNS 0
EKL 0
IP 0
PORT 0
VsID 0
CF 0
AI 0
VPD 0
PL 0
Other 0

File Content

package gov.va.med.ars.service.impl;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Stream;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import gov.va.med.ars.constants.ErrorMessages;
import gov.va.med.ars.constants.ReportsViewConstants;
import gov.va.med.ars.dao.ars.IReportsViewRepository;
import gov.va.med.ars.exceptions.GenericException;
import gov.va.med.ars.model.request.SearchReportRequest;
import gov.va.med.ars.model.response.GenericResponse;
import gov.va.med.ars.model.response.ReportResponse;
import gov.va.med.ars.service.IReportService;
import gov.va.med.domain.ars.ReportsView;

@Service
public class ReportServiceImpl implements IReportService {

private static final Logger logger = LogManager.getLogger(ReportServiceImpl.class);

DateFormat formatDateOfRequest = new SimpleDateFormat("MM/dd/yyyy");
DateFormat formatDateOfDB = new SimpleDateFormat("yyyyMMdd");

@Autowired
IReportsViewRepository reportsViewRepository;

@Override
public GenericResponse getReports(SearchReportRequest searchRequest) throws GenericException {

GenericResponse reportSearchResponse = null;
// front-end sometimes sends "" as requested sortColumn
// and we need to eventually use the same sortColumn to return
// reportSearchResponse
// setting it here to default sort value of attachIdLx if empty.
if (isNullOrEmpty(searchRequest.getSortColumn())) {
searchRequest.setSortColumn("attachIdLx");
}
PageRequest pageReq = generatePaginationWithSorting(searchRequest);
logger.info("Inside ReportServiceImpl.getReports()");
try {
boolean allFieldsPopulated = areAllFieldsPopulated(searchRequest);

if (allFieldsPopulated) {
logger.info("ReportServiceImpl.getReports(): calling repository for count...");
long countOfReports = reportsViewRepository.count(new Specification<ReportsView>() {
@Override
public Predicate toPredicate(Root<ReportsView> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicates = new ArrayList<>();

getQueryData(searchRequest, root, cb, predicates);

return cb.and(predicates.toArray(new Predicate[0]));
}
});

logger.info("countOfReports is " + countOfReports);

if (countOfReports > 0) {
int pageNumber = resetPageNumbersOnCount(searchRequest, countOfReports);
logger.info("ReportServiceImpl.getReports(): COUNT(*) from DB is: " + countOfReports);
reportSearchResponse = setGenericResponse(searchRequest, pageReq, countOfReports, pageNumber);
} else {
logger.info("ReportServiceImpl.getReports(): empty COUNT(*)! " + countOfReports);
reportSearchResponse = new GenericResponse(searchRequest.getPageNumber(),
searchRequest.getPageSize(), searchRequest.getSortColumn(), countOfReports);
return reportSearchResponse;
}
} else {
logger.info("Returning exception: all required fields must be populated");
throw new GenericException(ErrorMessages.INVALID_REQUEST, "All required fields must be populated.",
HttpStatus.BAD_REQUEST);
}
} catch (Exception e) {
throw new GenericException(ErrorMessages.DATA_ACCESS_ERROR, e.getMessage(),
HttpStatus.INTERNAL_SERVER_ERROR);
}
return reportSearchResponse;
}

private boolean isNullOrEmpty(String str) {
return str == null || str.trim().isEmpty();
}

private PageRequest generatePaginationWithSorting(SearchReportRequest searchRequest) {
PageRequest pageReq;
String sortColumn = setSortColumn(searchRequest.getSortColumn());
if (searchRequest.getDescending()) {
pageReq = new PageRequest(searchRequest.getPageNumber().intValue() - 1,
searchRequest.getPageSize().intValue(), Sort.Direction.DESC, sortColumn);
} else {
pageReq = new PageRequest(searchRequest.getPageNumber().intValue() - 1,
searchRequest.getPageSize().intValue(), Sort.Direction.ASC, sortColumn);
}
return pageReq;
}

private String setSortColumn(String sortColumn) {
if (isNotBlank(sortColumn)) {
switch (sortColumn) {
case ReportsViewConstants.ATTACH_ID_LX:
return "attachmentIdLx";
case ReportsViewConstants.ATTACHMENT_ID:
return "attachmentId";
case ReportsViewConstants.CLAIM_IDENTIFIER:
return "externalClaimId";
case ReportsViewConstants.FACILITY:
return "facility";
case ReportsViewConstants.PROVIDER_NAME:
return "providerName";
case ReportsViewConstants.PROVIDER_ZIP:
return "providerZip";
case ReportsViewConstants.PROVIDER_NPI:
return "providerNpi";
case ReportsViewConstants.PATIENT_FIRST_NAME:
return "patientFirstName";
case ReportsViewConstants.PATIENT_LAST_NAME:
return "patientLastName";
case ReportsViewConstants.PATIENT_IDENTIFIER:
return "patientIdentifierNumber";
case ReportsViewConstants.PATIENT_CONTROL_NUMBER:
return "patientControlNumber";
case ReportsViewConstants.CLAIM_SERVICE_START_DATE:
return "claimServiceStartDate";
case ReportsViewConstants.CLAIM_SERVICE_END_DATE:
return "claimServiceEndDate";
case ReportsViewConstants.ATTACHMENT_CONTROL_NUMBER:
return "attachmentControlNumber";
case ReportsViewConstants.REPORT_CODE:
return "reportCode";
case ReportsViewConstants.STATUS:
return "status";
case ReportsViewConstants.DATE_RECEIVED:
return "dateReceived";
case ReportsViewConstants.PATIENT_DOB:
return "patientDob";
default:
return "attachmentIdLx";
}
} else {
return "attachmentIdLx";
}
}

private boolean areAllFieldsPopulated(SearchReportRequest searchRequest) {

boolean result = Stream
.of(searchRequest.getPayerId(), searchRequest.getStartDate(), searchRequest.getEndDate(),
searchRequest.getTypeOf275(), searchRequest.getTypeOfReport())
.allMatch(req -> req != null && !((String) req).isEmpty());

logger.info("are all fields populated? " + result);

return result;

}

private void getQueryData(SearchReportRequest searchRequest, Root<ReportsView> root, CriteriaBuilder cb,
List<Predicate> predicates) {

addPredicateForReportType(searchRequest, root, cb, predicates);

addPredicateFor275Type(searchRequest, root, cb, predicates);

addPredicateForPayerId(searchRequest, root, cb, predicates);

addPredicateForClaimServiceDates(searchRequest, root, cb, predicates);

logger.info("end of getQueryData method");

}

private void addPredicateForClaimServiceDates(SearchReportRequest searchRequest, Root<ReportsView> root,
CriteriaBuilder cb, List<Predicate> predicates) {
if (isNotBlank(searchRequest.getStartDate()) && isNotBlank(searchRequest.getEndDate())) {
// evaluating startDate and endDate in request
String startDateInString = "";
String endDateInString = "";
try {
Date startDate = formatDateOfRequest.parse(searchRequest.getStartDate());
startDateInString = formatDateOfDB.format(startDate);

Date endDate = formatDateOfRequest.parse(searchRequest.getEndDate());
endDateInString = formatDateOfDB.format(endDate);

logger.info("Start Date " + startDateInString);
logger.info("End Date " + endDateInString);
} catch (ParseException e) {
logger.info("unable to parse current Date in search request");
e.printStackTrace();
}
if(searchRequest.getReceivedDateRequested()) {
predicates.add(cb.between(root.get("dateReceived"), startDateInString, endDateInString));
} else {
/*predicates.add(cb.between(root.get("claimServiceStartDate"), startDateInString, endDateInString));
predicates.add(cb.between(root.get("claimServiceEndDate"), startDateInString, endDateInString));*/
predicates.add(cb.or(cb.between(root.get("claimServiceStartDate"), startDateInString, endDateInString), cb.between(root.get("claimServiceEndDate"), startDateInString, endDateInString)));
}
}
}

private void addPredicateForPayerId(SearchReportRequest searchRequest, Root<ReportsView> root, CriteriaBuilder cb,
List<Predicate> predicates) {
// evaluating payerId in request
if (isNotBlank(searchRequest.getPayerId())) {
logger.info("6. looking for Payer Id of " + searchRequest.getPayerId());
predicates.add(cb.equal(root.get("payerId"), searchRequest.getPayerId()));
}
}

private void addPredicateFor275Type(SearchReportRequest searchRequest, Root<ReportsView> root, CriteriaBuilder cb,
List<Predicate> predicates) {
// evaluating whether to show solicited or unsolicited
String typeOf275 = searchRequest.getTypeOf275();

if (isNotBlank(typeOf275)) {
if ("solicited".equalsIgnoreCase(typeOf275)) {
logger.info("5a. looking for solicited 275s, because typeOf275 from request is " + typeOf275);
predicates.add(cb.equal(root.get("trn01"), "2"));
} else if ("unsolicited".equalsIgnoreCase(typeOf275)) {
logger.info("5b. looking for UNsolicited 275s, because typeOf275 from request is " + typeOf275);
predicates.add(cb.equal(root.get("trn01"), "1"));
} else if ("all".equalsIgnoreCase(typeOf275)) {
logger.info("5c. looking for ALL 275s, because typeOf275 from request is " + typeOf275);
}
}

}

private void addPredicateForReportType(SearchReportRequest searchRequest, Root<ReportsView> root,
CriteriaBuilder cb, List<Predicate> predicates) {
// evaluating whether to show matched or unmatched
String typeOfReport = searchRequest.getTypeOfReport();

if (isNotBlank(typeOfReport)) {
if ("matched".equalsIgnoreCase(typeOfReport)) {
logger.info("4a. looking for matched reports, because typeOfReport from request is " + typeOfReport);
predicates.add(cb.isNotNull(root.get("externalClaimId")));
} else if ("unmatched".equalsIgnoreCase(typeOfReport)) {
logger.info("4b. looking for UNmatched reports, because typeOfReport from request is " + typeOfReport);
predicates.add(cb.isNull(root.get("externalClaimId")));
} else if ("all".equalsIgnoreCase(typeOfReport)) {
logger.info("4c. looking for ALL reports, because typeOfReport from request is " + typeOfReport);
}
}

}

private int resetPageNumbersOnCount(SearchReportRequest searchRequest, long countOfReports) {
int pageNumber = searchRequest.getPageNumber();

if (countOfReports <= (searchRequest.getPageSize() * searchRequest.getPageNumber())) {
Integer resultCountIntVal = (int) countOfReports;
float pageNumberFloat = (float) resultCountIntVal / (float) searchRequest.getPageSize();
pageNumber = (int) Math.ceil(pageNumberFloat);

logger.info("resetPageNumbersOnCount() : pageNumber is :" + pageNumber + " and pageSize is :"
+ searchRequest.getPageSize());
}
return pageNumber;
}

private GenericResponse setGenericResponse(SearchReportRequest searchRequest, PageRequest pageReq, Long resultCount,
int pageNumber) {
logger.info("8. in setGenericResponse method");
GenericResponse searchResponse = new GenericResponse(searchRequest.getPageNumber(), searchRequest.getPageSize(),
searchRequest.getSortColumn(), resultCount);

List<ReportResponse> responseList = querySpecification(searchRequest, pageReq);
searchResponse.setResponse(responseList);

return searchResponse;
}

private List<ReportResponse> querySpecification(SearchReportRequest searchRequest, PageRequest pageReq) {
logger.info("9. in querySpecification method");
Page<ReportsView> rvPage = reportsViewRepository.findAll(new Specification<ReportsView>() {
@Override
public Predicate toPredicate(Root<ReportsView> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicates = new ArrayList<>();
logger.info("about to call getQueryData again");
getQueryData(searchRequest, root, cb, predicates);

return cb.and(predicates.toArray(new Predicate[0]));
}
}, pageReq);
logger.info("finished querySpecification's repository.findAll()");

return assignData(rvPage);
}

private List<ReportResponse> assignData(Page<ReportsView> reportsViewPage) {
logger.info("in assignData");

List<ReportResponse> responseList = new ArrayList<>();
for (ReportsView rv : reportsViewPage) {
String claimStartString = "";
String claimEndString = "";
String dateReceivedStr = "";
String patientDobStr = "";
try {
if (isNotBlank(rv.getClaimServiceStartDate())) {
Date claimStartDate = formatDateOfDB.parse(rv.getClaimServiceStartDate());
claimStartString = formatDateOfRequest.format(claimStartDate);
}

if (isNotBlank(rv.getClaimServiceEndDate())) {
Date claimEndDate = formatDateOfDB.parse(rv.getClaimServiceEndDate());
claimEndString = formatDateOfRequest.format(claimEndDate);
}

if (isNotBlank(rv.getDateReceived())) {
Date dateReceived = formatDateOfDB.parse(rv.getDateReceived());
dateReceivedStr = formatDateOfRequest.format(dateReceived);
}

if (isNotBlank(rv.getPatientDob())) {
Date patientDob = formatDateOfDB.parse(rv.getPatientDob());
patientDobStr = formatDateOfRequest.format(patientDob);
}
} catch (ParseException e) {
logger.info("unable to parse current Date in search request");
e.printStackTrace();
}

ReportResponse response = new ReportResponse();
response.setAttachIdLx(rv.getAttachmentIdLx());
response.setAttachmentId(rv.getAttachmentId());
response.setProviderName(rv.getProviderName());
response.setProviderZip(rv.getProviderZip());
response.setProviderNpi(rv.getProviderNpi());
response.setPatientFirstName(rv.getPatientFirstName());
response.setPatientLastName(rv.getPatientLastName());
response.setPatientName(rv.getPatientLastName() + ", " + rv.getPatientFirstName());
response.setPatientIdentifierNumber(rv.getPatientIdentifierNumber());
response.setPatientControlNumber(rv.getPatientControlNumber());
response.setClaimServiceStartDate(claimStartString);
response.setClaimServiceEndDate(claimEndString);
response.setExternalClaimId(rv.getExternalClaimId());
response.setAttachmentControlNumber(rv.getAttachmentControlNumber());
response.setStatus(rv.getStatus());
response.setPayerId(rv.getPayerId());
response.setDateReceived(dateReceivedStr);
response.setFacility(rv.getFacility());
response.setReportCode(rv.getReportCode());
response.setPatientDob(patientDobStr);
response.setAttachmentType(rv.getAttachmentType());
if ("1".equalsIgnoreCase(rv.getTrn01())) {
response.setIsSolicited(false);
} else if ("2".equalsIgnoreCase(rv.getTrn01())) {
response.setIsSolicited(true);
}
responseList.add(response);
}
return responseList;
}

private boolean isNotBlank(String str) {
if (str != null && !str.isEmpty()) {
return true;
} else {
return false;
}
}

}