package gov.nysenate.openleg.service.spotcheck.agenda;
import gov.nysenate.openleg.config.Environment;
import gov.nysenate.openleg.dao.agenda.reference.AgendaAlertDao;
import gov.nysenate.openleg.dao.spotcheck.CommitteeAgendaReportDao;
import gov.nysenate.openleg.dao.spotcheck.SpotCheckReportDao;
import gov.nysenate.openleg.model.agenda.*;
import gov.nysenate.openleg.model.spotcheck.agenda.AgendaAlertInfoCommittee;
import gov.nysenate.openleg.model.entity.CommitteeId;
import gov.nysenate.openleg.model.spotcheck.*;
import gov.nysenate.openleg.service.spotcheck.base.BaseSpotCheckReportService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
public abstract class BaseAgendaCheckReportService extends BaseSpotCheckReportService<CommitteeAgendaAddendumId> {
private static final Logger logger = LoggerFactory.getLogger(BaseAgendaCheckReportService.class);
@Autowired
CommitteeAgendaReportDao reportDao;
@Autowired
AgendaSpotCheckService checkService;
@Autowired
AgendaAlertDao agendaAlertDao;
@Autowired
Environment environment;
/** --- Implemented Methods --- */
@Override
public SpotCheckRefType getSpotcheckRefType() {
return SpotCheckRefType.LBDC_AGENDA_ALERT;
}
@Override
protected SpotCheckReportDao<CommitteeAgendaAddendumId> getReportDao() {
return reportDao;
}
/** {@inheritDoc} */
@Override
public SpotCheckReport<CommitteeAgendaAddendumId> generateReport(LocalDateTime start, LocalDateTime end) throws ReferenceDataNotFoundEx, Exception {
// Create a new report instance
SpotCheckReport<CommitteeAgendaAddendumId> report = new SpotCheckReport<>();
// Get unchecked references from within the specified time range
logger.info("Getting agenda references...");
List<AgendaAlertInfoCommittee> references = getReferences(start, end);
// Use the earliest reference date as the report reference date
references.sort((a, b) -> a.getReferenceId().getRefActiveDateTime().compareTo(b.getReferenceId().getRefActiveDateTime()));
SpotCheckReferenceId refId = references.get(0).getReferenceId();
// The report date/time should be truncated to the second to make it easier to query
report.setReportId(new SpotCheckReportId(SpotCheckRefType.LBDC_AGENDA_ALERT,
refId.getRefActiveDateTime(),
LocalDateTime.now()));
logger.info("Checking references...");
// Check the references to generate observations, which are added to the report
report.addObservations(getObservations(references));
report.setNotes(getNotes());
return report;
}
/** --- Internal Methods --- */
/**
* Gets all eligible Agenda Alert references with reference dates between the start and end date times
* @throws ReferenceDataNotFoundEx if no references were found
*/
protected abstract List<AgendaAlertInfoCommittee> getReferences(LocalDateTime start, LocalDateTime end) throws ReferenceDataNotFoundEx;
/**
* Retrieves an agenda for the week of the given date
*
* @param agendaAlertInfoCommittee@return Agenda
* @throws AgendaNotFoundEx
*/
protected abstract Agenda getAgenda(AgendaAlertInfoCommittee agendaAlertInfoCommittee) throws AgendaNotFoundEx;
/**
* Marks the given reference as being checked
* @param reference AgendaAlertInfoCommittee
*/
protected abstract void setReferenceChecked(AgendaAlertInfoCommittee reference);
protected String getNotes() {
return null;
}
/**
* Given a list of references, performs checks on the corresponding data, generating a list of observations
* @return List<SpotcheckObservation>
*/
protected List<SpotCheckObservation<CommitteeAgendaAddendumId>> getObservations(List<AgendaAlertInfoCommittee> references) {
List<SpotCheckObservation<CommitteeAgendaAddendumId>> observations = new ArrayList<>();
List<AgendaAlertInfoCommittee> checkedReferences = new ArrayList<>();
for (AgendaAlertInfoCommittee reference : references) {
Agenda agenda = null;
try {
// Attempt to get the committee meeting info that corresponds to the reference
agenda = getAgenda(reference);
String addendumId = reference.getAddendum().getValue();
CommitteeId committeeId = reference.getCommitteeId();
if (agenda.getAgendaInfoAddendum(addendumId) == null
|| agenda.getAgendaInfoAddendum(addendumId).getCommittee(committeeId) == null) {
throw new AgendaNotFoundEx("could not find committee meeting addendum " + reference.getAgendaAlertInfoCommId());
}
AgendaInfoCommittee content = agenda.getAgendaInfoAddendum(addendumId).getCommittee(committeeId);
// Check the content against the reference, generating an observation
observations.add(checkService.check(content, reference));
checkedReferences.add(reference);
} catch (AgendaNotFoundEx ex) {
// Add a data not found mismatch if the reference is past its grace period
if (LocalDateTime.now().minus(environment.getSpotcheckAlertGracePeriod())
.isAfter(reference.getReferenceId().getRefActiveDateTime())) {
// Add a missing data observation if the committee meeting info was not found
// if the agenda number is missing, we set the agenda number to -1
AgendaId obsAgId = agenda != null ? agenda.getId()
: ex.getAgendaId() != null ? ex.getAgendaId()
: new AgendaId(-1, 0);
SpotCheckObservation<CommitteeAgendaAddendumId> obs = new SpotCheckObservation<>(reference.getReferenceId(),
reference.getAgendaAlertInfoCommId().getCommiteeAgendaAddendumId(obsAgId));
obs.addMismatch(new SpotCheckMismatch(SpotCheckMismatchType.OBSERVE_DATA_MISSING,
"", reference.getAgendaAlertInfoCommId().toString()));
observations.add(obs);
logger.info("Committee Meeting Agenda {} | {} mismatch(es). | {}",
reference.getAgendaAlertInfoCommId(), obs.getMismatches().size(), obs.getMismatchTypes(false));
checkedReferences.add(reference);
}
}
}
// Cancel the report if no references were checked
if (checkedReferences.isEmpty()) {
throw new SpotCheckAbortException();
}
checkedReferences.forEach(this::setReferenceChecked);
return observations;
}
}