diff --git a/packages/openchs-android/package-lock.json b/packages/openchs-android/package-lock.json index d96abb1ec..1132341fd 100644 --- a/packages/openchs-android/package-lock.json +++ b/packages/openchs-android/package-lock.json @@ -33,7 +33,7 @@ "lodash": "4.17.21", "moment": "2.29.4", "native-base": "3.4.9", - "openchs-models": "1.31.14", + "openchs-models": "1.31.16", "prop-types": "15.8.1", "react": "18.2.0", "react-native": "0.72.3", @@ -16433,9 +16433,9 @@ } }, "node_modules/openchs-models": { - "version": "1.31.14", - "resolved": "https://registry.npmjs.org/openchs-models/-/openchs-models-1.31.14.tgz", - "integrity": "sha512-y3ngUTqsvFJSH44/lQrQlAi2YUWXW2fKiacE5KSuKJV7NyOdd/WXUQu11JZW9y5o7MTWw4uuNSMh7NaDjRQcnA==", + "version": "1.31.16", + "resolved": "https://registry.npmjs.org/openchs-models/-/openchs-models-1.31.16.tgz", + "integrity": "sha512-OcgGFTYGgFhDPFcb+taZkMA1/p7TvGZCZk4vWcBAIyF8byba0PRrkY88EcRnqeWzIi3So3qYZohQoZlkIYMsPQ==", "dependencies": { "uuid": "^9.0.1" }, @@ -35159,9 +35159,9 @@ } }, "openchs-models": { - "version": "1.31.14", - "resolved": "https://registry.npmjs.org/openchs-models/-/openchs-models-1.31.14.tgz", - "integrity": "sha512-y3ngUTqsvFJSH44/lQrQlAi2YUWXW2fKiacE5KSuKJV7NyOdd/WXUQu11JZW9y5o7MTWw4uuNSMh7NaDjRQcnA==", + "version": "1.31.16", + "resolved": "https://registry.npmjs.org/openchs-models/-/openchs-models-1.31.16.tgz", + "integrity": "sha512-OcgGFTYGgFhDPFcb+taZkMA1/p7TvGZCZk4vWcBAIyF8byba0PRrkY88EcRnqeWzIi3So3qYZohQoZlkIYMsPQ==", "requires": { "uuid": "^9.0.1" } diff --git a/packages/openchs-android/src/action/program/ProgramEncounterCancelState.js b/packages/openchs-android/src/action/program/ProgramEncounterCancelState.js index 66bde03ec..e6b9ff5f2 100644 --- a/packages/openchs-android/src/action/program/ProgramEncounterCancelState.js +++ b/packages/openchs-android/src/action/program/ProgramEncounterCancelState.js @@ -62,7 +62,7 @@ class ProgramEncounterCancelState extends AbstractDataEntryState { } getNextScheduledVisits(ruleService, context) { - const nextScheduledVisits = ruleService.getNextScheduledVisits(this.getEntity(), this.getEntityType()); + const nextScheduledVisits = ruleService.getNextScheduledVisits(this.getEntity(), this.getEntityType()).filter((x) => !this.isAlreadyScheduled(this.programEncounter.programEnrolment, x)); return context.get(IndividualService).validateAndInjectOtherSubjectForScheduledVisit(this.getEntity().individual, nextScheduledVisits); } diff --git a/packages/openchs-android/src/state/AbstractDataEntryState.js b/packages/openchs-android/src/state/AbstractDataEntryState.js index 183f05e04..85cccd08e 100644 --- a/packages/openchs-android/src/state/AbstractDataEntryState.js +++ b/packages/openchs-android/src/state/AbstractDataEntryState.js @@ -350,6 +350,15 @@ class AbstractDataEntryState { getEntityResultSetByType(context) { return [] } + + isAlreadyScheduled(programEnrolment, newlyScheduledEncounter) { + //paranoid code + if (_.isNil(programEnrolment) || _.isNil(programEnrolment.everScheduledEncountersOfType)) return false; + + return _.some(programEnrolment.everScheduledEncountersOfType(newlyScheduledEncounter.encounterType), (alreadyScheduledEncounter) => { + return General.datesAreSame(newlyScheduledEncounter.earliestDate, alreadyScheduledEncounter.earliestVisitDateTime) && General.datesAreSame(newlyScheduledEncounter.maxDate, alreadyScheduledEncounter.maxVisitDateTime) && newlyScheduledEncounter.name === alreadyScheduledEncounter.name; + }); + } } export default AbstractDataEntryState; diff --git a/packages/openchs-android/src/state/ProgramEncounterState.js b/packages/openchs-android/src/state/ProgramEncounterState.js index 83f145cdc..71c785350 100644 --- a/packages/openchs-android/src/state/ProgramEncounterState.js +++ b/packages/openchs-android/src/state/ProgramEncounterState.js @@ -1,17 +1,13 @@ import AbstractDataEntryState from "./AbstractDataEntryState"; import Wizard from "./Wizard"; -import { - AbstractEncounter, - ObservationsHolder, - ProgramEncounter, - StaticFormElementGroup -} from "avni-models"; +import {AbstractEncounter, ObservationsHolder, ProgramEncounter, StaticFormElementGroup} from "avni-models"; import ConceptService from "../service/ConceptService"; import _ from 'lodash'; import IndividualService from "../service/IndividualService"; import EntityService from "../service/EntityService"; import ObservationHolderActions from "../action/common/ObservationsHolderActions"; import TimerState from "./TimerState"; +import General from "../utility/General"; class ProgramEncounterState extends AbstractDataEntryState { constructor(formElementGroup, wizard, isNewEntity, programEncounter, filteredFormElements, workLists, messageDisplayed, timerState, isFirstFlow) { @@ -109,6 +105,7 @@ class ProgramEncounterState extends AbstractDataEntryState { getNextScheduledVisits(ruleService, context) { const nextScheduledVisits = ruleService.getNextScheduledVisits(this.programEncounter, ProgramEncounter.schema.name, []) + .filter((x) => !this.isAlreadyScheduled(this.programEncounter.programEnrolment, x)) .map(k => _.assignIn({}, k)); return context.get(IndividualService).validateAndInjectOtherSubjectForScheduledVisit(this.programEncounter.individual, nextScheduledVisits); } diff --git a/packages/openchs-android/src/state/ProgramEnrolmentState.js b/packages/openchs-android/src/state/ProgramEnrolmentState.js index cb8ad1a90..6e1e599f1 100644 --- a/packages/openchs-android/src/state/ProgramEnrolmentState.js +++ b/packages/openchs-android/src/state/ProgramEnrolmentState.js @@ -132,12 +132,12 @@ class ProgramEnrolmentState extends AbstractDataEntryState { getNextScheduledVisits(ruleService, context) { if (this.usage === ProgramEnrolmentState.UsageKeys.Enrol) { - const nextScheduledVisits = ruleService.getNextScheduledVisits(this.enrolment, ProgramEnrolment.schema.name, []); + const nextScheduledVisits = ruleService.getNextScheduledVisits(this.enrolment, ProgramEnrolment.schema.name, []) + .filter((x) => !this.isAlreadyScheduled(this.enrolment, x)); return context.get(IndividualService).validateAndInjectOtherSubjectForScheduledVisit(this.enrolment.individual, nextScheduledVisits); } else { return null; } - } static isInitialised(programEnrolmentState) { diff --git a/packages/openchs-android/src/utility/General.js b/packages/openchs-android/src/utility/General.js index 87a80b189..088886a4a 100644 --- a/packages/openchs-android/src/utility/General.js +++ b/packages/openchs-android/src/utility/General.js @@ -201,8 +201,14 @@ class General { return new Date(date.getFullYear(), date.getMonth(), date.getDate()); } + static toISTDate(x) { + if (x.toString().includes("18:30:00")) + return moment(x).add(330, "m").toDate(); + return x; + } + static datesAreSame(a, b) { - return moment(a).isSame(moment(b), 'day'); + return moment(General.toISTDate(a)).isSame(moment(General.toISTDate(b)), 'day'); } static dateAIsAfterB(a, b) { diff --git a/packages/openchs-android/src/views/settings/DevSettingsView.js b/packages/openchs-android/src/views/settings/DevSettingsView.js index 15e39b25b..2bedc8b85 100644 --- a/packages/openchs-android/src/views/settings/DevSettingsView.js +++ b/packages/openchs-android/src/views/settings/DevSettingsView.js @@ -18,6 +18,7 @@ import RuleEvaluationService from "../../service/RuleEvaluationService"; import {Rule} from 'openchs-models'; import SelectableItemGroup from "../primitives/SelectableItemGroup"; import UserInfoService from "../../service/UserInfoService"; +import moment from "moment"; @Path('/devSettingsView') class DevSettingsView extends AbstractComponent { @@ -93,6 +94,10 @@ class DevSettingsView extends AbstractComponent { Server URL: this.dispatchAction(Actions.ON_SERVER_URL_CHANGE, {value: text})}/> + + Current App Time: + {moment().format("DD MMM YYYY hh:mm a")} + ); } }