-
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 && (
+
+ }
+ onChange={programChange}
+ defaultValue={
+ programs.find((program) => {
+ return program.value === "Routine Testing";
+ })?.id
+ }
+ value={orderFormValues?.sampleOrderItems?.programId}
+ >
+
+ {programs.map((program) => {
+ return (
+
+ );
+ })}
+
+
+ )}
+
+ >
+ );
+};
+
+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 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());
+ }
+ }
+
+ }
+
+}