From db1c562f7970331f8be1f25c71a056e4ed40e27a Mon Sep 17 00:00:00 2001
From: Amoghavarsh <93114621+5Amogh@users.noreply.github.com>
Date: Thu, 25 Sep 2025 11:54:58 +0530
Subject: [PATCH 01/62] Update pom.xml
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index dee19366..3cf9dfcc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
4.0.0com.iemr.common.identityidentity-api
- 3.1.0
+ 3.8.0war
From 6e0d0f705c88dd63dfebeb16235700ba4c5ac28c Mon Sep 17 00:00:00 2001
From: Vanitha S <116701245+vanitha1822@users.noreply.github.com>
Date: Fri, 22 May 2026 13:52:02 +0530
Subject: [PATCH 02/62] Merge Release 3.6.2 to Main (#163)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Elasticsearch implementation for Beneficiary Search (#123)
* fix: ES Implementation-mapping, indexing and async records
* fix: add service for ES Search
* fix: search implementation
* fix: add additional fields as per the requirement
* fix: comment extra fields
* fix: rename the files, remove commented code
* fix: update pom.xml
* fix: revert advancesearch
* fix: add properties
* fix: coderabbit comments
* fix: remove comment code
* fix: accept numeric values for search
* fix: update the env variable
* fix: advance search functionality
* fix: update the advance search ES functionality
* fix: sync and fetch benid
* fix: size limit issue
* fix: improve response time
* fix: updated the end point to advancedSearchES
* fix: age issue while moving to nurse worklist (#130)
* Optimize the Elasticsearch for better Response Time (#131)
* fix: optimize the index and reduce the size
* fix: align indent
* fix: abha / health id issue
* fix: sync optimization
* fix: get abha created date
* fix: state issue
* fix: village issue
* fix: add abha details
* fix: abha fix and refresh index
* fix: refresh index
* fix: remove duplicate dependency
* fix: fuzzy search, resume, refresh api's
* fix: add middlename, maritalstatus
* fix: remove refresh while bulk indexing
* fix: add license
* fix: remove the bean function to create the index automatically (#133)
* Fix ES Issue in the Query (#137)
* fix: ES Exception
* fix: ES exception
* Nd/vs/fix es (#138)
* fix: ES Exception
* fix: ES exception
* fix: enable multi-word fuzzy search requirement (#139)
* fix: enable multi-word fuzzy search requirement
* Downgrade version from 3.6.2 to 3.6.1
* fix: multi-word search (#140)
* Fix the column mismatch issue in beneficiary search (#142)
* fix: column mismatch issue
* fix: update marital status
* add new column in rmnch table for death and child record
* add new column in rmnch table for death and child record
* Cherry-pick health and version API enhancements to release-3.6.1 (#145)
* feat(health,version): add health and version endpoints
* feat(health,version): add health and version endpoints without auth
* fix(health): remove unused private methods
* fix(health): fix exception issue
* fix(health): redact error details for unauthenticated health checks
* fix code quality issues and reduce cognitive complexity
* feat(health): add MySQL health endpoint
* refactor(health): simplify MySQL health check and remove sensitive details
* fix(health): remove unused imports and variables
* refactor(health): address nitpicks (configurable ES scheme, log noise, graceful shutdown, record)
* fix(health): scope PROCESSLIST lock-wait check to application DB user
* refactor(health): remove unused params and reuse response/error constants
* fix(health): remove unused imports and methods
* chore(health): clean up unused imports, params, and dead helpers
* fix(health): avoid sharing JDBC connections across threads in advanced MySQL checks
* refactor(health): reuse REDIS_COMPONENT constant and extract nested try block
* fix(health): avoid blocking DB I/O under write lock and restore interrupt flag
* fix(health): cancel in-flight futures on generic failure
* feat(health,version): add index existance, read-only detection, canary write for elasticsearch health check
* refactor(health): reduce cognitive complexity, remove dead throws, and clean code smells
* Rebase 3.6.2 (#150)
* fix: enable multi-word fuzzy search requirement (#139)
* fix: enable multi-word fuzzy search requirement
* Downgrade version from 3.6.2 to 3.6.1
* fix: multi-word search (#140)
* Fix the column mismatch issue in beneficiary search (#142)
* fix: column mismatch issue
* fix: update marital status
* add new column in rmnch table for death and child record
* add new column in rmnch table for death and child record
* Cherry-pick health and version API enhancements to release-3.6.1 (#145)
* feat(health,version): add health and version endpoints
* feat(health,version): add health and version endpoints without auth
* fix(health): remove unused private methods
* fix(health): fix exception issue
* fix(health): redact error details for unauthenticated health checks
* fix code quality issues and reduce cognitive complexity
* feat(health): add MySQL health endpoint
* refactor(health): simplify MySQL health check and remove sensitive details
* fix(health): remove unused imports and variables
* refactor(health): address nitpicks (configurable ES scheme, log noise, graceful shutdown, record)
* fix(health): scope PROCESSLIST lock-wait check to application DB user
* refactor(health): remove unused params and reuse response/error constants
* fix(health): remove unused imports and methods
* chore(health): clean up unused imports, params, and dead helpers
* fix(health): avoid sharing JDBC connections across threads in advanced MySQL checks
* refactor(health): reuse REDIS_COMPONENT constant and extract nested try block
* fix(health): avoid blocking DB I/O under write lock and restore interrupt flag
* fix(health): cancel in-flight futures on generic failure
* feat(health,version): add index existance, read-only detection, canary write for elasticsearch health check
* refactor(health): reduce cognitive complexity, remove dead throws, and clean code smells
---------
Co-authored-by: Saurav Mishra
Co-authored-by: Saurav Mishra <80103738+SauravBizbRolly@users.noreply.github.com>
Co-authored-by: KOPPIREDDY DURGA PRASAD <144464542+DurgaPrasad-54@users.noreply.github.com>
* feat(jwt): enhance jwt validation logging and public endpoint check (#151)
* fix: pom version (#152)
* Add the missing properties for 1097_Preprod (#153)
* fix: add the missing properties
* fix: update db url
* docs: add CLAUDE.md for Claude Code guidance
* fix: map sexualOrientationID during beneficiary update in 1097
convertIdentityEditDTOToMBeneficiarydetail() was missing sexualOrientationID
and sexualOrientationType, so the field was never persisted on update.
Co-Authored-By: Claude Sonnet 4.6
* Sexual orientation data not reflecting under DB record (#157)
* fix: enable multi-word fuzzy search requirement (#139)
* fix: enable multi-word fuzzy search requirement
* Downgrade version from 3.6.2 to 3.6.1
* fix: multi-word search (#140)
* Fix the column mismatch issue in beneficiary search (#142)
* fix: column mismatch issue
* fix: update marital status
* add new column in rmnch table for death and child record
* add new column in rmnch table for death and child record
* Cherry-pick health and version API enhancements to release-3.6.1 (#145)
* feat(health,version): add health and version endpoints
* feat(health,version): add health and version endpoints without auth
* fix(health): remove unused private methods
* fix(health): fix exception issue
* fix(health): redact error details for unauthenticated health checks
* fix code quality issues and reduce cognitive complexity
* feat(health): add MySQL health endpoint
* refactor(health): simplify MySQL health check and remove sensitive details
* fix(health): remove unused imports and variables
* refactor(health): address nitpicks (configurable ES scheme, log noise, graceful shutdown, record)
* fix(health): scope PROCESSLIST lock-wait check to application DB user
* refactor(health): remove unused params and reuse response/error constants
* fix(health): remove unused imports and methods
* chore(health): clean up unused imports, params, and dead helpers
* fix(health): avoid sharing JDBC connections across threads in advanced MySQL checks
* refactor(health): reuse REDIS_COMPONENT constant and extract nested try block
* fix(health): avoid blocking DB I/O under write lock and restore interrupt flag
* fix(health): cancel in-flight futures on generic failure
* feat(health,version): add index existance, read-only detection, canary write for elasticsearch health check
* refactor(health): reduce cognitive complexity, remove dead throws, and clean code smells
* fix: map sexualOrientationID during beneficiary update in 1097
convertIdentityEditDTOToMBeneficiarydetail() was missing sexualOrientationID
and sexualOrientationType, so the field was never persisted on update.
Co-Authored-By: Claude Sonnet 4.6
---------
Co-authored-by: Vanitha S <116701245+vanitha1822@users.noreply.github.com>
Co-authored-by: Saurav Mishra
Co-authored-by: Saurav Mishra <80103738+SauravBizbRolly@users.noreply.github.com>
Co-authored-by: KOPPIREDDY DURGA PRASAD <144464542+DurgaPrasad-54@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6
* feat: add getBenFamilyDetails API and fix searchFamily queries
- Add POST /family/getBenFamilyDetails endpoint that returns full family
details (master record + all members) for a given beneficiaryRegId
- Fix searchFamily and searchFamilyWithFamilyId queries: replace
noOfmembers > 0 guard with deleted=false filter so families with
zero/null member count and soft-deleted records are handled correctly;
also make villageId optional and use LIKE prefix match for familyName
Co-Authored-By: Claude Sonnet 4.6
* fix: preserve existing occupation and education when incoming values are null
During beneficiary edit, convertIdentityEditDTOToMBeneficiarydetail creates
a fresh entity and overwrites all columns on save. Added null-guards for
occupationId, occupation, educationId, and education so existing DB values
are preserved when the incoming DTO omits them — consistent with the existing
pattern for familyId and headOfFamily_Relation.
Co-Authored-By: Claude Sonnet 4.6
* fix: replace in-memory queue with SELECT FOR UPDATE SKIP LOCKED for BenRegId allocation (#159)
* aam-2126 Memeberlist is not displying properly
* fix: aam-2313 phone number leading with zero - removed zero (#161)
* Allowing numbers with zero is search by phone number. (#162)
* fix: aam-2313 phone number leading with zero - removed zero
* fix: aam-2313 serach by user phone number fix for number leading with zero
---------
Co-authored-by: Saurav Mishra
Co-authored-by: Saurav Mishra <80103738+SauravBizbRolly@users.noreply.github.com>
Co-authored-by: KOPPIREDDY DURGA PRASAD <144464542+DurgaPrasad-54@users.noreply.github.com>
Co-authored-by: SnehaRH
Co-authored-by: Claude Sonnet 4.6
Co-authored-by: SnehaRH <77656297+snehar-nd@users.noreply.github.com>
---
CLAUDE.md | 73 +++++++++++++++
pom.xml | 2 +-
src/main/environment/1097_ci.properties | 1 -
src/main/environment/1097_example.properties | 1 -
.../FamilyTaggingController.java | 14 +++
.../common/identity/repo/BenContactRepo.java | 10 ++-
.../identity/repo/BenRegIdMappingRepo.java | 9 ++
.../repo/familyTag/FamilyTagRepo.java | 8 +-
.../service/BenRegIdClaimService.java | 89 +++++++++++++++++++
.../identity/service/IdentityService.java | 60 +++++++------
.../familyTagging/FamilyTagService.java | 2 +
.../familyTagging/FamilyTagServiceImpl.java | 44 ++++++++-
.../utils/JwtUserIdValidationFilter.java | 7 +-
13 files changed, 279 insertions(+), 41 deletions(-)
create mode 100644 CLAUDE.md
create mode 100644 src/main/java/com/iemr/common/identity/service/BenRegIdClaimService.java
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 00000000..ae3f45c7
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,73 @@
+# CLAUDE.md - Identity-API
+
+## Project Overview
+
+Identity-API is the beneficiary identity management service for the AMRIT platform. It handles beneficiary creation, search, update, and deduplication across dual database profiles (`db_iemr` main and `db_identity`). It supports RMNCH (Reproductive, Maternal, Newborn, Child, and Adolescent Health) data management, family tagging, Elasticsearch-based beneficiary search, and health ID linkage.
+
+## Tech Stack
+
+- Java 17, Spring Boot 3.2.2, Maven
+- Spring Data JPA / Hibernate, MySQL 8.0
+- Elasticsearch (Spring Data Elasticsearch for beneficiary search indexing)
+- Redis for session management
+- Lombok (1.18.36), MapStruct
+- SpringDoc OpenAPI (Swagger UI at `/swagger-ui.html`)
+- ECS logging (logback-ecs-encoder)
+- JaCoCo for test coverage
+- Packaged as WAR for Wildfly deployment
+
+## Build & Run
+
+```bash
+mvn clean install -DENV_VAR=local # Build
+mvn spring-boot:run -DENV_VAR=local # Run locally
+mvn -B package --file pom.xml -P # Package WAR (dev, local, test, ci, uat)
+mvn test # Run tests
+```
+
+Environment config: `src/main/resources/common_.properties` is copied to `application.properties` at build time.
+
+## Key Packages (`com.iemr.common.identity`)
+
+- **controller/** - REST endpoints:
+ - `IdentityController` - Core beneficiary CRUD (create, search, update, search by phone/ID/name)
+ - `IdentityESController` - Elasticsearch-based beneficiary search
+ - `rmnch/RMNCHMobileAppController` - RMNCH mobile app data sync
+ - `familyTagging/FamilyTaggingController` - Family tagging and family search
+ - `elasticsearch/ElasticsearchSyncController` - Elasticsearch sync management
+ - `health/HealthController` - Health check endpoint
+ - `version/VersionController` - API version info
+- **service/** - Business logic:
+ - `IdentityService` - Core identity operations
+ - `rmnch/` - RMNCH beneficiary management
+ - `familyTagging/` - Family tagging logic
+ - `elasticsearch/` - Elasticsearch indexing and sync
+ - `health/` - Health check service
+- **domain/** - Core JPA entities for beneficiary data:
+ - `MBeneficiaryregidmapping` - Beneficiary registration ID mapping
+ - `MBeneficiaryaddress`, `MBeneficiarycontact`, `MBeneficiaryAccount` - Beneficiary demographics
+ - `MBeneficiaryfamilymapping` - Family relationships
+ - `MBeneficiaryconsent` - Consent management
+ - `VBenAdvanceSearch` - View for advanced search queries
+- **data/** - Additional data models:
+ - `rmnch/` - RMNCH-specific entities (CBAC details, born birth details, household details, NCD/TB/HRP data)
+ - `elasticsearch/` - Elasticsearch document models and sync job
+ - `familyTagging/` - Family tagging models
+- **dto/** - Data transfer objects for API requests/responses
+- **repo/** - Spring Data JPA and Elasticsearch repositories
+- **mapper/** - MapStruct mappers for entity-DTO conversion
+- **filter/** - Servlet filters
+- **security/** - Security configuration
+- **utils/** - Utilities (Redis, HTTP, validation, session, gateway, email, exception handling)
+- **config/** - Application configuration
+
+## Architecture Notes
+
+- Dual-profile beneficiary storage: main identity in `db_identity`, with mapping to `db_iemr` for AMRIT platform integration
+- Elasticsearch integration provides fast full-text beneficiary search with background sync jobs
+- RMNCH module handles field-worker mobile app data (CBAC screening, household surveys, birth details)
+- Family tagging enables linking beneficiaries into family units with search by family ID
+- MapStruct mappers handle complex entity-to-DTO transformations
+- Health ID (ABHA) linkage stored per beneficiary for ABDM integration
+- Beneficiary deduplication logic via advanced search views
+- Artifact ID: `identity-api`, group: `com.iemr.common.identity`, version: 3.6.1
diff --git a/pom.xml b/pom.xml
index f29361fd..c3b57f1c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
4.0.0com.iemr.common.identityidentity-api
- 3.6.1
+ 3.6.2war
diff --git a/src/main/environment/1097_ci.properties b/src/main/environment/1097_ci.properties
index 0e8deded..514f675d 100644
--- a/src/main/environment/1097_ci.properties
+++ b/src/main/environment/1097_ci.properties
@@ -24,7 +24,6 @@ spring.redis.host=@env.REDIS_HOST@
cors.allowed-origins=@env.CORS_ALLOWED_ORIGINS@
-
# Elasticsearch Configuration
elasticsearch.host=@env.ELASTICSEARCH_HOST@
elasticsearch.port=@env.ELASTICSEARCH_PORT@
diff --git a/src/main/environment/1097_example.properties b/src/main/environment/1097_example.properties
index ab87d360..ba2f3211 100644
--- a/src/main/environment/1097_example.properties
+++ b/src/main/environment/1097_example.properties
@@ -31,4 +31,3 @@ elasticsearch.index.beneficiary=beneficiary_index
# Enable/Disable ES (for gradual rollout)
elasticsearch.enabled=true
-
diff --git a/src/main/java/com/iemr/common/identity/controller/familyTagging/FamilyTaggingController.java b/src/main/java/com/iemr/common/identity/controller/familyTagging/FamilyTaggingController.java
index 19323611..b347bd50 100644
--- a/src/main/java/com/iemr/common/identity/controller/familyTagging/FamilyTaggingController.java
+++ b/src/main/java/com/iemr/common/identity/controller/familyTagging/FamilyTaggingController.java
@@ -116,6 +116,20 @@ public String untagFamily(@RequestBody String comingReq) {
return response.toString();
}
+ @Operation(summary = "Get family tagging details by beneficiary ID")
+ @PostMapping(value = { "/getBenFamilyDetails" }, consumes = "application/json", produces = "application/json")
+ public String getFamilyDetailsByBeneficiaryId(@RequestBody String comingReq) {
+ OutputResponse response = new OutputResponse();
+ try {
+ String s = familyTagService.getFamilyDetailsByBeneficiaryId(comingReq);
+ response.setResponse(s);
+ } catch (Exception e) {
+ logger.error("Error in fetching family details by beneficiary ID : " + e);
+ response.setError(5000, "Error in fetching family details by beneficiary ID : " + e.getLocalizedMessage());
+ }
+ return response.toString();
+ }
+
@Operation(summary = "Edit beneficiary family details")
@PostMapping(value = { "/editFamilyTagging" }, consumes = "application/json", produces = "application/json")
public String editFamilyDetails(@RequestBody String comingReq) {
diff --git a/src/main/java/com/iemr/common/identity/repo/BenContactRepo.java b/src/main/java/com/iemr/common/identity/repo/BenContactRepo.java
index fdbda216..02334684 100644
--- a/src/main/java/com/iemr/common/identity/repo/BenContactRepo.java
+++ b/src/main/java/com/iemr/common/identity/repo/BenContactRepo.java
@@ -49,8 +49,12 @@ public interface BenContactRepo extends CrudRepository findByPreferredSMSPhoneNumOrderByBenContactsIDAsc(String smsPhoneNum);
- @Query("select c from MBeneficiarycontact c where c.preferredPhoneNum = :phoneNum ")
- List findByAnyPhoneNum(@Param("phoneNum") String phoneNum);
+ // @Query("select c from MBeneficiarycontact c where c.preferredPhoneNum = :phoneNum ")
+ // List findByAnyPhoneNum(@Param("phoneNum") String phoneNum);
+
+ @Query("select c from MBeneficiarycontact c where c.preferredPhoneNum IN :variants")
+ List findByAnyPhoneNum(@Param("variants") List variants);
+
@Query("select c from MBeneficiarycontact c where c.preferredPhoneNum = :phoneNum or c.phoneNum1 = :phoneNum "
@@ -70,4 +74,6 @@ public interface BenContactRepo extends CrudRepository findTop10000ByProvisionedAndReserved(Boolean isProvisioned,Boolean isReserved);
+ /**
+ * Atomically selects and locks the next available registration ID row.
+ * SKIP LOCKED ensures concurrent servers each get a distinct row without blocking each other,
+ * eliminating duplicate BenRegId assignments when multiple app instances share the same database.
+ */
+ @Transactional
+ @Query(value = "SELECT * FROM m_beneficiaryregidmapping WHERE Provisioned = false AND Reserved = false ORDER BY BenRegId ASC LIMIT 1 FOR UPDATE SKIP LOCKED", nativeQuery = true)
+ MBeneficiaryregidmapping findAndLockNextAvailable();
+
}
diff --git a/src/main/java/com/iemr/common/identity/repo/familyTag/FamilyTagRepo.java b/src/main/java/com/iemr/common/identity/repo/familyTag/FamilyTagRepo.java
index 4451fd37..88d05388 100644
--- a/src/main/java/com/iemr/common/identity/repo/familyTag/FamilyTagRepo.java
+++ b/src/main/java/com/iemr/common/identity/repo/familyTag/FamilyTagRepo.java
@@ -42,12 +42,10 @@ public interface FamilyTagRepo extends CrudRepository {
public int untagFamily(@Param("benFamilyTagId") List benFamilyTagId,@Param("modifiedBy") String modifiedBy);
- @Query("SELECT obj FROM BenFamilyMapping obj WHERE obj.familyName =:familyName AND obj.villageId =:villageId AND (obj.noOfmembers is not null "
- + " AND obj.noOfmembers >0)")
+ @Query("SELECT obj FROM BenFamilyMapping obj WHERE obj.familyName LIKE CONCAT(:familyName, '%') AND (:villageId IS NULL OR obj.villageId =:villageId) AND (obj.deleted IS NULL OR obj.deleted = false)")
List searchFamily(@Param("familyName") String familyName,@Param("villageId") Integer villageId);
-
- @Query("SELECT obj FROM BenFamilyMapping obj WHERE obj.familyName =:familyName AND obj.villageId =:villageId AND obj.familyId =:familyId AND (obj.noOfmembers is not null "
- + " AND obj.noOfmembers >0)")
+
+ @Query("SELECT obj FROM BenFamilyMapping obj WHERE obj.familyName LIKE CONCAT(:familyName, '%') AND (:villageId IS NULL OR obj.villageId =:villageId) AND obj.familyId =:familyId AND (obj.deleted IS NULL OR obj.deleted = false)")
List searchFamilyWithFamilyId(@Param("familyName") String familyName,@Param("villageId") Integer villageId,@Param("familyId") String familyId);
@Query("SELECT obj FROM BenFamilyMapping obj WHERE obj.familyId =:familyId")
diff --git a/src/main/java/com/iemr/common/identity/service/BenRegIdClaimService.java b/src/main/java/com/iemr/common/identity/service/BenRegIdClaimService.java
new file mode 100644
index 00000000..ba2c32eb
--- /dev/null
+++ b/src/main/java/com/iemr/common/identity/service/BenRegIdClaimService.java
@@ -0,0 +1,89 @@
+/*
+* AMRIT – Accessible Medical Records via Integrated Technology
+* Integrated EHR (Electronic Health Records) Solution
+*
+* Copyright (C) "Piramal Swasthya Management and Research Institute"
+*
+* This file is part of AMRIT.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see https://www.gnu.org/licenses/.
+*/
+package com.iemr.common.identity.service;
+
+import java.sql.Timestamp;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.iemr.common.identity.domain.MBeneficiaryregidmapping;
+import com.iemr.common.identity.repo.BenRegIdMappingRepo;
+
+/**
+ * Handles atomic beneficiary registration ID claiming.
+ *
+ * Uses SELECT ... FOR UPDATE SKIP LOCKED so that each application instance
+ * obtains a distinct, exclusive row. Multiple servers sharing the same database
+ * will never receive the same BenRegId, preventing
+ * SQLIntegrityConstraintViolationException duplicate-key errors that occurred
+ * with the previous in-memory ArrayDeque queue approach.
+ *
+ * REQUIRES_NEW propagation ensures the SELECT + UPDATE happens in its own
+ * short-lived transaction, releasing the row lock immediately after the ID is
+ * marked reserved — keeping lock contention to a minimum.
+ */
+@Service
+public class BenRegIdClaimService {
+
+ private static final Logger logger = LoggerFactory.getLogger(BenRegIdClaimService.class);
+
+ @Autowired
+ private BenRegIdMappingRepo regIdRepo;
+
+ /**
+ * Atomically claims the next available registration ID.
+ *
+ *
+ *
Opens a brand-new transaction (REQUIRES_NEW).
+ *
Executes SELECT … FOR UPDATE SKIP LOCKED to lock exactly one row.
+ * Concurrent callers on other servers/threads skip the locked row and
+ * get the next one — no two callers ever see the same row.
+ *
Marks the row {@code reserved = true} and flushes it within the same
+ * transaction so the change is visible to other connections the moment
+ * this method returns.
+ *
+ *
+ * @return the reserved {@link MBeneficiaryregidmapping} with {@code reserved=true}
+ * @throws IllegalStateException if the ID pool is exhausted
+ */
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public MBeneficiaryregidmapping claimNextAvailableRegId() {
+ MBeneficiaryregidmapping regMap = regIdRepo.findAndLockNextAvailable();
+ if (regMap == null) {
+ throw new IllegalStateException(
+ "No available registration IDs in the pool. "
+ + "Please contact the system administrator to import more IDs.");
+ }
+ if (regMap.getCreatedDate() == null) {
+ regMap.setCreatedDate(new Timestamp(System.currentTimeMillis()));
+ }
+ regMap.setReserved(true);
+ regMap = regIdRepo.save(regMap);
+ logger.info("BenRegIdClaimService: claimed BenRegId={}", regMap.getBenRegId());
+ return regMap;
+ }
+}
diff --git a/src/main/java/com/iemr/common/identity/service/IdentityService.java b/src/main/java/com/iemr/common/identity/service/IdentityService.java
index 08b9fbbe..afb193e3 100644
--- a/src/main/java/com/iemr/common/identity/service/IdentityService.java
+++ b/src/main/java/com/iemr/common/identity/service/IdentityService.java
@@ -25,8 +25,8 @@
import java.math.BigInteger;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
-import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@@ -154,6 +154,8 @@ private JdbcTemplate getJdbcTemplate() {
@Autowired
BenRegIdMappingRepo regIdRepo;
@Autowired
+ private BenRegIdClaimService benRegIdClaimService;
+ @Autowired
BenServiceMappingRepo serviceMapRepo;
@Autowired
MBeneficiaryAccountRepo accountRepo;
@@ -555,7 +557,15 @@ public List getBeneficiariesByPhoneNum(String phoneNum)
List list = new ArrayList<>();
try {
- List benContact = contactRepo.findByAnyPhoneNum(phoneNum);
+ // List benContact = contactRepo.findByAnyPhoneNum(phoneNum);
+
+ String clean = phoneNum.trim();
+ if (clean.startsWith("+91")) clean = clean.substring(3);
+ else if (clean.startsWith("91") && clean.length() == 12) clean = clean.substring(2);
+ else if (clean.startsWith("0") && clean.length() == 11) clean = clean.substring(1);
+
+ List variants = Arrays.asList(clean, "0" + clean, "91" + clean, "+91" + clean);
+ List benContact = contactRepo.findByAnyPhoneNum(variants);
logger.info(benContact.size() + " contacts found for phone number " + phoneNum);
@@ -1038,6 +1048,18 @@ public void editIdentity(IdentityEditDTO identity) throws MissingMandatoryFields
if (benDetails.getOther() != null) {
mbDetl.setOther(benDetails.getOther());
}
+ if (mbDetl.getOccupationId() == null && benDetails.getOccupationId() != null) {
+ mbDetl.setOccupationId(benDetails.getOccupationId());
+ }
+ if (mbDetl.getOccupation() == null && benDetails.getOccupation() != null) {
+ mbDetl.setOccupation(benDetails.getOccupation());
+ }
+ if (mbDetl.getEducationId() == null && benDetails.getEducationId() != null) {
+ mbDetl.setEducationId(benDetails.getEducationId());
+ }
+ if (mbDetl.getEducation() == null && benDetails.getEducation() != null) {
+ mbDetl.setEducation(benDetails.getEducation());
+ }
// Extract and set extra fields
// String identityJson = new Gson().toJson(json);
@@ -1337,6 +1359,8 @@ private MBeneficiarydetail convertIdentityEditDTOToMBeneficiarydetail(IdentityEd
if (dto.getOtherFields() != null) {
beneficiarydetail.setOtherFields(dto.getOtherFields());
}
+ beneficiarydetail.setSexualOrientationID(dto.getSexualOrientationID());
+ beneficiarydetail.setSexualOrientationType(dto.getSexualOrientationType());
return beneficiarydetail;
}
@@ -1345,34 +1369,13 @@ private MBeneficiarydetail convertIdentityEditDTOToMBeneficiarydetail(IdentityEd
* @param identity
* @return
*/
- ArrayDeque queue = new ArrayDeque<>();
-
public BeneficiaryCreateResp createIdentity(IdentityDTO identity) {
logger.info("IdentityService.createIdentity - start");
- List list = null;
- MBeneficiaryregidmapping regMap = null;
- synchronized (queue) {
- if (queue.isEmpty()) {
- logger.info("fetching 10000 rows");
- list = regIdRepo.findTop10000ByProvisionedAndReserved(false, false);
- logger.info("Adding SynchronousQueue start-- ");
- for (MBeneficiaryregidmapping map : list) {
- queue.add(map);
- }
- logger.info("Adding SynchronousQueue end-- ");
- }
- regMap = queue.removeFirst();
- }
- regMap.setReserved(true);
- if (regMap.getCreatedDate() == null) {
- SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT);
- String dateToStoreInDataBase = sdf.format(new Date());
- Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase);
- regMap.setCreatedDate(ts);
- }
-
- regIdRepo.save(regMap);
+ // Atomically claim the next available ID using SELECT … FOR UPDATE SKIP LOCKED.
+ // This is safe across multiple app servers sharing the same database — each server
+ // locks and reserves a distinct row, so duplicate BenRegId inserts cannot occur.
+ MBeneficiaryregidmapping regMap = benRegIdClaimService.claimNextAvailableRegId();
regMap.setProvisioned(true);
@@ -1665,6 +1668,9 @@ private String cleanPhoneNumber(String phoneNumber) {
} else if (cleaned.startsWith("91") && cleaned.length() == 12) {
// Handle case where + is already removed but 91 remains
cleaned = cleaned.substring(2);
+ } else if (cleaned.startsWith("0") && cleaned.length() == 11) {
+ // Handle case where number starts with 0 and is 11 digits long
+ cleaned = cleaned.substring(1);
}
return cleaned.trim();
diff --git a/src/main/java/com/iemr/common/identity/service/familyTagging/FamilyTagService.java b/src/main/java/com/iemr/common/identity/service/familyTagging/FamilyTagService.java
index 85e8cfba..5bf22b36 100644
--- a/src/main/java/com/iemr/common/identity/service/familyTagging/FamilyTagService.java
+++ b/src/main/java/com/iemr/common/identity/service/familyTagging/FamilyTagService.java
@@ -36,4 +36,6 @@ public interface FamilyTagService {
public String searchFamily(String request) throws IEMRException;
public String editFamilyDetails(String request) throws IEMRException;
+
+ public String getFamilyDetailsByBeneficiaryId(String request) throws IEMRException;
}
diff --git a/src/main/java/com/iemr/common/identity/service/familyTagging/FamilyTagServiceImpl.java b/src/main/java/com/iemr/common/identity/service/familyTagging/FamilyTagServiceImpl.java
index 2a60571b..f44eecf8 100644
--- a/src/main/java/com/iemr/common/identity/service/familyTagging/FamilyTagServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/familyTagging/FamilyTagServiceImpl.java
@@ -37,6 +37,7 @@
import com.google.gson.JsonParser;
import com.iemr.common.identity.data.familyTagging.BenFamilyMapping;
import com.iemr.common.identity.data.familyTagging.FamilyMembers;
+import com.iemr.common.identity.data.familyTagging.FamilySearchResponse;
import com.iemr.common.identity.domain.MBeneficiarydetail;
import com.iemr.common.identity.domain.MBeneficiarymapping;
import com.iemr.common.identity.exception.IEMRException;
@@ -264,10 +265,49 @@ public String getFamilyDetails(String request) throws IEMRException {
throw new IEMRException("Error while fetching family member details :" + e.getLocalizedMessage());
}
}
+ @Override
+ public String getFamilyDetailsByBeneficiaryId(String request) throws IEMRException {
+ try {
+ BenFamilyMapping reqObj = InputMapper.gson().fromJson(request, BenFamilyMapping.class);
+ if (reqObj.getBeneficiaryRegId() == null)
+ throw new IEMRException("beneficiaryRegId is required");
+
+ MBeneficiarymapping mapping = benMappingRepo
+ .getBenDetailsId(BigInteger.valueOf(reqObj.getBeneficiaryRegId()));
+ if (mapping == null || mapping.getBenDetailsId() == null)
+ throw new IEMRException("Beneficiary not found");
+
+ List benDetails = benDetailRepo
+ .findByBeneficiaryDetailsIdOrderByBeneficiaryDetailsIdAsc(mapping.getBenDetailsId());
+ if (benDetails == null || benDetails.isEmpty() || benDetails.get(0).getFamilyId() == null)
+ return "No family tagged to this beneficiary";
+
+ String familyId = benDetails.get(0).getFamilyId();
+
+ BenFamilyMapping familyMaster = familyTagRepo.searchFamilyByFamilyId(familyId);
+ List memberList = benDetailRepo.getFamilyDetails(familyId);
+
+ FamilySearchResponse resp = new FamilySearchResponse();
+ if (familyMaster != null) {
+ resp.setFamilyId(familyMaster.getFamilyId());
+ resp.setFamilyName(familyMaster.getFamilyName());
+ resp.setHeadOfTheFamily(familyMaster.getFamilyHeadName());
+ resp.setNoOfMembers(familyMaster.getNoOfmembers());
+ }
+ List memberResponseList = new ArrayList<>();
+ addFamilyMembersToList(memberList, memberResponseList);
+ resp.setFamilyMembers(memberResponseList);
+
+ return new Gson().toJson(resp);
+ } catch (Exception e) {
+ throw new IEMRException(
+ "Error while fetching family details by beneficiary ID : " + e.getLocalizedMessage());
+ }
+ }
+
private void addFamilyMembersToList(List list, List responseList) {
- StringBuilder name = new StringBuilder("");
for (MBeneficiarydetail obj : list) {
-
+ StringBuilder name = new StringBuilder("");
FamilyMembers famObj = new FamilyMembers();
BigInteger benRegId = benMappingRepo.getBenRegId(obj.getBeneficiaryDetailsId(), obj.getVanID());
if (benRegId != null)
diff --git a/src/main/java/com/iemr/common/identity/utils/JwtUserIdValidationFilter.java b/src/main/java/com/iemr/common/identity/utils/JwtUserIdValidationFilter.java
index af81ea34..cf959aa6 100644
--- a/src/main/java/com/iemr/common/identity/utils/JwtUserIdValidationFilter.java
+++ b/src/main/java/com/iemr/common/identity/utils/JwtUserIdValidationFilter.java
@@ -43,10 +43,13 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo
return;
}
String path = request.getRequestURI();
- logger.info("JwtUserIdValidationFilter invoked for path: {}", path);
+
+ String servletPath = request.getServletPath();
+ logger.info("JwtUserIdValidationFilter invoked for requestURI: {}, servletPath: {}", path, servletPath);
// Skip JWT validation for public endpoints
- if (path.equals("/health") || path.equals("/version")) {
+ if (servletPath.equals("/health") || servletPath.equals("/version") ||
+ path.endsWith("/health") || path.endsWith("/version")) {
logger.info("Public endpoint accessed: {} - skipping JWT validation", path);
filterChain.doFilter(servletRequest, servletResponse);
return;
From 93d43907f9fcd38723165ca5c9e896207f88f383 Mon Sep 17 00:00:00 2001
From: vishwab1
Date: Fri, 5 Jun 2026 16:15:22 +0530
Subject: [PATCH 03/62] feat: write anthropometry from rmnch/syncDataToAmrit to
i_beneficiarydetails.otherFields
Mobile sends height/weight/bmi/temperature in beneficiaryDetails payload.
i_beneficiarydetails_rmnch has no these columns so they were lost.
FLW-API getBeneficiaryData reads from otherFields (temperatureValue key).
- RMNCHBeneficiaryDetailsRmnch: @Transient height/weight/bmi/temperature
- BenDetailRepo: updateOtherFieldsByBenRegId query
- RmnchDataSyncServiceImpl: merge anthropometry into otherFields after save
Co-Authored-By: Claude Sonnet 4.6
---
.../rmnch/RMNCHBeneficiaryDetailsRmnch.java | 15 +++++++
.../common/identity/repo/BenDetailRepo.java | 5 +++
.../rmnch/RmnchDataSyncServiceImpl.java | 43 ++++++++++++++++++-
3 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHBeneficiaryDetailsRmnch.java b/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHBeneficiaryDetailsRmnch.java
index 4cab210c..c0b5c864 100644
--- a/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHBeneficiaryDetailsRmnch.java
+++ b/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHBeneficiaryDetailsRmnch.java
@@ -550,4 +550,19 @@ public class RMNCHBeneficiaryDetailsRmnch {
@Expose
private Boolean isDeactivate;
+ // Anthropometry fields sent by Stop TB mobile app via beneficiaryDetails payload.
+ // i_beneficiarydetails_rmnch has no these columns — stored in i_beneficiarydetails.otherFields instead.
+ @Expose
+ @Transient
+ private Double height;
+ @Expose
+ @Transient
+ private Double weight;
+ @Expose
+ @Transient
+ private Double bmi;
+ @Expose
+ @Transient
+ private Double temperature; // stored as "temperatureValue" in otherFields to match getBeneficiaryData key
+
}
diff --git a/src/main/java/com/iemr/common/identity/repo/BenDetailRepo.java b/src/main/java/com/iemr/common/identity/repo/BenDetailRepo.java
index 4e8bcc01..413298ba 100644
--- a/src/main/java/com/iemr/common/identity/repo/BenDetailRepo.java
+++ b/src/main/java/com/iemr/common/identity/repo/BenDetailRepo.java
@@ -148,6 +148,11 @@ int untagFamily(@Param("modifiedBy") String modifiedBy, @Param("vanSerialNo") Bi
@Query("SELECT b FROM MBeneficiarydetail b WHERE b.familyId =:familyid ")
List searchByFamilyId(@Param("familyid") String familyid);
+ @Transactional
+ @Modifying
+ @Query("UPDATE MBeneficiarydetail d SET d.otherFields = :otherFields WHERE d.mBeneficiarymapping.benRegId = :benRegId")
+ int updateOtherFieldsByBenRegId(@Param("benRegId") BigInteger benRegId, @Param("otherFields") String otherFields);
+
/**
* Find complete beneficiary data by IDs from Elasticsearch
*/
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
index bd973193..43d715ee 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
@@ -72,6 +72,8 @@
import com.iemr.common.identity.repo.rmnch.RMNCHCBACDetailsRepo;
import com.iemr.common.identity.repo.rmnch.RMNCHHouseHoldDetailsRepo;
import com.iemr.common.identity.repo.rmnch.RMNCHMBenMappingRepo;
+import com.iemr.common.identity.domain.MBeneficiarydetail;
+import com.iemr.common.identity.repo.BenDetailRepo;
import com.iemr.common.identity.repo.rmnch.RMNCHMBenRegIdMapRepo;
import com.iemr.common.identity.utils.config.ConfigProperties;
import com.iemr.common.identity.utils.exception.IEMRException;
@@ -110,7 +112,8 @@ public class RmnchDataSyncServiceImpl implements RmnchDataSyncService {
private RMNCHBenContactRepo rMNCHBenContactRepo;
@Autowired
private RMNCHMBenRegIdMapRepo rMNCHMBenRegIdMapRepo;
-
+ @Autowired
+ private BenDetailRepo benDetailRepo;
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
@Override
public String syncDataToAmrit(String requestOBJ) throws Exception {
@@ -190,6 +193,22 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
// update beneficiary data in i_beneficiarydetails table
rMNCHBenDetailsRepo.saveAll(benDetailsList);
+ // Write anthropometry (height/weight/bmi/temperature) to i_beneficiarydetails.otherFields.
+ // i_beneficiarydetails_rmnch has no these columns; FLW-API getBeneficiaryData reads from otherFields.
+ for (RMNCHBeneficiaryDetailsRmnch obj : benDetailsExtraList) {
+ if (obj.getBenRegId() != null && hasAnthropometryData(obj)) {
+ try {
+ MBeneficiarydetail benDetail = benDetailRepo.findByBenRegId(obj.getBenRegId());
+ if (benDetail != null) {
+ String merged = mergeAnthropometry(benDetail.getOtherFields(), obj);
+ benDetailRepo.updateOtherFieldsByBenRegId(obj.getBenRegId(), merged);
+ }
+ } catch (Exception ex) {
+ logger.warn("Failed to update otherFields for benRegId: " + obj.getBenRegId() + " - " + ex.getMessage());
+ }
+ }
+ }
+
// born birth details
if (jsnOBJ != null && jsnOBJ.has("bornBirthDeatils")) {
RMNCHBornBirthDetails[] objArr1 = InputMapper.gson()
@@ -267,6 +286,28 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
return new Gson().toJson(resultMap);
}
+
+ private boolean hasAnthropometryData(RMNCHBeneficiaryDetailsRmnch obj) {
+ return obj.getHeight() != null || obj.getWeight() != null
+ || obj.getBmi() != null || obj.getTemperature() != null;
+ }
+
+ private String mergeAnthropometry(String existingOtherFields, RMNCHBeneficiaryDetailsRmnch obj) {
+ JsonObject json = new JsonObject();
+ if (existingOtherFields != null && !existingOtherFields.isBlank()) {
+ try {
+ json = new JsonParser().parse(existingOtherFields).getAsJsonObject();
+ } catch (Exception ignored) {
+ }
+ }
+ if (obj.getHeight() != null) json.addProperty("height", obj.getHeight());
+ if (obj.getWeight() != null) json.addProperty("weight", obj.getWeight());
+ if (obj.getBmi() != null) json.addProperty("bmi", obj.getBmi());
+ // mobile sends "temperature"; FLW-API getBeneficiaryData reads "temperatureValue"
+ if (obj.getTemperature() != null) json.addProperty("temperatureValue", obj.getTemperature());
+ return new Gson().toJson(json);
+ }
+
@Override
public String getBenData(String requestOBJ, String authorisation) throws Exception {
String outputResponse = null;
From 1f4fa23ab16d1e69aa0d394c63543c9c987e266b Mon Sep 17 00:00:00 2001
From: vishwab1
Date: Fri, 5 Jun 2026 17:56:21 +0530
Subject: [PATCH 04/62] feat: stamp vanID from Redis on all 4 RMNCH entities in
syncDataToAmrit
Reads camp:vanID and camp:parkingPlaceID from Redis (written by MMU-API
on van login) and stamps them onto RMNCHBeneficiaryDetailsRmnch,
RMNCHBornBirthDetails, RMNCHCBACdetails, and RMNCHHouseHoldDetails when
the mobile payload carries VanID=null or 0. Also writes anthropometry
(height/weight/bmi/temperature) from mobile beneficiaryDetails payload
into i_beneficiarydetails.otherFields so FLW-API getBeneficiaryData can
return them. Gracefully skips if Redis has no camp configured.
Co-Authored-By: Claude Sonnet 4.6
---
.../rmnch/RmnchDataSyncServiceImpl.java | 33 +++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
index 43d715ee..2205001d 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
@@ -74,6 +74,7 @@
import com.iemr.common.identity.repo.rmnch.RMNCHMBenMappingRepo;
import com.iemr.common.identity.domain.MBeneficiarydetail;
import com.iemr.common.identity.repo.BenDetailRepo;
+import com.iemr.common.identity.utils.redis.RedisStorage;
import com.iemr.common.identity.repo.rmnch.RMNCHMBenRegIdMapRepo;
import com.iemr.common.identity.utils.config.ConfigProperties;
import com.iemr.common.identity.utils.exception.IEMRException;
@@ -114,6 +115,8 @@ public class RmnchDataSyncServiceImpl implements RmnchDataSyncService {
private RMNCHMBenRegIdMapRepo rMNCHMBenRegIdMapRepo;
@Autowired
private BenDetailRepo benDetailRepo;
+ @Autowired
+ private RedisStorage redisStorage;
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
@Override
public String syncDataToAmrit(String requestOBJ) throws Exception {
@@ -125,6 +128,20 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
ArrayList cBACDetailsIds = new ArrayList<>();
ArrayList houseHoldDetailsIds = new ArrayList<>();
+ // Read camp vanID/parkingPlaceID from Redis (set by MMU-API on van login)
+ Integer campVanID = null;
+ Integer campParkingPlaceID = null;
+ try {
+ String vanVal = redisStorage.getObject("camp:vanID", false, 0);
+ String ppVal = redisStorage.getObject("camp:parkingPlaceID", false, 0);
+ if (vanVal != null && !vanVal.isBlank()) campVanID = Integer.parseInt(vanVal);
+ if (ppVal != null && !ppVal.isBlank()) campParkingPlaceID = Integer.parseInt(ppVal);
+ } catch (Exception ignored) {
+ // no camp configured — vanID stamping skipped
+ }
+ final Integer vanID = campVanID;
+ final Integer parkingPlaceID = campParkingPlaceID;
+
try {
if (requestOBJ != null && !requestOBJ.isEmpty()) {
JsonObject jsnOBJ = new JsonObject();
@@ -168,6 +185,10 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
}
obj.setRelatedBeneficiaryIdsDB(sb.toString());
}
+ if (obj.getVanID() == null && vanID != null) {
+ obj.setVanID(vanID);
+ obj.setParkingPlaceID(parkingPlaceID);
+ }
RMNCHMBeneficiarydetail rmnchmBeneficiarydetail =
rMNCHBenDetailsRepo.getByBenRegID(obj.getBenRegId());
if (rmnchmBeneficiarydetail != null) {
@@ -220,6 +241,10 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
RMNCHBornBirthDetails temp = rMNCHBornBirthDetailsRepo.getByRegID(benRegID);
if (temp != null)
obj.setBornBirthDeatilsId(temp.getBornBirthDeatilsId());
+ if (obj.getVanID() == null && vanID != null) {
+ obj.setVanID(vanID);
+ obj.setParkingPlaceID(parkingPlaceID);
+ }
}
bornBirthList = (ArrayList) rMNCHBornBirthDetailsRepo
.saveAll(bornBirthList);
@@ -243,6 +268,10 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
RMNCHCBACdetails temp = rMNCHCBACDetailsRepo.getByRegID(benRegID);
if (temp != null)
obj.setCBACDetailsid(temp.getCBACDetailsid());
+ if (obj.getVanID() == null && vanID != null) {
+ obj.setVanID(vanID);
+ obj.setParkingPlaceID(parkingPlaceID);
+ }
}
cbacList = (ArrayList) rMNCHCBACDetailsRepo.saveAll(cbacList);
@@ -260,6 +289,10 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
.getByHouseHoldID(obj.getHouseoldId());
if (temp != null)
obj.setHouseHoldDetailsId(temp.getHouseHoldDetailsId());
+ if (obj.getVanID() == null && vanID != null) {
+ obj.setVanID(vanID);
+ obj.setParkingPlaceID(parkingPlaceID);
+ }
}
houseHoldList = (ArrayList) rMNCHHouseHoldDetailsRepo
.saveAll(houseHoldList);
From 09d88f650e38e64c4f11ff73bac982d6633d4fa7 Mon Sep 17 00:00:00 2001
From: vishwab1
Date: Fri, 5 Jun 2026 18:23:47 +0530
Subject: [PATCH 05/62] fix: preserve @Transient anthropometry fields lost
after JPA saveAll merge
Hibernate merge() returns new managed instances that do not carry
@Transient field values (height/weight/bmi/temperature). Keep a
reference to the original list before saveAll so the anthropometry
loop reads from objects that still have the mobile payload values.
Co-Authored-By: Claude Sonnet 4.6
---
.../identity/service/rmnch/RmnchDataSyncServiceImpl.java | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
index 2205001d..754e574e 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
@@ -207,6 +207,9 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
}
+ // Keep original list before saveAll — @Transient fields (height/weight/bmi/temperature)
+ // are lost in the JPA-managed instances returned by merge()
+ List benDetailsOriginalList = new ArrayList<>(benDetailsExtraList);
benDetailsExtraList = (ArrayList) rMNCHBeneficiaryDetailsRmnchRepo
.saveAll(benDetailsExtraList);
@@ -216,7 +219,7 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
// Write anthropometry (height/weight/bmi/temperature) to i_beneficiarydetails.otherFields.
// i_beneficiarydetails_rmnch has no these columns; FLW-API getBeneficiaryData reads from otherFields.
- for (RMNCHBeneficiaryDetailsRmnch obj : benDetailsExtraList) {
+ for (RMNCHBeneficiaryDetailsRmnch obj : benDetailsOriginalList) {
if (obj.getBenRegId() != null && hasAnthropometryData(obj)) {
try {
MBeneficiarydetail benDetail = benDetailRepo.findByBenRegId(obj.getBenRegId());
From 23675d23532bafdc21801ccd84b905c38cd42c55 Mon Sep 17 00:00:00 2001
From: vishwab1
Date: Fri, 12 Jun 2026 13:56:10 +0530
Subject: [PATCH 06/62] fix: prevent camp:vanID deletion on every
syncDataToAmrit call
getObject("camp:vanID", false, 0) was calling EXPIRE key 0 which
immediately deletes the key in Redis after every sync. Replaced with
getRaw() which reads the value without modifying TTL, so camp:vanID
persists across multiple syncs until MMU logout.
Co-Authored-By: Claude Sonnet 4.6
---
.../identity/service/rmnch/RmnchDataSyncServiceImpl.java | 4 ++--
.../com/iemr/common/identity/utils/redis/RedisStorage.java | 7 +++++++
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
index 754e574e..efbfc210 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
@@ -132,8 +132,8 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
Integer campVanID = null;
Integer campParkingPlaceID = null;
try {
- String vanVal = redisStorage.getObject("camp:vanID", false, 0);
- String ppVal = redisStorage.getObject("camp:parkingPlaceID", false, 0);
+ String vanVal = redisStorage.getRaw("camp:vanID");
+ String ppVal = redisStorage.getRaw("camp:parkingPlaceID");
if (vanVal != null && !vanVal.isBlank()) campVanID = Integer.parseInt(vanVal);
if (ppVal != null && !ppVal.isBlank()) campParkingPlaceID = Integer.parseInt(ppVal);
} catch (Exception ignored) {
diff --git a/src/main/java/com/iemr/common/identity/utils/redis/RedisStorage.java b/src/main/java/com/iemr/common/identity/utils/redis/RedisStorage.java
index 04a3f1d8..98ced6fa 100644
--- a/src/main/java/com/iemr/common/identity/utils/redis/RedisStorage.java
+++ b/src/main/java/com/iemr/common/identity/utils/redis/RedisStorage.java
@@ -67,6 +67,13 @@ public String getObject(String key, Boolean extendExpirationTime, int expiration
return userRespFromRedis;
}
+ public String getRaw(String key) {
+ RedisConnection redCon = connection.getConnection();
+ byte[] data = redCon.get(key.getBytes());
+ redCon.close();
+ return data != null ? new String(data) : null;
+ }
+
public Long deleteObject(String key) throws RedisSessionException {
RedisConnection redCon = connection.getConnection();
Long userRespFromRedis = Long.valueOf(0L);
From 68df190ea20b453b8ddc7d3454e915c11e640193 Mon Sep 17 00:00:00 2001
From: vishwab1
Date: Tue, 16 Jun 2026 16:32:08 +0530
Subject: [PATCH 07/62] feat(stoptb): add stoptb.enforce.vanid flag to
syncDataToAmrit
The Stop TB mobile app calls this RMNCH sync endpoint directly to save
household details. Same issue as elsewhere: vanID stamping is skipped
silently when Redis has no camp:vanID, so household records end up
with vanID=NULL. When stoptb.enforce.vanid=true, sync now fails with a
clear error instead.
---
src/main/environment/common_ci.properties | 3 +++
src/main/environment/common_docker.properties | 3 +++
src/main/environment/common_example.properties | 5 +++++
.../identity/service/rmnch/RmnchDataSyncServiceImpl.java | 9 +++++++++
4 files changed, 20 insertions(+)
diff --git a/src/main/environment/common_ci.properties b/src/main/environment/common_ci.properties
index 98736180..916f5712 100644
--- a/src/main/environment/common_ci.properties
+++ b/src/main/environment/common_ci.properties
@@ -22,6 +22,9 @@ fhir-url=@env.FHIR_API@
# Redis Config
spring.redis.host=@env.REDIS_HOST@
+# Stop TB: when true, RMNCH data sync fails with an error if camp (vanID) is not configured
+stoptb.enforce.vanid=@env.STOPTB_ENFORCE_VANID@
+
cors.allowed-origins=@env.CORS_ALLOWED_ORIGINS@
# Elasticsearch Configuration
diff --git a/src/main/environment/common_docker.properties b/src/main/environment/common_docker.properties
index 8f66c5b0..5aa71373 100644
--- a/src/main/environment/common_docker.properties
+++ b/src/main/environment/common_docker.properties
@@ -22,6 +22,9 @@ fhir-url=${FHIR_API}
# Redis Config
spring.redis.host=${REDIS_HOST}
+# Stop TB: when true, RMNCH data sync fails with an error if camp (vanID) is not configured
+stoptb.enforce.vanid=${STOPTB_ENFORCE_VANID}
+
cors.allowed-origins=${CORS_ALLOWED_ORIGINS}
# Elasticsearch Configuration
diff --git a/src/main/environment/common_example.properties b/src/main/environment/common_example.properties
index 28eda5ea..bbc5251b 100644
--- a/src/main/environment/common_example.properties
+++ b/src/main/environment/common_example.properties
@@ -17,6 +17,11 @@ fhir-url=http://localhost:8093/
# Redis Config
spring.redis.host=localhost
+
+# Stop TB: when true, RMNCH data sync fails with an error if camp (vanID) is not
+# configured instead of silently skipping vanID stamping
+stoptb.enforce.vanid=false
+
cors.allowed-origins=http://localhost:*
# Elasticsearch Configuration
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
index efbfc210..4de97f6f 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
@@ -117,6 +117,11 @@ public class RmnchDataSyncServiceImpl implements RmnchDataSyncService {
private BenDetailRepo benDetailRepo;
@Autowired
private RedisStorage redisStorage;
+
+ // When true, sync fails loudly if camp is not configured instead of silently
+ // skipping vanID stamping
+ @Value("${stoptb.enforce.vanid:false}")
+ private boolean enforceVanID;
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
@Override
public String syncDataToAmrit(String requestOBJ) throws Exception {
@@ -139,6 +144,10 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
} catch (Exception ignored) {
// no camp configured — vanID stamping skipped
}
+ if (campVanID == null && enforceVanID) {
+ throw new Exception(
+ "Camp not configured: vanID missing. Please select van/service point in MMU before syncing data.");
+ }
final Integer vanID = campVanID;
final Integer parkingPlaceID = campParkingPlaceID;
From caa8e349c05b42c429fa21bec674c272823ec786 Mon Sep 17 00:00:00 2001
From: vishwab1
Date: Tue, 16 Jun 2026 16:33:49 +0530
Subject: [PATCH 08/62] chore: bump version to 3.8.2
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 06f2a240..613011c5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
4.0.0com.iemr.common.identityidentity-api
- 3.6.2
+ 3.8.2war
From 5367efaedd595cd71e978febd62cb5bd72f8fcdb Mon Sep 17 00:00:00 2001
From: Saurav Mishra
Date: Tue, 16 Jun 2026 17:43:42 +0530
Subject: [PATCH 09/62] fix duplicate ben id issue
---
.../repo/rmnch/RMNCHBenDetailsRepo.java | 3 +-
.../repo/rmnch/RMNCHHouseHoldDetailsRepo.java | 6 ++-
.../rmnch/RmnchDataSyncServiceImpl.java | 50 +++++++++++--------
3 files changed, 36 insertions(+), 23 deletions(-)
diff --git a/src/main/java/com/iemr/common/identity/repo/rmnch/RMNCHBenDetailsRepo.java b/src/main/java/com/iemr/common/identity/repo/rmnch/RMNCHBenDetailsRepo.java
index 104fe902..1bc948a3 100644
--- a/src/main/java/com/iemr/common/identity/repo/rmnch/RMNCHBenDetailsRepo.java
+++ b/src/main/java/com/iemr/common/identity/repo/rmnch/RMNCHBenDetailsRepo.java
@@ -22,6 +22,7 @@
package com.iemr.common.identity.repo.rmnch;
import java.math.BigInteger;
+import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
@@ -38,5 +39,5 @@ public RMNCHMBeneficiarydetail getByIdAndVanID(@Param("vanSerialNo") BigInteger
@Query(" SELECT t FROM RMNCHMBeneficiarydetail t WHERE t.id = " +
"(SELECT m.benDetailsId from RMNCHMBeneficiarymapping m where m.benRegId = :beneficiaryRegID)")
- public RMNCHMBeneficiarydetail getByBenRegID(@Param("beneficiaryRegID") BigInteger beneficiaryRegID);
+ public List getByBenRegID(@Param("beneficiaryRegID") BigInteger beneficiaryRegID);
}
diff --git a/src/main/java/com/iemr/common/identity/repo/rmnch/RMNCHHouseHoldDetailsRepo.java b/src/main/java/com/iemr/common/identity/repo/rmnch/RMNCHHouseHoldDetailsRepo.java
index 4aed3c87..76490cbd 100644
--- a/src/main/java/com/iemr/common/identity/repo/rmnch/RMNCHHouseHoldDetailsRepo.java
+++ b/src/main/java/com/iemr/common/identity/repo/rmnch/RMNCHHouseHoldDetailsRepo.java
@@ -28,11 +28,13 @@
import com.iemr.common.identity.data.rmnch.RMNCHHouseHoldDetails;
+import java.util.List;
+
@Repository
public interface RMNCHHouseHoldDetailsRepo extends CrudRepository {
@Query(" SELECT t FROM RMNCHHouseHoldDetails t WHERE t.id = :vanSerialNo AND t.VanID = :vanID")
public RMNCHHouseHoldDetails getByIdAndVanID(@Param("vanSerialNo") long vanSerialNo, @Param("vanID") int vanID);
- @Query(" SELECT t FROM RMNCHHouseHoldDetails t WHERE t.houseoldId =:houseoldId ")
- public RMNCHHouseHoldDetails getByHouseHoldID(@Param("houseoldId") long houseoldId);
+ @Query("SELECT t FROM RMNCHHouseHoldDetails t WHERE t.houseoldId = :houseoldId")
+ List getByHouseHoldID(@Param("houseoldId") long houseoldId);
}
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
index 568d4c1a..8b1e73da 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
@@ -167,20 +167,22 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
}
obj.setRelatedBeneficiaryIdsDB(sb.toString());
}
- RMNCHMBeneficiarydetail rmnchmBeneficiarydetail =
- rMNCHBenDetailsRepo.getByBenRegID(obj.getBenRegId());
- if (rmnchmBeneficiarydetail != null) {
- rmnchmBeneficiarydetail.setFirstName(obj.getFirstName());
- rmnchmBeneficiarydetail.setLastName(obj.getLastName());
- rmnchmBeneficiarydetail.setFatherName(obj.getFatherName());
- rmnchmBeneficiarydetail.setMotherName(obj.getMotherName());
- rmnchmBeneficiarydetail.setDob(obj.getDob());
- rmnchmBeneficiarydetail.setSpousename(obj.getSpousename());
- rmnchmBeneficiarydetail.setGender(obj.getGender());
- rmnchmBeneficiarydetail.setGenderId(obj.getGenderId());
- rmnchmBeneficiarydetail.setMaritalstatus(obj.getMaritalstatus());
- rmnchmBeneficiarydetail.setMaritalstatusId(obj.getMaritalstatusId());
- benDetailsList.add(rmnchmBeneficiarydetail);
+ if(!rMNCHBenDetailsRepo.getByBenRegID(obj.getBenRegId()).isEmpty()){
+ RMNCHMBeneficiarydetail rmnchmBeneficiarydetail =
+ rMNCHBenDetailsRepo.getByBenRegID(obj.getBenRegId()).get(0);
+ if (rmnchmBeneficiarydetail != null) {
+ rmnchmBeneficiarydetail.setFirstName(obj.getFirstName());
+ rmnchmBeneficiarydetail.setLastName(obj.getLastName());
+ rmnchmBeneficiarydetail.setFatherName(obj.getFatherName());
+ rmnchmBeneficiarydetail.setMotherName(obj.getMotherName());
+ rmnchmBeneficiarydetail.setDob(obj.getDob());
+ rmnchmBeneficiarydetail.setSpousename(obj.getSpousename());
+ rmnchmBeneficiarydetail.setGender(obj.getGender());
+ rmnchmBeneficiarydetail.setGenderId(obj.getGenderId());
+ rmnchmBeneficiarydetail.setMaritalstatus(obj.getMaritalstatus());
+ rmnchmBeneficiarydetail.setMaritalstatusId(obj.getMaritalstatusId());
+ benDetailsList.add(rmnchmBeneficiarydetail);
+ }
}
}
@@ -239,10 +241,14 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
List houseHoldList = Arrays.asList(objArr3);
for (RMNCHHouseHoldDetails obj : houseHoldList) {
- RMNCHHouseHoldDetails temp = rMNCHHouseHoldDetailsRepo
- .getByHouseHoldID(obj.getHouseoldId());
- if (temp != null)
- obj.setHouseHoldDetailsId(temp.getHouseHoldDetailsId());
+ if(!rMNCHHouseHoldDetailsRepo
+ .getByHouseHoldID(obj.getHouseoldId()).isEmpty()){
+ RMNCHHouseHoldDetails temp = rMNCHHouseHoldDetailsRepo
+ .getByHouseHoldID(obj.getHouseoldId()).get(0);
+ if (temp != null)
+ obj.setHouseHoldDetailsId(temp.getHouseHoldDetailsId());
+ }
+
}
houseHoldList = (ArrayList) rMNCHHouseHoldDetailsRepo
.saveAll(houseHoldList);
@@ -438,8 +444,12 @@ private String getMappingsForAddressIDs(List addressLi
// 20-09-2021,end
if (benDetailsRMNCHOBJ != null && benDetailsRMNCHOBJ.getHouseoldId() != null)
- benHouseHoldRMNCHROBJ = rMNCHHouseHoldDetailsRepo
- .getByHouseHoldID(benDetailsRMNCHOBJ.getHouseoldId());
+ if(!rMNCHHouseHoldDetailsRepo
+ .getByHouseHoldID(benDetailsRMNCHOBJ.getHouseoldId()).isEmpty()){
+ benHouseHoldRMNCHROBJ = rMNCHHouseHoldDetailsRepo
+ .getByHouseHoldID(benDetailsRMNCHOBJ.getHouseoldId()).get(0);
+ }
+
}
if (benDetailsRMNCHOBJ == null)
From 8d83a9af95d3280c080d3060bdadcaf94aedae34 Mon Sep 17 00:00:00 2001
From: Saurav Mishra
Date: Wed, 17 Jun 2026 14:03:20 +0530
Subject: [PATCH 10/62] save abha id in health maping with beneficiaryID
---
.../rmnch/RMNCHMobileAppController.java | 4 +-
.../service/rmnch/RmnchDataSyncService.java | 2 +-
.../rmnch/RmnchDataSyncServiceImpl.java | 67 +++++++++++++++++--
src/main/resources/application.properties | 1 +
4 files changed, 66 insertions(+), 8 deletions(-)
diff --git a/src/main/java/com/iemr/common/identity/controller/rmnch/RMNCHMobileAppController.java b/src/main/java/com/iemr/common/identity/controller/rmnch/RMNCHMobileAppController.java
index cbb91cce..5552e90f 100644
--- a/src/main/java/com/iemr/common/identity/controller/rmnch/RMNCHMobileAppController.java
+++ b/src/main/java/com/iemr/common/identity/controller/rmnch/RMNCHMobileAppController.java
@@ -59,11 +59,11 @@ public class RMNCHMobileAppController {
@PostMapping(value = "/syncDataToAmrit", consumes = "application/json", produces = "application/json")
@Operation(summary = "Sync data to AMRIT for already regestered beneficiary with AMRIT beneficiary id ")
- public String syncDataToAmrit(@RequestBody String requestOBJ) {
+ public String syncDataToAmrit(@RequestBody String requestOBJ,@RequestHeader(value = "Authorization") String authorization) {
OutputResponse response = new OutputResponse();
try {
if (requestOBJ != null) {
- String s = rmnchDataSyncService.syncDataToAmrit(requestOBJ);
+ String s = rmnchDataSyncService.syncDataToAmrit(requestOBJ,authorization);
response.setResponse(s);
} else
response.setError(5000, "Invalid/NULL request obj");
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncService.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncService.java
index 845e79f9..7bbcb316 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncService.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncService.java
@@ -22,7 +22,7 @@
package com.iemr.common.identity.service.rmnch;
public interface RmnchDataSyncService {
- public String syncDataToAmrit(String requestOBJ) throws Exception;
+ public String syncDataToAmrit(String requestOBJ, String authorization) throws Exception;
public String saveBeneficiaryDetailsAfterRegistration(
Long beneficiaryID,
Long beneficiaryRegID,
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
index a62450ed..d2284ee5 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
@@ -33,8 +33,6 @@
import java.util.Map;
import java.util.regex.Pattern;
-import com.iemr.common.identity.utils.OutputResponse;
-import io.swagger.v3.oas.annotations.Operation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -78,8 +76,6 @@
import com.iemr.common.identity.utils.exception.IEMRException;
import com.iemr.common.identity.utils.http.HttpUtils;
import com.iemr.common.identity.utils.mapper.InputMapper;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
@Service
@Qualifier("rmnchServiceImpl")
@@ -115,7 +111,8 @@ public class RmnchDataSyncServiceImpl implements RmnchDataSyncService {
private RMNCHMBenRegIdMapRepo rMNCHMBenRegIdMapRepo;
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
@Override
- public String syncDataToAmrit(String requestOBJ) throws Exception {
+ public String syncDataToAmrit(String requestOBJ, String authorization) throws Exception {
+
Map resultMap = new HashMap();
@@ -133,6 +130,8 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
// other tables data saving
// ben details RMNCH extra fields details
+ logger.info("Request object of syncDataToAmrit: "+jsnOBJ);
+
BigInteger benRegID = null;
@@ -187,6 +186,14 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
rmnchmBeneficiarydetail.setMaritalstatus(obj.getMaritalstatus());
rmnchmBeneficiarydetail.setMaritalstatusId(obj.getMaritalstatusId());
benDetailsList.add(rmnchmBeneficiarydetail);
+ if (jsnOBJ.has("abhaId") && !jsnOBJ.get("abhaId").isJsonNull()) {
+ String abhaId = jsnOBJ.get("abhaId").getAsString();
+ if(!abhaId.isEmpty() || abhaId!=null){
+ mapHealthIDToBeneficiary(authorization,rmnchmBeneficiarydetail.getBenRegId().longValue(),rmnchmBeneficiarydetail.getBenficieryid().longValue(),abhaId,rmnchmBeneficiarydetail.getCreatedBy(),rmnchmBeneficiarydetail.getFirstName(),rmnchmBeneficiarydetail.getLastName(),rmnchmBeneficiarydetail.getDob().toString(),rmnchmBeneficiarydetail.getProviderServiceMapID());
+
+ }
+ }
+
}
}
@@ -285,6 +292,56 @@ public String syncDataToAmrit(String requestOBJ) throws Exception {
return new Gson().toJson(resultMap);
}
+ public String mapHealthIDToBeneficiary(String authorization,
+ Long benRegID,
+ Long beneficiaryID,
+ String abhaId,
+ String createdBy,String firstName,String lastName,String dob,Integer providerServiceMapId) {
+ try {
+ Map requestMap = new HashMap<>();
+
+ requestMap.put("beneficiaryRegID", benRegID);
+ requestMap.put("beneficiaryID", beneficiaryID);
+ requestMap.put("healthIdNumber", abhaId);
+
+ requestMap.put("createdBy", createdBy);
+ requestMap.put("providerServiceMapId", providerServiceMapId);
+ requestMap.put("isNew", false);
+
+ // ABHA Profile
+ Map abhaProfile = new HashMap<>();
+ abhaProfile.put("ABHANumber", abhaId);
+
+ List phrAddress = new ArrayList<>();
+ phrAddress.add(abhaId + "@abdm");
+
+ abhaProfile.put("phrAddress", phrAddress);
+ abhaProfile.put("firstName", firstName);
+ abhaProfile.put("middleName", "");
+ abhaProfile.put("lastName", lastName);
+ abhaProfile.put("dob", dob);
+
+ requestMap.put("ABHAProfile", abhaProfile);
+
+ HttpUtils utils = new HttpUtils();
+
+ HashMap header = new HashMap<>();
+ header.put("Authorization", authorization);
+
+ String responseStr = utils.post(
+ ConfigProperties.getPropertyByName("fhir-url")
+ + ConfigProperties.getPropertyByName("mapHealthIDToBeneficiary"),
+ new Gson().toJson(requestMap),
+ header);
+ logger.info("Save abha id in health mapping:"+responseStr.toString());
+ return responseStr;
+ }catch (Exception e){
+ logger.info("Error Save Health Id");
+ return "Error Save Health Id: "+e.getMessage();
+ }
+
+ }
+
@Override
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 12be1b44..79ba181f 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -148,6 +148,7 @@ spring.jpa.properties.hibernate.show_sql=false
door-to-door-page-size=2
get-HRP-Status=ANC/getHRPStatus
getHealthID=healthID/getBenhealthID
+mapHealthIDToBeneficiary=healthIDRecord/mapHealthIDToBeneficiary
spring.main.allow-bean-definition-overriding=true
spring.main.allow-circular-references=true
From 3b7dd5200937faa4a7bf965933dcf0b7d5c6e111 Mon Sep 17 00:00:00 2001
From: Saurav Mishra
Date: Wed, 17 Jun 2026 16:27:15 +0530
Subject: [PATCH 11/62] abha id add in entity class
---
.../identity/data/rmnch/RMNCHBeneficiaryDetailsRmnch.java | 3 +++
.../identity/data/rmnch/RMNCHMBeneficiarydetail.java | 4 ++++
.../identity/service/rmnch/RmnchDataSyncServiceImpl.java | 7 ++-----
3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHBeneficiaryDetailsRmnch.java b/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHBeneficiaryDetailsRmnch.java
index 4cab210c..e403b3d7 100644
--- a/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHBeneficiaryDetailsRmnch.java
+++ b/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHBeneficiaryDetailsRmnch.java
@@ -550,4 +550,7 @@ public class RMNCHBeneficiaryDetailsRmnch {
@Expose
private Boolean isDeactivate;
+ @Expose
+ @Transient
+ private String abhaId;
}
diff --git a/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHMBeneficiarydetail.java b/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHMBeneficiarydetail.java
index 397c5a66..d9221675 100644
--- a/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHMBeneficiarydetail.java
+++ b/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHMBeneficiarydetail.java
@@ -214,4 +214,8 @@ public class RMNCHMBeneficiarydetail {
@Expose
@Transient
private Integer ProviderServiceMapID;
+
+ @Expose
+ @Transient
+ private String abhaId;
}
\ No newline at end of file
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
index d2284ee5..27ca8739 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
@@ -186,12 +186,9 @@ public String syncDataToAmrit(String requestOBJ, String authorization) throws Ex
rmnchmBeneficiarydetail.setMaritalstatus(obj.getMaritalstatus());
rmnchmBeneficiarydetail.setMaritalstatusId(obj.getMaritalstatusId());
benDetailsList.add(rmnchmBeneficiarydetail);
- if (jsnOBJ.has("abhaId") && !jsnOBJ.get("abhaId").isJsonNull()) {
- String abhaId = jsnOBJ.get("abhaId").getAsString();
- if(!abhaId.isEmpty() || abhaId!=null){
- mapHealthIDToBeneficiary(authorization,rmnchmBeneficiarydetail.getBenRegId().longValue(),rmnchmBeneficiarydetail.getBenficieryid().longValue(),abhaId,rmnchmBeneficiarydetail.getCreatedBy(),rmnchmBeneficiarydetail.getFirstName(),rmnchmBeneficiarydetail.getLastName(),rmnchmBeneficiarydetail.getDob().toString(),rmnchmBeneficiarydetail.getProviderServiceMapID());
+ if (obj.getAbhaId()!=null && !obj.getAbhaId().isEmpty()) {
+ mapHealthIDToBeneficiary(authorization,obj.getBenRegId().longValue(),obj.getBenficieryid().longValue(),obj.getAbhaId(),obj.getCreatedBy(),obj.getFirstName(),obj.getLastName(),obj.getDob().toString(),obj.getProviderServiceMapID());
- }
}
}
From 1d8dbe75ce20d33ac2f192e21cb1c399cbd35d9d Mon Sep 17 00:00:00 2001
From: Saurav Mishra
Date: Wed, 17 Jun 2026 16:37:16 +0530
Subject: [PATCH 12/62] abha id add in entity class
---
.../common/identity/service/rmnch/RmnchDataSyncServiceImpl.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
index 27ca8739..962c31c8 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
@@ -333,7 +333,7 @@ public String mapHealthIDToBeneficiary(String authorization,
logger.info("Save abha id in health mapping:"+responseStr.toString());
return responseStr;
}catch (Exception e){
- logger.info("Error Save Health Id");
+ logger.info("Error Save Health Id"+e);
return "Error Save Health Id: "+e.getMessage();
}
From 1801efed23e349b400fe1da51cfafb42c565764c Mon Sep 17 00:00:00 2001
From: Saurav Mishra
Date: Wed, 17 Jun 2026 17:31:48 +0530
Subject: [PATCH 13/62] abha id add in entity class
---
.../identity/service/rmnch/RmnchDataSyncServiceImpl.java | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
index 962c31c8..d5dd5a1b 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
@@ -109,6 +109,9 @@ public class RmnchDataSyncServiceImpl implements RmnchDataSyncService {
private RMNCHBenContactRepo rMNCHBenContactRepo;
@Autowired
private RMNCHMBenRegIdMapRepo rMNCHMBenRegIdMapRepo;
+
+ @Value("${fhir-url}")
+ private String fhirUrl;
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
@Override
public String syncDataToAmrit(String requestOBJ, String authorization) throws Exception {
@@ -326,8 +329,7 @@ public String mapHealthIDToBeneficiary(String authorization,
header.put("Authorization", authorization);
String responseStr = utils.post(
- ConfigProperties.getPropertyByName("fhir-url")
- + ConfigProperties.getPropertyByName("mapHealthIDToBeneficiary"),
+ fhirUrl+ConfigProperties.getPropertyByName("mapHealthIDToBeneficiary"),
new Gson().toJson(requestMap),
header);
logger.info("Save abha id in health mapping:"+responseStr.toString());
From 594ab594c19898d10ea6c75e8a612e99d027de6a Mon Sep 17 00:00:00 2001
From: Saurav Mishra
Date: Wed, 17 Jun 2026 17:43:32 +0530
Subject: [PATCH 14/62] abha id add in entity class
---
.../identity/controller/rmnch/RMNCHMobileAppController.java | 2 +-
.../common/identity/service/rmnch/RmnchDataSyncServiceImpl.java | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/main/java/com/iemr/common/identity/controller/rmnch/RMNCHMobileAppController.java b/src/main/java/com/iemr/common/identity/controller/rmnch/RMNCHMobileAppController.java
index 5552e90f..f8a8957f 100644
--- a/src/main/java/com/iemr/common/identity/controller/rmnch/RMNCHMobileAppController.java
+++ b/src/main/java/com/iemr/common/identity/controller/rmnch/RMNCHMobileAppController.java
@@ -59,7 +59,7 @@ public class RMNCHMobileAppController {
@PostMapping(value = "/syncDataToAmrit", consumes = "application/json", produces = "application/json")
@Operation(summary = "Sync data to AMRIT for already regestered beneficiary with AMRIT beneficiary id ")
- public String syncDataToAmrit(@RequestBody String requestOBJ,@RequestHeader(value = "Authorization") String authorization) {
+ public String syncDataToAmrit(@RequestBody String requestOBJ,@RequestHeader(value = "jwttoken") String authorization) {
OutputResponse response = new OutputResponse();
try {
if (requestOBJ != null) {
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
index d5dd5a1b..dffbf5df 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
@@ -328,6 +328,7 @@ public String mapHealthIDToBeneficiary(String authorization,
HashMap header = new HashMap<>();
header.put("Authorization", authorization);
+
String responseStr = utils.post(
fhirUrl+ConfigProperties.getPropertyByName("mapHealthIDToBeneficiary"),
new Gson().toJson(requestMap),
From ec021c4a27c03aa0406a141264a168af92c85b5e Mon Sep 17 00:00:00 2001
From: Saurav Mishra
Date: Wed, 17 Jun 2026 17:48:36 +0530
Subject: [PATCH 15/62] abha id add in entity class
---
.../common/identity/service/rmnch/RmnchDataSyncServiceImpl.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
index dffbf5df..c7f9e795 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
@@ -299,6 +299,7 @@ public String mapHealthIDToBeneficiary(String authorization,
String createdBy,String firstName,String lastName,String dob,Integer providerServiceMapId) {
try {
Map requestMap = new HashMap<>();
+ logger.info("authorization:"+authorization);
requestMap.put("beneficiaryRegID", benRegID);
requestMap.put("beneficiaryID", beneficiaryID);
From 5a83005d1895e31443170e7d47adffd24cfef1b3 Mon Sep 17 00:00:00 2001
From: Saurav Mishra
Date: Wed, 17 Jun 2026 17:59:41 +0530
Subject: [PATCH 16/62] abha id add in entity class
---
.../rmnch/RmnchDataSyncServiceImpl.java | 61 +++++++++++++++----
1 file changed, 48 insertions(+), 13 deletions(-)
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
index c7f9e795..f73a2d98 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
@@ -40,6 +40,7 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
+import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@@ -76,6 +77,8 @@
import com.iemr.common.identity.utils.exception.IEMRException;
import com.iemr.common.identity.utils.http.HttpUtils;
import com.iemr.common.identity.utils.mapper.InputMapper;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.RestTemplate;
@Service
@Qualifier("rmnchServiceImpl")
@@ -298,8 +301,11 @@ public String mapHealthIDToBeneficiary(String authorization,
String abhaId,
String createdBy,String firstName,String lastName,String dob,Integer providerServiceMapId) {
try {
+ RestTemplate restTemplate = new RestTemplate();
+
+ logger.info("Authorization Token : {}", authorization);
+
Map requestMap = new HashMap<>();
- logger.info("authorization:"+authorization);
requestMap.put("beneficiaryRegID", benRegID);
requestMap.put("beneficiaryID", beneficiaryID);
@@ -324,21 +330,50 @@ public String mapHealthIDToBeneficiary(String authorization,
requestMap.put("ABHAProfile", abhaProfile);
- HttpUtils utils = new HttpUtils();
+ String requestBody = new Gson().toJson(requestMap);
+
+ String url = fhirUrl
+ + ConfigProperties.getPropertyByName("mapHealthIDToBeneficiary");
+
+ logger.info("Calling URL : {}", url);
+ logger.info("Request Body : {}", requestBody);
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+
+ // Agar token me Bearer nahi aa raha hai
+ if (authorization != null && !authorization.startsWith("Bearer ")) {
+ authorization = "Bearer " + authorization;
+ }
+
+ headers.set("Authorization", authorization);
+
+ HttpEntity entity =
+ new HttpEntity<>(requestBody, headers);
+
+ ResponseEntity response = restTemplate.exchange(
+ url,
+ HttpMethod.POST,
+ entity,
+ String.class
+ );
+
+ logger.info("ABHA Mapping Response : {}", response.getBody());
+
+ return response.getBody();
+
+ } catch (HttpClientErrorException e) {
+
+ logger.error("HTTP Error Status : {}", e.getStatusCode());
+ logger.error("HTTP Error Response : {}", e.getResponseBodyAsString(), e);
+
+ return "HTTP Error : " + e.getStatusCode();
- HashMap header = new HashMap<>();
- header.put("Authorization", authorization);
+ } catch (Exception e) {
+ logger.error("Error while saving Health ID Mapping", e);
- String responseStr = utils.post(
- fhirUrl+ConfigProperties.getPropertyByName("mapHealthIDToBeneficiary"),
- new Gson().toJson(requestMap),
- header);
- logger.info("Save abha id in health mapping:"+responseStr.toString());
- return responseStr;
- }catch (Exception e){
- logger.info("Error Save Health Id"+e);
- return "Error Save Health Id: "+e.getMessage();
+ return "Error Save Health Id : " + e.getMessage();
}
}
From 32db7e19a23ca42fc02d06830a8ab14d20a84452 Mon Sep 17 00:00:00 2001
From: Saurav Mishra
Date: Wed, 17 Jun 2026 18:18:37 +0530
Subject: [PATCH 17/62] abha id add in entity class
---
.../identity/service/rmnch/RmnchDataSyncServiceImpl.java | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
index f73a2d98..131d55f4 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
@@ -340,13 +340,9 @@ public String mapHealthIDToBeneficiary(String authorization,
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
-
// Agar token me Bearer nahi aa raha hai
- if (authorization != null && !authorization.startsWith("Bearer ")) {
- authorization = "Bearer " + authorization;
- }
- headers.set("Authorization", authorization);
+ headers.set("Jwttoken", authorization);
HttpEntity entity =
new HttpEntity<>(requestBody, headers);
From a90fe132d315f1822b9fac9e9affcb5b05acfc0c Mon Sep 17 00:00:00 2001
From: Saurav Mishra
Date: Wed, 17 Jun 2026 18:32:16 +0530
Subject: [PATCH 18/62] abha id add in entity class
---
.../service/rmnch/RmnchDataSyncServiceImpl.java | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
index 131d55f4..e11aba38 100644
--- a/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
+++ b/src/main/java/com/iemr/common/identity/service/rmnch/RmnchDataSyncServiceImpl.java
@@ -24,6 +24,7 @@
import java.math.BigInteger;
import java.sql.Date;
import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
import java.time.Period;
import java.util.ArrayList;
import java.util.Arrays;
@@ -302,7 +303,17 @@ public String mapHealthIDToBeneficiary(String authorization,
String createdBy,String firstName,String lastName,String dob,Integer providerServiceMapId) {
try {
RestTemplate restTemplate = new RestTemplate();
-
+ String formattedDob = dob;
+
+ try {
+ if (dob != null && dob.contains(" ")) {
+ Timestamp timestamp = Timestamp.valueOf(dob);
+ formattedDob = new SimpleDateFormat("dd-MM-yyyy")
+ .format(timestamp);
+ }
+ } catch (Exception ex) {
+ logger.warn("DOB format conversion failed, sending original DOB : {}", dob);
+ }
logger.info("Authorization Token : {}", authorization);
Map requestMap = new HashMap<>();
@@ -326,7 +337,8 @@ public String mapHealthIDToBeneficiary(String authorization,
abhaProfile.put("firstName", firstName);
abhaProfile.put("middleName", "");
abhaProfile.put("lastName", lastName);
- abhaProfile.put("dob", dob);
+ abhaProfile.put("dob", formattedDob);
+
requestMap.put("ABHAProfile", abhaProfile);
From 8185f5a9e1264295b0ffd08858b1382833719bc5 Mon Sep 17 00:00:00 2001
From: Sehjot Singh Pannu
Date: Thu, 18 Jun 2026 17:09:32 +0530
Subject: [PATCH 19/62] feat(STOP-148): add GPS location capture support for
beneficiary and RMNCH records
Introduces GPS-related fields (gpsLatitude, gpsLongitude, digipin, gpsTimestamp, isGpsUnavailable, and gpsUnavailableReason) across beneficiary address and RMNCH domain models, including MBeneficiaryaddress, Address DTO, RMNCHBeneficiaryDetailsRmnch, and RMNCHHouseHoldDetails.
Enhances IdentityMapper and IdentityService to map and persist GPS information between incoming DTOs and beneficiary address entities.
Updates RmnchDataSyncServiceImpl to extract and synchronize GPS details from the nested i_bendemographics payload during beneficiary sync, and to parse gpsTimestamp from household details during RMNCH household data processing.
---
.../rmnch/RMNCHBeneficiaryDetailsRmnch.java | 24 ++
.../data/rmnch/RMNCHHouseHoldDetails.java | 69 +++--
.../iemr/common/identity/domain/Address.java | 8 +
.../identity/domain/MBeneficiaryaddress.java | 60 ++--
.../identity/mapper/IdentityMapper.java | 84 +++---
.../identity/service/IdentityService.java | 262 +++++++++---------
.../rmnch/RmnchDataSyncServiceImpl.java | 49 +++-
7 files changed, 346 insertions(+), 210 deletions(-)
diff --git a/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHBeneficiaryDetailsRmnch.java b/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHBeneficiaryDetailsRmnch.java
index 4cab210c..0477fd4a 100644
--- a/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHBeneficiaryDetailsRmnch.java
+++ b/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHBeneficiaryDetailsRmnch.java
@@ -550,4 +550,28 @@ public class RMNCHBeneficiaryDetailsRmnch {
@Expose
private Boolean isDeactivate;
+ @Expose
+ @Column(name = "gpsLatitude")
+ private Double gpsLatitude;
+
+ @Expose
+ @Column(name = "gpsLongitude")
+ private Double gpsLongitude;
+
+ @Expose
+ @Column(name = "digipin")
+ private String digipin;
+
+ @Expose
+ @Column(name = "gpsTimestamp")
+ private Timestamp gpsTimestamp;
+
+ @Expose
+ @Column(name = "isGpsUnavailable", nullable = false, columnDefinition = "TINYINT(1) DEFAULT 0")
+ private Boolean isGpsUnavailable = false;
+
+ @Expose
+ @Column(name = "gpsUnavailableReason")
+ private String gpsUnavailableReason;
+
}
diff --git a/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHHouseHoldDetails.java b/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHHouseHoldDetails.java
index 8aa8ed47..b73f9b00 100644
--- a/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHHouseHoldDetails.java
+++ b/src/main/java/com/iemr/common/identity/data/rmnch/RMNCHHouseHoldDetails.java
@@ -1,24 +1,24 @@
/*
-* AMRIT – Accessible Medical Records via Integrated Technology
-* Integrated EHR (Electronic Health Records) Solution
-*
-* Copyright (C) "Piramal Swasthya Management and Research Institute"
-*
-* This file is part of AMRIT.
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program. If not, see https://www.gnu.org/licenses/.
-*/
+ * AMRIT – Accessible Medical Records via Integrated Technology
+ * Integrated EHR (Electronic Health Records) Solution
+ *
+ * Copyright (C) "Piramal Swasthya Management and Research Institute"
+ *
+ * This file is part of AMRIT.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see https://www.gnu.org/licenses/.
+ */
package com.iemr.common.identity.data.rmnch;
import java.sql.Timestamp;
@@ -31,11 +31,12 @@
import jakarta.persistence.Table;
import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
import lombok.Data;
/**
- *
+ *
* @author de40034072
*
*/
@@ -359,4 +360,30 @@ public class RMNCHHouseHoldDetails {
@Column(name = "mohallaName")
private String mohallaName;
+ @Expose
+ @SerializedName("latitude")
+ @Column(name = "gpsLatitude")
+ private Double gpsLatitude;
+
+ @Expose
+ @SerializedName("longitude")
+ @Column(name = "gpsLongitude")
+ private Double gpsLongitude;
+
+ @Expose
+ @Column(name = "digipin")
+ private String digipin;
+
+ @Expose
+ @Column(name = "gpsTimestamp")
+ private Timestamp gpsTimestamp;
+
+ @Expose
+ @Column(name = "isGpsUnavailable", nullable = false, columnDefinition = "TINYINT(1) DEFAULT 0")
+ private Boolean isGpsUnavailable = false;
+
+ @Expose
+ @Column(name = "gpsUnavailableReason")
+ private String gpsUnavailableReason;
+
}
diff --git a/src/main/java/com/iemr/common/identity/domain/Address.java b/src/main/java/com/iemr/common/identity/domain/Address.java
index c37b4507..dfce1672 100644
--- a/src/main/java/com/iemr/common/identity/domain/Address.java
+++ b/src/main/java/com/iemr/common/identity/domain/Address.java
@@ -23,6 +23,8 @@
import lombok.Data;
+import java.sql.Timestamp;
+
public @Data class Address {
private String addrLine1;
private String addrLine2;
@@ -51,4 +53,10 @@
private Integer vanID;
private Integer parkingPlaceID;
+ private Double gpsLatitude;
+ private Double gpsLongitude;
+ private String digipin;
+ private Timestamp gpsTimestamp;
+ private Boolean isGpsUnavailable;
+ private String gpsUnavailableReason;
}
diff --git a/src/main/java/com/iemr/common/identity/domain/MBeneficiaryaddress.java b/src/main/java/com/iemr/common/identity/domain/MBeneficiaryaddress.java
index 0e2ab415..d5eaf7bd 100644
--- a/src/main/java/com/iemr/common/identity/domain/MBeneficiaryaddress.java
+++ b/src/main/java/com/iemr/common/identity/domain/MBeneficiaryaddress.java
@@ -1,24 +1,24 @@
/*
-* AMRIT – Accessible Medical Records via Integrated Technology
-* Integrated EHR (Electronic Health Records) Solution
-*
-* Copyright (C) "Piramal Swasthya Management and Research Institute"
-*
-* This file is part of AMRIT.
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program. If not, see https://www.gnu.org/licenses/.
-*/
+ * AMRIT – Accessible Medical Records via Integrated Technology
+ * Integrated EHR (Electronic Health Records) Solution
+ *
+ * Copyright (C) "Piramal Swasthya Management and Research Institute"
+ *
+ * This file is part of AMRIT.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see https://www.gnu.org/licenses/.
+ */
package com.iemr.common.identity.domain;
import java.io.Serializable;
@@ -39,7 +39,7 @@
/**
* The persistent class for the m_beneficiaryaddress database table.
- *
+ *
*/
@Entity
@Table(name = "i_beneficiaryaddress")
@@ -260,6 +260,24 @@ public class MBeneficiaryaddress implements Serializable {
// END OF new column added for data sync
+ @Column(name = "gpsLatitude")
+ private Double gpsLatitude;
+
+ @Column(name = "gpsLongitude")
+ private Double gpsLongitude;
+
+ @Column(name = "digipin")
+ private String digipin;
+
+ @Column(name = "gpsTimestamp")
+ private Timestamp gpsTimestamp;
+
+ @Column(name = "isGpsUnavailable", nullable = false, columnDefinition = "TINYINT(1) DEFAULT 0")
+ private Boolean isGpsUnavailable = false;
+
+ @Column(name = "gpsUnavailableReason")
+ private String gpsUnavailableReason;
+
public MBeneficiaryaddress setCurrentAddress(Address address) {
this.currAddrLine1 = address.getAddrLine1();
this.currAddrLine2 = address.getAddrLine2();
diff --git a/src/main/java/com/iemr/common/identity/mapper/IdentityMapper.java b/src/main/java/com/iemr/common/identity/mapper/IdentityMapper.java
index bc3ad686..765acb97 100644
--- a/src/main/java/com/iemr/common/identity/mapper/IdentityMapper.java
+++ b/src/main/java/com/iemr/common/identity/mapper/IdentityMapper.java
@@ -1,24 +1,24 @@
/*
-* AMRIT – Accessible Medical Records via Integrated Technology
-* Integrated EHR (Electronic Health Records) Solution
-*
-* Copyright (C) "Piramal Swasthya Management and Research Institute"
-*
-* This file is part of AMRIT.
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program. If not, see https://www.gnu.org/licenses/.
-*/
+ * AMRIT – Accessible Medical Records via Integrated Technology
+ * Integrated EHR (Electronic Health Records) Solution
+ *
+ * Copyright (C) "Piramal Swasthya Management and Research Institute"
+ *
+ * This file is part of AMRIT.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see https://www.gnu.org/licenses/.
+ */
package com.iemr.common.identity.mapper;
import java.sql.Timestamp;
@@ -66,7 +66,7 @@ public interface IdentityMapper {
MBeneficiarymapping identityDTOToMBeneficiarymapping(IdentityDTO dto);
-
+
@Mapping(source = "defaultNo", target = "shareAnonymousWithGovt")
@Mapping(source = "defaultNo", target = "shareAnonymousWithMedicalCommunity")
@@ -93,7 +93,7 @@ public interface IdentityMapper {
MBeneficiaryconsent identityDTOToDefaultMBeneficiaryconsent(IdentityDTO dto, Boolean defaultYes, Boolean defaultNo);
-
+
// @Mapping(source = "dto.areaId", target = "areaId")
// @Mapping(source = "dto.beneficiaryRegId", target = "beneficiaryRegID")
@@ -144,7 +144,7 @@ public interface IdentityMapper {
// @Mapping(source = "dto.vanID", target = "vanID")
// @Mapping(source = "dto.parkingPlaceId", target = "parkingPlaceID")
// MBeneficiarydetail identityDTOToMBeneficiarydetail(IdentityDTO dto);
-
+
@Mapping(source = "benFamilyDTO.isEmergencyContact", target = "isEmergencyContact")
@Mapping(source = "benFamilyDTO.relationshipToSelf", target = "relationshipToSelf")
@@ -152,7 +152,7 @@ public interface IdentityMapper {
@Mapping(source = "createdBy", target = "createdBy")
@Mapping(source = "createdDate", target = "createdDate")
MBeneficiaryfamilymapping identityDTOToMBeneficiaryfamilymapping(BenFamilyDTO benFamilyDTO, String createdBy,
- Timestamp createdDate);
+ Timestamp createdDate);
List identityDTOListToMBeneficiaryfamilymappingList(List list);
@@ -210,6 +210,12 @@ MBeneficiaryfamilymapping identityDTOToMBeneficiaryfamilymapping(BenFamilyDTO be
@Mapping(target = "currentAddress.village", source = "map.MBeneficiaryaddress.currVillage")
@Mapping(target = "currentAddress.addressValue", source = "map.MBeneficiaryaddress.currAddressValue")
@Mapping(target = "currentAddress.pinCode", source = "map.MBeneficiaryaddress.currPinCode")
+ @Mapping(target = "currentAddress.gpsLatitude", source = "map.MBeneficiaryaddress.gpsLatitude")
+ @Mapping(target = "currentAddress.gpsLongitude", source = "map.MBeneficiaryaddress.gpsLongitude")
+ @Mapping(target = "currentAddress.digipin", source = "map.MBeneficiaryaddress.digipin")
+ @Mapping(target = "currentAddress.gpsTimestamp", source = "map.MBeneficiaryaddress.gpsTimestamp")
+ @Mapping(target = "currentAddress.isGpsUnavailable", source = "map.MBeneficiaryaddress.isGpsUnavailable")
+ @Mapping(target = "currentAddress.gpsUnavailableReason", source = "map.MBeneficiaryaddress.gpsUnavailableReason")
@Mapping(target = "emergencyAddress.addrLine1", source = "map.MBeneficiaryaddress.emerAddrLine1")
@Mapping(target = "emergencyAddress.addrLine2", source = "map.MBeneficiaryaddress.emerAddrLine2")
@Mapping(target = "emergencyAddress.addrLine3", source = "map.MBeneficiaryaddress.emerAddrLine3")
@@ -296,13 +302,13 @@ MBeneficiaryfamilymapping identityDTOToMBeneficiaryfamilymapping(BenFamilyDTO be
@Mapping(target = "beneficiaryDetails.title", source = "map.MBeneficiarydetail.title")
@Mapping(target = "beneficiaryDetails.zoneId", source = "map.MBeneficiarydetail.zoneId")
@Mapping(target = "contacts", expression = "java( map != null && map.getMBeneficiarycontact() != null && "
- + "map.getMBeneficiarydetail() != null ? "
- + "Phone.createContactList(map.getMBeneficiarycontact(), "
- + "(benRegId != null ? benRegId.toString() : null), "
- + "(map.getMBeneficiarydetail().getFirstName() != null ? map.getMBeneficiarydetail().getFirstName() : \"\") + \" \" + "
- + "(map.getMBeneficiarydetail().getMiddleName() != null ? map.getMBeneficiarydetail().getMiddleName() : \"\") + \" \" + "
- + "(map.getMBeneficiarydetail().getLastName() != null ? map.getMBeneficiarydetail().getLastName() : \"\") "
- + ") : null)")
+ + "map.getMBeneficiarydetail() != null ? "
+ + "Phone.createContactList(map.getMBeneficiarycontact(), "
+ + "(map.getBenRegId() != null ? map.getBenRegId().toString() : null), "
+ + "(map.getMBeneficiarydetail().getFirstName() != null ? map.getMBeneficiarydetail().getFirstName() : \"\") + \" \" + "
+ + "(map.getMBeneficiarydetail().getMiddleName() != null ? map.getMBeneficiarydetail().getMiddleName() : \"\") + \" \" + "
+ + "(map.getMBeneficiarydetail().getLastName() != null ? map.getMBeneficiarydetail().getLastName() : \"\") "
+ + ") : null)")
@Mapping(target = "permanentAddress.zoneID", source = "map.MBeneficiaryaddress.permZoneID")
@Mapping(target = "permanentAddress.zoneName", source = "map.MBeneficiaryaddress.permZone")
@@ -334,13 +340,13 @@ MBeneficiaryfamilymapping identityDTOToMBeneficiaryfamilymapping(BenFamilyDTO be
@Mapping(target = "accountNo", source = "map.MBeneficiaryAccount.accountNo")
@Mapping(target = "benAccountID", source = "map.benAccountID")
@Mapping(target = "ageAtMarriage", expression = "java(map != null && map.getMBeneficiarydetail() != null ? "
- + "MBeneficiarydetail.getAgeAtMarriageCalc(map.getMBeneficiarydetail().getDob(), "
- + "map.getMBeneficiarydetail().getMarriageDate(), "
- + "map.getMBeneficiarydetail().getAgeAtMarriage()) : null)")
+ + "MBeneficiarydetail.getAgeAtMarriageCalc(map.getMBeneficiarydetail().getDob(), "
+ + "map.getMBeneficiarydetail().getMarriageDate(), "
+ + "map.getMBeneficiarydetail().getAgeAtMarriage()) : null)")
@Mapping(target = "marriageDate", expression = "java(map != null && map.getMBeneficiarydetail() != null ? "
- + "MBeneficiarydetail.getMarriageDateCalc(map.getMBeneficiarydetail().getDob(), "
- + "map.getMBeneficiarydetail().getMarriageDate(), "
- + "map.getMBeneficiarydetail().getAgeAtMarriage()) : null)")
+ + "MBeneficiarydetail.getMarriageDateCalc(map.getMBeneficiarydetail().getDob(), "
+ + "map.getMBeneficiarydetail().getMarriageDate(), "
+ + "map.getMBeneficiarydetail().getAgeAtMarriage()) : null)")
@Mapping(target = "literacyStatus", source = "map.MBeneficiarydetail.literacyStatus")
@Mapping(target = "motherName", source = "map.MBeneficiarydetail.motherName")
@@ -481,7 +487,7 @@ List mapToMBeneficiaryfamilymappingWithBenFamilyDTOList(
@Mapping(source = "dto.createdDate", target = "createdDate")
@Mapping(source = "dto.vanID", target = "vanID")
@Mapping(source = "dto.parkingPlaceId", target = "parkingPlaceID")
- // End
+ // End
MBeneficiaryAccount identityDTOToMBeneficiaryAccount(IdentityDTO dto);
@InheritInverseConfiguration
@@ -490,7 +496,7 @@ List mapToMBeneficiaryfamilymappingWithBenFamilyDTOList(
@Mapping(source = "dto.benImage", target = "benImage")
@Mapping(source = "dto.agentName", target = "createdBy")
@Mapping(source = "dto.createdDate", target = "createdDate")
-
+
@Mapping(source = "dto.vanID", target = "vanID")
@Mapping(source = "dto.parkingPlaceId", target = "parkingPlaceID")
diff --git a/src/main/java/com/iemr/common/identity/service/IdentityService.java b/src/main/java/com/iemr/common/identity/service/IdentityService.java
index 6e8a71ef..212e8b5c 100644
--- a/src/main/java/com/iemr/common/identity/service/IdentityService.java
+++ b/src/main/java/com/iemr/common/identity/service/IdentityService.java
@@ -1,23 +1,23 @@
/*
-* AMRIT – Accessible Medical Records via Integrated Technology
-* Integrated EHR (Electronic Health Records) Solution
-*
-* Copyright (C) "Piramal Swasthya Management and Research Institute"
-*
-* This file is part of AMRIT.
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program. If not, see https://www.gnu.org/licenses/.
+ * AMRIT – Accessible Medical Records via Integrated Technology
+ * Integrated EHR (Electronic Health Records) Solution
+ *
+ * Copyright (C) "Piramal Swasthya Management and Research Institute"
+ *
+ * This file is part of AMRIT.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see https://www.gnu.org/licenses/.
*/
package com.iemr.common.identity.service;
@@ -229,7 +229,7 @@ public List getBeneficiaries(IdentitySearchDTO searchDTO)
if (list3.get(i) == null || list3.get(i).getBeneficiaryDetails() == null
|| list3.get(i).getBeneficiaryDetails().getFirstName() == null
|| !list3.get(i).getBeneficiaryDetails().getFirstName()
- .equalsIgnoreCase(searchDTO.getFirstName())) {
+ .equalsIgnoreCase(searchDTO.getFirstName())) {
list3.remove(i);
i--;
@@ -241,7 +241,7 @@ public List getBeneficiaries(IdentitySearchDTO searchDTO)
if (list3.get(i) == null || list3.get(i).getBeneficiaryDetails() == null
|| list3.get(i).getBeneficiaryDetails().getLastName() == null
|| !list3.get(i).getBeneficiaryDetails().getLastName()
- .equalsIgnoreCase(searchDTO.getLastName())) {
+ .equalsIgnoreCase(searchDTO.getLastName())) {
list3.remove(i);
i--;
@@ -286,7 +286,7 @@ public List getBeneficiaries(IdentitySearchDTO searchDTO)
if (list3.get(i) == null || list3.get(i).getCurrentAddress() == null
|| list3.get(i).getCurrentAddress().getDistrictId() == null
|| !list3.get(i).getCurrentAddress().getDistrictId()
- .equals(searchDTO.getCurrentAddress().getDistrictId())) {
+ .equals(searchDTO.getCurrentAddress().getDistrictId())) {
list3.remove(i);
i--;
@@ -298,7 +298,7 @@ public List getBeneficiaries(IdentitySearchDTO searchDTO)
if (list3.get(i) == null || list3.get(i).getCurrentAddress() == null
|| list3.get(i).getCurrentAddress().getVillageId() == null
|| !list3.get(i).getCurrentAddress().getVillageId()
- .equals(searchDTO.getCurrentAddress().getVillageId())) {
+ .equals(searchDTO.getCurrentAddress().getVillageId())) {
list3.remove(i);
i--;
@@ -515,7 +515,7 @@ public List getBeneficiariesByBenId(BigInteger benId)
/**
*
- * @param BenRegId
+ * @param benRegId
* @return
*/
public List getBeneficiariesByBenRegId(BigInteger benRegId)
@@ -591,104 +591,104 @@ public List getBeneficiariesByPhoneNum(String phoneNum)
}
-/**
- * Advanced search using Elasticsearch with fallback to database
- */
-public Map advancedSearchBeneficiariesES(
- String firstName, String middleName, String lastName, Integer genderId, java.util.Date dob,
- Integer stateId, Integer districtId, Integer blockId, Integer villageId,
- String fatherName, String spouseName, String maritalStatus, String phoneNumber,
- String beneficiaryId, String healthId, String aadharNo,
- Integer userId, String auth, Boolean is1097) throws Exception {
-
- try {
- logger.info("IdentityService.advancedSearchBeneficiariesES - start");
- logger.info("ES enabled: {}", esEnabled);
-
- Map response = new HashMap<>();
-
- if (esEnabled) {
- logger.info("Using Elasticsearch for advanced search");
-
- // Call Elasticsearch service
- List