package edu.ncsu.csc.itrust.action; import java.text.SimpleDateFormat; //import java.util.Date; import java.util.ArrayList; import java.util.List; import edu.ncsu.csc.itrust.EmailUtil; import edu.ncsu.csc.itrust.action.base.EditOfficeVisitBaseAction; import edu.ncsu.csc.itrust.beans.*; import edu.ncsu.csc.itrust.beans.forms.EditPrescriptionsForm; import edu.ncsu.csc.itrust.dao.DAOFactory; import edu.ncsu.csc.itrust.dao.mysql.*; import edu.ncsu.csc.itrust.enums.TransactionType; import edu.ncsu.csc.itrust.exception.DBException; import edu.ncsu.csc.itrust.exception.PrescriptionFieldException; import edu.ncsu.csc.itrust.exception.PrescriptionWarningException; import edu.ncsu.csc.itrust.exception.FormValidationException; import edu.ncsu.csc.itrust.exception.ITrustException; import edu.ncsu.csc.itrust.validate.EditPrescriptionsValidator; /** * Edits a patient's prescription information. Used by hcp-uap/editPrescription.jsp */ public class EditPrescriptionsAction extends EditOfficeVisitBaseAction { private PrescriptionsDAO psDAO; private NDCodesDAO medDAO; private DrugInteractionDAO interactionsDAO; private PrescriptionReportDAO rptDAO; private AllergyDAO allergyDAO; private PatientDAO patientDAO; private EmailUtil emailUtil; private PersonnelDAO personnelDAO; private PrescriptionOverrideDAO prescriptionOverrideDAO; private EventLoggingAction loggingAction; /** * Creates a new action by initializing the office visit * database access object. * * @param factory * @throws ITrustException */ public EditPrescriptionsAction(DAOFactory factory, long hcpid, String pidString, String ovIDString) throws ITrustException { super(factory, hcpid, pidString, ovIDString); init(factory); } /** * A prescription action that is part of an office visit that is not yet * saved. All attempts to modify this action will throw exceptions. Once * the office visit is saved, obtain a new EditPrescriptionsAction using * the four-argument constructor. (This is done automatically by the * EditOfficeVisitAction class.) * @param factory * @param hcpid * @param pidString * @throws ITrustException */ public EditPrescriptionsAction(DAOFactory factory, long hcpid, String pidString) throws ITrustException { super(factory, hcpid, pidString); init(factory); } private void init(DAOFactory factory){ psDAO = factory.getPrescriptionsDAO(); medDAO = factory.getNDCodesDAO(); interactionsDAO = factory.getDrugInteractionDAO(); allergyDAO = factory.getAllergyDAO(); rptDAO = factory.getPrescriptionReportDAO(); patientDAO = factory.getPatientDAO(); emailUtil = new EmailUtil(factory); personnelDAO = new PersonnelDAO(factory); prescriptionOverrideDAO = new PrescriptionOverrideDAO(factory); loggingAction = new EventLoggingAction(factory); } /** * Checks the prescription bean for interactions, allergies, and legal * values. * @param pres The prescription bean. * @throws ITrustException */ private void checkForAllergiesAndInteractions(PrescriptionBean pres) throws ITrustException { List<String> warnings = checkInteraction(pres); warnings.addAll(checkAllergy(pres)); if (!warnings.isEmpty()) { PatientBean patient = patientDAO.getPatient(getPid()); PersonnelBean hcp = personnelDAO.getPersonnel(getHcpid()); loggingAction.logEvent(TransactionType.OVERRIDE_INTERACTION_WARNING, hcp.getMID(), patient.getMID(), pres.getMedication().getNDCode()+ " Override: "+pres.getReasons().toString()); if(validOverride(pres)){ emailUtil.sendEmail(makeEmail(pres, warnings)); }else{ throw new PrescriptionWarningException(warnings); } } if ("".equals(pres.getInstructions())) { throw new PrescriptionFieldException("Instructions are required."); } } /** * Indicates if the prescription bean has a valid allergy/interaction * override. */ private boolean validOverride(PrescriptionBean pres) { return pres.getReasons() != null && pres.getReasons().size()>0; } /** * Returns a string suitable for a user warning message that a * drug-interaction was detected. */ private String formatInteractionWarning(PrescriptionBean newPrescription, PrescriptionBean oldPrescription, DrugInteractionBean bean) { String startDate = new SimpleDateFormat("MM/dd/yyyy").format(oldPrescription.getStartDate()); String endDate = new SimpleDateFormat("MM/dd/yyyy").format(oldPrescription.getEndDate()); return String.format("Currently Prescribed: %s. Start Date: %s, End Date: %s. Interactions: %s - %s. Description: %s", oldPrescription.getMedication().getDescription(), startDate, endDate, oldPrescription.getMedication().getDescription(), newPrescription.getMedication().getDescription(), bean.getDescription() ); } /** * Returns a string suitable for a user warning message that a * drug-allergy warning was detected. */ private String formatAllergyWarning(AllergyBean bean) throws DBException { return "Allergy: " + bean.getDescription() + ". First Found: " + new SimpleDateFormat("MM/dd/yyyy").format(bean.getFirstFound()); } /** * Checks to see if the given prescription has an interaction with any * other previously prescribed prescriptions. * @param newPrescription * @return A list of interaction warning messages. The list is empty if no * interactions were detected. * @throws ITrustException */ private List<String> checkInteraction(PrescriptionBean newPrescription) throws ITrustException { ArrayList<String> warnings = new ArrayList<String>(); try { SimpleDateFormat needed = new SimpleDateFormat("yyyy/MM/dd"); String startdate = needed.format(newPrescription.getStartDate()); String enddate = needed.format(newPrescription.getEndDate()); String drug = newPrescription.getMedication().getNDCode(); startdate = startdate.replaceAll("/", "-"); enddate = enddate.replaceAll("/", "-"); List<PrescriptionReportBean> prBeanList = rptDAO.byDate(getPid(), startdate, enddate); List<DrugInteractionBean> dBeanList = interactionsDAO.getInteractions(drug); for (PrescriptionReportBean prBean : prBeanList) { String oldDrug = prBean.getPrescription().getMedication().getNDCode(); PrescriptionBean oldPrescription = prBean.getPrescription(); for (DrugInteractionBean dBean : dBeanList) { String intDrug1 = dBean.getFirstDrug(); String intDrug2 = dBean.getSecondDrug(); if (oldDrug.equals(intDrug1) && drug.equals(intDrug2)) { warnings.add(formatInteractionWarning(newPrescription, oldPrescription, dBean)); } else if (oldDrug.equals(intDrug2) && drug.equals(intDrug1)) { warnings.add(formatInteractionWarning(newPrescription, oldPrescription, dBean)); } } } } catch (DBException e) { throw new ITrustException(e.getMessage()); } return warnings; } /** * Checks to see if the patient is allergic to the given prescription. * @return A list of allergy warnings. The list is empty if no allergies * were detected. * @throws ITrustException * @throws PrescriptionWarningException */ private List<String> checkAllergy(PrescriptionBean pres) throws ITrustException, PrescriptionWarningException { ArrayList<String> warnings = new ArrayList<String>(); try { List<AllergyBean> allergyList = allergyDAO.getAllergies(getPid()); MedicationBean medBean = pres.getMedication(); if (medBean != null) { String newDrug = medBean.getNDCode(); for (AllergyBean allergyBean : allergyList) { //Allergy: Aspirin. First Found: 12/20/2008. if (newDrug.equals(allergyBean.getNDCode())) { warnings.add(formatAllergyWarning(allergyBean)); } } } } catch (DBException e){ throw new ITrustException(e.getMessage()); } return warnings; } /** * Edits an existing prescription in the database. If the office visit is * unsaved, this will throw an exception. * * @param pres The prescription bean that has been changed. * @throws ITrustException */ public void editPrescription(PrescriptionBean pres) throws ITrustException { verifySaved(); checkForAllergiesAndInteractions(pres); psDAO.edit(pres); } /** * @return A list of all prescriptions for this office visit. (If the * office visit is unsaved, this returns an empty list.) * @throws DBException */ public List<PrescriptionBean> getPrescriptions() throws DBException { if (isUnsaved()) { return new ArrayList<PrescriptionBean>(); } else { return psDAO.getList(getOvID()); } } /** * Add a prescription to this office visit. If the office visit is * unsaved, this will throw an exception. * @param pres * @throws ITrustException */ public void addPrescription(PrescriptionBean pres) throws ITrustException { verifySaved(); checkForAllergiesAndInteractions(pres); long medID = psDAO.add(pres); for(OverrideReasonBean reason : pres.getReasons()){ reason.setPresID(medID); prescriptionOverrideDAO.add(reason); } } /** * Delete a prescription from this office visit. If the office visit is * unsaved, this will throw an exception. * @param pres * @throws DBException * @throws ITrustException */ public void deletePrescription(PrescriptionBean pres) throws DBException, ITrustException { verifySaved(); psDAO.remove(pres.getId()); prescriptionOverrideDAO.remove(pres.getId()); } /** * Returns a list of known medications. This can be called even if the * office visit is unsaved. * @throws DBException * @throws ITrustException */ public List<MedicationBean> getMedications() throws DBException, ITrustException { return medDAO.getAllNDCodes(); } /** * Validates a prescription form, converts it into a bean, and returns that bean. * @param form The form to convert. * @param defaultInstructions The default value given in the instructions * field. If the field equals this value, the validation will fail. * @return * @throws FormValidationException * @throws DBException */ public PrescriptionBean formToBean(EditPrescriptionsForm form, String defaultInstructions) throws FormValidationException, DBException { EditPrescriptionsValidator validator = new EditPrescriptionsValidator(defaultInstructions); validator.validate(form); PrescriptionBean bean = new PrescriptionBean(); bean.setVisitID(getOvID()); MedicationBean med = medDAO.getNDCode(form.getMedID()); bean.setMedication(med); bean.setDosage(Integer.valueOf(form.getDosage())); bean.setStartDateStr(form.getStartDate()); bean.setEndDateStr(form.getEndDate()); bean.setInstructions(form.getInstructions()); ArrayList<OverrideReasonBean> reasons = new ArrayList<OverrideReasonBean>(); for(String reason : form.getOverrideCodes()){ OverrideReasonBean override = new OverrideReasonBean(); override.setORCode(reason); reasons.add(override); } bean.setReasons(reasons); bean.setOverrideReasonOther(form.getOverrideOther()); return bean; } /** * Creates a fake e-mail to notify the user that their records have been altered. * * @return the e-mail to be sent * @throws DBException */ private Email makeEmail(PrescriptionBean pres, List<String> warnings) throws DBException{ Email email = new Email(); PatientBean patient = patientDAO.getPatient(getPid()); PersonnelBean hcp = personnelDAO.getPersonnel(getHcpid()); List<String> toAddrs = new ArrayList<String>(); toAddrs.add(patient.getEmail()); StringBuffer buf = new StringBuffer(); for(String warning : warnings){ buf.append(warning); buf.append("\n"); } String message = "Health care professional " + hcp.getFullName() + " has prescribed " + pres.getMedication().getDescription() + ". However, the following warning(s) were found:" + buf.toString(); email.setFrom("no-reply@itrust.com"); email.setToList(toAddrs); // patient and personal representative email.setSubject(String.format("Prescription warning")); email.setBody(message); return email; } }