Skip to content

Conversation

@VeronicaMuthee
Copy link
Collaborator

Added calculateExpression for the Mental Health Assessment PHQ-9 Score

  1. Added a calculate object with a calculateExpression to the PHQ-9 score field that automatically sums all 9 questions Scoring Logic.

  2. Each answer is mapped to its correct score:
    Not at all (160215AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) = 0 Several days (167000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) = 1 More than half the days (167001AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) = 2 Nearly every day (167002AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) = 3

  3. Read-only Field - Added a readonly behavior to the score field so users can't manually edit it

… score

1) Added a calculate object with a calculateExpression to the PHQ-9 score field that automatically sums all 9 questions
Scoring Logic.

2) Each answer is mapped to its correct score:
Not at all (160215AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) = 0
Several days (167000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) = 1
More than half the days (167001AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) = 2
Nearly every day (167002AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) = 3

3) Read-only Field - Added a readonly behavior to the score field so users can't manually edit it
@VeronicaMuthee VeronicaMuthee changed the title Mental Health Assessment PHQ-9 Score calculateExpression O3-5088: Add Automatic Calculation for PHQ-9 Total Score in Mental Health Assessment Form Oct 7, 2025
"max": "27",
"min": "0",
"showDate": "",
"calculate": {
Copy link
Member

@denniskigen denniskigen Oct 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inline calculateExpression here is quite long (~1000 chars) and repeats the UUID-to-score mapping 9 times. Could we consider factoring it out into a reusable custom expression helper function in the form engine instead?

We could add a calcPHQ9Score() helper to common-expression-helpers.ts (similar to calcBMI(), calcEDD(), etc) that looks like this:

/**
 * Calculates PHQ-9 (Patient Health Questionnaire-9) depression screening score
 * Supports both PHQ-2 (questions 1-2) and full PHQ-9 (questions 1-9)
 * Handles hidden/conditional questions by treating undefined/null values as 0
 * 
 * @param responses - Variable number of PHQ question responses (concept UUIDs)
 * @returns Total score (0-27 for full PHQ-9, 0-6 for PHQ-2 only)
 * 
 * @example
 * // PHQ-2 negative screen (questions 3-9 hidden)
 * calcPHQ9Score(phq2_1, phq2_2, phq9_3, phq9_4, phq9_5, phq9_6, phq9_7, phq9_8, phq9_9)
 * // Returns: 0 if both answered "Not at all"
 * 
 * @example
 * // Full PHQ-9
 * calcPHQ9Score(phq2_1, phq2_2, phq9_3, phq9_4, phq9_5, phq9_6, phq9_7, phq9_8, phq9_9)
 * // Returns: Sum of all 9 responses (0-27)
 */
calcPHQ9Score = (...responses: (string | null | undefined)[]): number => {
  const scoreMap: Record<string, number> = {
    '160215AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': 0, // Not at all
    '167000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': 1, // Several days
    '167001AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': 2, // More than half the days
    '167002AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': 3, // Nearly every day
  };

  return responses.reduce((sum, answer) => {
    return sum + (answer ? (scoreMap[answer] ?? 0) : 0);
  }, 0);
};

And then we could simplify the calculateExpression in this form by leveraging the new expression helper as follows:

  "calculate": {
    "calculateExpression": "calcPHQ9Score(phq2_1, phq2_2, phq9_3, phq9_4, phq9_5, phq9_6, phq9_7, phq9_8, phq9_9)"
  }

Benefits of this approach:

  • Easier to read, test, and maintain
  • Centralizes the UUID mapping logic
  • Follows DRY principle
  • Matches the architectural pattern used elsewhere in the codebase

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@denniskigen thanks for your feedback, are you suggesting that the change (custom expression helper function) should be implemented in the form engine’s codebase, not directly in the form JSON? @samuelmale is this something you can assist us?

Copy link
Member

@denniskigen denniskigen Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: PR merged. Should be available soon.

…ssessment Form

Summary of Changes

Automated PHQ-9 Scoring
Forms now support automatic calculation of PHQ-9 scores (range: 0–27) without manual entry. The score is computed based on responses to the nine PHQ items at the point of form entry.

Refactor to Reusable Calculation Function
Instead of repeating long inline calculateExpression logic across forms, the scoring logic has been moved into a clean, reusable helper function within the front-end form engine. This simplifies form JSON, improves maintainability, and ensures consistent application of depression screening logic.
This update aligns with and builds on the enhancement implemented in PR: openmrs/openmrs-esm-patient-chart#2787
@VeronicaMuthee
Copy link
Collaborator Author

@denniskigen please review the changes i have made based on the changes you implemented on this PR

Copy link
Member

@denniskigen denniskigen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks, @VeronicaMuthee!

@denniskigen denniskigen merged commit 9663965 into main Oct 20, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants