avniproject / avni-models Goto Github PK
View Code? Open in Web Editor NEWAvni data model to be used by front end clients
Home Page: https://avniproject.org
License: GNU Affero General Public License v3.0
Avni data model to be used by front end clients
Home Page: https://avniproject.org
License: GNU Affero General Public License v3.0
In "Lend a hand India" org, for "LAHI Intern" Subject, "Internship LAHI" Program, "LAHI INTERN ATTENDANCE" Program Encounter is to be created.
As part of the ProgramEncounter's Decision rule, we need to fetch "Date of Attendance" concept value from within the "Attendance Day" RepeatableQuestionGroup's groupObservations.
Attempting this results in failure, as following method fails to handle the array nature of "Attendance Day" RepeatableQuestionGroup :
const dateOfAttendance = programEncounter.findObservation("Date of Attendance","Attendance Day");
**ERROR: undefined is not an object (evaluating 't.concept.name')**
In avni-models, AbstractEncounter.js:
findObservation(conceptNameOrUuid, parentConceptNameOrUuid) {
const observations = _.isNil(parentConceptNameOrUuid) ? this.observations : this.findGroupedObservation(parentConceptNameOrUuid);
return _.find(observations, (observation) => {
return (observation.concept.name === conceptNameOrUuid) || (observation.concept.uuid === conceptNameOrUuid);
});
}
ERROR is at "(observation.concept.name === conceptNameOrUuid)".. observation.concept is undefined.
Instead, we should fetch the value from the first entry in RepeatableQuestionGroup as follows:
const groupedObservations = programEncounter.findGroupedObservation("Attendance Day");
const groupObservations = _.isEmpty(groupedObservations) ? [] : groupedObservations[0].groupObservations;
const dateOfAttendance = _.find(groupObservations, (observation) => {
return (observation.concept.name === "Date of Attendance");
});
Usecase:
Currently when I want to check when an individual is actively enrolled in a program(say Child program) in say, in report card query, I need to do the below:
enrolment.program.name === 'Child' && _.isNil(enrolment.programExitDateTime) && !enrolment.voided
Instead I would like to have a method, in models like below:
const isActive = (programName) => {
return this.program.name === programName && _.isNil(this.programExitDateTime) && !this.voided
}
Need:
As a part of this story we'll add new model classes in client for syncing dashboard and card metadata.
So In lahi we have requirement for dashboard Interested but not applied to get latest general encounter Program Eligibility and check Status is "Interested but not applied" or not. For that we are currently using individual.findLatestObservationFromEncounters() to get that but when there are two general encounter it is giving proper data.
For general encounter create one method to get observation from last completed encounter.
method should give observation form the last completed encounter.
Motivation :
In apf we have one location form which contains one field called Geographically hard to reach village. In ANC program encounter concept Pregnancy geographically high risk? depends that. So based on location property we have to change the value. So currently method like getObservationReadableValue is missing.
Problem :
Currently we manually doing below steps to get that value of location property in program encounter. So add method to get location concept value.
'use strict';
({params, imports}) => {
const programEncounter = params.entity;
const moment = imports.moment;
const formElement = params.formElement;
const _ = imports.lodash;
let visibility = true;
let value = 'No';
let answersToSkip = [];
let validationErrors = [];
const locationProperties = programEncounter.programEnrolment.individual.lowestAddressLevel.locationProperties;
if(locationProperties.length > 0){
const locationProperty = locationProperties.filter(prop=>prop.concept.name == 'Geographically hard to reach village');
if(locationProperty.length==1){
const valueJSON = locationProperty[0].valueJSON;
const answer = JSON.parse(valueJSON).answer;
if(answer=="8ebbf088-f292-483e-9084-7de919ce67b7"){
console.log('geographical high risk');
value = 'Yes'
}
}
}
return new imports.rulesConfig.FormElementStatus(formElement.uuid, visibility, value, answersToSkip, validationErrors);
};
The following snippet ideally should give some value only if there is a visit scheduled of the specified type which is not completed and cancelled. (and not consider the visit user is completing) But at any moment it gives 'hello>>>>', [ { that: {} } ] irrespective if there is already a visit scheduled or a scheduled visit is being completed of that type.
As an implementor we do not have any way to identify if the visit is already scheduled or not!
const hello = programEncounter.programEnrolment.scheduledEncountersOfType('Child followup');
console.log('hello>>>>', hello);
See attached sync log from the server. While other entity syncs take very little time, save of encounters progressively degrades pretty fast.
App version: 3.38.5
This is caused by higher number of encounters per subject. In this case, when number of encounters per subject goes to the 100s, save takes a lot of time.
Root cause is the slow implementation of BaseEntity.mergeOn()
method. This method takes m parents, looks at all their children and returns one parent with unique values of all their children in it. For m subjects with n encounters each, the merge has a loop that iterates m * n * n times. m is usually around 1-10 and n can go from 1 to 1000.
The purpose of the merge is to identify unique values in a list of m * n items. If we use hashmaps instead of doing a triple loop, this operation can be done with a complexity of O(m*n).
https://app.zenhub.com/files/64590403/5bb599a4-6a6c-4a55-80fc-257b65a9e7d3/download
In Jss Phulwari programs, "Child enrolment" form, ..
During EnrolmentId FormElement rule execution, we fail to fetch affiliatedGroups, resulting in "Enrolment ID" not being set.
const phulwariName = _.get(_.find(programEnrolment.individual.affiliatedGroups, ({voided}) => !voided), ['groupSubject', 'firstName'], '');
After ReactNative upgrade, we are not able to access temp property affiliatedGroups in Individual from enrolment during ProgramEnrolment Create / edit. This is due to the fact that, individual returned for enrolment.individual is the realmDb object, which is fetched fresh from db.
Therefore the rule fails to fetch affiliatedGroups on individual of an enrolment, and therefore "Enrolment ID" generation fails.
We cannot convert temp property affiliatedGroups to persistent value of individual, as the individual does not get saved duing enrolment form filling. Therefore the only solution is to switch to using Enrolment to store the temp property affiliatedGroups and modify the Rules suitably. This has already been tested to work in dev environment.
We do not like the approach of using temporary variables for storing the affiliatedGroups information. All such details should be passed to the ruleEvaluationService as part of the entityContext object.
Also, in the Subject/ Person summary view, pass the required affiliatedGroups separately from state during invocation and dont expect it to be a temp variable in Individual.
After the release, Support team would need to modify all rules that refer to "individual.affiliatedGroups" to instead use "params.entityContext.affiliatedGroups".
const phulwariName = _.get(_.find(programEnrolment.individual.affiliatedGroups, ({voided}) => !voided), ['groupSubject', 'firstName'], '');
const phulwariName = _.get(_.find(params.entityContext.affiliatedGroups, ({voided}) => !voided), ['groupSubject', 'firstName'], '');
##Support ticket
https://avni.freshdesk.com/a/tickets/2925
Case:
mapObservations
functions in both code bases. This I think has lead to duplication of code for mapping the observations.Need:
What can be done:
fromObs
methods in concept classes.Issue: For question group concepts, model functions doesn't execute as expected in message rule
Ticket: https://avni.freshdesk.com/a/tickets/2518 - workaround for this issue was done by using the model function in decision rule here
Steps to reproduce:
Expectation:
let dateTime = programEncounter.getObservationValue("Date of Attendance", "Attendance Day");
and
const groupedObservations = programEncounter.findGroupedObservation("Attendance Day");
const groupObservations = _.isEmpty(groupedObservations) ? [] : groupedObservations[0].groupObservations;
const dateOfAttendance = _.find(groupObservations, (observation) => {
return (observation.concept.name === "Date of Attendance");
});
in message rule should return date as expected.
Analysis:
Printing the observations in decision rule vs in message rule:
looks like observations when sent from server to rule-server to execute message rule is not handled for group observations but in client since the data is accessible it works in decision rule.
With the introduction of subject and location concept data types, there is need to update the model to allow for richer display of these data types on the clients.
Tech tasks:
Acceptance criteria:
All observations in Registration, Enrolment, Encounter, Program encounter should continue to be shown as before. Observations with concepts data type Subject will be linked to the particular subject.
Publish html documentation on https://avniproject.github.io/avni-models/
Issue:
getEncounters function in Individual.js and ProgramEnrolment.js has facility to consider cancelled encounters as well. But it is not considering cancelDateTime when sorting the encounters. Hence when need to get the latest(including cancelled encounters) another sorting as below need to be done in the report card query:
const encounters = enrolment.getEncounters(false);
const sortedEncounters = _.sortBy(encounters, (encounter) => {
return _.isNil(encounter.cancelDateTime)? moment().diff(encounter.encounterDateTime) :
moment().diff(encounter.cancelDateTime)});
const latestEncounter = _.head(sortedEncounters);
Significance of fixing this issue:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.