Closed nupoorkhandelwal closed 11 months ago
"use strict";
({params, imports}) => {
const programEncounter = params.entity;
const scheduleBuilder = new imports.rulesConfig.VisitScheduleBuilder({
programEncounter
});
const hasExitedProgram = programEncounter => programEncounter.programEnrolment.programExitDateTime;
const cancelReason = programEncounter.findCancelEncounterObservation('Visit cancel reason').getReadableValue();
if (!hasExitedProgram(programEncounter)) {
if (programEncounter.encounterType.name == 'ANC Clinic Visit' && cancelReason != 'Delivery/Abortion') {
const nextANCDate = programEncounter.findCancelEncounterObservation('Date of next ANC Visit').getReadableValue();
// const edd = programEncounter.programEnrolment.hasObservation('EDD') ? programEncounter.programEnrolment.getObservationValue('EDD') : //imports.moment().toDate();
const edd = programEncounter.programEnrolment.getObservationValue('EDD');
const visitDate = programEncounter.earliestVisitDateTime || programEncounter.encounterDateTime;
if (imports.moment(edd).isSameOrBefore(imports.moment(nextANCDate), 'date')) {
if ((programEncounter.programEnrolment.hasEncounter('Delivery', 'Delivery')) === false)
scheduleBuilder
.add({
name: "Delivery",
encounterType: "Delivery",
earliestDate: imports.moment(edd).toDate(),
maxDate: imports.moment(edd).add(0, 'days').toDate()
});
} else {
scheduleBuilder
.add({
name: "ANC Clinic Visit",
encounterType: "ANC Clinic Visit",
earliestDate: imports.moment(nextANCDate).toDate(),
maxDate: imports.moment(nextANCDate).add(8, 'days').toDate()
}).whenItem(!_.isEmpty(nextANCDate))
.is.not.truthy;
if (!_.isEqual(programEncounter.individual.lowestAddressLevel.name, 'Non programme village')) {
scheduleBuilder
.add({
name: "ANC Home Visit",
encounterType: "ANC Home Visit",
earliestDate: imports.moment(visitDate).add(1, 'days').toDate(),
maxDate: imports.moment(visitDate).add(8, 'days').toDate()
}).whenItem(!_.isEmpty(visitDate))
.is.not.truthy;
}
}
}
// if (programEncounter.encounterType.name == 'ANC Home Visit' && cancelReason != 'Delivery/Abortion') {
// const nextANCDate = programEncounter.findCancelEncounterObservation('Date of next ANC Visit').getReadableValue();
// const edd = programEncounter.programEnrolment.getObservationValue('EDD');
// if (imports.moment(edd).isSameOrBefore(imports.moment(nextANCDate), 'date')) {
// if ((programEncounter.programEnrolment.hasEncounter('Delivery', 'Delivery')) === false)
// scheduleBuilder
// .add({
// name: "Delivery",
// encounterType: "Delivery",
// earliestDate: imports.moment(edd).toDate(),
// maxDate: imports.moment(edd).add(0, 'days').toDate()
// });
// } else if (!_.isEqual(programEncounter.individual.lowestAddressLevel.name, 'Non programme village')) {
// scheduleBuilder
// .add({
// name: "ANC Home Visit",
// encounterType: "ANC Home Visit",
// earliestDate: imports.moment(nextANCDate).toDate(),
// maxDate: imports.moment(nextANCDate).add(8, 'days').toDate()
// }).whenItem(!_.isEmpty(nextANCDate))
// .is.not.truthy;
// }
// }
if (programEncounter.encounterType.name == 'Abortion followup') {
const visitDate = programEncounter.encounterDateTime || programEncounter.earliestVisitDateTime;
const dateOfAbortion = programEncounter.programEnrolment
.getObservationReadableValueInEntireEnrolment('Date and time of abortion');
const encounterScheduleAbortion = [
{"name": "Abortion followup-2", "earliest": 7, "max": 11},
{"name": "Abortion followup-3", "earliest": 15, "max": 19}
];
var schedule = _.chain(encounterScheduleAbortion).filter(e => imports.moment(visitDate).isSameOrBefore(imports.moment(dateOfAbortion).add(e.earliest, 'days'), 'date') === true).filter(e => (programEncounter.programEnrolment.hasEncounter('Abortion followup', e.name)) === false).first().value();
if (!_.isEmpty(schedule)) {
scheduleBuilder
.add({
name: schedule.name,
encounterType: "Abortion followup",
earliestDate: imports.moment(dateOfAbortion).add(schedule.earliest, 'days').toDate(),
maxDate: imports.moment(dateOfAbortion).add(schedule.max, 'days').toDate()
});
}
}
if (programEncounter.encounterType.name == 'Mother PNC') {
const visitDate = programEncounter.encounterDateTime || programEncounter.earliestVisitDateTime;
const dateOfDelivery = programEncounter.programEnrolment
.getObservationReadableValueInEntireEnrolment('Date and time when baby was out');
const encounterSchedulePNC = [
{"name": "PNC 2", "earliest": 1, "max": 4},
{"name": "PNC 3", "earliest": 2, "max": 5},
{"name": "PNC 4", "earliest": 6, "max": 9},
{"name": "PNC 5", "earliest": 14, "max": 17},
{"name": "PNC 6", "earliest": 28, "max": 31},
{"name": "PNC 7", "earliest": 41, "max": 44}
];
var schedule = _.chain(encounterSchedulePNC).filter(e => imports.moment(visitDate).isSameOrBefore(imports.moment(dateOfDelivery).add(e.earliest, 'days'), 'date') === true).filter(e => (programEncounter.programEnrolment.hasEncounter('Mother PNC', e.name)) === false).first().value();
if (!_.isEmpty(schedule)) {
scheduleBuilder
.add({
name: schedule.name,
encounterType: "Mother PNC",
earliestDate: imports.moment(dateOfDelivery).add(schedule.earliest, 'days').toDate(),
maxDate: imports.moment(dateOfDelivery).add(schedule.max, 'days').toDate()
});
}
}
if (programEncounter.encounterType.name == 'Child PNC') {
const visitDate = programEncounter.encounterDateTime || programEncounter.earliestVisitDateTime;
const dateOfBirth = programEncounter.individual.dateOfBirth;
const encounterSchedulePNC = [
{"name": "PNC 2", "earliest": 1, "max": 4},
{"name": "PNC 3", "earliest": 2, "max": 5},
{"name": "PNC 4", "earliest": 6, "max": 9},
{"name": "PNC 5", "earliest": 14, "max": 17},
{"name": "PNC 6", "earliest": 28, "max": 31},
{"name": "PNC 7", "earliest": 41, "max": 44}
];
var schedule = _.chain(encounterSchedulePNC).filter(e => imports.moment(visitDate).isSameOrBefore(imports.moment(dateOfBirth).add(e.earliest, 'days'), 'date') === true).filter(e => (programEncounter.programEnrolment.hasEncounter('Child PNC', e.name)) === false).first().value();
if (!_.isEmpty(schedule)) {
scheduleBuilder
.add({
name: schedule.name,
encounterType: "Child PNC",
earliestDate: imports.moment(dateOfBirth).add(schedule.earliest, 'days').toDate(),
maxDate: imports.moment(dateOfBirth).add(schedule.max, 'days').toDate()
});
}
}
if (programEncounter.encounterType.name == 'Referral Status') {
const visitDate = programEncounter.encounterDateTime || programEncounter.earliestVisitDateTime;
const followupDate = imports.moment(visitDate).add(4, 'days').toDate();
scheduleBuilder
.add({
name: "Referral Status-2",
encounterType: "Referral Status",
earliestDate: followupDate,
maxDate: imports.moment(followupDate).add(2, 'days').toDate()
}).whenItem(programEncounter.name == 'Referral Status-1')
.is.truthy;
}
}
const startOfNextMonth = (date) => {
return imports.moment(date).startOf('month').add(1, 'months').startOf('day').toDate();
};
const FEB = 1;
const AUG = 7;
class albendazole {
static findSlot(anyDate) {
anyDate = imports.moment(anyDate).startOf('day').toDate();
if (imports.moment(anyDate).month() < FEB) {
return imports.moment(anyDate).startOf('month').month(FEB).toDate();
}
if (imports.moment(anyDate).month() === FEB) {
return anyDate;
}
if (imports.moment(anyDate).month() < AUG) {
return imports.moment(anyDate).startOf('month').month(AUG).toDate();
}
if (imports.moment(anyDate).month() === AUG) {
return anyDate;
}
return imports.moment(anyDate).add(1, 'year').month(FEB).startOf('month').toDate();
}
static getVisitSchedule(_earliestDate) {
let earliestDate = imports.moment(_earliestDate).startOf('day').toDate();
let maxDate = imports.moment(earliestDate).endOf('month').toDate();
if (imports.moment(_earliestDate).month() === FEB) {
return {
name: 'Albendazole FEB',
encounterType: 'Albendazole',
earliestDate, maxDate,
}
}
return {
name: 'Albendazole AUG',
encounterType: 'Albendazole',
earliestDate, maxDate,
}
}
//it should simply be
//return albendazole.findSlot(moment(currentVisitScheduledDate).add(6, 'months').startOf('month').toDate())
//but need to test all scenarios
static findNextSlot(currentVisitScheduledDate) {
let guessedDate = startOfNextMonth(currentVisitScheduledDate);
return albendazole.findSlot(guessedDate);
}
}
class gmp {
static scheduleNext(scheduledDateTime, dayOfMonth) {
const earliestDate = imports.moment(scheduledDateTime).add(1, 'M').date(dayOfMonth).toDate();
const maxDate = imports.moment(earliestDate).add(3, 'days').toDate();
return {
name: "Growth Monitoring Visit",
encounterType: "Growth Monitoring",
earliestDate: earliestDate,
maxDate: maxDate
};
}
static scheduleOn(date) {
return {
name: "Growth Monitoring Visit",
encounterType: "Growth Monitoring",
earliestDate: date,
maxDate: date
};
}
static scheduleOnCancel(scheduledDateTime, dayOfMonth) {
const scheduleOnSameMonth = imports.moment(scheduledDateTime).date() < dayOfMonth;
const earliestDate = imports.moment(scheduledDateTime)
.add(scheduleOnSameMonth ? 0 : 1, 'M').date(dayOfMonth).toDate();
const maxDate = imports.moment(earliestDate).add(3, 'days').toDate();
return {
name: "Growth Monitoring Visit",
encounterType: "Growth Monitoring",
earliestDate: earliestDate,
maxDate: maxDate
}
}
}
if (programEncounter.encounterType.name == 'Growth Monitoring') {
const _ = imports.lodash;
if (programEncounter.programEnrolment.isActive) {
const myGroups = programEncounter.programEnrolment.individual.groups;
const groupSubject = _.get(_.find(myGroups, g => !g.voided && g.groupSubject.subjectType.name === 'Phulwari'), 'groupSubject');
if(!_.isNil(groupSubject)){
const dayOfMonth = groupSubject.getObservationReadableValue("Day of month for growth monitoring visit");
const year = imports.moment(programEncounter.earliestVisitDateTime).format("YYYY");
if (year != 2019) {
scheduleBuilder.add(gmp.scheduleOnCancel(programEncounter.earliestVisitDateTime, dayOfMonth));
}
}
}
}
if (programEncounter.encounterType.name == 'Albendazole') {
if (programEncounter.programEnrolment.isActive) {
scheduleBuilder.add(albendazole.getVisitSchedule(albendazole
.findNextSlot(programEncounter.earliestVisitDateTime)));
}
}
return scheduleBuilder.getAll();
};
set role jsscp;
-- to check rule failure
select *
from rule_failure_telemetry where is_closed = false
and error_message = '174:5:invalid statement encountered.'
;
-- close the failure rule
update rule_failure_telemetry
set is_closed = true,
last_modified_date_time = now(),
close_date_time = now(),
last_modified_by_id = (select id
from public.users where username = 'vedantr@jsscp')
where is_closed = false and error_message = '174:5:invalid statement encountered.'
-- rules which uses class keyword
select *
from form where visit_schedule_rule ilike '%class%' or decision_rule ilike '%class%' or validation_rule ilike '%class%';
@nupoorkhandelwal closed rule_failure_telemetry. moved it to prod.
--------------------------------
set role jsscp;
select *
from rule_failure_telemetry where is_closed = false
and ( error_message = 'Cannot read property ''chain'' of undefined' or error_message = 'Cannot read property ''isEmpty'' of undefined')
and rule_uuid = '8ffd8274-ca88-449f-857d-9638b7db792f'
;
update rule_failure_telemetry
set is_closed = true,
last_modified_date_time = now(),
close_date_time = now(),
last_modified_by_id = (select id
from public.users where username = 'vedantr@jsscp')
where is_closed = false
and ( error_message = 'Cannot read property ''chain'' of undefined' or error_message = 'Cannot read property ''isEmpty'' of undefined')
and rule_uuid = '8ffd8274-ca88-449f-857d-9638b7db792f';
@nupoorkhandelwal
resolved and closed error Cannot read property 'chain' of undefined and Cannot read property 'isEmpty' of undefined for rule_uuid '8ffd8274-ca88-449f-857d-9638b7db792f'.
moved changes to prod.
Context
Support ticket - https://avni.freshdesk.com/a/tickets/3147
On program encounter cancellation visits are not getting properly generated and corresponding rule is failing with error message -174:5:invalid statement encountered.'
Recently in the product javascript engine was changed from jsc to hermes, and one of the quirks of hermes is that it does not support the use of "class" within an eval statement.
Acceptance Criteria
Tech approach