diff --git a/pom.xml b/pom.xml
index 0ae3d0b9..3a0191c9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.iemr.common-API
common-api
- 3.4.0
+ 3.6.0
war
Common-API
@@ -111,6 +111,12 @@
+
+
+ com.google.firebase
+ firebase-admin
+ 9.4.3
+
org.springframework.boot
spring-boot-starter-data-jpa
diff --git a/src/main/environment/common_ci.properties b/src/main/environment/common_ci.properties
index a5e66660..d8865adf 100644
--- a/src/main/environment/common_ci.properties
+++ b/src/main/environment/common_ci.properties
@@ -32,6 +32,7 @@ identity-1097-api-url = @env.IDENTITY_1097_API_URL@
send-sms=@env.SEND_SMS@
sendSMSUrl = @env.SEND_SMS_URL@
source-address=@env.SMS_SOURCE_ADDRESS@
+sms-consent-source-address = @env.SMS_CONSENT_SOURCE_ADDRESS@
sms-username=@env.SMS_USERNAME@
sms-password=@env.SMS_PASSWORD@
send-message-url=@env.SMS_MESSAGE_URL@
@@ -40,6 +41,11 @@ send-message-url=@env.SMS_MESSAGE_URL@
start-sms-scheduler=true
cron-scheduler-sms=0 0/1 * * * ? *
+# Firebase Configuration
+firebase.enabled=@env.FIREBASE_ENABLE@
+# if using file
+firebase.credential-file=@env.FIREBASE_CREDENTIAL@
+
#### Email Configuration
send-email=@env.SEND_EMAIL@
spring.mail.host=@env.MAIL_HOST@
@@ -185,4 +191,5 @@ cors.allowed-origins=@env.CORS_ALLOWED_ORIGINS@
video-call-url=@env.VIDEO_CALL_URL@
jibri.output.path=@env.JIBRI_OUTPUT_PATH@
-video.recording.path=@env.VIDEO_RECORDING_PATH@
\ No newline at end of file
+video.recording.path=@env.VIDEO_RECORDING_PATH@
+generateBeneficiaryIDs-api-url=@env.GEN_BENEFICIARY_IDS_API_URL@
diff --git a/src/main/environment/common_docker.properties b/src/main/environment/common_docker.properties
index 41881886..2289c2c0 100644
--- a/src/main/environment/common_docker.properties
+++ b/src/main/environment/common_docker.properties
@@ -32,6 +32,7 @@ identity-1097-api-url = ${IDENTITY_1097_API_URL}
send-sms=${SEND_SMS}
sendSMSUrl = ${SEND_SMS_URL}
source-address=${SMS_SOURCE_ADDRESS}
+sms-consent-source-address=${SMS_CONSENT_SOURCE_ADDRESS}
sms-username=${SMS_USERNAME}
sms-password=${SMS_PASSWORD}
send-message-url=${SMS_MESSAGE_URL}
@@ -185,6 +186,13 @@ captcha.enable-captcha=${ENABLE_CAPTCHA}
cors.allowed-origins=${CORS_ALLOWED_ORIGINS}
+# # Firebase Configuration
+firebase.enabled=${FIREBASE_ENABLE}
+# # if using file
+firebase.credential-file=${FIREBASE_CREDENTIAL}
+
+
video-call-url=${VIDEO_CALL_URL}
jibri.output.path={JIBRI_OUTPUT_PATH}
-video.recording.path={VIDEO_RECORDING_PATH}
\ No newline at end of file
+video.recording.path={VIDEO_RECORDING_PATH}
+generateBeneficiaryIDs-api-url={GEN_BENEFICIARY_IDS_API_URL}
diff --git a/src/main/environment/common_example.properties b/src/main/environment/common_example.properties
index 09a526dd..bea76523 100644
--- a/src/main/environment/common_example.properties
+++ b/src/main/environment/common_example.properties
@@ -208,3 +208,5 @@ captcha.enable-captcha=true
cors.allowed-origins=http://localhost:*
+### generate Beneficiary IDs URL
+generateBeneficiaryIDs-api-url=/generateBeneficiaryController/generateBeneficiaryIDs
diff --git a/src/main/java/com/iemr/common/CommonApplication.java b/src/main/java/com/iemr/common/CommonApplication.java
index b9b797b2..e4a59994 100644
--- a/src/main/java/com/iemr/common/CommonApplication.java
+++ b/src/main/java/com/iemr/common/CommonApplication.java
@@ -29,7 +29,6 @@
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
-import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.client.RestTemplate;
diff --git a/src/main/java/com/iemr/common/config/firebase/FirebaseMessagingConfig.java b/src/main/java/com/iemr/common/config/firebase/FirebaseMessagingConfig.java
new file mode 100644
index 00000000..ebb697ec
--- /dev/null
+++ b/src/main/java/com/iemr/common/config/firebase/FirebaseMessagingConfig.java
@@ -0,0 +1,65 @@
+package com.iemr.common.config.firebase;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import com.google.firebase.FirebaseApp;
+import com.google.firebase.FirebaseOptions;
+import com.google.firebase.messaging.FirebaseMessaging;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.ClassPathResource;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Base64;
+
+@Configuration
+public class FirebaseMessagingConfig {
+ private Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());
+
+ @Value("${firebase.enabled:false}")
+ private boolean firebaseEnabled;
+
+ @Value("${firebase.credential-file:}")
+ private String firebaseCredentialFile;
+
+
+ @Bean
+ @ConditionalOnProperty(name = "firebase.enabled", havingValue = "true")
+ public FirebaseMessaging firebaseMessaging() throws IOException {
+ if (!firebaseEnabled) {
+ logger.error("⚠️ Firebase disabled by config");
+ return null;
+ }
+
+ try {
+ if (firebaseCredentialFile == null || firebaseCredentialFile.isBlank()) {
+ logger.error("⚠️ No Firebase credentials path provided");
+ return null; // don't throw, app will still start
+ }
+
+ GoogleCredentials credentials = GoogleCredentials.fromStream(
+ new ClassPathResource(firebaseCredentialFile).getInputStream()
+ );
+ FirebaseOptions options = FirebaseOptions.builder()
+ .setCredentials(credentials)
+ .build();
+
+ FirebaseApp firebaseApp = FirebaseApp.getApps().isEmpty()
+ ? FirebaseApp.initializeApp(options)
+ : FirebaseApp.getInstance();
+
+ return FirebaseMessaging.getInstance(firebaseApp);
+
+ } catch (Exception e) {
+ logger.error("⚠️ Firebase init failed: " + e.getMessage());
+ return null; // keep app running
+ }
+
+ }
+
+}
diff --git a/src/main/java/com/iemr/common/config/quartz/ScheduleForGrievanceDataSync.java b/src/main/java/com/iemr/common/config/quartz/ScheduleForGrievanceDataSync.java
index f016de3d..314b31ac 100644
--- a/src/main/java/com/iemr/common/config/quartz/ScheduleForGrievanceDataSync.java
+++ b/src/main/java/com/iemr/common/config/quartz/ScheduleForGrievanceDataSync.java
@@ -37,3 +37,4 @@ public void execute() {
}
}
+
diff --git a/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java b/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java
new file mode 100644
index 00000000..77492d89
--- /dev/null
+++ b/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java
@@ -0,0 +1,118 @@
+/*
+ * 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.beneficiaryConsent;
+
+import com.iemr.common.data.beneficiaryConsent.BeneficiaryConsentRequest;
+import com.iemr.common.service.beneficiaryOTPHandler.BeneficiaryOTPHandler;
+import com.iemr.common.utils.mapper.InputMapper;
+import com.iemr.common.utils.response.OutputResponse;
+import io.lettuce.core.dynamic.annotation.Param;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.ws.rs.core.MediaType;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+@RequestMapping(value = { "/beneficiaryConsent" })
+@RestController
+public class BeneficiaryConsentController {
+ final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
+
+ @Autowired
+ private BeneficiaryOTPHandler beneficiaryOTPHandler;
+
+ @Operation(summary = "Send Consent")
+ @RequestMapping(value = "/sendConsent", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON)
+ public String sendConsent(@Param(value = "{\"mobNo\":\"String\"}") @RequestBody String requestOBJ) {
+
+ OutputResponse response = new OutputResponse();
+
+ try {
+ BeneficiaryConsentRequest obj = InputMapper.gson().fromJson(requestOBJ, BeneficiaryConsentRequest.class);
+
+ String success = beneficiaryOTPHandler.sendOTP(obj); // method name unchanged if internal logic still uses 'OTP'
+ logger.info(success.toString());
+ response.setResponse(success);
+
+
+ } catch (Exception e) {
+ response.setError(500, "error : " + e);
+ }
+ return response.toString();
+ }
+
+ @Operation(summary = "Validate Consent")
+ @RequestMapping(value = "/validateConsent", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON)
+ public String validateConsent(@Param(value = "{\"mobNo\":\"String\",\"otp\":\"Integer\"}") @RequestBody String requestOBJ) {
+
+ OutputResponse response = new OutputResponse();
+
+ try {
+ BeneficiaryConsentRequest obj = InputMapper.gson().fromJson(requestOBJ, BeneficiaryConsentRequest.class);
+
+ JSONObject responseOBJ = beneficiaryOTPHandler.validateOTP(obj);
+ if (responseOBJ != null)
+ response.setResponse(responseOBJ.toString());
+ else
+ response.setError(500, "failure");
+
+ } catch (Exception e) {
+ logger.error("error in validating Consent : " + e);
+ response.setError(500, "error : " + e);
+ }
+ return response.toString();
+ }
+
+ @Operation(summary = "Resend Consent")
+ @RequestMapping(value = "/resendConsent", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON)
+ public String resendConsent(@Param(value = "{\"mobNo\":\"String\"}") @RequestBody String requestOBJ) {
+ logger.info(requestOBJ.toString());
+
+ OutputResponse response = new OutputResponse();
+
+ try {
+ BeneficiaryConsentRequest obj = InputMapper.gson().fromJson(requestOBJ, BeneficiaryConsentRequest.class);
+
+ String success = beneficiaryOTPHandler.resendOTP(obj);
+ logger.info(success.toString());
+
+ if (success.contains("otp"))
+ response.setResponse(success);
+ else
+ response.setError(500, "failure");
+
+ } catch (Exception e) {
+ logger.error("error in re-sending Consent : " + e);
+ response.setError(500, "error : " + e);
+ }
+ return response.toString();
+ }
+
+
+}
+
+
diff --git a/src/main/java/com/iemr/common/controller/dynamicForm/DynamicFormController.java b/src/main/java/com/iemr/common/controller/dynamicForm/DynamicFormController.java
new file mode 100644
index 00000000..a5f72bbf
--- /dev/null
+++ b/src/main/java/com/iemr/common/controller/dynamicForm/DynamicFormController.java
@@ -0,0 +1,98 @@
+package com.iemr.common.controller.dynamicForm;
+
+import com.iemr.common.dto.dynamicForm.FieldDTO;
+import com.iemr.common.dto.dynamicForm.FormDTO;
+import com.iemr.common.dto.dynamicForm.ModuleDTO;
+import com.iemr.common.service.dynamicForm.FormMasterService;
+import com.iemr.common.utils.response.ApiResponse;
+import jakarta.validation.Valid;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RequestMapping(value = "dynamicForm")
+@RestController
+public class DynamicFormController {
+ @Autowired
+ private FormMasterService formMasterService;
+
+ @PostMapping(value = "createModule",headers = "Authorization")
+ public ResponseEntity> createModule(@Valid @RequestBody ModuleDTO moduleDTO) {
+ try {
+ Object result = formMasterService.createModule(moduleDTO);
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(ApiResponse.success("Module created successfully", HttpStatus.OK.value(), result));
+ } catch (IllegalArgumentException e) {
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST)
+ .body(ApiResponse.error("Invalid module data: " + e.getMessage(), HttpStatus.BAD_REQUEST.value(), null));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+ .body(ApiResponse.error("Failed to create module", HttpStatus.INTERNAL_SERVER_ERROR.value(), null));
+ }
+ }
+
+ @PostMapping(value = "createForm",headers = "Authorization")
+ public ResponseEntity> createForm(@Valid @RequestBody FormDTO dto) {
+ try {
+ Object result = formMasterService.createForm(dto);
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(ApiResponse.success("Form created successfully", HttpStatus.OK.value(), result));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+ .body(ApiResponse.error("Failed to create form", HttpStatus.INTERNAL_SERVER_ERROR.value(), null));
+ }
+ }
+
+ @PostMapping(value = "createFields",headers = "Authorization")
+ public ResponseEntity> createField(@Valid @RequestBody List dto) {
+ try {
+ Object result = formMasterService.createField(dto);
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(ApiResponse.success("Fields created successfully", HttpStatus.OK.value(), result));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+ .body(ApiResponse.error("Failed to create fields", HttpStatus.INTERNAL_SERVER_ERROR.value(), null));
+ }
+ }
+
+ @PostMapping(value = "field/update",headers = "Authorization")
+ public ResponseEntity> updateField(@Valid @RequestBody FieldDTO dto) {
+ try {
+ Object result = formMasterService.updateField(dto);
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(ApiResponse.success("Field updated successfully", HttpStatus.OK.value(), result));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+ .body(ApiResponse.error("Failed to update field", HttpStatus.INTERNAL_SERVER_ERROR.value(), null));
+ }
+ }
+
+ @DeleteMapping(value = "delete/{fieldId}/field",headers = "Authorization")
+ public ResponseEntity> deleteField(@PathVariable Long fieldId) {
+ try {
+ formMasterService.deleteField(fieldId);
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(ApiResponse.success("Field deleted successfully", HttpStatus.OK.value(), null));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+ .body(ApiResponse.error("Failed to delete field", HttpStatus.INTERNAL_SERVER_ERROR.value(), null));
+ }
+ }
+
+ @GetMapping(value = "form/{formId}/fields")
+ public ResponseEntity> getStructuredForm(@PathVariable String formId) {
+ try {
+ Object result = formMasterService.getStructuredFormByFormId(formId);
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(ApiResponse.success("Form structure fetched successfully", HttpStatus.OK.value(), result));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+ .body(ApiResponse.error("Failed to fetch form structure", HttpStatus.INTERNAL_SERVER_ERROR.value(), null));
+ }
+ }
+
+
+}
diff --git a/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java b/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java
new file mode 100644
index 00000000..3bb10cfc
--- /dev/null
+++ b/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java
@@ -0,0 +1,61 @@
+/*
+* 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
+*/
+package com.iemr.common.controller.firebaseNotification;
+
+import com.iemr.common.model.notification.NotificationMessage;
+import com.iemr.common.model.notification.UserToken;
+import com.iemr.common.service.firebaseNotification.FirebaseNotificationService;
+import com.iemr.common.utils.exception.IEMRException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping(value= "/firebaseNotification",headers = "Authorization")
+public class FirebaseNotificationController {
+ final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
+
+ @Autowired
+ FirebaseNotificationService firebaseNotificationService;
+
+ @RequestMapping(value = "sendNotification",method = RequestMethod.POST,headers = "Authorization")
+ public String sendNotificationByToken(@RequestBody NotificationMessage notificationMessage){
+ return firebaseNotificationService.sendNotification(notificationMessage);
+ }
+
+ @RequestMapping(value = "updateToken",method = RequestMethod.POST,headers = "Authorization")
+ public String updateToken(@RequestBody UserToken userToken){
+ return firebaseNotificationService.updateToken(userToken);
+ }
+
+ @RequestMapping(value = "getToken",method = RequestMethod.GET,headers = "Authorization")
+ public String getUserToken() throws IEMRException {
+
+ return firebaseNotificationService.getUserToken();
+ }
+
+
+}
diff --git a/src/main/java/com/iemr/common/controller/nhmdashboard/NHMDetailCallReportScheduler.java b/src/main/java/com/iemr/common/controller/nhmdashboard/NHMDetailCallReportScheduler.java
index 5fd3e281..d02eb3f2 100644
--- a/src/main/java/com/iemr/common/controller/nhmdashboard/NHMDetailCallReportScheduler.java
+++ b/src/main/java/com/iemr/common/controller/nhmdashboard/NHMDetailCallReportScheduler.java
@@ -181,3 +181,4 @@ private BeneficiaryCall getCallDetail(DetailedCallReport detailedCallReport) {
}
}
+
diff --git a/src/main/java/com/iemr/common/controller/users/EmployeeSignatureController.java b/src/main/java/com/iemr/common/controller/users/EmployeeSignatureController.java
index a2156af1..e04fffc5 100644
--- a/src/main/java/com/iemr/common/controller/users/EmployeeSignatureController.java
+++ b/src/main/java/com/iemr/common/controller/users/EmployeeSignatureController.java
@@ -21,22 +21,28 @@
*/
package com.iemr.common.controller.users;
+import java.nio.charset.StandardCharsets;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.PropertySource;
+import org.springframework.http.CacheControl;
+import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.InvalidMediaTypeException;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.server.ResponseStatusException;
import com.google.gson.Gson;
import com.iemr.common.data.users.EmployeeSignature;
import com.iemr.common.service.users.EmployeeSignatureServiceImpl;
-import com.iemr.common.utils.mapper.InputMapper;
import com.iemr.common.utils.response.OutputResponse;
import io.swagger.v3.oas.annotations.Operation;
@@ -51,29 +57,45 @@ public class EmployeeSignatureController {
@Autowired
EmployeeSignatureServiceImpl employeeSignatureServiceImpl;
- private InputMapper inputMapper = new InputMapper();
-
private Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());
@Operation(summary = "Fetch file")
@RequestMapping(value = "/{userID}", headers = "Authorization", method = { RequestMethod.GET })
public ResponseEntity fetchFile(@PathVariable("userID") Long userID) throws Exception {
- OutputResponse response = new OutputResponse();
logger.debug("File download for userID" + userID);
try {
-
EmployeeSignature userSignID = employeeSignatureServiceImpl.fetchSignature(userID);
- return ResponseEntity.ok().contentType(MediaType.parseMediaType(userSignID.getFileType()))
- .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + userSignID.getFileName() + "\"")
- .body(userSignID.getSignature());
+ String originalName = userSignID.getFileName();
+ if (originalName == null || originalName.isBlank()) {
+ originalName = "signature";
+ }
+ HttpHeaders responseHeaders = new HttpHeaders();
+ responseHeaders.setContentDisposition(
+ ContentDisposition.attachment().filename(originalName, StandardCharsets.UTF_8).build());
+ responseHeaders.setCacheControl(CacheControl.noStore());
+ responseHeaders.add(HttpHeaders.PRAGMA, "no-cache");
+ responseHeaders.setExpires(0);
+ MediaType mediaType;
+ try {
+ mediaType = MediaType.parseMediaType(userSignID.getFileType());
+ } catch (InvalidMediaTypeException | NullPointerException e) {
+ mediaType = MediaType.APPLICATION_OCTET_STREAM;
+ }
+
+ byte[] fileBytes = userSignID.getSignature(); // MUST be byte[]
+ if (fileBytes == null || fileBytes.length == 0) {
+ throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Signature not found for userID: " + userID);
+ }
+
+ return ResponseEntity.ok().headers(responseHeaders).contentType(mediaType).contentLength(fileBytes.length)
+ .body(fileBytes);
} catch (Exception e) {
logger.error("File download for userID failed with exception " + e.getMessage(), e);
+ throw new Exception("Error while downloading file. Please contact administrator..");
}
- return ResponseEntity.badRequest().body(new byte[] {});
-
}
@Operation(summary = "Fetch file from central")
diff --git a/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java b/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java
index 28c7e4b9..080c8762 100644
--- a/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java
+++ b/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java
@@ -1,8 +1,8 @@
/*
-* AMRIT – Accessible Medical Records via Integrated Technology
-* Integrated EHR (Electronic Health Records) Solution
+* AMRIT – Accessible Medical Records via Integrated Technology
+* Integrated EHR (Electronic Health Records) Solution
*
-* Copyright (C) "Piramal Swasthya Management and Research Institute"
+* Copyright (C) "Piramal Swasthya Management and Research Institute"
*
* This file is part of AMRIT.
*
@@ -170,8 +170,8 @@ public String userAuthenticate(
JSONObject serviceRoleMap = new JSONObject();
JSONArray serviceRoleList = new JSONArray();
JSONObject previlegeObj = new JSONObject();
- if (m_User.getUserName() != null
- && (m_User.getDoLogout() == null || !m_User.getDoLogout())
+ 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());
@@ -187,7 +187,7 @@ public String userAuthenticate(
String refreshToken = null;
if (mUser.size() == 1) {
jwtToken = jwtUtil.generateToken(m_User.getUserName(), mUser.get(0).getUserID().toString());
-
+
User user = new User(); // Assuming the Users class exists
user.setUserID(mUser.get(0).getUserID());
user.setUserName(mUser.get(0).getUserName());
@@ -278,15 +278,16 @@ public ResponseEntity> refreshToken(@RequestBody Map request)
// Get user details
String userId = claims.get("userId", String.class);
User user = iemrAdminUserServiceImpl.getUserById(Long.parseLong(userId));
-
+
// Validate that the user still exists and is active
if (user == null) {
logger.warn("Token validation failed: user not found for userId in token.");
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Unauthorized.");
}
-
- if (user.getM_status() == null || !"Active".equalsIgnoreCase(user.getM_status().getStatus())) {
- logger.warn("Token validation failed: user account is inactive or not in 'Active' status.");
+
+ if (user.getM_status() == null || !("Active".equalsIgnoreCase(user.getM_status().getStatus())
+ || "New".equalsIgnoreCase(user.getM_status().getStatus()))) {
+ logger.warn("Token validation failed: user account is neither 'Active' nor 'New'.");
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Unauthorized.");
}
// Generate new tokens
@@ -294,7 +295,7 @@ public ResponseEntity> refreshToken(@RequestBody Map request)
Map tokens = new HashMap<>();
tokens.put("jwtToken", newJwt);
-
+
// Generate and store a new refresh token (token rotation)
String newRefreshToken = jwtUtil.generateRefreshToken(user.getUserName(), userId);
String newJti = jwtUtil.getJtiFromToken(newRefreshToken);
@@ -343,9 +344,10 @@ public String logOutUserFromConcurrentSession(
deleteSessionObjectByGettingSessionDetails(previousTokenFromRedis);
sessionObject.deleteSessionObject(previousTokenFromRedis);
response.setResponse("User successfully logged out");
- } else
+ } else{
logger.error("Unable to fetch session from redis");
throw new IEMRException("Session error. Please try again later");
+ }
}
} else {
throw new IEMRException("Invalid request object");
@@ -360,7 +362,7 @@ public String logOutUserFromConcurrentSession(
}
/**
- *
+ *
* function to return session object against userName
*/
private String getConcurrentCheckSessionObjectAgainstUser(String userName) {
@@ -466,7 +468,7 @@ public String superUserAuthenticate(
resMap.put("isAuthenticated", /* Boolean.valueOf(true) */true);
resMap.put("userName", mUser.getUserName());
jwtToken = jwtUtil.generateToken(m_User.getUserName(), mUser.getUserID().toString());
-
+
User user = new User(); // Assuming the Users class exists
user.setUserID(mUser.getUserID());
user.setUserName(mUser.getUserName());
@@ -561,7 +563,7 @@ public String getLoginResponse(HttpServletRequest request) {
if (authHeader.isEmpty()) {
// Try JWT token from header first
String jwtToken = request.getHeader("Jwttoken");
-
+
// If not in header, try cookie
if (jwtToken == null) {
Cookie[] cookies = request.getCookies();
@@ -574,15 +576,15 @@ public String getLoginResponse(HttpServletRequest request) {
}
}
}
-
+
if (jwtToken == null) {
logger.warn("Authentication failed: no token found in header or cookies.");
throw new IEMRException("Authentication failed. Please log in again.");
}
-
+
// Extract user ID from the JWT token
String userId = jwtUtil.getUserIdFromToken(jwtToken);
-
+
// Get user details and prepare response
User user = iemrAdminUserServiceImpl.getUserById(Long.parseLong(userId));
if (user == null) {
@@ -759,7 +761,7 @@ public String saveUserSecurityQuesAns(
}
/**
- *
+ *
* @return security qtns
*/
@Operation(summary = "Get security quetions")
@@ -908,7 +910,7 @@ public String userLogout(HttpServletRequest request) {
}
/**
- *
+ *
* @param key
* @return
*/
@@ -952,7 +954,7 @@ public String forceLogout(@RequestBody ForceLogoutRequestModel request, HttpServ
if (token == null) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
outputResponse.setError(new RuntimeException("No JWT token found in request"));
- return outputResponse.toString();
+ return outputResponse.toString();
}
// Validate the token: Check if it is expired or in the deny list
@@ -989,7 +991,7 @@ private String getJwtTokenFromCookies(HttpServletRequest request) {
return null;
}
-
+
@Operation(summary = "User force log out")
@RequestMapping(value = "/userForceLogout", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON, headers = "Authorization")
public String userForceLogout(
@@ -1212,4 +1214,19 @@ private JSONObject prepareAuthenticationResponse(User mUser, String remoteAddres
return iemrAdminUserServiceImpl.generateKeyAndValidateIP(responseObj, remoteAddress, remoteHost);
}
+ @Operation(summary = "Get UserId based on userName")
+ @GetMapping(value = "/userName/{userName}", produces = MediaType.APPLICATION_JSON, headers = "Authorization")
+ public ResponseEntity> getUserDetails(@PathVariable("userName") String userName) {
+ try {
+ List users = iemrAdminUserServiceImpl.getUserIdbyUserName(userName);
+ if (users.isEmpty()) {
+ return new ResponseEntity<>(Map.of("error", "UserName Not Found"), HttpStatus.NOT_FOUND);
+ }
+ User user = users.get(0);
+ return new ResponseEntity<>(Map.of("userName", user.getUserName(), "userId", user.getUserID()), HttpStatus.OK);
+ } catch (Exception e) {
+ return new ResponseEntity<>(Map.of("error", "Internal server error"), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ }
}
diff --git a/src/main/java/com/iemr/common/data/beneficiaryConsent/BeneficiaryConsentRequest.java b/src/main/java/com/iemr/common/data/beneficiaryConsent/BeneficiaryConsentRequest.java
new file mode 100644
index 00000000..ac629a3c
--- /dev/null
+++ b/src/main/java/com/iemr/common/data/beneficiaryConsent/BeneficiaryConsentRequest.java
@@ -0,0 +1,12 @@
+package com.iemr.common.data.beneficiaryConsent;
+
+import lombok.Data;
+
+@Data
+public class BeneficiaryConsentRequest {
+ private String mobNo;
+ private int otp;
+ private String userName;
+ private String designation;
+
+}
diff --git a/src/main/java/com/iemr/common/data/dynamic_from/FormDefinition.java b/src/main/java/com/iemr/common/data/dynamic_from/FormDefinition.java
new file mode 100644
index 00000000..9e62b6d9
--- /dev/null
+++ b/src/main/java/com/iemr/common/data/dynamic_from/FormDefinition.java
@@ -0,0 +1,30 @@
+package com.iemr.common.data.dynamic_from;
+import jakarta.persistence.*;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+@Entity
+@Data
+@Table(name = "form_master")
+public class FormDefinition {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private Long id;
+
+ @Column(name = "form_id")
+ private String formId;
+
+ @Column(name = "form_name")
+ private String formName;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "module_id")
+ private FormModule module;
+
+ @Column(name = "created_at")
+ private LocalDateTime createdAt = LocalDateTime.now();
+ @Column(name = "version")
+ private Integer version;
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/iemr/common/data/dynamic_from/FormField.java b/src/main/java/com/iemr/common/data/dynamic_from/FormField.java
new file mode 100644
index 00000000..39785ae9
--- /dev/null
+++ b/src/main/java/com/iemr/common/data/dynamic_from/FormField.java
@@ -0,0 +1,59 @@
+package com.iemr.common.data.dynamic_from;
+import jakarta.persistence.*;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Entity
+@Data
+@Table(name = "form_fields")
+public class FormField {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private Long id;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "form_id", referencedColumnName = "form_id")
+ private FormDefinition form;
+
+ @Column(name = "section_title")
+ private String sectionTitle;
+
+ @Column(name = "field_id")
+ private String fieldId;
+
+ @Column(name = "label")
+ private String label;
+
+ @Column(name = "type")
+ private String type;
+
+ @Column(name = "is_required")
+ private Boolean isRequired;
+
+ @Column(name = "is_visible")
+ private Boolean isVisible;
+
+ @Column(name = "default_value")
+ private String defaultValue;
+
+ @Column(name = "placeholder")
+ private String placeholder;
+
+ @Column(name = "options", columnDefinition = "json")
+ private String options;
+
+ @Column(name = "validation", columnDefinition = "json")
+ private String validation; // includes error messages now
+
+ @Column(name = "conditional", columnDefinition = "json")
+ private String conditional;
+
+ @Column(name = "sequence")
+ private Integer sequence;
+
+ @Column(name = "created_at")
+ private LocalDateTime createdAt = LocalDateTime.now();
+
+}
diff --git a/src/main/java/com/iemr/common/data/dynamic_from/FormModule.java b/src/main/java/com/iemr/common/data/dynamic_from/FormModule.java
new file mode 100644
index 00000000..ba5d0170
--- /dev/null
+++ b/src/main/java/com/iemr/common/data/dynamic_from/FormModule.java
@@ -0,0 +1,23 @@
+package com.iemr.common.data.dynamic_from;
+
+import jakarta.persistence.*;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Entity
+@Data
+@Table(name = "form_module")
+public class FormModule {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private Long id;
+
+ @Column(name = "module_name")
+ private String moduleName;
+
+ @Column(name = "created_at")
+ private LocalDateTime createdAt = LocalDateTime.now();
+
+}
diff --git a/src/main/java/com/iemr/common/data/userToken/UserTokenData.java b/src/main/java/com/iemr/common/data/userToken/UserTokenData.java
new file mode 100644
index 00000000..0646972e
--- /dev/null
+++ b/src/main/java/com/iemr/common/data/userToken/UserTokenData.java
@@ -0,0 +1,46 @@
+/*
+* 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
+*/
+package com.iemr.common.data.userToken;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.Data;
+
+import java.sql.Timestamp;
+
+@Entity
+@Table(name = "user_tokens", schema = "db_iemr")
+@Data
+public class UserTokenData {
+ @Id
+ @Column(name = "user_id")
+ Integer userId;
+ @Column(name = "token")
+ String token;
+ @Column(name = "updated_at")
+ Timestamp updatedAt;
+}
diff --git a/src/main/java/com/iemr/common/dto/dynamicForm/FieldDTO.java b/src/main/java/com/iemr/common/dto/dynamicForm/FieldDTO.java
new file mode 100644
index 00000000..894f03c2
--- /dev/null
+++ b/src/main/java/com/iemr/common/dto/dynamicForm/FieldDTO.java
@@ -0,0 +1,25 @@
+package com.iemr.common.dto.dynamicForm;
+
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class FieldDTO {
+ private Long id;
+ private String formId;
+ private String sectionTitle;
+ private String fieldId;
+ private String label;
+ private String type;
+ private Boolean isVisible;
+ private Boolean isRequired;
+ private String defaultValue;
+ private String placeholder;
+ private Integer sequence;
+ private String options; // ⬅️ changed from String to List
+ private String validation; // ⬅️ changed from String to Map
+ private String conditional; // ⬅️ changed from String to Map
+}
+
diff --git a/src/main/java/com/iemr/common/dto/dynamicForm/FieldResponseDTO.java b/src/main/java/com/iemr/common/dto/dynamicForm/FieldResponseDTO.java
new file mode 100644
index 00000000..3415d91a
--- /dev/null
+++ b/src/main/java/com/iemr/common/dto/dynamicForm/FieldResponseDTO.java
@@ -0,0 +1,24 @@
+package com.iemr.common.dto.dynamicForm;
+
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class FieldResponseDTO {
+ private Long id;
+ private String formId;
+ private String sectionTitle;
+ private String fieldId;
+ private String label;
+ private Boolean visible;
+ private String type;
+ private Boolean isRequired;
+ private String defaultValue;
+ private String placeholder;
+ private Integer sequence;
+ private List options;
+ private Map validation;
+ private Map conditional;
+}
\ No newline at end of file
diff --git a/src/main/java/com/iemr/common/dto/dynamicForm/FormDTO.java b/src/main/java/com/iemr/common/dto/dynamicForm/FormDTO.java
new file mode 100644
index 00000000..24788cac
--- /dev/null
+++ b/src/main/java/com/iemr/common/dto/dynamicForm/FormDTO.java
@@ -0,0 +1,10 @@
+package com.iemr.common.dto.dynamicForm;
+
+import lombok.Data;
+
+@Data
+public class FormDTO {
+ private String formId;
+ private String formName;
+ private Long moduleId;
+}
\ No newline at end of file
diff --git a/src/main/java/com/iemr/common/dto/dynamicForm/FormResponseDTO.java b/src/main/java/com/iemr/common/dto/dynamicForm/FormResponseDTO.java
new file mode 100644
index 00000000..26563927
--- /dev/null
+++ b/src/main/java/com/iemr/common/dto/dynamicForm/FormResponseDTO.java
@@ -0,0 +1,13 @@
+package com.iemr.common.dto.dynamicForm;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class FormResponseDTO {
+ private Integer version;
+ private String formId;
+ private String formName;
+ private List sections;
+}
diff --git a/src/main/java/com/iemr/common/dto/dynamicForm/GroupedFieldResponseDTO.java b/src/main/java/com/iemr/common/dto/dynamicForm/GroupedFieldResponseDTO.java
new file mode 100644
index 00000000..840c5097
--- /dev/null
+++ b/src/main/java/com/iemr/common/dto/dynamicForm/GroupedFieldResponseDTO.java
@@ -0,0 +1,11 @@
+package com.iemr.common.dto.dynamicForm;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class GroupedFieldResponseDTO {
+ private String sectionTitle;
+ private List fields;
+}
diff --git a/src/main/java/com/iemr/common/dto/dynamicForm/ModuleDTO.java b/src/main/java/com/iemr/common/dto/dynamicForm/ModuleDTO.java
new file mode 100644
index 00000000..3f4240c4
--- /dev/null
+++ b/src/main/java/com/iemr/common/dto/dynamicForm/ModuleDTO.java
@@ -0,0 +1,8 @@
+package com.iemr.common.dto.dynamicForm;
+
+import lombok.Data;
+
+@Data
+public class ModuleDTO {
+ private String moduleName;
+}
\ No newline at end of file
diff --git a/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java b/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java
index 431a267a..8e364eb3 100644
--- a/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java
+++ b/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java
@@ -54,6 +54,8 @@ public class CommonIdentityDTO {
private Integer beneficiaryRegId;
private Integer communityId;
private String community;
+ private Boolean isConsent=false;
+
private Timestamp dob;
private Integer ageAtMarriage;
private Integer educationId;
diff --git a/src/main/java/com/iemr/common/mapper/CommonIdentityMapperDecorator.java b/src/main/java/com/iemr/common/mapper/CommonIdentityMapperDecorator.java
index 5e8034af..1480f306 100644
--- a/src/main/java/com/iemr/common/mapper/CommonIdentityMapperDecorator.java
+++ b/src/main/java/com/iemr/common/mapper/CommonIdentityMapperDecorator.java
@@ -168,8 +168,17 @@ public CommonIdentityDTO beneficiaryModelCommonIdentityDTO(BeneficiaryModel bene
Short maritalStatusID = beneficiary.getMaritalStatusID();
if (maritalStatusID != null) {
commonIdentityDTO.setMaritalStatusId(maritalStatusID.intValue());
- commonIdentityDTO.setMaritalStatus(
- maritalStatusMapper.maritalStatusByIDToResponse(maritalStatusID.intValue()).getStatus());
+ var model = maritalStatusMapper.maritalStatusByIDToResponse(maritalStatusID.intValue());
+ if (model != null) {
+ commonIdentityDTO.setMaritalStatus(model.getStatus());
+ } else {
+ // Option 1: Return null
+ commonIdentityDTO.setMaritalStatus(null);
+ // Option 2: Or set a default
+ // commonIdentityDTO.setMaritalStatus("Unknown");
+ // Option 3: Or log a warning
+ // logger.warn("Invalid maritalStatusID: {}", maritalStatusID);
+ }
}
commonIdentityDTO.setMaritalStatus(beneficiary.getMaritalStatusName());
commonIdentityDTO.setGender(beneficiary.getGenderName());
diff --git a/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java b/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java
index dfb76d00..ed7c9cad 100644
--- a/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java
+++ b/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java
@@ -78,6 +78,10 @@ public class BeneficiaryModel implements Comparable {
// private List outboundCallRequests;
// private List beneficiaryCalls;
// private List feedbacks;
+ @Expose
+ private Boolean isConsent=false;
+
+
@Expose
private String beneficiaryID;
@Expose
diff --git a/src/main/java/com/iemr/common/model/notification/NotificationMessage.java b/src/main/java/com/iemr/common/model/notification/NotificationMessage.java
new file mode 100644
index 00000000..58343034
--- /dev/null
+++ b/src/main/java/com/iemr/common/model/notification/NotificationMessage.java
@@ -0,0 +1,38 @@
+/*
+* 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
+*/
+package com.iemr.common.model.notification;
+
+import lombok.Data;
+
+import java.util.Map;
+
+@Data
+public class NotificationMessage {
+ private String appType;
+ private String token;
+ private String title;
+ private String body;
+ private Map data;
+}
diff --git a/src/main/java/com/iemr/common/model/notification/UserToken.java b/src/main/java/com/iemr/common/model/notification/UserToken.java
new file mode 100644
index 00000000..3ea36588
--- /dev/null
+++ b/src/main/java/com/iemr/common/model/notification/UserToken.java
@@ -0,0 +1,33 @@
+/*
+* 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
+*/
+package com.iemr.common.model.notification;
+
+import lombok.Data;
+
+@Data
+public class UserToken {
+ Integer userId;
+ String token;
+}
diff --git a/src/main/java/com/iemr/common/repo/userToken/UserTokenRepo.java b/src/main/java/com/iemr/common/repo/userToken/UserTokenRepo.java
new file mode 100644
index 00000000..817f26f0
--- /dev/null
+++ b/src/main/java/com/iemr/common/repo/userToken/UserTokenRepo.java
@@ -0,0 +1,31 @@
+/*
+* 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
+*/
+package com.iemr.common.repo.userToken;
+
+import com.iemr.common.data.userToken.UserTokenData;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface UserTokenRepo extends JpaRepository {
+}
diff --git a/src/main/java/com/iemr/common/repository/dynamic_form/FieldRepository.java b/src/main/java/com/iemr/common/repository/dynamic_form/FieldRepository.java
new file mode 100644
index 00000000..4aea5698
--- /dev/null
+++ b/src/main/java/com/iemr/common/repository/dynamic_form/FieldRepository.java
@@ -0,0 +1,12 @@
+package com.iemr.common.repository.dynamic_form;
+
+import com.iemr.common.data.dynamic_from.FormField;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface FieldRepository extends JpaRepository {
+ List findByForm_FormIdOrderBySequenceAsc(String formId);
+}
diff --git a/src/main/java/com/iemr/common/repository/dynamic_form/FormRepository.java b/src/main/java/com/iemr/common/repository/dynamic_form/FormRepository.java
new file mode 100644
index 00000000..50331dd2
--- /dev/null
+++ b/src/main/java/com/iemr/common/repository/dynamic_form/FormRepository.java
@@ -0,0 +1,14 @@
+package com.iemr.common.repository.dynamic_form;
+
+import com.iemr.common.data.dynamic_from.FormDefinition;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface FormRepository extends JpaRepository {
+ Optional findByFormId(String formId);
+ List findByModule_Id(Long moduleId);
+}
\ No newline at end of file
diff --git a/src/main/java/com/iemr/common/repository/dynamic_form/ModuleRepository.java b/src/main/java/com/iemr/common/repository/dynamic_form/ModuleRepository.java
new file mode 100644
index 00000000..bafbfbea
--- /dev/null
+++ b/src/main/java/com/iemr/common/repository/dynamic_form/ModuleRepository.java
@@ -0,0 +1,10 @@
+package com.iemr.common.repository.dynamic_form;
+
+import com.iemr.common.data.dynamic_from.FormModule;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ModuleRepository extends CrudRepository {
+
+}
diff --git a/src/main/java/com/iemr/common/repository/sms/SMSTemplateRepository.java b/src/main/java/com/iemr/common/repository/sms/SMSTemplateRepository.java
index e5d741f0..06745eb0 100644
--- a/src/main/java/com/iemr/common/repository/sms/SMSTemplateRepository.java
+++ b/src/main/java/com/iemr/common/repository/sms/SMSTemplateRepository.java
@@ -22,6 +22,7 @@
package com.iemr.common.repository.sms;
import java.util.List;
+import java.util.Optional;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
@@ -56,7 +57,9 @@ public List getSMSTemplateByProviderServiceMapIDAndSMSTypeID(
@Query("select smsTemplate.dltTemplateId from SMSTemplate smsTemplate where smsTemplate.smsTemplateID = :smsTemplateID and smsTemplate.deleted <> true")
public String findDLTTemplateID(@Param("smsTemplateID") Integer smsTemplateID );
-
+
+ Optional findBySmsTemplateName(String smsTemplateName);
+
SMSTemplate findBySmsTemplateID(Integer smsTemplateID);
}
diff --git a/src/main/java/com/iemr/common/service/beneficiary/IdentityBeneficiaryServiceImpl.java b/src/main/java/com/iemr/common/service/beneficiary/IdentityBeneficiaryServiceImpl.java
index 697322c6..2e6ac1d4 100644
--- a/src/main/java/com/iemr/common/service/beneficiary/IdentityBeneficiaryServiceImpl.java
+++ b/src/main/java/com/iemr/common/service/beneficiary/IdentityBeneficiaryServiceImpl.java
@@ -26,15 +26,12 @@
import java.util.HashSet;
import java.util.List;
+import com.google.gson.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
-import com.google.gson.Gson;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
import com.iemr.common.dto.identity.BeneficiariesDTO;
import com.iemr.common.dto.identity.BeneficiariesPartialDTO;
import com.iemr.common.dto.identity.IdentityEditDTO;
@@ -54,20 +51,20 @@ public class IdentityBeneficiaryServiceImpl implements IdentityBeneficiaryServic
Logger logger = LoggerFactory.getLogger(this.getClass().getName());
private static HttpUtils httpUtils = new HttpUtils();
private InputMapper inputMapper = new InputMapper();
- private String identityBaseURL = ConfigProperties.getPropertyByName("identity-api-url");
- private String identity1097BaseURL = ConfigProperties.getPropertyByName("identity-1097-api-url");
+ @Value("${identity-api-url}")
+ private String identityBaseURL;
+ @Value("${identity-1097-api-url}")
+ private String identity1097BaseURL;
+
private static final String IDENTITY_BASE_URL = "IDENTITY_BASE_URL";
- private static final String BEN_GEN = ConfigProperties.getPropertyByName("genben-api");
- private static final String BEN_GEN_API_URL = ConfigProperties.getPropertyByName("generateBeneficiaryIDs-api-url");
- // public IdentityBeneficiaryServiceImpl()
- // {
- //
- //// if (urlRequest == null)
- //// {
- //// urlRequest = ConfigProperties.getPropertyByName("identity-api-url");
- //// }
- // }
+ @Value("${genben-api}")
+ private String BEN_GEN ;
+
+
+ @Value("${generateBeneficiaryIDs-api-url}")
+ private String BEN_GEN_API_URL ;
+
@Override
// public List getBeneficiaryListByIDs() {// search by regID
@@ -399,23 +396,38 @@ public List getBeneficiaryListByGovId(String identity, String
@Override
public String getIdentityResponse(String request, String auth, Boolean is1097) throws IEMRException {
-
String result;
HashMap header = new HashMap<>();
if (auth != null) {
header.put("Authorization", auth);
}
- result = httpUtils.post(ConfigProperties.getPropertyByName("identity-api-url-benCreate")
- .replace(IDENTITY_BASE_URL, (is1097 ? identity1097BaseURL : identityBaseURL)), request, header);
+ String apiUrl = ConfigProperties.getPropertyByName("identity-api-url-benCreate")
+ .replace(IDENTITY_BASE_URL, (is1097 ? identity1097BaseURL : identityBaseURL));
+ logger.info("Calling URL: {}", apiUrl);
+ logger.info("Request Payload: {}", request);
- OutputResponse identityResponse = inputMapper.gson().fromJson(result, OutputResponse.class);
- if (identityResponse.getStatusCode() == OutputResponse.USERID_FAILURE) {
- throw new IEMRException(identityResponse.getErrorMessage());
+ result = httpUtils.post(apiUrl, request, header);
+
+ if (result == null || result.isEmpty()) {
+ logger.error("Empty response from Identity API");
+ throw new IEMRException("No response received from Identity API");
+ }
+
+ try {
+ OutputResponse identityResponse = inputMapper.gson().fromJson(result, OutputResponse.class);
+ if (identityResponse.getStatusCode() == OutputResponse.USERID_FAILURE) {
+ throw new IEMRException(identityResponse.getErrorMessage());
+ }
+ } catch (JsonSyntaxException e) {
+ logger.error("JSON parsing error: {}", e.getMessage());
+ throw new IEMRException("Invalid response format from Identity API");
}
+
return result;
}
+
public Integer editIdentityEditDTO(IdentityEditDTO identityEditDTO, String auth, Boolean is1097)
throws IEMRException {
JsonParser parser = new JsonParser();
@@ -517,8 +529,11 @@ public List generateBeneficiaryIDs(String request, String a
if (auth != null) {
header.put("Authorization", auth);
}
+
+ logger.info("Request to generate ben IDs: " + request);
+ logger.info("Generating ben IDs API URL: " + BEN_GEN + BEN_GEN_API_URL);
result = httpUtils.post(BEN_GEN + BEN_GEN_API_URL, request, header);
-
+logger.info("Response from generate ben IDs: " + result);
OutputResponse identityResponse = inputMapper.gson().fromJson(result, OutputResponse.class);
if (identityResponse.getStatusCode() == OutputResponse.USERID_FAILURE) {
diff --git a/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java b/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java
index 7f6f6266..aa0c2a71 100644
--- a/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java
+++ b/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java
@@ -30,6 +30,8 @@
import java.util.ArrayList;
import java.util.List;
+import com.iemr.common.service.welcomeSms.WelcomeBenificarySmsService;
+import com.iemr.common.service.welcomeSms.WelcomeBenificarySmsServiceImpl;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -73,9 +75,14 @@ public class RegisterBenificiaryServiceImpl implements RegisterBenificiaryServic
@Autowired
IdentityBenEditMapper identityBenEditMapper;
+ @Autowired
+ private WelcomeBenificarySmsService welcomeBenificarySmsService;
+
@Autowired
Validator validator;
+
+
@Autowired
OutboundHistoryRepository outboundHistoryRepository;
@@ -170,17 +177,28 @@ private int updateDemographics(BeneficiaryDemographicsModel i_BenDemographics) {
@Override
public String save(BeneficiaryModel beneficiaryModel, HttpServletRequest servletRequest) throws Exception {
- // logger.info("benificiaryDetails: " + beneficiaryModel);
+ logger.info("benificiaryDetails: " + beneficiaryModel);
CommonIdentityDTO identityDTO = identityMapper.beneficiaryModelCommonIdentityDTO(beneficiaryModel);
+
setSaveDemographicDetails(identityDTO,beneficiaryModel);
- // identityDTO.setOtherFields(beneficiaryModel.getOtherFields());
+// identityDTO.setOtherFields(beneficiaryModel.getOtherFields());
+ identityDTO.setIsConsent(beneficiaryModel.getIsConsent());
+// identityDTO.setIsDeath(beneficiaryModel.getIsDeath());
+// identityDTO.setIsDeathValue(beneficiaryModel.getIsDeathValue());
+// identityDTO.setDateOfDeath(beneficiaryModel.getDateOfDeath());
+// identityDTO.setPlaceOfDeath(beneficiaryModel.getPlaceOfDeath());
+// identityDTO.setOtherPlaceOfDeath(beneficiaryModel.getOtherPlaceOfDeath());
+// identityDTO.setTimeOfDeath(beneficiaryModel.getTimeOfDeath());
+
+
identityDTO.setFaceEmbedding(beneficiaryModel.getFaceEmbedding());
identityDTO.setEmergencyRegistration(beneficiaryModel.isEmergencyRegistration());
identityDTO
.setBenFamilyDTOs(identityMapper.benPhoneMapListToBenFamilyDTOList(beneficiaryModel.getBenPhoneMaps()));
String request = new Gson().toJson(identityDTO);
+
if (beneficiaryModel.getIs1097() == null)
beneficiaryModel.setIs1097(false);
@@ -200,10 +218,18 @@ public String save(BeneficiaryModel beneficiaryModel, HttpServletRequest servlet
} else {
return response.toString();
}
+ if(beneficiary!=null){
+ if(beneficiary.getBenPhoneMaps().get(0).getPhoneNo()!=null){
+ welcomeBenificarySmsService.sendWelcomeSMStoBenificiary(beneficiary.getBenPhoneMaps().get(0).getPhoneNo(),beneficiary.getFirstName()+" "+beneficiary.getLastName(),beneficiary.getBeneficiaryID());
+ }
+ }
+
}
return OutputMapper.gson().toJson(beneficiary);
}
+
+
private void setSaveDemographicDetails(CommonIdentityDTO identityDTO, BeneficiaryModel beneficiaryModel) {
if(null != beneficiaryModel.getI_bendemographics()) {
identityDTO.setCommunity(beneficiaryModel.getI_bendemographics().getCommunityName());
diff --git a/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandler.java b/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandler.java
new file mode 100644
index 00000000..234640a8
--- /dev/null
+++ b/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandler.java
@@ -0,0 +1,14 @@
+package com.iemr.common.service.beneficiaryOTPHandler;
+
+import com.iemr.common.data.beneficiaryConsent.BeneficiaryConsentRequest;
+import com.iemr.common.data.otp.OTPRequestParsor;
+import org.json.JSONObject;
+
+public interface BeneficiaryOTPHandler {
+ public String sendOTP(BeneficiaryConsentRequest obj) throws Exception;
+
+ public JSONObject validateOTP(BeneficiaryConsentRequest obj) throws Exception;
+
+ public String resendOTP(BeneficiaryConsentRequest obj) throws Exception;
+
+}
diff --git a/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandlerImpl.java b/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandlerImpl.java
new file mode 100644
index 00000000..42e0acfe
--- /dev/null
+++ b/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandlerImpl.java
@@ -0,0 +1,236 @@
+/*
+ * 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.service.beneficiaryOTPHandler;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.primitives.Ints;
+import com.iemr.common.data.beneficiaryConsent.BeneficiaryConsentRequest;
+import com.iemr.common.data.otp.OTPRequestParsor;
+import com.iemr.common.data.sms.SMSTemplate;
+import com.iemr.common.data.sms.SMSType;
+import com.iemr.common.repository.sms.SMSTemplateRepository;
+import com.iemr.common.repository.sms.SMSTypeRepository;
+import com.iemr.common.service.otp.OTPHandler;
+import com.iemr.common.service.users.IEMRAdminUserServiceImpl;
+import com.iemr.common.utils.config.ConfigProperties;
+import com.iemr.common.utils.http.HttpUtils;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import java.security.MessageDigest;
+import java.security.SecureRandom;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+@Service
+public class BeneficiaryOTPHandlerImpl implements BeneficiaryOTPHandler {
+
+ @Autowired
+ HttpUtils httpUtils;
+ @Autowired
+ private IEMRAdminUserServiceImpl iEMRAdminUserServiceImpl;
+
+ final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
+ @Autowired
+ SMSTemplateRepository smsTemplateRepository;
+ private LoadingCache otpCache;
+
+ @Autowired
+ SMSTypeRepository smsTypeRepository;
+ @Value("${sms-template-name}")
+ private String smsTemplateName ;
+
+ private String smsTemplate;
+ @Value("${sms-username}")
+ private String smsUserName;
+
+ @Value("${sms-password}")
+ private String smsPassword ;
+
+ @Value("${sms-message-type}")
+ private String smsMessageType;
+
+ @Value("${sms-entityid}")
+ private String smsEntityId;
+
+ @Value("${sms-consent-source-address}")
+
+ private String smsConsentSourceAddress ;
+ @Value("${send-message-url}")
+ private String SMS_GATEWAY_URL;
+
+ private static final Integer EXPIRE_MIN = 5;
+
+ // Constructor for new object creation
+ public BeneficiaryOTPHandlerImpl() {
+ otpCache = CacheBuilder.newBuilder().expireAfterWrite(EXPIRE_MIN, TimeUnit.MINUTES)
+ .build(new CacheLoader() {
+ public String load(String key) {
+ return "0";
+ }
+ });
+ }
+
+ /***
+ * @param obj
+ * @return success if OTP sent successfully
+ */
+ @Override
+ public String sendOTP(BeneficiaryConsentRequest obj) throws Exception {
+ int otp = generateOTP(obj.getMobNo());
+ return sendSMS(otp, obj);
+ }
+
+ /***
+ * @param obj
+ * @return OTP verification success or failure
+ *
+ */
+ @Override
+ public JSONObject validateOTP(BeneficiaryConsentRequest obj) throws Exception {
+ String cachedOTP = otpCache.get(obj.getMobNo());
+ String inputOTPEncrypted = getEncryptedOTP(obj.getOtp());
+
+ if (cachedOTP.equalsIgnoreCase(inputOTPEncrypted)) {
+ JSONObject responseObj = new JSONObject();
+ responseObj.put("userName", obj.getMobNo());
+ responseObj.put("userID", obj.getMobNo());
+
+ JSONObject responseOBJ = iEMRAdminUserServiceImpl.generateKeyPostOTPValidation(responseObj);
+
+ return responseOBJ;
+ } else {
+ throw new Exception("Please enter valid OTP");
+ }
+
+ }
+
+ /***
+ * @param obj
+ * @return success if OTP re-sent successfully
+ */
+ @Override
+ public String resendOTP(BeneficiaryConsentRequest obj) throws Exception {
+ int otp = generateOTP(obj.getMobNo());
+ return sendSMS(otp, obj);
+ }
+
+ // generate 6 digit random no #
+ public int generateOTP(String authKey) throws Exception {
+ String generatedPassword = null;
+ Random random = SecureRandom.getInstanceStrong();
+ int otp = 100000 + random.nextInt(900000);
+
+ generatedPassword = getEncryptedOTP(otp);
+
+ if (otpCache != null)
+ otpCache.put(authKey, generatedPassword);
+ else {
+ BeneficiaryOTPHandlerImpl obj = new BeneficiaryOTPHandlerImpl();
+ obj.otpCache.put(authKey, generatedPassword);
+ }
+ return otp;
+ }
+
+ // SHA-256 encoding logic implemented
+ private String getEncryptedOTP(int otp) throws Exception {
+ MessageDigest md = MessageDigest.getInstance("SHA-256");
+ byte[] bytes = md.digest(Ints.toByteArray(otp));
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < bytes.length; i++) {
+ sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
+ }
+
+ return sb.toString();
+ }
+
+ // send SMS to beneficiary
+
+
+ public String sendSMS(int otp, BeneficiaryConsentRequest obj) {
+ logger.info("templateName"+smsTemplateName);
+
+ final RestTemplate restTemplate = new RestTemplate();
+
+ Optional smsTemplateData = smsTemplateRepository.findBySmsTemplateName(smsTemplateName);
+ List smsTemplateAllData = (List) smsTemplateRepository.findAll();
+ logger.info("AllData"+smsTemplateAllData.stream().toArray());
+
+ if(smsTemplateData.isPresent()){
+ smsTemplate = smsTemplateRepository.findBySmsTemplateID(smsTemplateData.get().getSmsTemplateID()).getSmsTemplate();
+
+ }
+
+ String sendSMSAPI = SMS_GATEWAY_URL;
+ logger.info("sms template"+smsTemplate);
+
+ try {
+ String message = smsTemplate
+ .replace("$$OTP$$",String.valueOf(otp));
+
+ // Build payload
+ Map payload = new HashMap<>();
+ payload.put("customerId",smsUserName);
+ payload.put("destinationAddress", obj.getMobNo());
+ payload.put("message", message);
+ payload.put("sourceAddress", smsConsentSourceAddress);
+ payload.put("messageType", smsMessageType);
+ payload.put("dltTemplateId", smsTemplateData.get().getDltTemplateId());
+ payload.put("entityId",smsEntityId );
+ payload.put("otp", true);
+ // Set headers
+ HttpHeaders headers = new HttpHeaders();
+ String auth = smsUserName + ":" + smsPassword;
+ headers.add("Authorization",
+ "Basic " + Base64.getEncoder().encodeToString(auth.getBytes()));
+
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ logger.info("payload: "+payload);
+ HttpEntity