Skip to content

Commit

Permalink
O3-2252 Calculated values shouldn't be overwritten by the Encounter's…
Browse files Browse the repository at this point in the history
… values
  • Loading branch information
CynthiaKamau committed Jun 11, 2024
1 parent 34d7cfb commit 95d24a8
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 9 deletions.
51 changes: 51 additions & 0 deletions __mocks__/use-initial-values/encounter.mock.json
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,57 @@
}
],
"resourceVersion": "2.1"
},
{
"uuid": "30f1206c-4354-4deb-9cfa-bcb18e934144",
"obsDatetime": "2024-06-11T11:43:33.000+0000",
"comment": null,
"voided": false,
"groupMembers": null,
"formFieldNamespace": "rfe-forms",
"formFieldPath": "rfe-forms-height",
"concept": {
"uuid": "5090AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"name": {
"uuid": "d17c467f-e5c1-30dc-b916-e7d5f9a8935a",
"name": "Height (cm)"
}
},
"value": 176.0
},
{
"uuid": "037aaaca-14f1-460c-bc59-579817569794",
"obsDatetime": "2024-06-11T11:43:33.000+0000",
"comment": null,
"voided": false,
"groupMembers": null,
"formFieldNamespace": "rfe-forms",
"formFieldPath": "rfe-forms-weight",
"concept": {
"uuid": "5089AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"name": {
"uuid": "c1015fd1-729b-33c7-82e8-0b14a5a824ed",
"name": "Weight (kg)"
}
},
"value": 56.0
},
{
"uuid": "5c281bdc-3798-4d18-b780-34e177e2fdb4",
"obsDatetime": "2024-06-11T11:43:33.000+0000",
"comment": null,
"voided": false,
"groupMembers": null,
"formFieldNamespace": "rfe-forms",
"formFieldPath": "rfe-forms-bmi",
"concept": {
"uuid": "1342AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"name": {
"uuid": "1431BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
"name": "Body mass index"
}
},
"value": 0
}
],
"orders": [
Expand Down
1 change: 1 addition & 0 deletions src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export function getLatestObs(patientUuid: string, conceptUuid: string, encounter
let params = `patient=${patientUuid}&code=${conceptUuid}${
encounterTypeUuid ? `&encounter.type=${encounterTypeUuid}` : ''
}`;

// the latest obs
params += '&_sort=-date&_count=1';
return openmrsFetch(`${fhirBaseUrl}/Observation?${params}`).then(({ data }) => {
Expand Down
115 changes: 110 additions & 5 deletions src/hooks/useInitialValues.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { act, renderHook } from '@testing-library/react';
import { act, renderHook, screen } from '@testing-library/react';
import { useInitialValues } from './useInitialValues';
import type { FormField, OpenmrsEncounter } from '../types';
import testEncounter from '__mocks__/use-initial-values/encounter.mock.json';
import testPatient from '__mocks__/use-initial-values/patient.mock.json';
import { ObsSubmissionHandler } from '../submission-handlers/obsHandler';
import { TestOrderSubmissionHandler } from '../submission-handlers/testOrderHandler';
import { CommonExpressionHelpers } from 'src/utils/common-expression-helpers';

const obsGroupMembers: Array<FormField> = [
{
Expand Down Expand Up @@ -120,6 +121,7 @@ let allFormFields: Array<FormField> = [
questions: [obsGroupMembers[0], obsGroupMembers[1]],
validators: [],
},

...obsGroupMembers,
];

Expand All @@ -138,6 +140,50 @@ const location = {

const encounter = testEncounter as OpenmrsEncounter;

const calculateExpressionFields: Array<FormField> = [
{
label: 'Height (cm)',
type: 'obs',
required: false,
id: 'height',
questionOptions: {
rendering: 'number',
concept: '5090AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
answers: [],
},
},
{
label: 'Weight (Kgs)',
type: 'obs',
required: false,
id: 'weight',
questionOptions: {
rendering: 'number',
concept: '5089AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
answers: [],
},
validators: [],
},
{
label: 'BMI:Kg/M2 (Function calcBMI | useFieldValue)',
type: 'obs',
required: false,
id: 'bmi',
questionOptions: {
rendering: 'number',
defaultValue: 0,
concept: '1342AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
isTransient: true,
disallowDecimals: false,
calculate: {
calculateExpression: "calcBMI(useFieldValue('height'),useFieldValue('weight'))",
},
},
validators: [],
questionInfo: 'this calculates BMI using calcBMI function and useFieldValue of weight and height',
},
];

jest.mock('../utils/expression-runner', () => {
const originalModule = jest.requireActual('../utils/expression-runner');
return {
Expand Down Expand Up @@ -171,7 +217,7 @@ describe('useInitialValues', () => {
setEncounterProvider: jest.fn,
setEncounterLocation: jest.fn,
encounterRole: '',
setEncounterRole: jest.fn
setEncounterRole: jest.fn,
},
formFieldHandlers,
),
Expand Down Expand Up @@ -210,7 +256,7 @@ describe('useInitialValues', () => {
setEncounterProvider: jest.fn,
setEncounterLocation: jest.fn,
encounterRole: '',
setEncounterRole: jest.fn
setEncounterRole: jest.fn,
},
formFieldHandlers,
),
Expand Down Expand Up @@ -273,7 +319,7 @@ describe('useInitialValues', () => {
setEncounterProvider: jest.fn,
setEncounterLocation: jest.fn,
encounterRole: '',
setEncounterRole: jest.fn
setEncounterRole: jest.fn,
},
formFieldHandlers,
),
Expand Down Expand Up @@ -314,7 +360,7 @@ describe('useInitialValues', () => {
setEncounterProvider: jest.fn,
setEncounterLocation: jest.fn,
encounterRole: '8cb3a399-d18b-4b62-aefb-5a0f948a3809',
setEncounterRole: jest.fn
setEncounterRole: jest.fn,
},
formFieldHandlers,
),
Expand All @@ -333,4 +379,63 @@ describe('useInitialValues', () => {
expect(allFormFields.find((field) => field.id === 'testOrder_1')).not.toBeNull();
expect(allFormFields.find((field) => field.id === 'testOrder_2')).not.toBeNull();
});

it('should return calculated values for calculated fields in "edit" mode', async () => {
let hook = null;
const allFields = JSON.parse(JSON.stringify(calculateExpressionFields));
const allFieldsKeys = allFields.map((f) => f.id);
let valuesMap = {
height: '',
wight: '',
bmi: '',
};

const helper = new CommonExpressionHelpers(
{ value: allFields[1], type: 'field' },
{},
allFields,
valuesMap,
allFieldsKeys,
);
await act(async () => {
hook = renderHook(() =>
useInitialValues(
[...allFormFields],
encounter,
false,
{
encounter: encounter,
patient: testPatient,
location,
sessionMode: 'enter',
encounterDate: encounterDate,
setEncounterDate: jest.fn,
encounterProvider: '2c95f6f5-788e-4e73-9079-5626911231fa',
setEncounterProvider: jest.fn,
setEncounterLocation: jest.fn,
encounterRole: '',
setEncounterRole: jest.fn,
},
formFieldHandlers,
),
);
});
const {
current: { initialValues, isBindingComplete },
} = hook.result;
expect(isBindingComplete).toBe(true);

const weightQuestionConcept = calculateExpressionFields.find((field) => field.id === 'weight').questionOptions
.concept;
const heightQuestionConcept = calculateExpressionFields.find((field) => field.id === 'height').questionOptions
.concept;

const heightVal = encounter.obs.find((obs) => obs.concept.uuid === heightQuestionConcept).value;
const weightVal = encounter.obs.find((obs) => obs.concept.uuid === weightQuestionConcept).value;
const calculatedBmi = helper.calcBMI(heightVal, weightVal);

expect(heightVal).not.toBeNull();
expect(weightVal).not.toBeNull();
expect(calculatedBmi).not.toBeNull();
});
});
26 changes: 22 additions & 4 deletions src/hooks/useInitialValues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function useInitialValues(
'encounterDatetime',
'encounterLocation',
'patientIdentifier',
'encounterRole'
'encounterRole',
];

useEffect(() => {
Expand Down Expand Up @@ -64,6 +64,8 @@ export function useInitialValues(
return;
}
if (encounter) {
const tempAsyncValues = {};

formFields
.filter((field) => isEmpty(field.meta?.previousValue))
.filter((field) => field.questionOptions.rendering !== 'file')
Expand All @@ -77,10 +79,27 @@ export function useInitialValues(
formFields,
encounterContext,
);

if (field.questionOptions.calculate?.calculateExpression) {
tempAsyncValues[field.id] = evaluateAsyncExpression(
field.questionOptions.calculate.calculateExpression,
{ value: field, type: 'field' },
formFields,
initialValues,
{
mode: encounterContext.sessionMode,
patient: encounterContext.patient,
},
);
}
if (field.type === 'obsGroup') {
return;
}
if (isEmpty(existingVal) && !isEmpty(field.questionOptions.defaultValue)) {
if (
isEmpty(existingVal) &&
!isEmpty(field.questionOptions.defaultValue) &&
!field.questionOptions.calculate?.calculateExpression
) {
existingVal = inferInitialValueFromDefaultFieldValue(
field,
encounterContext,
Expand All @@ -100,8 +119,7 @@ export function useInitialValues(
);
formFields.push(...flattenedFields);
setIsEncounterBindingComplete(true);
// TODO: Address behaviour in edit mode; see: https://issues.openmrs.org/browse/O3-2252
setAsyncInitValues({});
setAsyncInitValues({ ...(asyncInitValues ?? {}), ...tempAsyncValues });
} else {
const tempAsyncValues = {};
formFields
Expand Down

0 comments on commit 95d24a8

Please sign in to comment.