/** * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations under * the License. * * The Original Code is OpenELIS code. * * Copyright (C) CIRG, University of Washington, Seattle WA. All Rights Reserved. * */ package us.mn.state.health.lims.patient.saving; import java.sql.Timestamp; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.apache.commons.beanutils.DynaBean; import org.apache.commons.validator.GenericValidator; import org.apache.struts.action.ActionErrors; import us.mn.state.health.lims.analysis.valueholder.Analysis; import us.mn.state.health.lims.common.provider.query.SampleItemTestProvider; import us.mn.state.health.lims.common.services.StatusService; import us.mn.state.health.lims.common.services.StatusService.AnalysisStatus; import us.mn.state.health.lims.common.services.StatusService.RecordStatus; import us.mn.state.health.lims.common.util.DateUtil; import us.mn.state.health.lims.common.util.StringUtil; import us.mn.state.health.lims.common.util.validator.ActionError; import us.mn.state.health.lims.sample.form.ProjectData; import us.mn.state.health.lims.sample.util.CI.BaseProjectFormMapper; import us.mn.state.health.lims.sample.util.CI.BaseProjectFormMapper.TypeOfSampleTests; import us.mn.state.health.lims.sample.util.CI.ProjectForm; import us.mn.state.health.lims.sampleitem.valueholder.SampleItem; import us.mn.state.health.lims.typeofsample.valueholder.TypeOfSample; public class SampleEntry extends Accessioner { protected DynaBean dynaBean; protected HttpServletRequest request; public SampleEntry(DynaBean dynaBean, String sysUserId, HttpServletRequest request) throws Exception { super((String)dynaBean.get("labNo"), (String)dynaBean.get("subjectNumber"), (String)dynaBean.get("siteSubjectNumber"), sysUserId); this.projectFormMapper = getProjectFormMapper(dynaBean); this.projectFormMapper.setPatientForm(false); this.projectForm = projectFormMapper.getProjectForm(); findStatusSet(); this.dynaBean = dynaBean; this.request = request; this.newPatientStatus = RecordStatus.NotRegistered; this.newSampleStatus = RecordStatus.InitialRegistration; } @Override public boolean canAccession() { return (statusSet.getPatientRecordStatus() == null && statusSet.getSampleRecordStatus() == null); } @Override protected void populateSampleData() throws Exception { Timestamp receivedDate = DateUtil.convertStringDateStringTimeToTimestamp(projectFormMapper.getReceivedDate(), projectFormMapper.getReceivedTime()); Timestamp collectionDate = DateUtil.convertStringDateStringTimeToTimestamp(projectFormMapper.getCollectionDate(), projectFormMapper.getCollectionTime()); populateSample(receivedDate, collectionDate); populateSampleProject(); populateSampleOrganization(projectFormMapper.getOrganizationId()); populateSampleItems(); } protected void populateSampleItems() throws Exception { List<TypeOfSampleTests> typeofSampleTestList = projectFormMapper.getTypeOfSampleTests(); boolean testSampleMismatch = false; testSampleMismatch = (null == typeofSampleTestList) || (typeofSampleTestList.isEmpty()); if( !testSampleMismatch){ for( TypeOfSampleTests typeOfSampleTest : typeofSampleTestList){ if( typeOfSampleTest.tests.isEmpty()){ testSampleMismatch = true; break; } } } if( testSampleMismatch){ messages.add(ActionErrors.GLOBAL_MESSAGE, new ActionError("errors.no.sample")); throw new Exception("Mis-match between tests and sample types."); } Timestamp collectionDate = DateUtil.convertStringDateStringTimeToTimestamp(projectFormMapper.getCollectionDate(), projectFormMapper.getCollectionTime()); populateSampleItems(typeofSampleTestList, collectionDate); cleanupSampleItemsAndAnalysis(); } /** * Looking at each sampleType which was NOT checked, we pretend that it was checked and see what analysis WOULD be generated * combined with any test. * If there are any of those, we then try to find some sampleItems to delete and update along with appropriate analysis. * @param projectFormMapper */ // TODO PAHill this code relies on the correct spelling of the typeOfSample.description. These magic names should be // moved to one central spot so they are easier to find if needed to change. They also appear in the ProjectFormMapper, so // probably an enum there (BaseProjectFormMapper) could contain the known set for use there and here. protected void cleanupSampleItemsAndAnalysis() { String sampleId = this.sample.getId(); if (GenericValidator.isBlankOrNull(sampleId)) { return; } // try each type of sample tube and see what real test have gone away. ProjectData submittedProjectData = this.projectFormMapper.getProjectData(); if (!submittedProjectData.getDryTubeTaken()) { cleanupSampleAndAnalysis(sampleId, "Dry Tube"); } else { ProjectData tProjectData = buildProjectDataTestsReversed(submittedProjectData) ; tProjectData.setDryTubeTaken(true); cleanupExistingAnalysis(projectForm, sampleId, tProjectData); } if (!submittedProjectData.getEdtaTubeTaken()) { cleanupSampleAndAnalysis(sampleId, "EDTA Tube"); } else { ProjectData tProjectData = buildProjectDataTestsReversed(submittedProjectData) ; tProjectData.setEdtaTubeTaken(true); cleanupExistingAnalysis(projectForm, sampleId, tProjectData); } if (!submittedProjectData.getDbsTaken()) { cleanupSampleAndAnalysis(sampleId, "DBS"); } else { ProjectData tProjectData = buildProjectDataTestsReversed(submittedProjectData) ; tProjectData.setDbsTaken(true); cleanupExistingAnalysis(projectForm, sampleId, tProjectData); } return; } /** * Check if particular * @param sampleId * @param typeName */ private void cleanupSampleAndAnalysis(String sampleId, String typeName) { TypeOfSample typeOfSample = BaseProjectFormMapper.getTypeOfSampleByDescription(typeName); List<SampleItem> sampleItems = sampleItemDAO.getSampleItemsBySampleIdAndType(sampleId, typeOfSample); for (SampleItem sampleItem : sampleItems) { List<Analysis> analyses = analysisDAO.getAnalysesBySampleItem(sampleItem); if ( cleanupExistingAnalysis(analyses).size() != 0) { sampleItem.setSysUserId(sysUserId); sampleItemsToDelete.add(sampleItem); } } } /** * Find the analysis which are defined to be associated with checked sampleType in the projectdata. * update list of analysisToDelete, analysisToSave * Called with tests checked that are NOT wanted, so we can find those analysis and check to delete them * @param projectFormId - the name of form from the UI (typically the unique DIV id) * @param sampleId some sample * @param tProjectData a mocked up set data of data, representing a set of choices * @return */ private Map<String, SampleItem> cleanupExistingAnalysis(ProjectForm projectForm, String sampleId, ProjectData tProjectData) { try { List<Analysis> analysisList = SampleItemTestProvider.findAnalysis(sampleId, projectForm.getProjectFormId(), tProjectData); return cleanupExistingAnalysis(analysisList); } catch (IllegalArgumentException ignore) { return null; // reversing the test boxes resulted in NO valid resuest, so we can move on. } } private Map<String, SampleItem> cleanupExistingAnalysis(List<Analysis> analysisList) { String canceledId = StatusService.getInstance().getStatusID(AnalysisStatus.Canceled); Map<String, SampleItem> sampleItemsToDelete = new HashMap<String, SampleItem>(); // first we assume we'll delete them all for (Analysis analysis : analysisList) { SampleItem sampleItem = analysis.getSampleItem(); sampleItemsToDelete.put(sampleItem.getId(), sampleItem); } for (Analysis analysis : analysisList) { AnalysisStatus analysisStatus = StatusService.getInstance().getAnalysisStatusForID(analysis.getStatusId()); switch (analysisStatus) { case NotStarted: // deletable => leave sampleItem in the Delete list analysis.setSysUserId(sysUserId); analysisToDelete.add(analysis); break; case NonConforming_depricated: // not deletable => remove the sampleItem from the delete list SampleItem sampleItem = analysis.getSampleItem(); sampleItemsToDelete.remove(sampleItem.getId()); break; default: // not deletable => remove the sampleItem from the delete list sampleItem = analysis.getSampleItem(); sampleItemsToDelete.remove(sampleItem.getId()); // save this analysis for later updating analysis.setStatusId(canceledId); analysis.setSysUserId(sysUserId); analysisToUpdate.add(analysis); break; } } return sampleItemsToDelete; } /** * Creates a new projectData object with all Test which are NOT checked in the submitted projectData now checked * in the object returned * @param ProjectData - nothing but some Test properties are set in this object. */ private ProjectData buildProjectDataTestsReversed(ProjectData submitted) { ProjectData projectData = new ProjectData(); if ( !submitted.getCreatinineTest() ) projectData.setCreatinineTest(true); if ( !submitted.getGlycemiaTest() ) projectData.setGlycemiaTest(true); if ( !submitted.getGenotypingTest() ) projectData.setGenotypingTest(true); if ( !submitted.getNfsTest() ) projectData.setNfsTest(true); if ( !submitted.getSerologyHIVTest() ) projectData.setSerologyHIVTest(true); if ( !submitted.getTransaminaseTest() ) projectData.setTransaminaseTest(true); if ( !submitted.getCd4cd8Test() ) projectData.setCd4cd8Test(true); return projectData; } /** * @see us.mn.state.health.lims.patient.saving.Accessioner#persistSampleData() */ @Override protected void persistSampleData() throws Exception { // TODO Auto-generated method stub super.persistSampleData(); } /** * There are no lists in Sample forms, so no repeating OHs to update. * If there where the base class returning empty lists for all those without values and then the persist coding deleting * all sublists blindly and then rewriting them would be broken, so be careful if it comes to that. * * @see us.mn.state.health.lims.patient.saving.Accessioner#persistObservationHistoryLists() */ @Override protected void persistObservationHistoryLists() { // do nothing. See note above. Do not delete this method. } @Override protected String getActionLabel() { return StringUtil.getMessageForKey("banner.menu.createSample.Initial"); } }