Skip to content

Sn/es#33

Merged
snehar-nd merged 5 commits into
release-3.6.1from
sn/ES
Dec 31, 2025
Merged

Sn/es#33
snehar-nd merged 5 commits into
release-3.6.1from
sn/ES

Conversation

@snehar-nd
Copy link
Copy Markdown
Contributor

@snehar-nd snehar-nd commented Dec 29, 2025

📋 Description

JIRA ID:

Amm-2038

✅ Type of Change

  • New feature (non-breaking change which adds functionality)

ℹ️ Additional Information

Elasticsearch API integration foe Advance search.

Summary by CodeRabbit

  • New Features
    • Enhanced search capabilities with improved performance through optimized beneficiary, family tagging, and personal information lookups
    • Refined search input handling with debounced searches and updated validation patterns
    • Improved error handling and user feedback throughout search workflows, including advanced search functionality

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 29, 2025

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.

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

📝 Walkthrough

Walkthrough

This pull request introduces Elasticsearch support across multiple search and lookup components via a feature flag (isEnableES) initialized from environment configuration. Components branch their search logic to use Elasticsearch endpoints (identityQuickSearchES, advanceSearchIdentityES) when enabled, otherwise fall back to traditional search paths. Response handling and result restructuring logic is added to map Elasticsearch results into component-compatible formats.

Changes

Cohort / File(s) Summary
Elasticsearch Service Methods
src/registrar/services/registrar.service.ts
Added two new methods: identityQuickSearchES and advanceSearchIdentityES to interface with Elasticsearch endpoints via environment.elasticSearchUrl and environment.advanceElasticSearchUrl.
Search Component (Template & Logic)
src/registrar/search/search.component.html, search.component.ts
Enhanced template with pattern validation, ngModelChange handler, and conditional column headers. Expanded component logic with OnDestroy lifecycle, debounced search pipeline (Subject with debounceTime and distinctUntilChanged), new handlers (onSearchInputChange, onSearchButtonClick, handleESSearchResponse, searchRestructES, resetWorklist), and ES support in openSearchDialog with result mapping.
Beneficiary Details Components
src/registrar/beneficiary-details/beneficiary-details.component.ts, src/registrar/family-tagging/family-tagging-details/family-tagging-details.component.ts, src/registrar/registration/personal-information/personal-information.component.ts
Added isEnableES boolean flag initialized from environment in ngOnInit. Each component branches search logic in respective methods (getBenFamilyDetails, getBeneficiaryDetailsAfterFamilyTag, getParentDetails) to conditionally invoke identityQuickSearchES with ES-specific response handling, error management, and field mapping; retains non-ES fallback paths.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant SearchComp as Search Component
    participant RegistrarSvc as Registrar Service
    participant ES as Elasticsearch<br/>(when enabled)
    participant OldAPI as Traditional API<br/>(when disabled)

    User->>SearchComp: Enter search term & trigger search
    SearchComp->>SearchComp: Validate term (alphanumeric)
    
    alt isEnableES === true
        SearchComp->>RegistrarSvc: identityQuickSearchES(term)
        RegistrarSvc->>ES: POST to elasticSearchUrl
        ES-->>RegistrarSvc: Return ES results
        RegistrarSvc-->>SearchComp: Response with data[0]...
        SearchComp->>SearchComp: handleESSearchResponse()
        SearchComp->>SearchComp: searchRestructES() - map results<br/>(benName, genderName, district, etc.)
        SearchComp->>SearchComp: Display restructured results in table
    else isEnableES === false
        SearchComp->>RegistrarSvc: identityQuickSearch(term)
        RegistrarSvc->>OldAPI: Traditional search call
        OldAPI-->>RegistrarSvc: Return traditional results
        RegistrarSvc-->>SearchComp: Response
        SearchComp->>SearchComp: Use existing result handling
        SearchComp->>SearchComp: Display results in table
    end
    
    SearchComp-->>User: Show search results or error alert
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 A search reimagined, swift and true,
Elasticsearch paths now branch anew,
With debounced queries and flags so bright,
Traditional and elastic—both work just right! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Sn/es' is vague and non-descriptive, using branch naming convention rather than clearly conveying the main change (Elasticsearch integration for advanced search). Revise the title to clearly describe the main change, such as 'Integrate Elasticsearch API for advanced search functionality' or 'Add Elasticsearch support for beneficiary and parent lookup'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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.

@5Amogh
Copy link
Copy Markdown
Member

5Amogh commented Dec 29, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 29, 2025

✅ 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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/registrar/family-tagging/family-tagging-details/family-tagging-details.component.ts (1)

418-434: Potential null pointer: missing null check on data before accessing length.

In the non-ES path, beneficiaryDetails.data.length is accessed without first verifying that beneficiaryDetails.data exists. The ES path correctly checks beneficiaryDetails.data && before accessing length.

🔎 Suggested fix
     this.registrarService.identityQuickSearch(benReqObj).subscribe(
       (beneficiaryDetails: any) => {
-        if (beneficiaryDetails && beneficiaryDetails.data.length === 1) {
+        if (beneficiaryDetails && beneficiaryDetails.data && beneficiaryDetails.data.length === 1) {
           this.benFamilyId =
src/registrar/beneficiary-details/beneficiary-details.component.ts (1)

140-223: Race condition: Image fetch executes before beneficiary data is populated.

The getBeneficiaryImage call (lines 213-221) is executed immediately after subscribing to the search, but before the search response arrives. This means this.beneficiary.benImage = data.benImage at line 219 could fail because this.beneficiary may still be undefined.

Move the image fetch inside the success callbacks of both ES and non-ES branches.

🔎 Suggested fix
   getBenFamilyDetails() {
     this.route.params.subscribe((param) => {
       if (this.isEnableES) {
         // Use Elasticsearch search
         const searchTerm = param['beneficiaryId'];
         this.registrarService
           .identityQuickSearchES({ search: searchTerm })
           .subscribe(
             (res: any) => {
               if (res && res.data && res.data.length === 1) {
                 this.beneficiary = res.data[0];
                 this.benFamilyId = res.data[0].familyID || res.data[0].familyId;
                 this.beneficiaryName =
                   this.beneficiary.firstName +
                   (this.beneficiary.lastName !== undefined &&
                   this.beneficiary.lastName !== null &&
                   this.beneficiary.lastName !== ''
                     ? ' ' + this.beneficiary.lastName
                     : '');
                 this.regDate = moment
                   .utc(this.beneficiary.createdDate)
                   .format('DD-MM-YYYY hh:mm A');
+                // Fetch image after beneficiary is set
+                this.fetchBeneficiaryImage(param['beneficiaryRegID']);
               } else if (res && res.data && res.data.length > 1) {
                 // Multiple results handling...
               } else {
                 // Not found handling...
               }
             },
             // error handling...
           );
       } else {
         // Traditional search
         // ... similar change needed here
+        // Move image fetch inside success callback
       }
-
-      // Fetch beneficiary image (common for both ES and non-ES)
-      const benFlowID: any = param['beneficiaryRegID'];
-      this.beneficiaryDetailsService
-        .getBeneficiaryImage(benFlowID)
-        .subscribe((data: any) => {
-          if (data && data.benImage) {
-            this.beneficiary.benImage = data.benImage;
-          }
-        });
     });
   }
+
+  private fetchBeneficiaryImage(beneficiaryRegID: string) {
+    this.beneficiaryDetailsService
+      .getBeneficiaryImage(beneficiaryRegID)
+      .subscribe((data: any) => {
+        if (data && data.benImage && this.beneficiary) {
+          this.beneficiary.benImage = data.benImage;
+        }
+      });
+  }
🧹 Nitpick comments (5)
src/registrar/services/registrar.service.ts (1)

124-127: Minor formatting: missing blank line after method.

There's a missing blank line between identityQuickSearchES and clearBeneficiaryEditDetails, which is inconsistent with the rest of the file's formatting.

🔎 Suggested fix
   identityQuickSearchES(searchTerm: any) {
      return this.http.post(environment.elasticSearchUrl, searchTerm);
   }
+
   clearBeneficiaryEditDetails() {
src/registrar/registration/personal-information/personal-information.component.ts (1)

354-359: Remove debug console.log statements before merging.

Multiple console.log statements are present for debugging ES and parent search results. Consider removing these before production deployment.

🔎 Locations to clean up
-              console.log('ES Parent search result:', JSON.stringify(response, null, 4));
               this.personalInfoFormGroup.patchValue({
                 parentRegID: response.data[0].benPhoneMaps[0].parentBenRegID,
                 parentRelation: 11,
               });
-              console.log('Parent Reg ID (ES):', this.personalInfoFormGroup.value.parentRegID);

And similar occurrences at lines 365, 371, 398, 403, 409, 415.

Also applies to: 365-366, 398-403, 409-415

src/registrar/search/search.component.ts (2)

130-156: Good implementation of debounced search with RxJS.

The use of debounceTime, distinctUntilChanged, and switchMap is the correct pattern for typeahead search functionality.

However, the subscribe error callback pattern is deprecated in RxJS 7+. Consider using the observer object pattern.

🔎 Modern RxJS subscribe pattern
       .subscribe(
-        (response: any) => {
-          this.handleESSearchResponse(response);
-        },
-        (error: any) => {
-          this.confirmationService.alert(error, 'error');
-        }
+        {
+          next: (response: any) => {
+            this.handleESSearchResponse(response);
+          },
+          error: (error: any) => {
+            this.confirmationService.alert(error, 'error');
+          }
+        }
       );

159-166: Consider adding loading state for better UX.

The debounced search triggers after 3+ characters are typed, but there's no loading indicator while waiting for the debounce or API response.

src/registrar/search/search.component.html (1)

14-14: Redundant ternary operator - both branches are identical.

The placeholder has identical values for both isEnableES true and false cases. Simplify to just use the value directly.

🔎 Suggested fix
-            placeholder="{{ isEnableES ? currentLanguageSet?.ro?.benIDOrPhNo : currentLanguageSet?.ro?.benIDOrPhNo }}"
+            placeholder="{{ currentLanguageSet?.ro?.benIDOrPhNo }}"
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f453693 and fb6b49b.

📒 Files selected for processing (6)
  • src/registrar/beneficiary-details/beneficiary-details.component.ts
  • src/registrar/family-tagging/family-tagging-details/family-tagging-details.component.ts
  • src/registrar/registration/personal-information/personal-information.component.ts
  • src/registrar/search/search.component.html
  • src/registrar/search/search.component.ts
  • src/registrar/services/registrar.service.ts
🧰 Additional context used
🧠 Learnings (8)
📚 Learning: 2025-07-09T12:40:58.733Z
Learnt from: abhijeetw035
Repo: PSMRI/Common-UI PR: 20
File: src/registrar/registration/personal-information/personal-information.component.ts:29-29
Timestamp: 2025-07-09T12:40:58.733Z
Learning: In the AMRIT project, Common-UI is a git submodule (as defined in .gitmodules) that provides shared components and services. Import paths like `import { AmritTrackingService } from 'Common-UI/src/tracking';` are correct and resolve properly in the runtime environment where the submodule is initialized, even though they may not be visible in development environments where submodules aren't initialized.

Applied to files:

  • src/registrar/registration/personal-information/personal-information.component.ts
📚 Learning: 2025-07-09T12:40:58.733Z
Learnt from: abhijeetw035
Repo: PSMRI/Common-UI PR: 20
File: src/registrar/registration/personal-information/personal-information.component.ts:29-29
Timestamp: 2025-07-09T12:40:58.733Z
Learning: The Common-UI repository is designed to be used as a git submodule in other AMRIT applications. Import paths like `import { AmritTrackingService } from 'Common-UI/src/tracking';` are correct because they resolve properly in consuming applications where Common-UI is included as a submodule, even though the Common-UI repository itself doesn't contain a .gitmodules file.

Applied to files:

  • src/registrar/registration/personal-information/personal-information.component.ts
📚 Learning: 2024-12-10T08:42:10.330Z
Learnt from: helenKaryamsetty
Repo: PSMRI/Common-UI PR: 4
File: src/registrar/abha-components/abha-generation-success-component/abha-generation-success-component.component.ts:83-85
Timestamp: 2024-12-10T08:42:10.330Z
Learning: In this project, calling `assignSelectedLanguage()` inside `ngDoCheck()` is the standard approach used across components to handle language updates consistently.

Applied to files:

  • src/registrar/family-tagging/family-tagging-details/family-tagging-details.component.ts
  • src/registrar/beneficiary-details/beneficiary-details.component.ts
  • src/registrar/search/search.component.ts
📚 Learning: 2024-12-12T10:46:10.098Z
Learnt from: helenKaryamsetty
Repo: PSMRI/Common-UI PR: 5
File: src/registrar/abha-components/abha-enter-mobile-otp-component/abha-enter-mobile-otp-component.component.ts:44-48
Timestamp: 2024-12-12T10:46:10.098Z
Learning: In this Angular project, it is common practice to directly instantiate components like `SetLanguageComponent` for language management in methods such as `assignSelectedLanguage()`, rather than using a service. This is done to maintain consistency across the codebase.

Applied to files:

  • src/registrar/family-tagging/family-tagging-details/family-tagging-details.component.ts
  • src/registrar/beneficiary-details/beneficiary-details.component.ts
  • src/registrar/search/search.component.ts
📚 Learning: 2024-12-10T08:55:14.016Z
Learnt from: helenKaryamsetty
Repo: PSMRI/Common-UI PR: 4
File: src/registrar/abha-components/generate-abha-component/generate-abha-component.component.ts:79-84
Timestamp: 2024-12-10T08:55:14.016Z
Learning: In the Angular component `GenerateAbhaComponentComponent` (file path `src/registrar/abha-components/generate-abha-component/generate-abha-component.component.ts`), the `res.data.message` displayed using `confirmationService.alert()` contains only safe success messages and does not require additional sanitization before displaying to users.

Applied to files:

  • src/registrar/family-tagging/family-tagging-details/family-tagging-details.component.ts
📚 Learning: 2024-12-10T08:41:11.391Z
Learnt from: helenKaryamsetty
Repo: PSMRI/Common-UI PR: 4
File: src/registrar/abha-components/abha-generation-success-component/abha-generation-success-component.component.ts:70-78
Timestamp: 2024-12-10T08:41:11.391Z
Learning: In the `AbhaGenerationSuccessComponentComponent` class (`src/registrar/abha-components/abha-generation-success-component/abha-generation-success-component.component.ts`), the `GivePageToMobileEnterOtp()` method intentionally closes the newly opened dialog immediately after opening it with `dialogRef.close();` because, after routing to another component, the previous component should be closed.

Applied to files:

  • src/registrar/search/search.component.ts
📚 Learning: 2024-12-10T08:58:21.154Z
Learnt from: helenKaryamsetty
Repo: PSMRI/Common-UI PR: 4
File: src/registrar/abha-components/generate-abha-component/generate-abha-component.component.ts:37-41
Timestamp: 2024-12-10T08:58:21.154Z
Learning: In this project, the `assignSelectedLanguage()` method in components directly creates an instance of `SetLanguageComponent` to maintain a consistent language implementation across the project.

Applied to files:

  • src/registrar/search/search.component.ts
📚 Learning: 2024-12-10T08:59:11.297Z
Learnt from: helenKaryamsetty
Repo: PSMRI/Common-UI PR: 4
File: src/registrar/abha-components/abha-generation-success-component/abha-generation-success-component.component.ts:86-90
Timestamp: 2024-12-10T08:59:11.297Z
Learning: In this project, directly instantiating `SetLanguageComponent` is the standard method for language implementation to maintain consistency across the codebase.

Applied to files:

  • src/registrar/search/search.component.ts
🧬 Code graph analysis (1)
src/registrar/search/search.component.ts (1)
src/registrar/search-dialog/search-dialog.component.ts (1)
  • AfterViewChecked (269-271)
🔇 Additional comments (10)
src/registrar/services/registrar.service.ts (1)

143-147: LGTM - ES advanced search method follows existing patterns.

The new advanceSearchIdentityES method is consistent with the existing advanceSearchIdentity method pattern.

src/registrar/family-tagging/family-tagging-details/family-tagging-details.component.ts (2)

116-117: LGTM - Feature flag initialization follows project patterns.

The ES feature flag is correctly initialized with a fallback to false.


392-415: Field naming difference: familyID (ES) vs familyId (non-ES).

The ES path accesses familyID (uppercase D) while the non-ES path uses familyId (lowercase d). Ensure the ES API consistently returns familyID to avoid mapping issues.

src/registrar/registration/personal-information/personal-information.component.ts (1)

343-383: ES path looks correct with proper null checks and error handling.

The ES branch properly validates the response structure before accessing nested properties.

src/registrar/beneficiary-details/beneficiary-details.component.ts (1)

149-161: Good defensive coding: fallback for field name inconsistency.

The use of res.data[0].familyID || res.data[0].familyId handles potential field naming differences between ES and non-ES responses.

src/registrar/search/search.component.ts (3)

222-246: ES restructuring handles nested properties well with fallbacks.

The searchRestructES method properly handles variations in the ES response structure with fallback chains for genderName, districtName, and villageName.


391-405: Good defensive null check added for phoneMaps.

The added check if (!phoneMaps || !phoneMaps.length) at line 392 properly handles cases where ES results may not have phone mappings.


123-127: Proper cleanup in ngOnDestroy.

The subscription cleanup follows Angular best practices for preventing memory leaks.

src/registrar/search/search.component.html (2)

17-18: LGTM - Event handlers updated for ES-aware search.

The input and button now correctly route through the new unified onSearchButtonClick and onSearchInputChange handlers that branch based on isEnableES.

Also applies to: 27-27


159-162: Good - Table header adapts to ES mode.

When ES is enabled, the column header shows "Beneficiary Reg ID" to match the ES response structure. This provides correct labeling for users.

Comment thread src/registrar/search/search.component.ts
Comment thread src/registrar/beneficiary-details/beneficiary-details.component.ts Outdated
Comment thread src/registrar/beneficiary-details/beneficiary-details.component.ts Outdated
Comment thread src/registrar/beneficiary-details/beneficiary-details.component.ts Outdated
Comment thread src/registrar/beneficiary-details/beneficiary-details.component.ts Outdated
@snehar-nd snehar-nd merged commit f2aceff into release-3.6.1 Dec 31, 2025
@coderabbitai coderabbitai Bot mentioned this pull request Apr 24, 2026
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