Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
3c5b5b8
add bengali language translation on dynamic forms
SauravBizbRolly May 6, 2026
eb9de55
Merge pull request #406 from PSMRI/feature/add_bengali_language
SauravBizbRolly May 6, 2026
2cd890c
Merge remote-tracking branch 'upstream/vbb/release-3.8.1' into sm/rel…
SauravBizbRolly May 12, 2026
bc54def
change api version
SauravBizbRolly May 12, 2026
3e0bbb7
Sn/3.8.1 (#423)
snehar-nd May 22, 2026
cbb1817
fix: use stringRedisTemplate for jti: key read/delete in concurrent s…
vishwab1 May 22, 2026
8b548d3
fix: correct exempt roles and allow superadmin concurrent sessions
vishwab1 May 22, 2026
a8102b1
Merge pull request #424 from PSMRI/vb/fixSession
snehar-nd May 22, 2026
2c23d93
Implement feature multiple login attempt
SauravBizbRolly May 29, 2026
fe3336a
Implement feature multiple login attempt
SauravBizbRolly May 29, 2026
5424887
Merge pull request #426 from PSMRI/feature/handel_multiple_attempt_pa…
SauravBizbRolly Jun 4, 2026
a6a6d3c
fix: delete camp:vanID and camp:parkingPlaceID from Redis on MMU logout
vishwab1 Jun 12, 2026
758bf36
feat: add endpoint to expose server's LAN IP address
vishwab1 Jun 16, 2026
be92d7c
fix: extented the token expiry timing
snehar-nd Jun 16, 2026
fc1deba
Merge pull request #428 from PSMRI/sn/tokenExpiry
snehar-nd Jun 16, 2026
e04714b
fix issue of feature multiple login attempt
SauravBizbRolly Jun 22, 2026
fee73b3
Merge pull request #431 from PSMRI/fix_multiple_login_issue
SauravBizbRolly Jun 22, 2026
818257c
fix issue of feature multiple login attempt
SauravBizbRolly Jun 22, 2026
a27db85
fix issue of feature multiple login attempt
SauravBizbRolly Jun 22, 2026
38e4c02
Merge pull request #432 from PSMRI/fix_login_issue_multiple_login
SauravBizbRolly Jun 22, 2026
73caab7
Merge remote-tracking branch 'origin/main' into vb/release-3.8.2
vishwab1 Jun 25, 2026
d08403f
Merge remote-tracking branch 'origin/release-3.8.1' into vb/release-3…
vishwab1 Jun 25, 2026
5a34772
Merge remote-tracking branch 'origin/release-3.8.2' into vb/release-3…
vishwab1 Jun 25, 2026
c9a2694
Merge pull request #434 from PSMRI/vb/release-3.8.2
snehar-nd Jun 25, 2026
c3013e0
Increase timing of refresh token (#435)
SauravBizbRolly Jun 26, 2026
16dc5af
fix: restore remaining-attempts lockout message from PR #431
vishwab1 Jun 26, 2026
8743f34
Merge remote-tracking branch 'origin/release-3.8.2' into vb/release-3…
vishwab1 Jun 26, 2026
865c266
fix: restore account-lockout message from PR #432
vishwab1 Jun 26, 2026
89d1da2
Merge pull request #436 from PSMRI/vb/release-3.8.2
SauravBizbRolly Jun 26, 2026
d2efa54
fix: AMM-2343 on lock/Unlock the api was returning 500 error (#437)
snehar-nd Jun 29, 2026
01a5f5f
Merge StopTB-related fixes from release-3.8.3 into release-3.8.2 (#442)
vishwab1 Jul 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.iemr.common-API</groupId>
<artifactId>common-api</artifactId>
<version>3.8.1</version>
<version>3.8.2</version>
<packaging>war</packaging>

<name>Common-API</name>
Expand Down
2 changes: 1 addition & 1 deletion src/main/environment/common_docker.properties
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,4 @@ otp.ratelimit.enabled=${OTP_RATELIMIT_ENABLED}
otp.ratelimit.minute-limit=${OTP_RATELIMIT_MINUTE_LIMIT}
otp.ratelimit.hour-limit=${OTP_RATELIMIT_HOUR_LIMIT}
otp.ratelimit.day-limit=${OTP_RATELIMIT_DAY_LIMIT}
generateBeneficiaryIDs-api-url={GEN_BENEFICIARY_IDS_API_URL}
generateBeneficiaryIDs-api-url=${GEN_BENEFICIARY_IDS_API_URL}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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.controller.connect;

import java.util.LinkedHashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.iemr.common.utils.NetworkUtil;

import io.swagger.v3.oas.annotations.Operation;

/**
* Exposes the server's LAN address so a mobile device on the same wifi
* network can connect to this API.
*/
@RestController
@RequestMapping(value = "/public/connect")
public class ConnectController {

@Value("${server.port:8080}")
private int serverPort;

@Operation(summary = "Get the server's LAN IP address and port")
@GetMapping(value = "/info", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Map<String, Object>> getConnectInfo() {
Map<String, Object> response = new LinkedHashMap<>();
response.put("ip", NetworkUtil.getLanIPAddress());
response.put("port", serverPort);
return ResponseEntity.ok(response);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
private static final String USER_ID_FIELD = "userId";
private final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
private InputMapper inputMapper = new InputMapper();
private static final Set<String> CONCURRENT_SESSION_EXEMPT_ROLES = Set.of("provideradmin", "superadmin");

// @Value("${captcha.enable-captcha}")
private boolean enableCaptcha =false;
Expand Down Expand Up @@ -172,7 +173,17 @@
}

String decryptPassword = aesUtil.decrypt("Piramal12Piramal", m_User.getPassword());
List<User> mUser = iemrAdminUserServiceImpl.userAuthenticate(m_User.getUserName(), decryptPassword);


List<User> mUser = iemrAdminUserServiceImpl
.userAuthenticate(m_User.getUserName(), decryptPassword);


User loggedInUser = mUser.get(0);

loggedInUser.setFailedAttempt(0);

iemrAdminUserServiceImpl.save(loggedInUser);
Comment on lines +182 to +186

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

πŸ”’ Security & Privacy | 🟠 Major | ⚑ Quick win

Remove the duplicate stale account-state write. Successful authentication already clears and persists failed-attempt state in IEMRAdminUserServiceImpl; this later save can overwrite a concurrent failed-login/lock update.

  • src/main/java/com/iemr/common/controller/users/IEMRAdminController.java#L182-L186: do not reset and save the returned user again.
  • src/main/java/com/iemr/common/service/users/IEMRAdminUserService.java#L136-L136: remove the raw save(User) contract.
  • src/main/java/com/iemr/common/service/users/IEMRAdminUserServiceImpl.java#L1388-L1391: remove the corresponding repository delegation.
πŸ“ Affects 3 files
  • src/main/java/com/iemr/common/controller/users/IEMRAdminController.java#L182-L186 (this comment)
  • src/main/java/com/iemr/common/service/users/IEMRAdminUserService.java#L136-L136
  • src/main/java/com/iemr/common/service/users/IEMRAdminUserServiceImpl.java#L1388-L1391
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/iemr/common/controller/users/IEMRAdminController.java`
around lines 182 - 186, Remove the redundant failed-attempt reset and save after
successful authentication in IEMRAdminController.java:182-186, leaving
account-state persistence to IEMRAdminUserServiceImpl. Remove the raw save(User)
contract from IEMRAdminUserService.java:136 and its repository delegation from
IEMRAdminUserServiceImpl.java:1388-1391; update any resulting references as
needed.

JSONObject resMap = new JSONObject();
JSONObject serviceRoleMultiMap = new JSONObject();
JSONObject serviceRoleMap = new JSONObject();
Expand All @@ -181,11 +192,22 @@
if (m_User.getUserName() != null
&& (m_User.getDoLogout() == null || !m_User.getDoLogout())
&& (m_User.getWithCredentials() != null && m_User.getWithCredentials())) {
String tokenFromRedis = getConcurrentCheckSessionObjectAgainstUser(
m_User.getUserName().trim().toLowerCase());
if (tokenFromRedis != null) {
throw new IEMRException(
"You are already logged in,please confirm to logout from other device and login again");
String userRole = "";
if (mUser.size() == 1 && mUser.get(0).getM_UserServiceRoleMapping() != null) {
for (UserServiceRoleMapping usrm : mUser.get(0).getM_UserServiceRoleMapping()) {
if (usrm.getM_Role() != null && usrm.getM_Role().getRoleName() != null) {
userRole = usrm.getM_Role().getRoleName();
break;
}
}
}
if (!CONCURRENT_SESSION_EXEMPT_ROLES.contains(userRole.trim().toLowerCase())) {
String tokenFromRedis = getConcurrentCheckSessionObjectAgainstUser(
m_User.getUserName().trim().toLowerCase());
if (tokenFromRedis != null) {
throw new IEMRException(
"You are already logged in,please confirm to logout from other device and login again");
}
Comment on lines +195 to +210

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

πŸ”’ Security & Privacy | 🟠 Major | ⚑ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 5 'getUserServiceRoleMapping\s*\(|userExitsCheck\s*\(|CONCURRENT_SESSION_EXEMPT_ROLES' \
  src/main/java/com/iemr/common

rg -n -C 5 'IEMRAdminController|concurrent.*session|provideradmin|superadmin' \
  src/test/java

Repository: PSMRI/Common-API

Length of output: 38446


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '175,220p' src/main/java/com/iemr/common/controller/users/IEMRAdminController.java
printf '\n----\n'
sed -n '410,470p' src/main/java/com/iemr/common/controller/users/IEMRAdminController.java
printf '\n----\n'
sed -n '700,760p' src/main/java/com/iemr/common/service/users/IEMRAdminUserServiceImpl.java
printf '\n----\n'
sed -n '1328,1395p' src/main/java/com/iemr/common/service/users/IEMRAdminUserServiceImpl.java

Repository: PSMRI/Common-API

Length of output: 10532


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 4 'findByUserName\s*\(|userExitsCheck\s*\(' src/main/java/com/iemr/common

printf '\n----\n'
rg -n -C 6 'interface .*RepositoryCustom|class .*RepositoryCustom|findByUserName' src/main/java/com/iemr/common

printf '\n----\n'
sed -n '1,220p' src/main/java/com/iemr/common/repository/users/IEMRUserRepositoryCustom.java

Repository: PSMRI/Common-API

Length of output: 39428


Use the complete role mappings for concurrent-session checks.

  • src/main/java/com/iemr/common/controller/users/IEMRAdminController.java#L195-L210: this branch only inspects the first mapping, but getUserServiceRoleMapping() iterates a Set<Object[]>, so the chosen role can vary for multi-role users.
  • src/main/java/com/iemr/common/controller/users/IEMRAdminController.java#L437-L458: reload the mappings before applying the same check; userExitsCheck() returns users only, so this path should not depend on an already populated role collection.

Define whether an exempt role should match any mapping or require all mappings to be exempt, then add a multi-role test.

πŸ“ Affects 1 file
  • src/main/java/com/iemr/common/controller/users/IEMRAdminController.java#L195-L210 (this comment)
  • src/main/java/com/iemr/common/controller/users/IEMRAdminController.java#L437-L458
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/iemr/common/controller/users/IEMRAdminController.java`
around lines 195 - 210, The concurrent-session exemption currently inspects only
the first role mapping and may use an unpopulated collection. Update the checks
around IEMRAdminController’s login flow and the path near userExitsCheck() to
reload and inspect complete role mappings, defining and consistently applying
whether any or all roles must be exempt; add a multi-role test covering the
chosen behavior. Both affected sites require the same complete-mapping logic.

}
} else if (m_User.getUserName() != null && m_User.getDoLogout() != null && m_User.getDoLogout() == true) {
deleteSessionObject(m_User.getUserName().trim().toLowerCase());
Expand Down Expand Up @@ -254,7 +276,6 @@
// Facility data for ALL users - common pattern, empty if not applicable
try {
if (mUser.size() == 1) {
User loggedInUser = mUser.get(0);
String userRoleName = "";
if (loggedInUser.getM_UserServiceRoleMapping() != null) {
for (UserServiceRoleMapping usrm : loggedInUser.getM_UserServiceRoleMapping()) {
Expand Down Expand Up @@ -413,16 +434,28 @@
deleteSessionObjectByGettingSessionDetails(previousTokenFromRedis);
sessionObject.deleteSessionObject(previousTokenFromRedis);

// Denylist the active JWT so System 1's requests are immediately rejected
String usernameKey = mUsers.get(0).getUserName().trim().toLowerCase();
String jtiData = stringRedisTemplate.opsForValue().get("jti:" + usernameKey);
if (jtiData != null) {
String[] parts = jtiData.split("\\|", 2);
tokenDenylist.addTokenToDenylist(parts[0], jwtUtil.getAccessTokenExpiration());
if (parts.length > 1) {
redisTemplate.delete("user_" + parts[1]);
String userRole = "";
if (mUsers.get(0).getM_UserServiceRoleMapping() != null) {
for (UserServiceRoleMapping usrm : mUsers.get(0).getM_UserServiceRoleMapping()) {
if (usrm.getM_Role() != null && usrm.getM_Role().getRoleName() != null) {
userRole = usrm.getM_Role().getRoleName();
break;
}
}
}
if (!CONCURRENT_SESSION_EXEMPT_ROLES.contains(userRole.trim().toLowerCase())) {
// Denylist the active JWT so the first system's requests are immediately rejected
String usernameKey = mUsers.get(0).getUserName().trim().toLowerCase();
String jtiData = stringRedisTemplate.opsForValue().get("jti:" + usernameKey);
if (jtiData != null) {
String[] parts = jtiData.split("\\|", 2);
String jti = parts[0];
tokenDenylist.addTokenToDenylist(jti, jwtUtil.getAccessTokenExpiration());
if (parts.length > 1) {
redisTemplate.delete("user_" + parts[1]);
}
stringRedisTemplate.delete("jti:" + usernameKey);
}
stringRedisTemplate.delete("jti:" + usernameKey);
}

response.setResponse("User successfully logged out");
Expand Down Expand Up @@ -537,11 +570,13 @@
String refreshToken = null;
boolean isMobile = false;
if (m_User.getUserName() != null && (m_User.getDoLogout() == null || m_User.getDoLogout() == false)) {
String tokenFromRedis = getConcurrentCheckSessionObjectAgainstUser(
m_User.getUserName().trim().toLowerCase());
if (tokenFromRedis != null) {
throw new IEMRException(
"You are already logged in,please confirm to logout from other device and login again");
if (!CONCURRENT_SESSION_EXEMPT_ROLES.contains(m_User.getUserName().trim().toLowerCase())) {
String tokenFromRedis = getConcurrentCheckSessionObjectAgainstUser(
m_User.getUserName().trim().toLowerCase());
if (tokenFromRedis != null) {
throw new IEMRException(
"You are already logged in,please confirm to logout from other device and login again");
}
}
} else if (m_User.getUserName() != null && m_User.getDoLogout() != null && m_User.getDoLogout() == true) {
deleteSessionObject(m_User.getUserName().trim().toLowerCase());
Expand Down Expand Up @@ -1000,6 +1035,13 @@
try {
deleteSessionObjectByGettingSessionDetails(request.getHeader("Authorization"));
sessionObject.deleteSessionObject(request.getHeader("Authorization"));
try {

Check warning on line 1038 in src/main/java/com/iemr/common/controller/users/IEMRAdminController.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Extract this nested try block into a separate method.

See more on https://sonarcloud.io/project/issues?id=PSMRI_Common-API&issues=AZ8YVvgU-_kpGiYTbzWU&open=AZ8YVvgU-_kpGiYTbzWU&pullRequest=438
stringRedisTemplate.delete("camp:vanID");
stringRedisTemplate.delete("camp:parkingPlaceID");
logger.info("Camp config cleared from Redis on MMU logout");
} catch (Exception redisEx) {
logger.warn("Failed to clear camp Redis keys on logout: {}", redisEx.getMessage());
}
response.setResponse("Success");
} catch (Exception e) {
response.setError(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public class FormFieldOption {
@Column(name = "label_as")
private String labelAs;

@Column(name = "label_bn")
private String labelBn;

@Column(name = "sort_order")
private Integer sortOrder;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public class Translation {
private String hindiTranslation;
@Column(name = "assamese_translation")
private String assameseTranslation;
@Column(name = "bengali_translation")
private String bengaliTranslation;
@Column(name = "is_active")
private Boolean isActive;

Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/iemr/common/dto/identity/Address.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@
private String parkingPlaceName;
private Integer servicePointID;
private String servicePointName;
private Double gpsLatitude;
private Double gpsLongitude;
private String digipin;
private Long gpsTimestamp;
private Boolean isGpsUnavailable;
private String gpsUnavailableReason;
Comment on lines +55 to +60

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟑 Minor | ⚑ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Address.java =="
sed -n '1,220p' src/main/java/com/iemr/common/dto/identity/Address.java

echo
echo "== BenCompleteDetailMapperDecorator.java =="
sed -n '1,260p' src/main/java/com/iemr/common/mapper/BenCompleteDetailMapperDecorator.java

echo
echo "== Search for isGpsUnavailable usages =="
rg -n "isGpsUnavailable|getIsGpsUnavailable|setIsGpsUnavailable|GpsUnavailableReason|gpsUnavailable" src/main/java

Repository: PSMRI/Common-API

Length of output: 16013


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== BeneficiaryDemographicsModel excerpt =="
sed -n '150,220p' src/main/java/com/iemr/common/model/beneficiary/BeneficiaryDemographicsModel.java

echo
echo "== All direct reads of getIsGpsUnavailable =="
rg -n "getIsGpsUnavailable\\(" src/main/java

echo
echo "== All direct Boolean checks on isGpsUnavailable =="
rg -n "isGpsUnavailable|GpsUnavailable" src/main/java/com/iemr/common | sed -n '1,200p'

Repository: PSMRI/Common-API

Length of output: 4570


Preserve the isGpsUnavailable default when mapping from Address.

BeneficiaryDemographicsModel defaults this flag to false, but Address leaves it nullable and BenCompleteDetailMapperDecorator copies that null straight over, clearing the default. If null is not a meaningful third state, default the DTO to false or skip the setter when the source is null.

  • src/main/java/com/iemr/common/dto/identity/Address.java#L55-L60
  • src/main/java/com/iemr/common/mapper/BenCompleteDetailMapperDecorator.java#L161-L166
πŸ“ Affects 2 files
  • src/main/java/com/iemr/common/dto/identity/Address.java#L55-L60 (this comment)
  • src/main/java/com/iemr/common/mapper/BenCompleteDetailMapperDecorator.java#L161-L166
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/iemr/common/dto/identity/Address.java` around lines 55 -
60, The isGpsUnavailable default is being overwritten with null during Address
mapping. Update Address to default isGpsUnavailable to false or adjust
BenCompleteDetailMapperDecorator to avoid setting the target when the source
value is null; apply the corresponding change at
src/main/java/com/iemr/common/dto/identity/Address.java#L55-L60 and
src/main/java/com/iemr/common/mapper/BenCompleteDetailMapperDecorator.java#L161-L166,
preserving false as the default when no value is supplied.


public static Address bendemographicsAddressMapper(BeneficiaryDemographicsModel i_bendemographics) {
Address address = new Address();
Expand Down Expand Up @@ -87,6 +93,12 @@ public static Address bendemographicsAddressMapper(BeneficiaryDemographicsModel
address.setSubDistrictId(i_bendemographics.getBlockID());
address.setVillageId(i_bendemographics.getDistrictBranchID());
address.setPinCode(i_bendemographics.getPinCode());
address.setGpsLatitude(i_bendemographics.getLatitude());
address.setGpsLongitude(i_bendemographics.getLongitude());
address.setDigipin(i_bendemographics.getDigipin());
address.setGpsTimestamp(i_bendemographics.getGpsTimestamp());
address.setIsGpsUnavailable(i_bendemographics.getIsGpsUnavailable());
address.setGpsUnavailableReason(i_bendemographics.getGpsUnavailableReason());

return address;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,12 @@ public BeneficiaryDemographicsModel createBenDemographicsModel(BeneficiariesDTO
demographicsModel.setServicePointID(address.getServicePointID());
demographicsModel.setServicePointName(address.getServicePointName());
demographicsModel.setHabitation(address.getHabitation());
demographicsModel.setLatitude(address.getGpsLatitude());
demographicsModel.setLongitude(address.getGpsLongitude());
demographicsModel.setDigipin(address.getDigipin());
demographicsModel.setGpsTimestamp(address.getGpsTimestamp());
demographicsModel.setIsGpsUnavailable(address.getIsGpsUnavailable());
demographicsModel.setGpsUnavailableReason(address.getGpsUnavailableReason());
}
demographicsModel.setHealthCareWorkerID(benDetails.getHealthCareWorkerId());
demographicsModel.setPreferredLangID(beneficiariesDTO.getBeneficiaryDetails().getPreferredLanguageId());
Expand Down Expand Up @@ -216,6 +222,12 @@ protected Address beneficiaryDemographicsModelToAddress(BeneficiaryDemographicsM
address.setSubDistrict(
blockMapper.districtBlockToModelByID(beneficiaryDemographicsModel.getBlockID()).getBlockName());
}
address.setGpsLatitude(beneficiaryDemographicsModel.getLatitude());
address.setGpsLongitude(beneficiaryDemographicsModel.getLongitude());
address.setDigipin(beneficiaryDemographicsModel.getDigipin());
address.setGpsTimestamp(beneficiaryDemographicsModel.getGpsTimestamp());
address.setIsGpsUnavailable(beneficiaryDemographicsModel.getIsGpsUnavailable());
address.setGpsUnavailableReason(beneficiaryDemographicsModel.getGpsUnavailableReason());

return address;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,12 @@ protected Address beneficiaryDemographicsModelToAddress(BeneficiaryDemographicsM
address.setSubDistrict(
blockMapper.districtBlockToModelByID(beneficiaryDemographicsModel.getBlockID()).getBlockName());
}
address.setGpsLatitude(beneficiaryDemographicsModel.getLatitude());
address.setGpsLongitude(beneficiaryDemographicsModel.getLongitude());
address.setDigipin(beneficiaryDemographicsModel.getDigipin());
address.setGpsTimestamp(beneficiaryDemographicsModel.getGpsTimestamp());
address.setIsGpsUnavailable(beneficiaryDemographicsModel.getIsGpsUnavailable());
address.setGpsUnavailableReason(beneficiaryDemographicsModel.getGpsUnavailableReason());

return address;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ protected Address beneficiaryDemographicsModelToAddress(BeneficiaryDemographicsM
address.setSubDistrict(
blockMapper.districtBlockToModelByID(beneficiaryDemographicsModel.getBlockID()).getBlockName());
}
address.setGpsLatitude(beneficiaryDemographicsModel.getLatitude());
address.setGpsLongitude(beneficiaryDemographicsModel.getLongitude());
address.setDigipin(beneficiaryDemographicsModel.getDigipin());
address.setGpsTimestamp(beneficiaryDemographicsModel.getGpsTimestamp());
address.setIsGpsUnavailable(beneficiaryDemographicsModel.getIsGpsUnavailable());
address.setGpsUnavailableReason(beneficiaryDemographicsModel.getGpsUnavailableReason());

return address;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,19 @@ public class BeneficiaryDemographicsModel {
@Expose
private String habitation;

@Expose
private Double latitude;
@Expose
private Double longitude;
@Expose
private String digipin;
@Expose
private Long gpsTimestamp;
@Expose
private Boolean isGpsUnavailable = false;
@Expose
private String gpsUnavailableReason;

@Expose
private String occupation;
@Expose
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ public FormResponseDTO getStructuredFormByFormId(String formId, String lang, Str
} else if ("en".equalsIgnoreCase(lang)) {
translatedLabel = label.getEnglish();

}else if ("bn".equalsIgnoreCase(lang)) {
translatedLabel = label.getBengaliTranslation();

Comment on lines +163 to +165

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚑ Quick win

Preserve a fallback when Bengali text is unavailable.

These branches assign nullable Bengali values directly, so existing or partially translated records can produce null field labels, placeholders, and option labels. Use Bengali only when it is nonblank; otherwise retain the field/placeholder default and the English option label.

Also applies to: 177-179, 212-213

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/iemr/common/service/dynamicForm/FormMasterServiceImpl.java`
around lines 163 - 165, Update the Bengali branches in the relevant label,
placeholder, and option translation logic to use the Bengali translation only
when it is nonblank; otherwise preserve the existing field/placeholder default
or English option label. Apply this consistently to the branches assigning
translatedLabel and the corresponding symbols near the referenced locations.

}
}

Expand All @@ -171,6 +174,9 @@ public FormResponseDTO getStructuredFormByFormId(String formId, String lang, Str
} else if ("en".equalsIgnoreCase(lang)) {
translatedPlaceHolder = placeHolder.getEnglish();

} else if ("bn".equalsIgnoreCase(lang)) {
translatedPlaceHolder = placeHolder.getBengaliTranslation();

}
}

Expand Down Expand Up @@ -203,7 +209,8 @@ public FormResponseDTO getStructuredFormByFormId(String formId, String lang, Str
map.put("value", opt.getValue());
if ("hi".equalsIgnoreCase(lang)) map.put("label", opt.getLabelHi());
else if ("as".equalsIgnoreCase(lang)) map.put("label", opt.getLabelAs());
else map.put("label", opt.getLabelEn());
else if("en".equals(lang)) map.put("label", opt.getLabelEn());
else if("bn".equals(lang)) map.put("label", opt.getLabelBn());
Comment on lines +212 to +213

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟑 Minor | ⚑ Quick win

Use case-insensitive matching for option languages.

The field and placeholder paths use equalsIgnoreCase, but option selection requires exact en/bn casing. A request with lang=BN can therefore translate field text while omitting the option label; use equalsIgnoreCase consistently.

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/iemr/common/service/dynamicForm/FormMasterServiceImpl.java`
around lines 212 - 213, Update the option-language checks in
FormMasterServiceImpl to use case-insensitive matching for both English and
Bengali, replacing the exact comparisons in the branches that populate opt
labels. Preserve the existing label selection behavior while ensuring values
such as β€œBN” and β€œEN” select the corresponding translations.

return map;
})
.collect(Collectors.toList());
Expand Down
14 changes: 4 additions & 10 deletions src/main/java/com/iemr/common/service/health/HealthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ public class HealthService {
private static final String STATUS_VALUE = "Value";
private static final String STATUS_UP = "UP";
private static final String STATUS_DOWN = "DOWN";
private static final String STATUS_DEGRADED = "DEGRADED";
private static final String STATUS_NOT_CONFIGURED = "NOT_CONFIGURED";

// Thresholds
Expand Down Expand Up @@ -183,9 +182,11 @@ private Map<String, Object> checkDatabaseConnectivity() {
stmt.setQueryTimeout(3); // Bounds only the SELECT 1 execution
stmt.execute("SELECT 1");

// If SELECT 1 succeeds, use cached severity from background diagnostics
// SELECT 1 succeeded, so connectivity is UP regardless of background severity.
// Severity is a separate capacity/performance signal (pool usage, long transactions,
// etc.) β€” it must not be reported as a connectivity outage.
String severity = cachedDbSeverity.get();
result.put(FIELD_STATUS, resolveDatabaseStatus(severity));
result.put(FIELD_STATUS, STATUS_UP);
result.put(FIELD_SEVERITY, severity);

} catch (Exception e) {
Expand Down Expand Up @@ -402,13 +403,6 @@ private String performConnectionUsageCheck(Connection conn) {
}
return SEVERITY_OK;
}
private String resolveDatabaseStatus(String severity) {
return switch (severity) {
case SEVERITY_CRITICAL -> STATUS_DOWN;
case SEVERITY_WARNING -> STATUS_DEGRADED;
default -> STATUS_UP;
};
}
private String escalate(String current, String candidate) {
return severityRank(candidate) > severityRank(current) ? candidate : current;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,5 @@ public List<ServiceRoleScreenMapping> getUserServiceRoleMappingForProvider(Integ

boolean hasAdminPrivileges(Long userId) throws IEMRException;

User save(User loggedInUser);
}
Loading
Loading