diff --git a/frontend/src/App.js b/frontend/src/App.js index b40a446a57..0ed8924a79 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -18,7 +18,8 @@ import PatientManagement from "./components/patient/PatientManagement"; import PatientHistory from "./components/patient/PatientHistory"; import Workplan from "./components/workplan/Workplan"; import AddOrder from "./components/addOrder/Index"; -import ModifyOrder from "./components/modifyOrder/Index"; +import FindOrder from "./components/modifyOrder/Index"; +import ModifyOrder from "./components/modifyOrder/ModifyOrder"; import RoutineReports from "./components/Reports/Routine"; import StudyReports from "./components/Reports/Study"; import StudyValidation from "./components/validation/Index"; @@ -227,6 +228,12 @@ export default function App() { exact component={() => } role="Reception" + /> + } + role="Reception" /> {
-

Order Panels

+

+ +

- + { + console.log("default onAnswerChange function does nothing"); + }, + setAnswer, +}) => { + const getSelectOption = (answerOption, index) => { + if ("valueString" in answerOption) { + return ( + + ); + } else if ("valueCoding" in answerOption) { + return ( + + ); + } else { + return <>; + } + }; + + const renderQuestion = (item) => { + var options = []; + if ( + item.type == "choice" && + item.repeats === true && + "answerOption" in item + ) { + item.answerOption.map((answerOption) => { + if ("valueString" in answerOption) { + options.push({ + value: answerOption.valueString, + text: answerOption.valueString, + }); + } + if ("valueCoding" in answerOption) { + options.push({ + value: answerOption.valueCoding.code, + text: answerOption.valueCoding.display, + }); + } + }); + } + + return ( + <> +
+ {item.type == "boolean" && ( + + )} + {item.type == "choice" && item.repeats !== true && ( + + )} + {item.type == "choice" && item.repeats === true && ( + (item ? item.text : "")} + onChange={(changes) => { + var e = { target: {} }; + e.target.id = item.linkId; + e.target.value = changes.selectedItems; + onAnswerChange(e); + }} + value={setAnswer(item.linkId)} + selectionFeedback="top-after-reopen" + /> + )} + {item.type == "integer" && ( + + )} + {item.type == "decimal" && ( + + )} + {item.type == "date" && ( + + )} + {item.type == "time" && ( + + )} + {item.type == "string" && ( + + )} + {item.type == "text" && ( + + )} + {item.type == "quantity" && ( + + )} +
+ + ); + }; + if (questionnaire) { + var inputs = + "item" in questionnaire && + questionnaire.item.map((item, index) => { + return {renderQuestion(item)}; + }); + + var groups = []; + var children = []; + var i = 0; + for (; i < inputs.length; i++) { + children.push(inputs[i]); + if (children.length === 2) { + groups.push( +
+ {children} +
, + ); + children = []; + } + } + if (children.length > 0) { + groups.push( +
+ {children} +
, + ); + } + + return
{groups}
; + } else { + return <>; + } +}; + +export const ProgramSelect = ({ + programChange = () => { + console.log("default programChange function does nothing"); + }, + orderFormValues, +}) => { + const componentMounted = useRef(true); + + const [programs, setPrograms] = useState([]); + + const fetchPrograms = (programsList) => { + if (componentMounted.current) { + setPrograms(programsList); + } + }; + + useEffect(() => { + componentMounted.current = true; + getFromOpenElisServer("/rest/user-programs", fetchPrograms); + return () => { + componentMounted.current = false; + }; + }, []); + + return ( + <> +
+ {programs.length > 0 && ( +
+ +
+ )} +
+ + ); +}; + +const EditOrderEntryAdditionalQuestions = ({ + orderFormValues, + setOrderFormValues = () => { + console.log("default setOrderFormValues change function does nothing"); + }, +}) => { + const [questionnaire, setQuestionnaire] = useState({}); + const [questionnaireResponse, setQuestionnaireResponse] = useState({}); + const [loading, setLoading] = useState(true); + + useEffect(() => { + if (orderFormValues?.sampleOrderItems?.programId) { + getFromOpenElisServer( + "/program/" + + orderFormValues.sampleOrderItems.programId + + "/questionnaire", + setDefaultAdditionalQuestions, + ); + } + }, [orderFormValues]); + + const handleProgramSelection = (event) => { + if (event.target.value === "") { + setAdditionalQuestions(null); + setOrderFormValues({ + ...orderFormValues, + sampleOrderItems: { + ...orderFormValues.sampleOrderItems, + programId: null, + }, + }); + } else { + getFromOpenElisServer( + "/program/" + event.target.value + "/questionnaire", + setAdditionalQuestions, + ); + setOrderFormValues({ + ...orderFormValues, + sampleOrderItems: { + ...orderFormValues.sampleOrderItems, + programId: event.target.value, + }, + }); + } + }; + + function convertQuestionnaireToResponse(questionnaire) { + var items = []; + if (questionnaire && "item" in questionnaire) { + for (let i = 0; i < questionnaire.item.length; i++) { + let currentItem = questionnaire.item[i]; + items.push({ + linkId: currentItem.linkId, + definition: currentItem.definition, + text: currentItem.text, + answer: [], + }); + } + + var convertedQuestionnaireResponse = { + resourceType: "QuestionnaireResponse", + id: "", + questionnaire: "Questionnaire/" + questionnaire.id, + status: "in-progress", + item: items, + }; + return convertedQuestionnaireResponse; + } + return null; + } + + function setAdditionalQuestions(res) { + console.log(res); + setQuestionnaire(res); + var convertedQuestionnaireResponse = convertQuestionnaireToResponse(res); + setQuestionnaireResponse(convertedQuestionnaireResponse); + } + + function setDefaultAdditionalQuestions(res) { + if (loading) { + console.log(res); + setQuestionnaire(res); + setQuestionnaireResponse( + orderFormValues.sampleOrderItems.additionalQuestions, + ); + setLoading(false); + } + } + + const setAnswer = (linkId) => { + var responseItem = questionnaireResponse?.item?.find( + (item) => item.linkId === linkId, + ); + var questionnaireItem = questionnaire?.item?.find( + (item) => item.linkId === linkId, + ); + switch (questionnaireItem.type) { + case "boolean": + return responseItem?.answer ? responseItem?.answer[0].valueBoolean : ""; + case "decimal": + return responseItem?.answer ? responseItem?.answer[0].valueDecimal : ""; + case "integer": + return responseItem?.answer ? responseItem?.answer[0].valueInteger : ""; + case "date": + return responseItem?.answer ? responseItem?.answer[0].valueDate : ""; + case "time": + return responseItem?.answer ? responseItem?.answer[0].valueTime : ""; + case "string": + case "text": + return responseItem?.answer ? responseItem?.answer[0].valueString : ""; + case "quantity": + return responseItem?.answer + ? responseItem?.answer[0].valueQuantity + : ""; + case "choice": + if (responseItem?.answer) { + return responseItem.answer[0].valueCoding + ? responseItem?.answer[0].valueCoding.code + : responseItem?.answer[0].valueString; + } + } + }; + + const answerChange = (e) => { + const { id, value } = e.target; + + var updatedQuestionnaireResponse = { ...questionnaireResponse }; + var responseItem = updatedQuestionnaireResponse.item.find( + (item) => item.linkId === id, + ); + var questionnaireItem = questionnaire.item.find( + (item) => item.linkId === id, + ); + responseItem.answer = []; + if (value !== "") { + switch (questionnaireItem.type) { + case "boolean": + responseItem.answer.push({ valueBoolean: value }); + break; + case "decimal": + responseItem.answer.push({ valueDecimal: value }); + break; + case "integer": + responseItem.answer.push({ valueInteger: value }); + break; + case "date": + responseItem.answer.push({ valueDate: value }); + break; + case "time": + responseItem.answer.push({ valueTime: value }); + break; + case "string": + case "text": + responseItem.answer.push({ valueString: value }); + break; + case "quantity": + responseItem.answer.push({ valueQuantity: value }); + break; + case "choice": + //make single select and multiselect have the same shape to reuse code + var items = value; + if (!Array.isArray(items)) { + items = [{ value: value }]; + } + for (var i = 0; i < items.length; i++) { + var curValue = items[i].value; + var option = questionnaireItem?.answerOption?.find( + (option) => option?.valueCoding?.code === curValue, + ); + if (option) { + responseItem.answer.push({ valueCoding: option.valueCoding }); + } else { + option = questionnaireItem?.answerOption?.find( + (option) => option.valueString === curValue, + ); + if (option) { + responseItem.answer.push({ valueString: option.valueString }); + } else { + console.error( + "couldn't find a matching questionnaire answer for '" + + curValue + + "'", + ); + } + } + } + break; + } + } + setQuestionnaireResponse(updatedQuestionnaireResponse); + setOrderFormValues({ + ...orderFormValues, + sampleOrderItems: { + ...orderFormValues.sampleOrderItems, + additionalQuestions: updatedQuestionnaireResponse, + }, + }); + }; + + return ( + <> + +
+

Program

+ + + {questionnaireResponse && ( + + )} +
+
+ + ); +}; + +export default EditOrderEntryAdditionalQuestions; diff --git a/frontend/src/components/modifyOrder/EditSample.js b/frontend/src/components/modifyOrder/EditSample.js new file mode 100644 index 0000000000..8848c14752 --- /dev/null +++ b/frontend/src/components/modifyOrder/EditSample.js @@ -0,0 +1,153 @@ +import React, { useEffect, useRef, useState } from "react"; +import { Button, Link, Row, Stack } from "@carbon/react"; +import { Add } from "@carbon/react/icons"; +import { getFromOpenElisServer } from "../utils/Utils"; +import EditSampleType from "./EditSampleType"; +import { FormattedMessage } from "react-intl"; +const EditSample = (props) => { + const { samples, setSamples } = props; + const componentMounted = useRef(true); + const [elementsCounter, setElementsCounter] = useState(0); + + const [rejectSampleReasons, setRejectSampleReasons] = useState([]); + + const handleAddNewSample = () => { + let updateSamples = [...samples]; + let count = elementsCounter + 1; + updateSamples.push({ + index: count, + sampleRejected: false, + rejectionReason: "", + requestReferralEnabled: false, + referralItems: [], + sampleTypeId: "", + sampleXML: null, + panels: [], + tests: [], + }); + setSamples(updateSamples); + setElementsCounter(count); + }; + + const sampleTypeObject = (object) => { + let newState = [...samples]; + switch (true) { + case object.sampleTypeId !== undefined && object.sampleTypeId !== "": + newState[object.sampleObjectIndex].sampleTypeId = object.sampleTypeId; + break; + case object.sampleRejected: + newState[object.sampleObjectIndex].sampleRejected = + object.sampleRejected; + break; + case object.rejectionReason !== undefined && + object.rejectionReason !== null: + newState[object.sampleObjectIndex].rejectionReason = + object.rejectionReason; + break; + case object.selectedTests !== undefined && + object.selectedTests.length > 0: + newState[object.sampleObjectIndex].tests = object.selectedTests; + break; + case object.selectedPanels !== undefined && + object.selectedPanels.length > 0: + newState[object.sampleObjectIndex].panels = object.selectedPanels; + break; + case object.sampleXML !== undefined && object.sampleXML !== null: + newState[object.sampleObjectIndex].sampleXML = object.sampleXML; + break; + case object.requestReferralEnabled: + newState[object.sampleObjectIndex].requestReferralEnabled = + object.requestReferralEnabled; + break; + case object.referralItems !== undefined && + object.referralItems.length > 0: + newState[object.sampleObjectIndex].referralItems = object.referralItems; + break; + default: + props.setSamples(newState); + } + }; + + const removeSample = (index) => { + let updateSamples = samples.splice(index, 1); + setSamples(updateSamples); + }; + + const fetchRejectSampleReasons = (res) => { + if (componentMounted.current) { + setRejectSampleReasons(res); + } + }; + + const handleRemoveSample = (e, sample) => { + e.preventDefault(); + let filtered = samples.filter(function (element) { + return element !== sample; + }); + setSamples(filtered); + }; + + useEffect(() => { + getFromOpenElisServer( + "/rest/test-rejection-reasons", + fetchRejectSampleReasons, + ); + window.scrollTo(0, 0); + return () => { + componentMounted.current = false; + }; + }, []); + + useEffect(() => { + getFromOpenElisServer( + "/rest/test-rejection-reasons", + fetchRejectSampleReasons, + ); + window.scrollTo(0, 0); + return () => { + componentMounted.current = false; + }; + }, []); + + return ( + <> +

+ +

+ +
+ {samples.map((sample, i) => { + return ( +
+

+ {i + 1} +

+ handleRemoveSample(e, sample)}> + {} + + +
+ ); + })} + +
+ +
+
+
+
+ + ); +}; + +export default EditSample; diff --git a/frontend/src/components/modifyOrder/EditSampleType.js b/frontend/src/components/modifyOrder/EditSampleType.js new file mode 100644 index 0000000000..9c39e70b1d --- /dev/null +++ b/frontend/src/components/modifyOrder/EditSampleType.js @@ -0,0 +1,692 @@ +import React, { useContext, useEffect, useRef, useState } from "react"; +import { + Checkbox, + FormGroup, + Layer, + Search, + Select, + SelectItem, + Tag, + Tile, + Loading +} from "@carbon/react"; +import CustomCheckBox from "../common/CustomCheckBox"; +import CustomSelect from "../common/CustomSelect"; +import CustomDatePicker from "../common/CustomDatePicker"; +import CustomTimePicker from "../common/CustomTimePicker"; +import { NotificationKinds } from "../common/CustomNotification"; +import { FormattedMessage } from "react-intl"; +import { getFromOpenElisServer } from "../utils/Utils"; +import { NotificationContext } from "../layout/Layout"; +import { sampleTypeTestsStructure } from "../data/SampleEntryTestsForTypeProvider"; +import CustomTextInput from "../common/CustomTextInput"; +import OrderReferralRequest from "../addOrder/OrderReferralRequest"; +import UserSessionDetailsContext from "../../UserSessionDetailsContext"; + +const EditSampleType = (props) => { + const { userSessionDetails } = useContext(UserSessionDetailsContext); + const { index, rejectSampleReasons, removeSample, sample } = props; + const componentMounted = useRef(true); + const [sampleTypes, setSampleTypes] = useState([]); + const sampleTypesRef = useRef(null); + const [selectedSampleType, setSelectedSampleType] = useState({ + id: null, + name: "", + element_index: 0, + }); + const [sampleTypeTests, setSampleTypeTests] = useState( + sampleTypeTestsStructure, + ); + const [selectedTests, setSelectedTests] = useState([]); + const [searchBoxTests, setSearchBoxTests] = useState([]); + const [requestTestReferral, setRequestTestReferral] = useState(false); + const [referralReasons, setReferralReasons] = useState([]); + const [referralOrganizations, setReferralOrganizations] = useState([]); + const [testSearchTerm, setTestSearchTerm] = useState(""); + const [referralRequests, setReferralRequests] = useState([]); + const { setNotificationVisible, setNotificationBody } = + useContext(NotificationContext); + const [rejectionReasonsDisabled, setRejectionReasonsDisabled] = + useState(true); + const [selectedPanels, setSelectedPanels] = useState([]); + const [panelSearchTerm, setPanelSearchTerm] = useState(""); + const [searchBoxPanels, setSearchBoxPanels] = useState([]); + const [sampleXml, setSampleXml] = useState({ + collectionDate: "", + collector: "", + rejected: false, + rejectionReason: "", + collectionTime: "", + }); + const [loading, setLoading] = useState(true); + + const defaultSelect = { id: "", value: "Choose Rejection Reason" }; + + function handleCollectionDate(date) { + setSampleXml({ + ...sampleXml, + collectionDate: date, + }); + } + + function handleReasons(value) { + setSampleXml({ + ...sampleXml, + rejectionReason: value, + }); + props.sampleTypeObject({ + rejectionReason: value, + sampleObjectIndex: index, + }); + } + + function handleCollectionTime(time) { + setSampleXml({ + ...sampleXml, + collectionTime: time, + }); + } + + function handleCollector(value) { + setSampleXml({ + ...sampleXml, + collector: value, + }); + } + + useEffect(() => { + updateSampleXml(sampleXml, index); + }, [sampleXml]); + + const handleRemoveSampleTest = (index) => { + removeSample(index); + }; + + const handleReferralRequest = () => { + setRequestTestReferral(!requestTestReferral); + if (selectedTests.length > 0) { + const defaultReferralRequest = []; + selectedTests.map((test) => { + defaultReferralRequest.push({ + reasonForReferral: referralReasons[0].id, + referrer: + userSessionDetails.firstName + " " + userSessionDetails.lastName, + institute: referralOrganizations[0].id, + sentDate: "", + testId: test.id, + }); + }); + setReferralRequests(defaultReferralRequest); + } + }; + + const handleTestSearchChange = (event) => { + const query = event.target.value; + setTestSearchTerm(query); + const results = sampleTypeTests.tests.filter((test) => { + return test.name.toLowerCase().includes(query.toLowerCase()); + }); + setSearchBoxTests(results); + }; + + const handleRemoveSelectedTest = (test) => { + removedTestFromSelectedTests(test); + updateSampleTypeTests(test, false); + }; + + const handleFilterSelectTest = (test) => { + setTestSearchTerm(""); + addTestToSelectedTests(test); + updateSampleTypeTests(test, true); + }; + + function updateSampleTypeTests(test, userBenchChoice = false) { + let tests = [...sampleTypeTests.tests]; + let testIndex = findTestIndex(test.id); + tests[testIndex].userBenchChoice = userBenchChoice; + setSampleTypeTests({ ...sampleTypeTests, tests: tests }); + } + + const handleTestCheckbox = (e, test) => { + if (e.currentTarget.checked) { + updateSampleTypeTests(test, true); + addTestToSelectedTests(test); + } else { + updateSampleTypeTests(test, false); + removedTestFromSelectedTests(test); + } + }; + + function findTestById(testId) { + return sampleTypeTests.tests.find((test) => test.id === testId); + } + + function findTestIndex(testId) { + return sampleTypeTests.tests.findIndex((test) => test.id === testId); + } + + const triggerPanelCheckBoxChange = (isChecked, testMaps) => { + const testIds = testMaps.split(",").map((id) => id.trim()); + testIds.map((testId) => { + let testIndex = findTestIndex(testId); + let test = findTestById(testId); + if (testIndex !== -1) { + updateSampleTypeTests(test, isChecked); + if (isChecked) { + setSelectedTests((prevState) => { + return [...prevState, { id: test.id, name: test.name }]; + }); + } else { + removedTestFromSelectedTests(test); + } + } + }); + }; + + const removedTestFromSelectedTests = (test) => { + let index = 0; + for (let i in selectedTests) { + if (selectedTests[i].id === test.id) { + const newTests = selectedTests; + newTests.splice(index, 1); + setSelectedTests([...newTests]); + break; + } + index++; + } + }; + + function addReferralRequest(test) { + setReferralRequests([ + ...referralRequests, + { + reasonForReferral: referralReasons[0].id, + referrer: + userSessionDetails.firstName + " " + userSessionDetails.lastName, + institute: referralOrganizations[0].id, + sentDate: "", + testId: test.id, + }, + ]); + } + + function removeReferralRequest(test) { + let index = 0; + for (let x in referralRequests) { + if (referralRequests[x].testId === test.id) { + const newReferralRequests = referralRequests; + newReferralRequests.splice(index, 1); + setReferralRequests([...newReferralRequests]); + break; + } + index++; + } + } + + const handleFetchSampleTypeTests = (e, index) => { + setSelectedTests([]); + setReferralRequests([]); + const { value } = e.target; + const selectedSampleTypeOption = + sampleTypesRef.current.options[sampleTypesRef.current.selectedIndex].text; + setSelectedSampleType({ + ...selectedSampleType, + id: value, + name: selectedSampleTypeOption, + element_index: index, + }); + props.sampleTypeObject({ sampleTypeId: value, sampleObjectIndex: index }); + }; + + const updateSampleXml = (sampleXML, index) => { + props.sampleTypeObject({ sampleXML: sampleXML, sampleObjectIndex: index }); + }; + + const fetchSamplesTypes = (res) => { + if (componentMounted.current) { + setSampleTypes(res); + setLoading(false) + } + }; + + const fetchSampleTypeTests = (res) => { + if (componentMounted.current) { + setSampleTypeTests(res); + } + }; + + useEffect(() => { + if (props.sample.referralItems.length > 0 && referralReasons.length > 0) { + setRequestTestReferral(props.sample.requestReferralEnabled); + setReferralRequests(props.sample.referralItems); + } + }, [referralReasons]); + + useEffect(() => { + props.sampleTypeObject({ + requestReferralEnabled: requestTestReferral, + sampleObjectIndex: index, + }); + if (!requestTestReferral) { + setReferralRequests([]); + } + }, [requestTestReferral]); + + useEffect(() => { + props.sampleTypeObject({ + selectedTests: selectedTests, + sampleObjectIndex: index, + }); + }, [selectedTests]); + + useEffect(() => { + props.sampleTypeObject({ + referralItems: referralRequests, + sampleObjectIndex: index, + }); + }, [referralRequests]); + + const displayReferralReasonsOptions = (res) => { + if (componentMounted.current) { + setReferralReasons(res); + } + }; + const displayReferralOrgOptions = (res) => { + if (componentMounted.current) { + setReferralOrganizations(res); + } + }; + + function handleRejection(checked) { + if (checked) { + setNotificationBody({ + kind: NotificationKinds.warning, + title: , + message: , + }); + setNotificationVisible(true); + } + setSampleXml({ + ...sampleXml, + rejected: checked, + }); + setRejectionReasonsDisabled(!rejectionReasonsDisabled); + } + + const removedPanelFromSelectedPanels = (panel) => { + let index = 0; + let panelId = panel.id !== undefined ? panel.id : panel.panelId; + + for (let i in selectedPanels) { + if (selectedPanels[i].id === panelId) { + triggerPanelCheckBoxChange(false, selectedPanels[i].testMaps); + const newPanels = selectedPanels; + newPanels.splice(index, 1); + setSelectedPanels([...newPanels]); + break; + } + index++; + } + }; + + const handlePanelSearchChange = (event) => { + const query = event.target.value; + setPanelSearchTerm(query); + const results = sampleTypeTests.panels.filter((panel) => { + return panel.name.toLowerCase().includes(query.toLowerCase()); + }); + setSearchBoxPanels(results); + }; + + const handleFilterSelectPanel = (panel) => { + setPanelSearchTerm(""); + addPanelToSelectedPanels(panel); + }; + + const handlePanelCheckbox = (e, panel) => { + if (e.currentTarget.checked) { + addPanelToSelectedPanels(panel); + } else { + removedPanelFromSelectedPanels(panel); + } + }; + + const handleRemoveSelectedPanel = (panel) => { + removedPanelFromSelectedPanels(panel); + }; + + function addTestToSelectedTests(test) { + setSelectedTests([...selectedTests, { id: test.id, name: test.name }]); + } + + const addPanelToSelectedPanels = (panel) => { + setSelectedPanels([ + ...selectedPanels, + { id: panel.panelId, name: panel.name, testMaps: panel.testMaps }, + ]); + triggerPanelCheckBoxChange(true, panel.testMaps); + }; + + useEffect(() => { + componentMounted.current = true; + if (selectedSampleType.id !== "" && selectedSampleType.id != null) { + getFromOpenElisServer( + `/rest/sample-type-tests?sampleType=${selectedSampleType.id}`, + fetchSampleTypeTests, + ); + } + return () => { + componentMounted.current = false; + }; + }, [selectedSampleType.id]); + + useEffect(() => { + props.sampleTypeObject({ + sampleRejected: rejectionReasonsDisabled, + sampleObjectIndex: index, + }); + }, [rejectionReasonsDisabled]); + + useEffect(() => { + props.sampleTypeObject({ + selectedPanels: selectedPanels, + sampleObjectIndex: index, + }); + }, [selectedPanels]); + + const repopulateUI = () => { + if (props.sample !== null) { + setSelectedTests(props.sample.tests); + setSelectedPanels(props.sample.panels); + setSelectedSampleType({ + id: props.sample.sampleTypeId, + }); + } + }; + + useEffect(() => { + getFromOpenElisServer( + "/rest/referral-reasons", + displayReferralReasonsOptions, + ); + getFromOpenElisServer( + "/rest/referral-organizations", + displayReferralOrgOptions, + ); + repopulateUI(); + getFromOpenElisServer("/rest/user-sample-types", fetchSamplesTypes); + return () => { + componentMounted.current = false; + }; + }, []); + + return ( + <> + {loading && } +
+ + + handleRejection(value)} + label={} + /> + {sampleXml.rejected && ( + handleReasons(e)} + /> + )} + +
+ handleCollectionDate(date)} + labelText={} + className="inputText" + /> + + handleCollectionTime(time)} + className="inputText" + labelText={} + /> +
+
+ handleCollector(value)} + defaultValue={""} + labelText={} + className="inputText" + /> +
+
+
+

+ +

+
+ {selectedPanels && selectedPanels.length ? ( + <> + {selectedPanels.map((panel, panel_index) => ( + handleRemoveSelectedPanel(panel)} + style={{ marginRight: "0.5rem" }} + type={"green"} + > + {panel.name} + + ))} + + ) : ( + <> + )} +
+ + } + > + { + if (panelSearchTerm) { + return panelSearchTerm; + } + return ""; + })()} + /> +
+ {(() => { + if (!panelSearchTerm) return null; + if (searchBoxPanels && searchBoxPanels.length) { + return ( +
    + {searchBoxPanels.map((panel, panel_index) => ( +
  • handleFilterSelectPanel(panel)} + > + {panel.name} +
  • + ))} +
+ ); + } + return ( + <> + + + + {" "} + "{panelSearchTerm}"{" "} + + + + + ); + })()} +
+
+ {sampleTypeTests.panels != null && + sampleTypeTests.panels.map((panel) => { + return panel.name === "" ? ( + "" + ) : ( + handlePanelCheckbox(e, panel)} + labelText={panel.name} + id={`panel_` + index + "_" + panel.panelId} + key={index + panel.panelId} + /> + ); + })} +
+
+ +
+ {selectedTests && !selectedTests.length ? "" :

Order Tests

} +
+ {selectedTests && selectedTests.length ? ( + <> + {selectedTests.map((test, index) => ( + handleRemoveSelectedTest(test)} + style={{ marginRight: "0.5rem" }} + type={"red"} + > + {test.name} + + ))} + + ) : ( + <> + )} +
+ + { + if (testSearchTerm) { + return testSearchTerm; + } + return ""; + })()} + /> +
+ {(() => { + if (!testSearchTerm) return null; + if (searchBoxTests && searchBoxTests.length) { + return ( +
    + {searchBoxTests.map((test, test_index) => ( +
  • handleFilterSelectTest(test)} + > + {test.name} +
  • + ))} +
+ ); + } + return ( + <> + + + + No test found matching + "{testSearchTerm}"{" "} + + + + + ); + })()} +
+
+ {sampleTypeTests.tests != null && + sampleTypeTests.tests.map((test) => { + return test.name === "" ? ( + "" + ) : ( + handleTestCheckbox(e, test)} + labelText={test.name} + id={`test_` + index + "_" + test.id} + key={`test_checkBox_` + index + test.id} + checked={test.userBenchChoice} + /> + ); + })} +
+ +
+ + {requestTestReferral === true && ( + + )} +
+
+ + ); +}; + +export default EditSampleType; diff --git a/frontend/src/components/modifyOrder/Index.js b/frontend/src/components/modifyOrder/Index.js index 4c0452d8ce..b1dedcebe1 100644 --- a/frontend/src/components/modifyOrder/Index.js +++ b/frontend/src/components/modifyOrder/Index.js @@ -2,7 +2,7 @@ import React, { useContext } from "react"; import { FormattedMessage } from "react-intl"; import { Column, Grid, Heading, Section } from "@carbon/react"; -import ModifyOrder from "./ModifyOrder"; +import SearchOrder from "./SearchOrder"; import { AlertDialog } from "../common/CustomNotification"; import { NotificationContext } from "../layout/Layout"; @@ -22,7 +22,7 @@ const Index = () => { - +
); }; diff --git a/frontend/src/components/modifyOrder/ModifyOrder.js b/frontend/src/components/modifyOrder/ModifyOrder.js index 30797abb49..047ad6376a 100644 --- a/frontend/src/components/modifyOrder/ModifyOrder.js +++ b/frontend/src/components/modifyOrder/ModifyOrder.js @@ -1,23 +1,329 @@ -import React, { useState } from "react"; -import SearchPatientForm from "../patient/SearchPatientForm"; +import React, { useContext, useEffect, useState, useRef } from "react"; +import { useParams } from 'react-router-dom'; +import { Button, ProgressIndicator, ProgressStep, Stack ,Breadcrumb ,BreadcrumbItem ,Grid,Column ,Section ,Tag} from "@carbon/react"; +import EditSample from "./EditSample"; +import AddOrder from "../addOrder/AddOrder"; +import "../addOrder/add-order.scss"; +import { ModifyOrderFormValues } from "../formModel/innitialValues/OrderEntryFormValues"; +import { NotificationContext } from "../layout/Layout"; +import { AlertDialog, NotificationKinds } from "../common/CustomNotification"; +import { postToOpenElisServer, getFromOpenElisServer } from "../utils/Utils"; +import EditOrderEntryAdditionalQuestions from "./EditOrderEntryAdditionalQuestions"; +import OrderSuccessMessage from "../addOrder/OrderSuccessMessage"; +import { FormattedMessage ,useIntl} from "react-intl"; -function ModifyOrder() { - const [selectedPatient, setSelectedPatient] = useState({}); +export let sampleObject = { + index: 0, + sampleRejected: false, + rejectionReason: "", + sampleTypeId: "", + sampleXML: null, + panels: [], + tests: [], + requestReferralEnabled: false, + referralItems: [], +}; +const ModifyOrder = () => { + const firstPageNumber = 0; + const lastPageNumber = 3; + const programPageNumber = firstPageNumber + 0; + const samplePageNumber = firstPageNumber + 1; + const orderPageNumber = firstPageNumber + 2; + const successMsgPageNumber = lastPageNumber; - const getSelectedPatient = (patient) => { - setSelectedPatient(patient); - console.log("selectedPatient:" + selectedPatient); + const [page, setPage] = useState(firstPageNumber); + const [orderFormValues, setOrderFormValues] = useState(ModifyOrderFormValues); + const [samples, setSamples] = useState([sampleObject]); + + const componentMounted = useRef(false); + + useEffect(() => { + componentMounted.current = true; + let patientId = new URLSearchParams(window.location.search).get( + "patientId", + ); + let accessionNumber = new URLSearchParams(window.location.search).get( + "accessionNumber", + ); + accessionNumber = accessionNumber?accessionNumber:"" ; + patientId =patientId?patientId:""; + getFromOpenElisServer( + "/rest/SampleEdit?patientId=" + + patientId + + "&accessionNumber=" + + accessionNumber, + loadOrderValues, + ); + return () => { + componentMounted.current = false; + } + }, []); + + const loadOrderValues = (data) => { + if (componentMounted.current) { + setOrderFormValues(data); + } + } + + const { notificationVisible, setNotificationVisible, setNotificationBody } = + useContext(NotificationContext); + + const showAlertMessage = (msg, kind) => { + setNotificationVisible(true); + setNotificationBody({ + kind: kind, + title: , + message: msg, + }); + }; + + const handlePost = (status) => { + if (status === 200) { + showAlertMessage( + , + NotificationKinds.success, + ); + } else { + showAlertMessage( + , + NotificationKinds.error, + ); + } + }; + const handleSubmitOrderForm = (e) => { + e.preventDefault(); + setPage(page + 1); + console.log(JSON.stringify(orderFormValues)) + // postToOpenElisServer( + // "/rest/SamplePatientEntry", + // JSON.stringify(orderFormValues), + // handlePost, + // ); }; + useEffect(() => { + if (page === samplePageNumber + 1) { + attacheSamplesToFormValues(); + } + }, [page]); + + const attacheSamplesToFormValues = () => { + let sampleXmlString = null; + let referralItems = []; + if (samples.length > 0) { + if (samples[0].tests.length > 0) { + sampleXmlString = ''; + sampleXmlString += ""; + let tests = null; + samples.map((sampleItem) => { + if (sampleItem.tests.length > 0) { + tests = Object.keys(sampleItem.tests) + .map(function (i) { + return sampleItem.tests[i].id; + }) + .join(","); + sampleXmlString += ``; + } + if (sampleItem.referralItems.length > 0) { + const referredInstitutes = Object.keys(sampleItem.referralItems) + .map(function (i) { + return sampleItem.referralItems[i].institute; + }) + .join(","); + + const sentDates = Object.keys(sampleItem.referralItems) + .map(function (i) { + return sampleItem.referralItems[i].sentDate; + }) + .join(","); + + const referralReasonIds = Object.keys(sampleItem.referralItems) + .map(function (i) { + return sampleItem.referralItems[i].reasonForReferral; + }) + .join(","); + + const referrers = Object.keys(sampleItem.referralItems) + .map(function (i) { + return sampleItem.referralItems[i].referrer; + }) + .join(","); + referralItems.push({ + referrer: referrers, + referredInstituteId: referredInstitutes, + referredTestId: tests, + referredSendDate: sentDates, + referralReasonId: referralReasonIds, + }); + } + }); + sampleXmlString += ""; + } + } + setOrderFormValues({ + ...orderFormValues, + useReferral: true, + sampleXML: sampleXmlString, + referralItems: referralItems, + }); + }; + + const navigateForward = () => { + if (page <= lastPageNumber && page >= firstPageNumber) { + setPage(page + 1); + } + }; + + const navigateBackWards = () => { + if (page > firstPageNumber) { + setPage(page + -1); + } + }; + const handleTabClickHandler = (e) => { + setPage(e); + }; + const intl = useIntl(); + return ( <> -
- -
+ + {intl.formatMessage({ id: "home.label" })} + {intl.formatMessage({ id: "label.search.patient" })} + + + + +
+
+ {orderFormValues?.patientName ? (
+
+ + : + + {orderFormValues.patientName} +
+
+ {" "} + + : + + {orderFormValues.gender === "M" ? ( + + ) : ( + + )}{" "} + + : + {" "} + {orderFormValues.dob} +
+
+ + : + + {orderFormValues.accessionNumber}{" "} +
+
+ + : + + {orderFormValues.nationalId} +
+
+ ) : ( +
+
+ {" "} + {" "} +
+
+ )} +
+
+
+
+ +
+ {notificationVisible === true ? : ""} +
+

+ +

+ {page <= orderPageNumber && ( + handleTabClickHandler(e)} + > + } + /> + } + /> + } + /> + + )} + {page === programPageNumber && ( + + )} + {page === samplePageNumber && ( + + )} + {page === orderPageNumber && ( + + )} + + {page === successMsgPageNumber && ( + + )} +
+ {page !== firstPageNumber && page <= orderPageNumber && ( + + )} + + {page < orderPageNumber && ( + + )} + + {page === orderPageNumber && ( + + )} +
+
+
+
); -} +}; export default ModifyOrder; diff --git a/frontend/src/components/modifyOrder/SearchOrder.js b/frontend/src/components/modifyOrder/SearchOrder.js new file mode 100644 index 0000000000..e37bfc1f17 --- /dev/null +++ b/frontend/src/components/modifyOrder/SearchOrder.js @@ -0,0 +1,66 @@ +import React, { useState, useEffect, useRef } from "react"; +import SearchPatientForm from "../patient/SearchPatientForm"; +import { Button, Column, TextInput ,Grid ,Form} from "@carbon/react"; + +function SearchOrder() { + const [selectedPatient, setSelectedPatient] = useState({}); + const componentMounted = useRef(false); + const [accessionNumber, setAccessionNumber] = useState(""); + + const getSelectedPatient = (patient) => { + setSelectedPatient(patient); + console.log("selectedPatient:" + selectedPatient); + }; + + useEffect(() => { + componentMounted.current = true; + openPatientResults(selectedPatient.patientPK); + + return () => { + componentMounted.current = false; + }; + }, [selectedPatient]); + + const openPatientResults = (patientId) => { + if (patientId) { + window.location.href = "/ModifyOrder?patientId=" + patientId; + } + }; + + const handleSearch = (e) => { + e.preventDefault(); + window.location.href = "/ModifyOrder?accessionNumber=" + accessionNumber; + }; + + return ( + <> +
+
+ + +

Search By Accesion

+
+ + setAccessionNumber(e.target.value)} + /> + + + + +
+
+
+
+

Search By Patient

+ +
+ + ); +} + +export default SearchOrder; diff --git a/frontend/src/languages/en.json b/frontend/src/languages/en.json index 8c2ab1ba95..5335d953e9 100644 --- a/frontend/src/languages/en.json +++ b/frontend/src/languages/en.json @@ -291,7 +291,9 @@ "search.label.test" : "Select Test Name" , "search.label.sample" : "Select Sample Status" , "pathology.label.report" : "Pathology Report", - "patient.natioanalid":"National ID " + "patient.natioanalid":"National ID", + "sample.label.orderpanel":"Order Panels" + diff --git a/src/main/java/org/openelisglobal/common/services/SampleOrderService.java b/src/main/java/org/openelisglobal/common/services/SampleOrderService.java index 3756e6cf0d..ee776d0668 100644 --- a/src/main/java/org/openelisglobal/common/services/SampleOrderService.java +++ b/src/main/java/org/openelisglobal/common/services/SampleOrderService.java @@ -20,10 +20,12 @@ import java.util.List; import org.apache.commons.validator.GenericValidator; +import org.hl7.fhir.r4.model.QuestionnaireResponse; import org.openelisglobal.common.formfields.FormFields; import org.openelisglobal.common.util.ConfigurationProperties; import org.openelisglobal.common.util.DateUtil; import org.openelisglobal.common.util.StringUtil; +import org.openelisglobal.dataexchange.fhir.FhirUtil; import org.openelisglobal.observationhistory.service.ObservationHistoryService; import org.openelisglobal.observationhistory.service.ObservationHistoryServiceImpl.ObservationType; import org.openelisglobal.observationhistory.valueholder.ObservationHistory; @@ -32,6 +34,9 @@ import org.openelisglobal.organization.valueholder.Organization; import org.openelisglobal.patient.valueholder.Patient; import org.openelisglobal.person.valueholder.Person; +import org.openelisglobal.program.service.ProgramSampleService; +import org.openelisglobal.program.valueholder.Program; +import org.openelisglobal.program.valueholder.ProgramSample; import org.openelisglobal.provider.service.ProviderService; import org.openelisglobal.provider.valueholder.Provider; import org.openelisglobal.requester.valueholder.SampleRequester; @@ -51,6 +56,9 @@ @DependsOn({ "springContext" }) public class SampleOrderService { + + private ProgramSampleService programSampleService = SpringContext.getBean(ProgramSampleService.class); + private FhirUtil fhirUtil = SpringContext.getBean(FhirUtil.class); private static SampleService sampleService = SpringContext.getBean(SampleService.class); private static OrganizationService orgService = SpringContext.getBean(OrganizationService.class); private ObservationHistoryService observationHistoryService = SpringContext @@ -152,6 +160,14 @@ public SampleOrderItem getSampleOrderItem() { .getValueForSample(ObservationType.BILLING_REFERENCE_NUMBER, sample.getId())); sampleOrder.setProgram( observationHistoryService.getRawValueForSample(ObservationType.PROGRAM, sample.getId())); + String programName = observationHistoryService.getRawValueForSample(ObservationType.PROGRAM, sample.getId()); + ProgramSample programSample = programSampleService.getProgrammeSampleBySample(Integer.valueOf(sample.getId()), programName); + if (programSample != null) { + sampleOrder.setProgramId(programSample.getProgram().getId()); + sampleOrder.setAdditionalQuestions( + fhirUtil.getLocalFhirClient().read().resource(QuestionnaireResponse.class) + .withId(programSample.getQuestionnaireResponseUuid().toString()).execute()); + } RequesterService requesterService = new RequesterService(sample.getId()); sampleOrder.setProviderPersonId(requesterService.getRequesterPersonId()); diff --git a/src/main/java/org/openelisglobal/program/dao/ImmunohistochemistrySampleDAOImpl.java b/src/main/java/org/openelisglobal/program/dao/ImmunohistochemistrySampleDAOImpl.java index 4c2c8da103..3d3e013094 100644 --- a/src/main/java/org/openelisglobal/program/dao/ImmunohistochemistrySampleDAOImpl.java +++ b/src/main/java/org/openelisglobal/program/dao/ImmunohistochemistrySampleDAOImpl.java @@ -55,7 +55,7 @@ public Long getCountWithStatusBetweenDates(List stat @Override public List searchWithStatusAndAccesionNumber(List statuses, String labNumber) { - String sql = "from from ImmunohistochemistrySample is where is.status in (:statuses) and is.sample.accessionNumber = :labNumber"; + String sql = "from ImmunohistochemistrySample is where is.status in (:statuses) and is.sample.accessionNumber = :labNumber"; Query query = entityManager.unwrap(Session.class).createQuery(sql, ImmunohistochemistrySample.class); query.setParameterList("statuses", statuses.stream().map(e -> e.toString()).collect(Collectors.toList())); query.setParameter("labNumber" ,labNumber); @@ -66,7 +66,7 @@ public List searchWithStatusAndAccesionNumber(List query = entityManager.unwrap(Session.class).createQuery(sql, ImmunohistochemistrySample.class); query.setParameter("pathologySampleId" ,pathologySampleId); query.setMaxResults(1); diff --git a/src/main/java/org/openelisglobal/program/dao/ProgramSampleDAO.java b/src/main/java/org/openelisglobal/program/dao/ProgramSampleDAO.java index 71bc8d1bd7..75b24fc1b5 100644 --- a/src/main/java/org/openelisglobal/program/dao/ProgramSampleDAO.java +++ b/src/main/java/org/openelisglobal/program/dao/ProgramSampleDAO.java @@ -4,4 +4,5 @@ import org.openelisglobal.program.valueholder.ProgramSample; public interface ProgramSampleDAO extends BaseDAO { + ProgramSample getProgrammeSampleBySample(Integer sampleId ,String programName); } diff --git a/src/main/java/org/openelisglobal/program/dao/ProgramSampleDAOImpl.java b/src/main/java/org/openelisglobal/program/dao/ProgramSampleDAOImpl.java index d3b5dd99ae..5fafadcd21 100644 --- a/src/main/java/org/openelisglobal/program/dao/ProgramSampleDAOImpl.java +++ b/src/main/java/org/openelisglobal/program/dao/ProgramSampleDAOImpl.java @@ -1,5 +1,7 @@ package org.openelisglobal.program.dao; +import org.hibernate.Session; +import org.hibernate.query.Query; import org.openelisglobal.common.daoimpl.BaseDAOImpl; import org.openelisglobal.program.valueholder.ProgramSample; import org.springframework.stereotype.Component; @@ -11,4 +13,30 @@ public class ProgramSampleDAOImpl extends BaseDAOImpl im ProgramSampleDAOImpl() { super(ProgramSample.class); } + + @Override + public ProgramSample getProgrammeSampleBySample(Integer sampleId , String programName) { + String className; + switch (programName.toLowerCase()) { + case "pathology": + className = "PathologySample"; + break; + case "immunohistochemistry": + className = "ImmunohistochemistrySample"; + break; + case "cytology": + className = "CytologySample"; + break; + default: + className = "PathologySample"; + break; + } + + String sql = "from "+ className +" ps where ps.sample.id = :sampleId"; + Query query = entityManager.unwrap(Session.class).createQuery(sql, ProgramSample.class); + query.setParameter("sampleId", sampleId); + query.setMaxResults(1); + ProgramSample programme = (ProgramSample)query.uniqueResult(); + return programme; + } } diff --git a/src/main/java/org/openelisglobal/program/service/ProgramSampleService.java b/src/main/java/org/openelisglobal/program/service/ProgramSampleService.java index 0e7afead99..94be7ab256 100644 --- a/src/main/java/org/openelisglobal/program/service/ProgramSampleService.java +++ b/src/main/java/org/openelisglobal/program/service/ProgramSampleService.java @@ -4,4 +4,5 @@ import org.openelisglobal.program.valueholder.ProgramSample; public interface ProgramSampleService extends BaseObjectService { + ProgramSample getProgrammeSampleBySample(Integer sampleId ,String programName); } diff --git a/src/main/java/org/openelisglobal/program/service/ProgramSampleServiceImpl.java b/src/main/java/org/openelisglobal/program/service/ProgramSampleServiceImpl.java index 76405a6d15..2a42eb6605 100644 --- a/src/main/java/org/openelisglobal/program/service/ProgramSampleServiceImpl.java +++ b/src/main/java/org/openelisglobal/program/service/ProgramSampleServiceImpl.java @@ -20,4 +20,9 @@ public class ProgramSampleServiceImpl extends BaseObjectServiceImpl excludedAnalysisStatusList; + private static final Set ENTERED_STATUS_SAMPLE_LIST = new HashSet<>(); + private static final Collection ABLE_TO_CANCEL_ROLE_NAMES = new ArrayList<>(); + + static { + excludedAnalysisStatusList = new HashSet<>(); + excludedAnalysisStatusList.add( + Integer.parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.Canceled))); + + ENTERED_STATUS_SAMPLE_LIST + .add(Integer.parseInt(SpringContext.getBean(IStatusService.class).getStatusID(SampleStatus.Entered))); + ABLE_TO_CANCEL_ROLE_NAMES.add("Validator"); + ABLE_TO_CANCEL_ROLE_NAMES.add("Validation"); + ABLE_TO_CANCEL_ROLE_NAMES.add("Biologist"); + } + + @Autowired + private SampleItemService sampleItemService; + @Autowired + private SampleService sampleService; + @Autowired + private TestService testService; +// @Autowired +// private OrganizationOrganizationTypeService orgOrgTypeService; + @Autowired + private TypeOfSampleService typeOfSampleService; + @Autowired + private AnalysisService analysisService; + @Autowired + private TypeOfSampleTestService typeOfSampleTestService; + @Autowired + private SampleHumanService sampleHumanService; + @Autowired + private UserRoleService userRoleService; + @Autowired + private SampleEditService sampleEditService; + @Autowired + private UserService userService; + + @GetMapping(value = "SampleEdit", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public SampleEditForm showSampleEdit(HttpServletRequest request , @RequestParam(required = false) String accessionNumber, @RequestParam(required = false) String patientId) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { + + SampleEditForm form = new SampleEditForm(); + form.setFormAction("SampleEdit"); + + request.getSession().setAttribute(SAVE_DISABLED, TRUE); + + boolean allowedToCancelResults = userModuleService.isUserAdmin(request) + || userRoleService.userInRole(getSysUserId(request), ABLE_TO_CANCEL_ROLE_NAMES); + boolean isEditable = "readwrite".equals(request.getSession().getAttribute(SAMPLE_EDIT_WRITABLE)) + || "readwrite".equals(request.getParameter("type")); + form.setIsEditable(isEditable); + + + if (GenericValidator.isBlankOrNull(accessionNumber) && !GenericValidator.isBlankOrNull(patientId) ) { + accessionNumber = getMostRecentAccessionNumberForPaitient(patientId); + } + if (!GenericValidator.isBlankOrNull(accessionNumber)) { + form.setAccessionNumber(accessionNumber); + form.setSearchFinished(Boolean.TRUE); + + Sample sample = getSample(accessionNumber); + + if (sample != null && !GenericValidator.isBlankOrNull(sample.getId())) { + + List sampleItemList = getSampleItems(sample); + setPatientInfo(form, sample); + List currentTestList = getCurrentTestInfo(sampleItemList, accessionNumber, + allowedToCancelResults); + form.setExistingTests(currentTestList); + setAddableTestInfo(form, sampleItemList, accessionNumber); + setAddableSampleTypes(form, request); + setSampleOrderInfo(form, sample); + form.setAbleToCancelResults(hasResults(currentTestList, allowedToCancelResults)); + String maxAccessionNumber; + if (sampleItemList.size() > 0) { + maxAccessionNumber = accessionNumber + "-" + + sampleItemList.get(sampleItemList.size() - 1).getSortOrder(); + } else { + maxAccessionNumber = accessionNumber + "-0"; + } + form.setMaxAccessionNumber(maxAccessionNumber); + form.setIsConfirmationSample(sampleService.isConfirmationSample(sample)); + } else { + form.setNoSampleFound(Boolean.TRUE); + } + } else { + form.setSearchFinished(Boolean.FALSE); + if ("readwrite".equals(request.getParameter("type"))) { + request.getSession().setAttribute(SAMPLE_EDIT_WRITABLE, "readwrite"); + } + } + + if (FormFields.getInstance().useField(FormFields.Field.InitialSampleCondition)) { + form.setInitialSampleConditionList( + DisplayListService.getInstance().getList(ListType.INITIAL_SAMPLE_CONDITION)); + } + if (FormFields.getInstance().useField(FormFields.Field.SampleNature)) { + form.setSampleNatureList(DisplayListService.getInstance().getList(ListType.SAMPLE_NATURE)); + } + // form.setRejectReasonList(DisplayListService.getInstance().getList(ListType.REJECTION_REASONS)); + form.setCurrentDate(DateUtil.getCurrentDateAsText()); + PatientSearch patientSearch = new PatientSearch(); + patientSearch.setLoadFromServerWithPatient(true); + patientSearch.setSelectedPatientActionButtonText(MessageUtil.getMessage("label.patient.search.select")); + form.setPatientSearch(patientSearch); + form.setWarning(true); + + addFlashMsgsToRequest(request); + return form; + } + + @Override + protected String findLocalForward(String forward) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'findLocalForward'"); + } + + private Boolean hasResults(List currentTestList, boolean allowedToCancelResults) { + if (!allowedToCancelResults) { + return false; + } + + for (SampleEditItem editItem : currentTestList) { + if (editItem.isHasResults()) { + return true; + } + } + + return false; + } + + private void setSampleOrderInfo(SampleEditForm form, Sample sample) + throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { + SampleOrderService sampleOrderService = new SampleOrderService(sample); + form.setSampleOrderItems(sampleOrderService.getSampleOrderItem()); + } + + private String getMostRecentAccessionNumberForPaitient(String patientID) { + String accessionNumber = null; + if (!GenericValidator.isBlankOrNull(patientID)) { + List samples = sampleService.getSamplesForPatient(patientID); + + int maxId = 0; + for (Sample sample : samples) { + if (Integer.parseInt(sample.getId()) > maxId) { + maxId = Integer.parseInt(sample.getId()); + accessionNumber = sample.getAccessionNumber(); + } + } + + } + return accessionNumber; + } + + private Sample getSample(String accessionNumber) { + return sampleService.getSampleByAccessionNumber(accessionNumber); + } + + private List getSampleItems(Sample sample) { + + return sampleItemService.getSampleItemsBySampleIdAndStatus(sample.getId(), ENTERED_STATUS_SAMPLE_LIST); + } + + private void setPatientInfo(SampleEditForm form, Sample sample) + throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { + + Patient patient = sampleHumanService.getPatientForSample(sample); + PatientService patientPatientService = SpringContext.getBean(PatientService.class); + PersonService personService = SpringContext.getBean(PersonService.class); + personService.getData(patient.getPerson()); + + form.setPatientName(patientPatientService.getLastFirstName(patient)); + form.setDob(patientPatientService.getEnteredDOB(patient)); + form.setGender(patientPatientService.getGender(patient)); + form.setNationalId(patientPatientService.getNationalId(patient)); + } + + private List getCurrentTestInfo(List sampleItemList, String accessionNumber, + boolean allowedToCancelAll) { + List currentTestList = new ArrayList<>(); + + for (SampleItem sampleItem : sampleItemList) { + addCurrentTestsToList(sampleItem, currentTestList, accessionNumber, allowedToCancelAll); + } + + return currentTestList; + } + + private void addCurrentTestsToList(SampleItem sampleItem, List currentTestList, + String accessionNumber, boolean allowedToCancelAll) { + + TypeOfSample typeOfSample = typeOfSampleService.get(sampleItem.getTypeOfSampleId()); + + List analysisList = analysisService.getAnalysesBySampleItemsExcludingByStatusIds(sampleItem, + excludedAnalysisStatusList); + + List analysisSampleItemList = new ArrayList<>(); + + String collectionDate = DateUtil.convertTimestampToStringDate(sampleItem.getCollectionDate()); + String collectionTime = DateUtil.convertTimestampToStringTime(sampleItem.getCollectionDate()); + boolean canRemove = true; + for (Analysis analysis : analysisList) { + SampleEditItem sampleEditItem = new SampleEditItem(); + + sampleEditItem.setTestId(analysis.getTest().getId()); + sampleEditItem.setTestName(TestServiceImpl.getUserLocalizedTestName(analysis.getTest())); + sampleEditItem.setSampleItemId(sampleItem.getId()); + + boolean canCancel = allowedToCancelAll || (!SpringContext.getBean(IStatusService.class) + .matches(analysis.getStatusId(), AnalysisStatus.Canceled) + && SpringContext.getBean(IStatusService.class).matches(analysis.getStatusId(), + AnalysisStatus.NotStarted)); + + if (!canCancel) { + canRemove = false; + } + sampleEditItem.setCanCancel(canCancel); + sampleEditItem.setAnalysisId(analysis.getId()); + sampleEditItem + .setStatus(SpringContext.getBean(IStatusService.class).getStatusNameFromId(analysis.getStatusId())); + sampleEditItem.setSortOrder(analysis.getTest().getSortOrder()); + sampleEditItem.setHasResults(!SpringContext.getBean(IStatusService.class).matches(analysis.getStatusId(), + AnalysisStatus.NotStarted)); + + analysisSampleItemList.add(sampleEditItem); + } + + if (!analysisSampleItemList.isEmpty()) { + Collections.sort(analysisSampleItemList, testComparator); + SampleEditItem firstItem = analysisSampleItemList.get(0); + + firstItem.setAccessionNumber(accessionNumber + "-" + sampleItem.getSortOrder()); + firstItem.setSampleType(typeOfSample.getLocalizedName()); + firstItem.setCanRemoveSample(canRemove); + firstItem.setCollectionDate(collectionDate == null ? "" : collectionDate); + firstItem.setCollectionTime(collectionTime); + currentTestList.addAll(analysisSampleItemList); + } + } + + private void setAddableTestInfo(SampleEditForm form, List sampleItemList, String accessionNumber) + throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { + List possibleTestList = new ArrayList<>(); + + for (SampleItem sampleItem : sampleItemList) { + addPossibleTestsToList(sampleItem, possibleTestList, accessionNumber); + } + + form.setPossibleTests(possibleTestList); + // form.setTestSectionList(DisplayListService.getInstance().getList(ListType.TEST_SECTION_ACTIVE)); + } + + private void setAddableSampleTypes(SampleEditForm form, HttpServletRequest request) + throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { + form.setSampleTypes(userService.getUserSampleTypes(getSysUserId(request), Constants.ROLE_RECEPTION)); + } + + private void addPossibleTestsToList(SampleItem sampleItem, List possibleTestList, + String accessionNumber) { + + TypeOfSample typeOfSample = typeOfSampleService.get(sampleItem.getTypeOfSampleId()); + + List typeOfSampleTestList = typeOfSampleTestService + .getTypeOfSampleTestsForSampleType(typeOfSample.getId()); + List typeOfTestSampleItemList = new ArrayList<>(); + + for (TypeOfSampleTest typeOfSampleTest : typeOfSampleTestList) { + SampleEditItem sampleEditItem = new SampleEditItem(); + + sampleEditItem.setTestId(typeOfSampleTest.getTestId()); + Test test = testService.get(typeOfSampleTest.getTestId()); + if ("Y".equals(test.getIsActive()) && test.getOrderable()) { + sampleEditItem.setTestName(TestServiceImpl.getUserLocalizedTestName(test)); + sampleEditItem.setSampleItemId(sampleItem.getId()); + sampleEditItem.setSortOrder(test.getSortOrder()); + typeOfTestSampleItemList.add(sampleEditItem); + } + } + + if (!typeOfTestSampleItemList.isEmpty()) { + Collections.sort(typeOfTestSampleItemList, testComparator); + + typeOfTestSampleItemList.get(0).setAccessionNumber(accessionNumber + "-" + sampleItem.getSortOrder()); + typeOfTestSampleItemList.get(0).setSampleType(typeOfSample.getLocalizedName()); + + possibleTestList.addAll(typeOfTestSampleItemList); + } + + } + private Errors validateNewAccessionNumber(String accessionNumber, Errors errors) { + ValidationResults results = AccessionNumberUtil.correctFormat(accessionNumber, false); + + if (results != ValidationResults.SUCCESS) { + errors.reject("sample.entry.invalid.accession.number.format", + "sample.entry.invalid.accession.number.format"); + } else if (AccessionNumberUtil.isUsed(accessionNumber)) { + errors.reject("sample.entry.invalid.accession.number.used", "sample.entry.invalid.accession.number.used"); + } + + return errors; + } + + private Sample updateAccessionNumberInSample(SampleEditForm form) { + Sample sample = sampleService.getSampleByAccessionNumber(form.getAccessionNumber()); + + if (sample != null) { + sample.setAccessionNumber(form.getNewAccessionNumber()); + sample.setSysUserId(getSysUserId(request)); + } + + return sample; + } + + private boolean accessionNumberChanged(SampleEditForm form) { + String newAccessionNumber = form.getNewAccessionNumber(); + + return !GenericValidator.isBlankOrNull(newAccessionNumber) + && !newAccessionNumber.equals(form.getAccessionNumber()); + + } + + private static class SampleEditItemComparator implements Comparator { + + @Override + public int compare(SampleEditItem o1, SampleEditItem o2) { + if (GenericValidator.isBlankOrNull(o1.getSortOrder()) + || GenericValidator.isBlankOrNull(o2.getSortOrder())) { + return o1.getTestName().compareTo(o2.getTestName()); + } + + try { + return Integer.parseInt(o1.getSortOrder()) - Integer.parseInt(o2.getSortOrder()); + } catch (NumberFormatException e) { + return o1.getTestName().compareTo(o2.getTestName()); + } + } + + } + +}