helper-functions

Avni JavaScript Methods Reference Guide

Last Updated: September 29, 2025
Purpose: Complete structured reference for all Avni JavaScript rule methods
Audience: Rule developers, implementers, and technical teams


Observation Access Methods

getObservationReadableValue(conceptNameOrUuid, parentConceptNameOrUuid)

Available on: Individual, ProgramEnrolment, AbstractEncounter (Encounter, ProgramEncounter)

Purpose: Gets the human-readable/display value of an observation, automatically formatting based on concept type.

Parameters:

  • conceptNameOrUuid (String): Name or UUID of the concept to find
  • parentConceptNameOrUuid (String, optional): Parent concept for grouped observations

Returns: String, Number, Date, Array, or undefined - The readable representation of the observation value

Examples:

// Basic usage on different entities
const treatmentDate = programEnrolment.getObservationReadableValue("Treatment Start date");
const childWeight = programEncounter.getObservationReadableValue('Weight of Child');
const mobileNumber = individual.getObservationReadableValue('Mobile Number');

// For coded concepts - returns answer names instead of UUIDs
const status = individual.getObservationReadableValue('Treatment Status'); 
// Returns: "Completed" instead of "uuid-12345"

// With grouped observations
const systolic = encounter.getObservationReadableValue('Systolic', 'Blood Pressure');

// Null-safe usage with fallback
const value = individual.getObservationReadableValue('Optional Field') || 'Not specified';

// Date formatting example
const dueDate = programEnrolment.getObservationReadableValue("Expected Date of Delivery");
// Returns: "15/03/2024" (formatted date) instead of Date object

getObservationValue(conceptNameOrUuid, parentConceptNameOrUuid)

Available on: Individual, ProgramEnrolment, AbstractEncounter (Encounter, ProgramEncounter)

Purpose: Gets the raw value of an observation without formatting.

Parameters:

  • conceptNameOrUuid (String): Name or UUID of the concept to find
  • parentConceptNameOrUuid (String, optional): Parent concept for grouped observations

Returns: Raw value (String, Number, Date, Array, concept UUID for coded) or undefined

Examples:

// Get raw values for calculations
const weight = programEncounter.getObservationValue("Weight");
const height = individual.getObservationValue("Height in cm");

// For coded concepts - returns concept UUIDs
const genderUUID = individual.getObservationValue("Gender");
// Returns: "uuid-male-concept" instead of "Male"

// Use in mathematical calculations
if (height && weight) {
    const bmi = weight / ((height / 100) * (height / 100));
}

// Date comparisons with raw dates
const dueDate = programEnrolment.getObservationValue("Expected Date of Delivery");
if (dueDate && moment().isAfter(dueDate)) {
    // Pregnancy is overdue
}

// Multi-select coded values return arrays of UUIDs
const symptoms = encounter.getObservationValue("Symptoms");
// Returns: ["fever-uuid", "cough-uuid", "headache-uuid"]

findObservation(conceptNameOrUuid, parentConceptNameOrUuid)

Available on: Individual, AbstractEncounter (Encounter, ProgramEncounter)

Purpose: Finds and returns the observation object itself, allowing access to all observation properties and methods.

Parameters:

  • conceptNameOrUuid (String): Name or UUID of the concept to find
  • parentConceptNameOrUuid (String, optional): Parent concept for grouped observations

Returns: Observation object or undefined

Examples:

// Find observation object
const mobileObs = individual.findObservation('Mobile Number');
const weightObs = encounter.findObservation('Weight');

// Check existence and access properties
if (mobileObs) {
    const value = mobileObs.getValue();
    const readableValue = mobileObs.getReadableValue();
    const isAbnormal = mobileObs.isAbnormal();
}

// Using with concept UUIDs
const obs = individual.findObservation('a1b2c3d4-e5f6-7890-abcd-ef1234567890');

// Grouped observations
const systolicObs = encounter.findObservation('Systolic', 'Blood Pressure Group');

// Chain operations
const weight = encounter.findObservation('Weight')?.getValue() || 0;

findLatestObservationInEntireEnrolment(conceptNameOrUuid, currentEncounter)

Available on: ProgramEnrolment, ProgramEncounter

Purpose: Finds the most recent observation for a concept across the entire program enrolment lifecycle, including all encounters.

Parameters:

  • conceptNameOrUuid (String): Name or UUID of the concept to find
  • currentEncounter (ProgramEncounter, optional): Current encounter to exclude from search

Returns: Observation object or undefined

Examples:

// Track treatment progression
const latestPhase = programEnrolment.findLatestObservationInEntireEnrolment("Treatment phase type");
if (latestPhase) {
    const currentPhase = latestPhase.getReadableValue();
}

// Monitor compliance over time
const compliance = programEnrolment.findLatestObservationInEntireEnrolment("Compliance of previous month");

// Compare with previous values (excluding current encounter)
const previousWeight = programEncounter.findLatestObservationInEntireEnrolment("Weight", programEncounter);
const currentWeight = programEncounter.getObservationValue("Weight");
if (previousWeight && currentWeight) {
    const weightChange = currentWeight - previousWeight.getValue();
}

// Historical data for decision making
const lastTestResult = programEnrolment.findLatestObservationInEntireEnrolment("Lab Test Result");
const daysSinceTest = lastTestResult ? 
    moment().diff(lastTestResult.encounterDateTime, 'days') : null;

hasObservation(conceptNameOrUuid)

Available on: AbstractEncounter (Encounter, ProgramEncounter), ProgramEnrolment

Purpose: Checks if an observation exists for the given concept without retrieving the value.

Parameters:

  • conceptNameOrUuid (String): Name or UUID of the concept to check

Returns: Boolean

Examples:

// Conditional logic based on data availability
if (programEnrolment.hasObservation("Comorbidity")) {
    const comorbidity = programEnrolment.getObservationReadableValue("Comorbidity");
    // Process comorbidity data
}

// Form completion validation
if (!encounter.hasObservation("Blood Pressure")) {
    validationErrors.push("Blood pressure measurement is required");
}

// Check multiple required fields
const requiredFields = ['Weight', 'Height', 'Temperature'];
const missingFields = requiredFields.filter(field => !encounter.hasObservation(field));
if (missingFields.length > 0) {
    return `Missing required fields: ${missingFields.join(', ')}`;
}

Age and Time Calculation Methods

getAgeInYears(asOnDate, precise)

Available on: Individual

Purpose: Calculates age in years from the individual's date of birth.

Parameters:

  • asOnDate (Date, optional): Date to calculate age as of (defaults to current date)
  • precise (Boolean, optional): Whether to use precise calculation (defaults to false)

Returns: Number (age in years)

Examples:

// Basic usage - current age
const currentAge = individual.getAgeInYears();

// Age at specific date (enrollment, encounter, etc.)
const ageAtEnrolment = individual.getAgeInYears(programEnrolment.enrolmentDateTime);
const ageAtEncounter = individual.getAgeInYears(encounter.encounterDateTime);

// Eligibility rules
return individual.isFemale() && individual.getAgeInYears() >= 15 && individual.getAgeInYears() <= 49;

// Age-based protocols
if (individual.getAgeInYears() < 18) {
    // Pediatric protocols
    return "Pediatric dosage required";
} else if (individual.getAgeInYears() >= 65) {
    // Geriatric considerations
    return "Monitor for age-related complications";
}

// Precise calculation when needed
const preciseAge = individual.getAgeInYears(moment(), true);

// Validation
if (individual.getAgeInYears() > 120) {
    return ValidationResult.failure("age", "Age seems unrealistic");
}

getAgeInMonths(asOnDate, precise)

Available on: Individual

Purpose: Calculates age in months from the individual's date of birth, particularly useful for pediatric care.

Parameters:

  • asOnDate (Date, optional): Date to calculate age as of (defaults to current date)
  • precise (Boolean, optional): Whether to use precise calculation (defaults to false)

Returns: Number (age in months)

Examples:

// Basic usage for infants and children
const ageInMonths = individual.getAgeInMonths();

// Pediatric age categories
if (individual.getAgeInMonths() < 6) {
    return "Newborn (0-6 months)";
} else if (individual.getAgeInMonths() < 12) {
    return "Infant (6-12 months)";
} else if (individual.getAgeInMonths() < 24) {
    return "Toddler (12-24 months)";
}

// Immunization scheduling
const currentMonths = individual.getAgeInMonths();
if (currentMonths >= 9 && currentMonths <= 11) {
    return "9-11 month vaccinations due";
}

// Growth monitoring protocols
if (individual.getAgeInMonths() < 24) {
    return "Monthly weight monitoring required";
} else if (individual.getAgeInMonths() < 60) {
    return "Quarterly growth assessment";
}

// Nutritional guidelines
const months = individual.getAgeInMonths();
if (months >= 6 && months < 24) {
    return "Complementary feeding period";
}

getAgeInWeeks(asOnDate, precise)

Available on: Individual

Purpose: Calculates age in weeks from the individual's date of birth, useful for newborn care.

Parameters:

  • asOnDate (Date, optional): Date to calculate age as of (defaults to current date)
  • precise (Boolean, optional): Whether to use precise calculation (defaults to false)

Returns: Number (age in weeks)

Examples:

// Newborn care protocols
const ageInWeeks = individual.getAgeInWeeks();

if (ageInWeeks < 2) {
    return "First 2 weeks - daily monitoring required";
} else if (ageInWeeks <= 6) {
    return "6-week pediatric checkup due";
}

// Early immunization schedule
if (ageInWeeks >= 6) {
    return "6-week vaccinations (DPT, OPV, Hepatitis B) due";
} else if (ageInWeeks >= 10) {
    return "10-week vaccinations due";
}

// Breastfeeding support
if (ageInWeeks < 26) { // Less than 6 months
    return "Exclusive breastfeeding recommended";
}

getAge(asOnDate)

Available on: Individual

Purpose: Returns age as a Duration object with appropriate units, providing smart formatting.

Parameters:

  • asOnDate (Date, optional): Date to calculate age as of (defaults to current date)

Returns: Duration object with smart unit selection

Examples:

// Smart age display
const ageDuration = individual.getAge();
console.log(ageDuration.toString()); // "25 years" or "8 months" or "3 weeks"

// Use in summary strings
const summary = `${individual.name}, Age: ${individual.getAge().toString()}, ${individual.gender.name}`;

// Duration object automatically chooses appropriate units:
// - Years if age > 1 year
// - Months if age < 1 year but > 0 months  
// - Zero years if age < 1 month

// Access duration properties
const age = individual.getAge();
if (age.isInYears()) {
    // Handle adult protocols
} else if (age.isInMonths()) {
    // Handle infant protocols
}

Cancel Encounter Methods

findCancelEncounterObservation(conceptNameOrUuid)

Available on: AbstractEncounter (Encounter, ProgramEncounter)

Purpose: Finds observation from cancelled encounter data.

Parameters:

  • conceptNameOrUuid (String): Name or UUID of the concept to find

Returns: Observation object or undefined

Examples:

// Find cancellation reason
const cancelReason = encounter.findCancelEncounterObservation('Cancellation reason');
if (cancelReason) {
    const reason = cancelReason.getReadableValue();
}

// Find next steps from cancelled encounter
const nextStep = programEncounter.findCancelEncounterObservation('Select next step');

// Rescheduling logic based on cancellation data
const cancelObs = encounter.findCancelEncounterObservation('Cancel reason UUID');
if (cancelObs) {
    const value = cancelObs.getValue();
    if (value === 'patient-not-available-uuid') {
        // Schedule follow-up
    }
}

// Analyze cancellation patterns
const cancelDate = encounter.findCancelEncounterObservation('Cancel date');
const cancelReason = encounter.findCancelEncounterObservation('Cancel reason');

findCancelEncounterObservationReadableValue(conceptNameOrUuid)

Available on: AbstractEncounter (Encounter, ProgramEncounter)

Purpose: Gets the readable value from cancelled encounter observation.

Parameters:

  • conceptNameOrUuid (String): Name or UUID of the concept to find

Returns: String (readable value) or undefined

Examples:

// Get readable cancellation information
const nextStep = programEncounter.findCancelEncounterObservationReadableValue("Select next step");
const cancelReason = encounter.findCancelEncounterObservationReadableValue('Why was visit cancelled?');

// Conditional rescheduling logic
if (cancelReason === 'Patient not available') {
    return {
        name: "Follow-up Visit",
        earliestDate: moment().add(3, 'days').toDate(),
        maxDate: moment().add(7, 'days').toDate()
    };
} else if (cancelReason === 'Medical emergency') {
    return {
        name: "Emergency Follow-up",
        earliestDate: moment().add(1, 'day').toDate(),
        maxDate: moment().add(2, 'days').toDate()
    };
}

// Display cancelled visit summary
const cancelDetails = {
    reason: encounter.findCancelEncounterObservationReadableValue('Cancel reason'),
    nextAction: encounter.findCancelEncounterObservationReadableValue('Next action'),
    rescheduled: encounter.findCancelEncounterObservationReadableValue('Rescheduled for')
};

Encounter Navigation Methods

getEncounters(removeCancelledEncounters)

Available on: Individual, ProgramEnrolment

Purpose: Retrieves encounters sorted by date (most recent first), with option to exclude cancelled encounters.

Parameters:

  • removeCancelledEncounters (Boolean):
    • true - Return only completed encounters
    • false - Return all encounters including cancelled ones

Returns: Array of Encounter/ProgramEncounter objects sorted by encounter date (descending)

Examples:

// Get completed encounters only
const completedEncounters = individual.getEncounters(true);
const completedProgramEncounters = programEnrolment.getEncounters(true);

// Get all encounters including cancelled
const allEncounters = individual.getEncounters(false);

// Find most recent encounter
const latestEncounter = individual.getEncounters(true)[0];

// Filter by encounter type
const ancEncounters = individual.getEncounters(true)
    .filter(enc => enc.encounterType.name === 'ANC');

// Count encounters
const visitCount = programEnrolment.getEncounters(true).length;

// Find encounters in date range
const recentEncounters = individual.getEncounters(true)
    .filter(enc => moment(enc.encounterDateTime).isAfter(moment().subtract(30, 'days')));

// Check if any encounters exist
if (individual.getEncounters(true).length === 0) {
    return "No completed visits found";
}

findLatestObservationFromEncounters(conceptNameOrUuid, currentEncounter)

Available on: Individual

Purpose: Finds the latest observation for a concept from all individual encounters (across all programs).

Parameters:

  • conceptNameOrUuid (String): Name or UUID of the concept to find
  • currentEncounter (Encounter, optional): Current encounter to exclude from search

Returns: Observation object or undefined

Examples:

// Find latest vital signs across all visits
const latestBP = individual.findLatestObservationFromEncounters('Blood Pressure');
const latestWeight = individual.findLatestObservationFromEncounters('Weight');

// Exclude current encounter from search
const previousWeight = individual.findLatestObservationFromEncounters('Weight', currentEncounter);
const currentWeight = currentEncounter.getObservationValue('Weight');

if (previousWeight && currentWeight) {
    const weightChange = currentWeight - previousWeight.getValue();
    if (weightChange > 5) {
        return "Significant weight gain since last visit";
    }
}

// Cross-program data access
const techStatus = individual.findLatestObservationFromEncounters('Tech Mahindra Status');
const statusValue = techStatus ? techStatus.getReadableValue() : "No previous status";

// Trend analysis
const latestHbA1c = individual.findLatestObservationFromEncounters('HbA1c');
if (latestHbA1c) {
    const daysSinceTest = moment().diff(latestHbA1c.encounterDateTime, 'days');
    if (daysSinceTest > 90) {
        return "HbA1c test overdue (last test " + daysSinceTest + " days ago)";
    }
}

findLastEncounterOfType(currentEncounter, encounterTypes)

Available on: Individual

Purpose: Finds the most recent encounter of specified types before the current encounter.

Parameters:

  • currentEncounter (Encounter): Current encounter to exclude from search
  • encounterTypes (Array): Array of encounter type names to search for

Returns: Encounter object or undefined

Examples:

// Find last ANC visit
const lastANC = individual.findLastEncounterOfType(currentEncounter, ['ANC']);

// Find last follow-up of any type
const lastFollowUp = individual.findLastEncounterOfType(currentEncounter, 
    ['Follow-up 1', 'Follow-up 2', 'Follow-up 3']);

// Calculate interval between visits
if (lastANC) {
    const daysSinceLastVisit = moment(currentEncounter.encounterDateTime)
        .diff(lastANC.encounterDateTime, 'days');
    
    if (daysSinceLastVisit > 28) {
        return "Visit interval exceeded recommended 4 weeks";
    }
}

// Access data from previous visit
if (lastFollowUp) {
    const previousCompliance = lastFollowUp.getObservationReadableValue('Treatment Compliance');
    const currentCompliance = currentEncounter.getObservationReadableValue('Treatment Compliance');
    
    if (previousCompliance === 'Good' && currentCompliance === 'Poor') {
        return "Compliance has declined since last visit";
    }
}

scheduledEncounters()

Available on: Individual

Purpose: Gets all scheduled encounters that haven't been completed or cancelled.

Returns: Array of scheduled encounters

Examples:

// Check for pending visits
const pendingVisits = individual.scheduledEncounters();

// Count overdue visits
const overdueVisits = individual.scheduledEncounters()
    .filter(enc => moment().isAfter(enc.maxVisitDateTime));

if (overdueVisits.length > 0) {
    return `${overdueVisits.length} visits are overdue`;
}

// Find next due visit
const nextVisit = individual.scheduledEncounters()
    .sort((a, b) => a.earliestVisitDateTime - b.earliestVisitDateTime)[0];

if (nextVisit) {
    const daysUntilDue = moment(nextVisit.earliestVisitDateTime).diff(moment(), 'days');
    return `Next visit due in ${daysUntilDue} days`;
}

scheduledEncountersOfType(encounterTypeName)

Available on: Individual

Purpose: Gets scheduled encounters of a specific type.

Parameters:

  • encounterTypeName (String): Name of the encounter type to filter by

Returns: Array of scheduled encounters of the specified type

Examples:

// Check for scheduled ANC visits
const scheduledANC = individual.scheduledEncountersOfType('ANC');

// Check if delivery is scheduled
const scheduledDelivery = individual.scheduledEncountersOfType('Delivery');
if (scheduledDelivery.length > 0) {
    const deliveryDue = moment(scheduledDelivery[0].earliestVisitDateTime);
    return `Delivery scheduled for ${deliveryDue.format('DD/MM/YYYY')}`;
}

// Immunization scheduling
const scheduledVaccination = individual.scheduledEncountersOfType('Vaccination');
if (scheduledVaccination.length === 0 && individual.getAgeInMonths() >= 6) {
    return "6-month vaccination overdue";
}

Individual and Subject Methods

isFemale()

Available on: Individual

Purpose: Checks if the individual's gender is female.

Returns: Boolean

Examples:

// Basic gender check
if (individual.isFemale()) {
    // Female-specific logic
}

// Eligibility for reproductive health programs
return individual.isFemale() && individual.getAgeInYears() >= 15 && individual.getAgeInYears() <= 49;

// Pregnancy program eligibility
if (programName === 'Pregnancy Care' && !individual.isFemale()) {
    return {
        eligible: false,
        message: "Only females are eligible for pregnancy care program"
    };
}

// Gender-specific screening
if (individual.isFemale() && individual.getAgeInYears() >= 21) {
    return "Eligible for cervical cancer screening";
}

// Combined conditions
if (individual.isFemale() && individual.getAgeInYears() > 10 && individual.getAgeInYears() < 19) {
    return "Eligible for adolescent girl program";
}

isMale()

Available on: Individual

Purpose: Checks if the individual's gender is male.

Returns: Boolean

Examples:

// Basic gender check
if (individual.isMale()) {
    // Male-specific logic
}

// Male-specific screening eligibility
if (individual.isMale() && individual.getAgeInYears() >= 50) {
    return "Eligible for prostate screening";
}

// Program exclusion validation
if (programName === 'Maternal Health' && individual.isMale()) {
    return {
        eligible: false,
        message: "Males cannot enroll in maternal health program"
    };
}

// Age and gender combined rules
if (individual.isMale() && individual.getAgeInYears() >= 40) {
    return "Consider cardiovascular risk assessment";
}

isPerson()

Available on: Individual

Purpose: Checks if the subject type is a person (as opposed to household, group, etc.).

Returns: Boolean

Examples:

// Person-specific logic
if (individual.isPerson()) {
    const genderText = individual.gender.name;
    const ageText = individual.getAge().toString();
} else {
    // Handle non-person subjects (groups, households)
}

// Display formatting
const subtitle1 = individual.isPerson() ? individual.gender.name : "";
const subtitle2 = individual.isPerson() ? individual.getAge().toString() : "";

// Validation rules
if (individual.isPerson()) {
    // Apply person-specific validation
    return individual.isFemale() && individual.getAgeInYears() >= 15;
} else {
    // Handle group/household validation
}

isHousehold()

Available on: Individual

Purpose: Checks if the subject type is a household.

Returns: Boolean

Examples:

// Household-specific rules
if (individual.isHousehold()) {
    // Apply household-level validation and logic
}

// Filter household subjects
const households = subjects.filter(subject => subject.isHousehold());

// Check if individual belongs to households
const belongsToHousehold = _.some(individual.groups, group => 
    group.groupSubject.isHousehold());

// Household member count validation
if (individual.isHousehold()) {
    const memberCount = individual.groupSubjects.length;
    if (memberCount === 0) {
        return "Household must have at least one member";
    }
}

isGroup()

Available on: Individual

Purpose: Checks if the subject type is a group.

Returns: Boolean

Examples:

// Group-specific processing
if (individual.isGroup()) {
    // Handle group operations
    const memberCount = individual.groupSubjects.length;
}

// Group validation
if (individual.isGroup() && individual.groupSubjects.length < 5) {
    return "Self-help group must have at least 5 members";
}

getMobileNumber()

Available on: Individual

Purpose: Gets mobile number from observations using mobile number concept.

Returns: String (mobile number) or undefined

Examples:

// Get mobile number for notifications
const mobileNumber = individual.getMobileNumber();
if (mobileNumber) {
    // Send SMS notification
    console.log(`Sending SMS to ${mobileNumber}`);
}

// Validation
const mobile = individual.getMobileNumber();
if (!mobile && isRequired) {
    return ValidationResult.failure("mobile", "Mobile number is required");
}

// Display with fallback
const displayNumber = individual.getMobileNumber() || "Not provided";

nameString

Available on: Individual

Purpose: Gets formatted name string based on subject type.

Returns: String (formatted name)

Examples:

// Get formatted name
const displayName = individual.nameString;

// For persons: "John Doe Smith"
// For users: "Admin(You)" 
// For other subjects: "Group Name"

// Use in displays
const summary = `Patient: ${individual.nameString}, Age: ${individual.getAge()}`;

// Name with unique identifier (for specific subject types like Farmer)
const uniqueName = individual.nameStringWithUniqueAttribute;
// Returns: "John Doe (9876543210)" if mobile number exists

Location and Address Methods

lowestAddressLevel

Available on: Individual

Purpose: Gets the lowest (most specific) address level for the individual.

Returns: AddressLevel object

Examples:

// Access address information
const addressLevel = individual.lowestAddressLevel;
const villageName = addressLevel.name;
const addressType = addressLevel.type;

// Get address lineage
const titleLineage = addressLevel.titleLineage;

// Check for web application context
const webapp = individual.lowestAddressLevel.titleLineage;
if (webapp) {
    // Web application specific logic
    // Skip location-based validations
} else {
    // Mobile application logic
}

// Address-based rules
if (individual.lowestAddressLevel.name === "High Risk Village") {
    return "Apply high-risk protocols";
}

lowestTwoLevelAddress(i18n)

Available on: Individual

Purpose: Gets formatted address string with the lowest two levels of address hierarchy.

Parameters:

  • i18n (Object): Internationalization object for translation

Returns: String (formatted address)

Examples:

// Display compact address
const compactAddress = individual.lowestTwoLevelAddress(i18n);
// Returns: "Village Name, Block Name"

// Use in summaries with fallback
const location = individual.lowestTwoLevelAddress(i18n) || 'Address not specified';

// Address validation
const address = individual.lowestTwoLevelAddress(i18n);
if (!address || address.trim() === '') {
    return ValidationResult.failure("address", "Address is required");
}

fullAddress(i18n)

Available on: Individual

Purpose: Gets complete address lineage from lowest to highest level.

Parameters:

  • i18n (Object): Internationalization object for translation

Returns: String (complete address hierarchy)

Examples:

// Full address hierarchy
const fullAddr = individual.fullAddress(i18n);
// Returns: "Village, Block, District, State"

// Use for detailed address display
const addressDetail = {
    compact: individual.lowestTwoLevelAddress(i18n),
    full: individual.fullAddress(i18n)
};

// Geographic analysis
const addressComponents = individual.fullAddress(i18n).split(', ');
const state = addressComponents[addressComponents.length - 1];

Relationship and Group Methods

getRelatives(relationName, inverse)

Available on: Individual

Purpose: Gets all relatives by relation name.

Parameters:

  • relationName (String): Name of the relation to find
  • inverse (Boolean, optional): Whether to check inverse relation (default: false)

Returns: Array of Individual objects

Examples:

// Get all children (inverse of parent relation)
const children = individual.getRelatives('Parent', true);

// Get all siblings
const siblings = individual.getRelatives('Sibling');

// Family size calculation
const spouse = individual.getRelative('Spouse');
const children = individual.getRelatives('Parent', true);
const familySize = 1 + children.length + (spouse ? 1 : 0);

// Child immunization tracking
children.forEach(child => {
    const childAge = child.getAgeInMonths();
    if (childAge >= 6 && childAge < 24) {
        // Track immunization status
    }
});

// Family history analysis
const parents = individual.getRelatives('Child', true); // Get parents
const familyHistory = [];
parents.forEach(parent => {
    const diabetes = parent.getObservationReadableValue('Diabetes History');
    if (diabetes === 'Yes') {
        familyHistory.push('Parental diabetes');
    }
});

getRelative(relationName, inverse)

Available on: Individual

Purpose: Gets the first relative by relation name.

Parameters:

  • relationName (String): Name of the relation to find
  • inverse (Boolean, optional): Whether to check inverse relation (default: false)

Returns: Individual object or undefined

Examples:

// Get spouse
const spouse = individual.getRelative('Spouse');
if (spouse) {
    const spouseAge = spouse.getAgeInYears();
}

// Get mother
const mother = individual.getRelative('Mother');

// Get primary child (useful for parent-child relationships)
const primaryChild = individual.getRelative('Parent', true);

// Conditional logic based on relationships
if (spouse && spouse.isFemale() && spouse.getAgeInYears() >= 15) {
    // Include spouse in reproductive health program
}

// Family contact information
const emergencyContact = individual.getRelative('Emergency Contact');
const emergencyNumber = emergencyContact ? emergencyContact.getMobileNumber() : null;

getGroups()

Available on: Individual

Purpose: Gets all non-voided groups that this individual belongs to.

Returns: Array of GroupSubject objects

Examples:

// Get household information
const household = individual.getGroups().filter(grp => 
    grp.groupSubject.subjectType.type === 'Household')[0];

if (household) {
    const householdName = household.groupSubject.name;
    const householdMembers = household.groupSubject.groupSubjects.length;
}

// Check group membership
const groups = individual.getGroups();
if (groups.length > 0) {
    // Individual belongs to groups
    const groupNames = groups.map(g => g.groupSubject.name);
}

// Self-help group membership
const shgMembership = individual.getGroups().find(g => 
    g.groupSubject.subjectType.name === 'Self Help Group');

if (shgMembership) {
    // Access SHG-specific benefits
}

getGroupSubjects()

Available on: Individual

Purpose: Gets all non-voided group subjects where this individual is a member.

Returns: Array of GroupSubject objects

Examples:

// Get all group memberships
const groupMemberships = individual.getGroupSubjects();

// Find specific group type membership
const shgMembership = individual.getGroupSubjects()
    .find(gs => gs.groupSubject.subjectType.name === 'SHG');

// Check member role
groupMemberships.forEach(membership => {
    if (membership.groupRole.isHeadOfHousehold) {
        // Individual is head of household
    }
});

// Count group memberships
const membershipCount = individual.getGroupSubjects().length;
if (membershipCount === 0) {
    return "Individual is not part of any group";
}

Validation and Status Methods

hasBeenEdited()

Available on: AbstractEncounter (Encounter, ProgramEncounter)

Purpose: Checks if encounter has been edited (filled with data).

Returns: Boolean

Examples:

// Check if encounter is completed
if (encounter.hasBeenEdited()) {
    // Encounter has been filled with data
    const completionDate = encounter.encounterDateTime;
} else {
    // Encounter is still scheduled/pending
}

// Validation for editing
if (encounter.hasBeenEdited() && !userCanEditCompletedEncounters) {
    return {
        editable: false,
        message: "Cannot edit completed encounters"
    };
}

// Cancellation eligibility
if (!encounter.hasBeenEdited() && !encounter.isCancelled()) {
    // Can be cancelled
}

isCancelled()

Available on: AbstractEncounter (Encounter, ProgramEncounter)

Purpose: Checks if encounter has been cancelled.

Returns: Boolean

Examples:

// Check cancellation status
if (encounter.isCancelled()) {
    const cancelReason = encounter.findCancelEncounterObservationReadableValue('Cancel Reason');
    const cancelDate = encounter.cancelDateTime;
}

// Filter active encounters
const activeEncounters = individual.encounters.filter(enc => 
    !enc.isCancelled() && enc.hasBeenEdited());

// Rescheduling logic
if (encounter.isCancelled()) {
    const reason = encounter.findCancelEncounterObservationReadableValue('Cancel Reason');
    if (reason === 'Patient unavailable') {
        // Automatic rescheduling
        return {
            name: "Rescheduled Visit",
            earliestDate: moment().add(7, 'days').toDate()
        };
    }
}

isScheduled()

Available on: AbstractEncounter (Encounter, ProgramEncounter)

Purpose: Checks if encounter is scheduled (not filled and not cancelled).

Returns: Boolean

Examples:

// Check if visit is pending
if (encounter.isScheduled()) {
    const daysUntilDue = moment(encounter.earliestVisitDateTime).diff(moment(), 'days');
    if (daysUntilDue < 0) {
        return "Visit is overdue";
    } else {
        return `Visit due in ${daysUntilDue} days`;
    }
}

// Count scheduled visits
const pendingVisits = individual.encounters.filter(enc => enc.isScheduled()).length;

// Overdue visit check
const overdueVisits = individual.encounters.filter(enc => 
    enc.isScheduled() && moment().isAfter(enc.maxVisitDateTime));

isRejectedEntity()

Available on: Individual, AbstractEncounter (Encounter, ProgramEncounter)

Purpose: Checks if entity has been rejected in the approval workflow.

Returns: Boolean

Examples:

// Check individual approval status
if (individual.isRejectedEntity()) {
    return "Individual registration has been rejected";
}

// Check encounter approval status
if (encounter.isRejectedEntity()) {
    const rejectionReason = encounter.latestEntityApprovalStatus.comment;
    return `Encounter rejected: ${rejectionReason}`;
}

// Filter approved entities
const approvedEncounters = encounters.filter(enc => !enc.isRejectedEntity());
const approvedIndividuals = individuals.filter(ind => !ind.isRejectedEntity());

// Conditional processing
if (!individual.isRejectedEntity()) {
    // Process approved individual
}

Media and Utility Methods

findMediaObservations()

Available on: Individual, AbstractEncounter (Encounter, ProgramEncounter)

Purpose: Finds all media observations (images, videos, audio files).

Returns: Array of media observations

Examples:

// Get all media attachments
const mediaObs = individual.findMediaObservations();

// Process different media types
mediaObs.forEach(obs => {
    if (obs.concept.datatype === 'Image') {
        // Handle image observation
        const imageUrl = obs.getValue();
    } else if (obs.concept.datatype === 'Video') {
        // Handle video observation
    }
});

// Check for profile pictures or documents
const profileImages = individual.findMediaObservations()
    .filter(obs => obs.concept.name.includes('Profile'));

// Count media attachments
const mediaCount = encounter.findMediaObservations().length;
if (mediaCount === 0) {
    return "No supporting documents attached";
}

getProfilePicture()

Available on: Individual

Purpose: Gets the profile picture path/URL.

Returns: String (image path) or undefined

Examples:

// Display profile picture
const profilePic = individual.getProfilePicture();
if (profilePic) {
    // Show image in UI
    console.log(`Profile picture: ${profilePic}`);
} else {
    // Show default avatar
}

// Validation
const hasPicture = !!individual.getProfilePicture();
if (requiresPhoto && !hasPicture) {
    return ValidationResult.failure("photo", "Profile picture is required");
}

getEntityTypeName()

Available on: Individual, AbstractEncounter (Encounter, ProgramEncounter)

Purpose: Gets the entity type name for identification and logging.

Returns: String

Examples:

// Get type for logging
const entityType = individual.getEntityTypeName(); // Returns subject type name like "Person", "Household"
const encounterType = encounter.getEntityTypeName(); // Returns encounter type name like "ANC", "Delivery"

// Conditional logic based on type
if (individual.getEntityTypeName() === "Household") {
    // Household-specific logic
} else if (individual.getEntityTypeName() === "Person") {
    // Person-specific logic
}

// Logging and auditing
console.log(`Processing ${entity.getEntityTypeName()}: ${entity.uuid}`);

toJSON()

Available on: Individual, ProgramEncounter

Purpose: Gets JSON representation of the entity for serialization.

Returns: Object (JSON representation)

Examples:

// Serialize for logging or transmission
const individualData = individual.toJSON();
const encounterData = programEncounter.toJSON();

// Log for debugging
console.log("Individual data:", JSON.stringify(individual.toJSON(), null, 2));

// Data export
const exportData = {
    individual: individual.toJSON(),
    encounters: individual.encounters.map(enc => enc.toJSON ? enc.toJSON() : enc)
};