Skip to content

AMM-2127 clinical observation search is not working.#264

Merged
snehar-nd merged 6 commits intorelease-3.6.2from
sn/3.6.1
Mar 25, 2026
Merged

AMM-2127 clinical observation search is not working.#264
snehar-nd merged 6 commits intorelease-3.6.2from
sn/3.6.1

Conversation

@snehar-nd
Copy link
Copy Markdown
Contributor

@snehar-nd snehar-nd commented Mar 23, 2026

📋 Description

JIRA ID:

AMM-2127

✅ Type of Change

  • 🐞 Bug fix (non-breaking change which resolves an issue)

Summary by CodeRabbit

  • New Features

    • Enhanced search functionality for clinical observations and significant findings with improved autocomplete experience.
  • Bug Fixes

    • Fixed potential null reference errors in success message handling.
  • Refactor

    • Removed unnecessary required field constraints from prescription form inputs.
    • Removed mandatory prescription entry validation requirement.

snehar-nd and others added 4 commits February 27, 2026 12:21
* fix: aam-2159 changed text from advancesearch to advanced search

* fix: amm-1979 validation for prescription

* Correct spelling in 'advanceBeneficiarySearch'

---------

Co-authored-by: 5Amogh <amoghavarsh@navadhiti.com>
Co-authored-by: Amoghavarsh <93114621+5Amogh@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 23, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 25522d63-5a9a-460a-a08b-3b6f8b910d06

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The pull request refactors the findings component to replace custom directives with Angular Material autocomplete components for clinical observations and significant findings searches. Additionally, required attributes are removed from prescription form controls, doctor-only prescription validation is eliminated, and success alert messages are updated with optional chaining fallbacks.

Changes

Cohort / File(s) Summary
Findings Autocomplete Refactor
src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.html, src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.ts
Replaced custom directive-based autocomplete with Angular Material mat-autocomplete. Added per-row suggestion state arrays (suggestedObservationsList, suggestedFindingsSearchList). Implemented search handlers (onObservationInputKeyup, onFindingsInputKeyup) that query masterdata service when input reaches 3+ characters, display formatters (displayObservation, displayFindings), and selection handlers (onObservationSelected, onFindingsSelected) that patch reactive form groups. Updated row templates with keyed inputs and option selection bindings. Adjusted remove-button visibility logic to check form control disabled state.
Prescription Form Validation
src/app/app-modules/nurse-doctor/case-record/general-case-record/prescription/prescription.component.html, src/app/app-modules/nurse-doctor/quick-consult/quick-consult.component.html
Removed required attribute from multiple Angular Material form controls across both files: mat-select for form/dose/frequency/quantity and medicine input with matAutocomplete.
Workarea Validation & Error Handling
src/app/app-modules/nurse-doctor/workarea/workarea.component.ts
Deleted doctor-only prescription validation logic that required at least one prescribed drug. Updated success-alert message calls to use optional chaining with fallback strings (this.current_language_set?.alerts?.info?.datafillSuccessfully ?? 'Data saved successfully').

Sequence Diagram

sequenceDiagram
    participant User as User Input
    participant Component as Findings Component
    participant Service as Masterdata Service
    participant Form as Reactive Form

    User->>Component: onObservationInputKeyup(value, index)
    Component->>Component: Trim & validate input (≥3 chars)
    Component->>Service: searchDiagnosisBasedOnPageNo(term, 0)
    Service-->>Component: results.data.sctMaster
    Component->>Component: suggestedObservationsList[index] = results
    
    User->>Component: Select option from dropdown
    Component->>Component: onObservationSelected(selected, index)
    Component->>Form: Patch FormGroup with conceptID, term, clinicalObservationsProvided
    Form-->>Component: Form updated
    Component->>Component: Update remove-button visibility check

    User->>Component: onFindingsInputKeyup(value, index)
    Component->>Component: Trim & validate input (≥3 chars)
    Component->>Component: resetFindingsCheckbox(term)
    Component->>Service: searchDiagnosisBasedOnPageNo(term, 0)
    Service-->>Component: results.data.sctMaster
    Component->>Component: suggestedFindingsSearchList[index] = results
    
    User->>Component: Select option from dropdown
    Component->>Component: onFindingsSelected(selected, index)
    Component->>Form: Patch FormGroup with conceptID, term, significantFindingsProvided
    Form-->>Component: Form updated
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A bushy-tailed review of search and form,
Where autocomplete flows in proper form,
No directives dance, Material shines bright,
Validations refined, alerts take flight,
Observations hop and findings align—
The findings refactor hops just fine! 🌟

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'AMM-2127 clinical observation search is not working' directly addresses the main bug fix in the PR—restoring clinical observation search functionality via Angular Material autocomplete.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sn/3.6.1

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@snehar-nd
Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 23, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.ts`:
- Around line 733-765: The code currently calls resetFindingsCheckbox(term) from
onFindingsInputKeyup and onFindingsSelected which derives enableIsHistory from
the transient input string and causes the checkbox state to follow the
last-edited row; instead, change resetFindingsCheckbox to recompute the checkbox
state from the form array contents (the FormArray 'significantFindingsList'
inside generalFindingsForm) by scanning its entries for existing findings/flags
(e.g., term, conceptID, or isForHistory) and set enableIsHistory/isForHistory
based on that aggregate state; update calls in onFindingsInputKeyup and
onFindingsSelected to pass nothing or the form array if needed and ensure
enableIsHistory is not derived from the single textbox value anymore.
- Around line 87-88: The autocomplete responses can overwrite newer input when
slower requests resolve later; update the component (where
suggestedObservationsList and suggestedFindingsSearchList are populated — the
search/request handlers used on keyup and the methods around the noted ranges)
to track the latest query per row (e.g. a map/array latestQueryByIndex keyed by
row index or suggestion id) and set latestQueryByIndex[index] = currentTerm
before firing the request; when the async response arrives, compare
response.term (or the original requested term) against latestQueryByIndex[index]
and only apply the results to suggestedObservationsList /
suggestedFindingsSearchList if they match; alternatively use per-request cancel
tokens (AbortController) or RxJS switchMap where available to ensure stale
responses are ignored.
- Around line 699-729: The selected option object is being stored into form
control clinicalObservationsProvided, causing the visible text and the SNOMED
pair (term/conceptID) to diverge when the user edits the text; change
onObservationSelected to store only the selected.term (string) into
clinicalObservationsProvided and still set conceptID and term controls from the
selected object (use selected?.term || '' for the visible field and
selected?.conceptID || null for conceptID), and update onObservationInputKeyup
to clear the associated conceptID/term when the user types (e.g., set
conceptID=null and term='' when term.length < 3 or when typing invalidates a
previous selection). Apply the same change to the corresponding
significantFindings handlers (the equivalent
onSignificantFindingSelected/onSignificantFindingInputKeyup functions) so the
visible text and SNOMED code stay in sync.

In `@src/app/app-modules/nurse-doctor/workarea/workarea.component.ts`:
- Around line 3903-3913: The post-save flow sometimes passes a string into
getHealthIDDetails that later interpolates
this.current_language_set.common.doYouWantToLinkCareContext without null-safety;
ensure every else branch (where you call getHealthIDDetails from the save
success blocks around the shown diffs and at lines referenced) builds a
null-safe prompt before calling confirmationService.confirmCareContext. Update
getHealthIDDetails to compute a fallback like const linkCareContextText =
this.current_language_set?.common?.doYouWantToLinkCareContext ?? 'Do you want to
link care context?'; and pass `${successResponseFromAPI}.
${linkCareContextText}` into confirmationService.confirmCareContext, and ensure
the confirmation subscribe handlers call fetchHealthIDDetailsOnConfirmation() or
basedOnRoleNavigateToWorklist()/navigateToSpecialistWorklist() as appropriate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eca44946-d50b-478c-b2df-0bcf1d2daa13

📥 Commits

Reviewing files that changed from the base of the PR and between 6029c52 and 152460c.

📒 Files selected for processing (5)
  • src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.html
  • src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.ts
  • src/app/app-modules/nurse-doctor/case-record/general-case-record/prescription/prescription.component.html
  • src/app/app-modules/nurse-doctor/quick-consult/quick-consult.component.html
  • src/app/app-modules/nurse-doctor/workarea/workarea.component.ts
💤 Files with no reviewable changes (2)
  • src/app/app-modules/nurse-doctor/quick-consult/quick-consult.component.html
  • src/app/app-modules/nurse-doctor/case-record/general-case-record/prescription/prescription.component.html

Comment on lines +87 to +88
suggestedObservationsList: any = [];
suggestedFindingsSearchList: any = [];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Prevent stale autocomplete responses from overwriting newer input.

Every keyup starts a fresh request, but the response handler never checks whether that row has already moved on to a different term. If a slower request returns last, it will repopulate the suggestions with an older prefix. The quick-consult search path already guards against this with a per-index latest-query check.

Also applies to: 699-710, 733-745

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.ts`
around lines 87 - 88, The autocomplete responses can overwrite newer input when
slower requests resolve later; update the component (where
suggestedObservationsList and suggestedFindingsSearchList are populated — the
search/request handlers used on keyup and the methods around the noted ranges)
to track the latest query per row (e.g. a map/array latestQueryByIndex keyed by
row index or suggestion id) and set latestQueryByIndex[index] = currentTerm
before firing the request; when the async response arrives, compare
response.term (or the original requested term) against latestQueryByIndex[index]
and only apply the results to suggestedObservationsList /
suggestedFindingsSearchList if they match; alternatively use per-request cancel
tokens (AbortController) or RxJS switchMap where available to ensure stale
responses are ignored.

Comment on lines +699 to +729
onObservationInputKeyup(value: string, index: number) {
const term = (value || '').trim();
if (term.length >= 3) {
this.masterdataService.searchDiagnosisBasedOnPageNo(term, 0).subscribe({
next: (results: any) => {
this.suggestedObservationsList[index] =
results?.data?.sctMaster ?? [];
},
error: () => {
console.error('Error fetching observation data');
},
});
} else {
this.suggestedObservationsList[index] = [];
}
}

displayObservation(obs: any): string {
return typeof obs === 'string' ? obs : obs?.term || '';
}

onObservationSelected(selected: any, index: number) {
const observationsFormArray = this.generalFindingsForm.get(
'clinicalObservationsList',
) as FormArray;
const observationsFormGroup = observationsFormArray.at(index) as FormGroup;
observationsFormGroup.patchValue({
clinicalObservationsProvided: selected,
conceptID: selected?.conceptID || null,
term: selected?.term || null,
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Keep the visible text and selected SNOMED code in sync.

These handlers now store the whole option object in clinicalObservationsProvided / significantFindingsProvided, and later typing does not clear the previously selected term/conceptID. That lets a row display edited text while still submitting the old code pair. The previous directive flow stored the term string in *Provided, not the full object.

Suggested fix
  onObservationInputKeyup(value: string, index: number) {
    const term = (value || '').trim();
+   const observationsFormGroup = (
+     (this.generalFindingsForm.get('clinicalObservationsList') as FormArray).at(
+       index,
+     ) as FormGroup
+   );
+   if ((observationsFormGroup.get('term')?.value ?? '') !== term) {
+     observationsFormGroup.patchValue(
+       {
+         term: null,
+         conceptID: null,
+       },
+       { emitEvent: false },
+     );
+   }
    if (term.length >= 3) {
      this.masterdataService.searchDiagnosisBasedOnPageNo(term, 0).subscribe({
        next: (results: any) => {
          this.suggestedObservationsList[index] =
            results?.data?.sctMaster ?? [];
        },
        error: () => {
          console.error('Error fetching observation data');
        },
      });
    } else {
      this.suggestedObservationsList[index] = [];
    }
  }

  onObservationSelected(selected: any, index: number) {
    const observationsFormArray = this.generalFindingsForm.get(
      'clinicalObservationsList',
    ) as FormArray;
    const observationsFormGroup = observationsFormArray.at(index) as FormGroup;
    observationsFormGroup.patchValue({
-     clinicalObservationsProvided: selected,
+     clinicalObservationsProvided: selected?.term || null,
      conceptID: selected?.conceptID || null,
      term: selected?.term || null,
    });
  }

  onFindingsInputKeyup(value: string, index: number) {
    const term = (value || '').trim();
+   const findingsFormGroup = (
+     (this.generalFindingsForm.get('significantFindingsList') as FormArray).at(
+       index,
+     ) as FormGroup
+   );
+   if ((findingsFormGroup.get('term')?.value ?? '') !== term) {
+     findingsFormGroup.patchValue(
+       {
+         term: null,
+         conceptID: null,
+       },
+       { emitEvent: false },
+     );
+   }
    this.resetFindingsCheckbox(term);
    if (term.length >= 3) {
      this.masterdataService.searchDiagnosisBasedOnPageNo(term, 0).subscribe({
        next: (results: any) => {
          this.suggestedFindingsSearchList[index] =
            results?.data?.sctMaster ?? [];
        },
        error: () => {
          console.error('Error fetching findings data');
        },
      });
    } else {
      this.suggestedFindingsSearchList[index] = [];
    }
  }

  onFindingsSelected(selected: any, index: number) {
    const findingsFormArray = this.generalFindingsForm.get(
      'significantFindingsList',
    ) as FormArray;
    const findingsFormGroup = findingsFormArray.at(index) as FormGroup;
    findingsFormGroup.patchValue({
-     significantFindingsProvided: selected,
+     significantFindingsProvided: selected?.term || null,
      conceptID: selected?.conceptID || null,
      term: selected?.term || null,
    });
    this.resetFindingsCheckbox(selected?.term);
  }

Also applies to: 733-765

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.ts`
around lines 699 - 729, The selected option object is being stored into form
control clinicalObservationsProvided, causing the visible text and the SNOMED
pair (term/conceptID) to diverge when the user edits the text; change
onObservationSelected to store only the selected.term (string) into
clinicalObservationsProvided and still set conceptID and term controls from the
selected object (use selected?.term || '' for the visible field and
selected?.conceptID || null for conceptID), and update onObservationInputKeyup
to clear the associated conceptID/term when the user types (e.g., set
conceptID=null and term='' when term.length < 3 or when typing invalidates a
previous selection). Apply the same change to the corresponding
significantFindings handlers (the equivalent
onSignificantFindingSelected/onSignificantFindingInputKeyup functions) so the
visible text and SNOMED code stay in sync.

…care context

- Fix race condition in clinical observations and significant findings autocomplete
  by tracking latest query per row index and discarding stale responses
- Fix text/SNOMED code desync by storing only term string on selection and
  clearing conceptID/term fields on keyup before new selection
- Fix checkbox visibility by scanning entire significantFindingsList array
  instead of relying on the last-edited row's transient state
- Add null-safe optional chaining in getHealthIDDetails() before confirmCareContext()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
13.7% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@snehar-nd snehar-nd merged commit 04fe2e9 into release-3.6.2 Mar 25, 2026
1 of 3 checks 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.

2 participants