Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
50c5952
Elasticsearch implementation for Beneficiary Search (#324)
vanitha1822 Dec 18, 2025
1bc9298
variable added
sac2kadam Dec 31, 2025
4b975ff
Merge pull request #330 from PSMRI/add_ci_docker_properties
drtechie Dec 31, 2025
65efdc7
Elastic Search Implementation for Advanced Search (#327)
vanitha1822 Jan 8, 2026
17620d3
fix:signature check for mmu
vishwab1 Jan 9, 2026
68b246e
Merge pull request #335 from PSMRI/release-3.6.1-sign
snehar-nd Jan 9, 2026
c3bc3cb
fix: retrive any user without deleted
vishwab1 Jan 13, 2026
8dcdfc3
Merge pull request #336 from PSMRI/release-3.6.1-sign
snehar-nd Jan 13, 2026
134fa75
fix: update KM filepath
vanitha1822 Jan 29, 2026
c6e42d9
FLW-713 Remove All File Upload Options (#350)
SauravBizbRolly Jan 30, 2026
f487978
Move code to 3.6.1 to 3.8.0 (#372)
vishwab1 Mar 12, 2026
1cc3888
fix: add OTP rate limiting to prevent OTP flooding on sendConsent end…
vishwab1 Mar 12, 2026
01110c1
Health api (#376)
vishwab1 Mar 18, 2026
1f8111c
feature for hindi translation for CG
SauravBizbRolly Apr 10, 2026
d97a721
Merge pull request #393 from PSMRI/feature/hindhi_translation_changes
SauravBizbRolly Apr 10, 2026
62b53af
Merge remote-tracking branch 'upstream/release-3.6.3' into merge_3.8.…
SauravBizbRolly Apr 16, 2026
29aec50
Merge remote-tracking branch 'upstream/release-3.8.1' into merge_3.8.…
SauravBizbRolly Apr 16, 2026
e39df83
add otp_consent template key
SauravBizbRolly May 2, 2026
304230a
fix welcome sms code
SauravBizbRolly May 2, 2026
81241a9
fix welcome sms code
SauravBizbRolly May 3, 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
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ public String createBeneficiary(
OutputResponse response = new OutputResponse();

logger.info("Create beneficiary request " + beneficiaryModel);
logger.info("Common-api Call: Create bene");
try {

response.setResponse(registerBenificiaryService.save(beneficiaryModel, httpRequest));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ public class FormField {
@Column(name = "created_at")
private LocalDateTime createdAt = LocalDateTime.now();

@Column(name = "option_key")
private String optionKey;



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.iemr.common.data.dynamic_from;

import jakarta.persistence.*;
import lombok.Data;

@Entity
@Table(name = "form_field_options")
@Data
public class FormFieldOption {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@Column(name = "option_key")
private String optionKey;

@Column(name = "value")
private String value;

@Column(name = "label_en")
private String labelEn;

@Column(name = "label_hi")
private String labelHi;

@Column(name = "label_as")
private String labelAs;

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

// getters/setters
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
private Integer sequence;
private Boolean isEditable;
private Integer stateCode;
private List<String> options;
public List<Map<String, Object>> options;

Check warning on line 23 in src/main/java/com/iemr/common/dto/dynamicForm/FieldResponseDTO.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make options a static final constant or non-public and provide accessors if needed.

See more on https://sonarcloud.io/project/issues?id=PSMRI_Common-API&issues=AZ38ApwWtsfJDtCC-uLv&open=AZ38ApwWtsfJDtCC-uLv&pullRequest=405
private Map<String, Object> validation;
private Map<String, Object> conditional;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.iemr.common.repository.dynamic_form;
import com.iemr.common.data.dynamic_from.FormFieldOption;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface FormFieldOptionRepository
extends JpaRepository<FormFieldOption, Integer> {

List<FormFieldOption> findByOptionKeyOrderBySortOrderAsc(String optionKey);

}
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@
}

@Override
public String save(BeneficiaryModel beneficiaryModel, HttpServletRequest servletRequest) throws Exception {

Check failure on line 191 in src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 24 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=PSMRI_Common-API&issues=AZ38ApuGtsfJDtCC-uLu&open=AZ38ApuGtsfJDtCC-uLu&pullRequest=405

logger.info("benificiaryDetails: " + beneficiaryModel);

Expand Down Expand Up @@ -224,9 +224,28 @@
} 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());
if (beneficiary != null && beneficiary.getBenPhoneMaps() != null && !beneficiary.getBenPhoneMaps().isEmpty()) {
String phoneNo = beneficiary.getBenPhoneMaps().get(0).getPhoneNo();

if (phoneNo != null && !phoneNo.trim().isEmpty()) {
String beneficiaryName = (beneficiary.getFirstName() != null ? beneficiary.getFirstName() : "") + " " +
(beneficiaryModel.getLastName() != null ? beneficiaryModel.getLastName() : "");

try {
logger.info("[SMS] Attempting to send welcome SMS to: " + phoneNo);
String smsResult = welcomeBenificarySmsService.sendWelcomeSMStoBenificiary(
phoneNo,
beneficiaryName.trim(),
beneficiary.getBeneficiaryID()

);
logger.info("[SMS]: "+ smsResult);

} catch (Exception smsError) {
// SMS failed but beneficiary is already created - don't fail the request
logger.warn("[SMS] Failed to send SMS: " + smsError.getMessage() +
" - But beneficiary already created successfully");
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ public class BeneficiaryOTPHandlerImpl implements BeneficiaryOTPHandler {

@Autowired
SMSTypeRepository smsTypeRepository;
@Value("${sms-template-name}")
private String smsTemplateName ;
private String smsTemplateName = "otp_consent" ;

private String smsTemplate;
@Value("${sms-username}")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package com.iemr.common.service.dynamicForm;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iemr.common.data.dynamic_from.FormDefinition;
import com.iemr.common.data.dynamic_from.FormField;
import com.iemr.common.data.dynamic_from.FormFieldOption;
import com.iemr.common.data.dynamic_from.FormModule;
import com.iemr.common.data.translation.Translation;
import com.iemr.common.data.users.UserServiceRole;
import com.iemr.common.dto.dynamicForm.*;
import com.iemr.common.repository.dynamic_form.FieldRepository;
import com.iemr.common.repository.dynamic_form.FormFieldOptionRepository;
import com.iemr.common.repository.dynamic_form.FormRepository;
import com.iemr.common.repository.dynamic_form.ModuleRepository;
import com.iemr.common.repository.translation.TranslationRepo;
Expand Down Expand Up @@ -43,6 +46,9 @@
@Autowired
private JwtUtil jwtUtil;

@Autowired
private FormFieldOptionRepository formFieldOptionRepo ;

@Override
public FormModule createModule(ModuleDTO dto) {
FormModule module = new FormModule();
Expand Down Expand Up @@ -135,24 +141,40 @@
Integer finalStateId = stateId;
List<FieldResponseDTO> fieldDtos = fields.stream().filter(formField -> (formField.getStateCode().equals(0) || formField.getStateCode().equals(finalStateId)))
.map(field -> {
String labelKey = field.getFieldId(); // field label already contains label_key
String labelKey = field.getFieldId();

Translation label = translationRepo.findByLabelKeyAndIsActive(labelKey, true)
.orElse(null);

Translation t = translationRepo.findByLabelKeyAndIsActive(labelKey, true)
Translation placeHolder = translationRepo.findByLabelKeyAndIsActive("placeholder_"+labelKey, true)
.orElse(null);

String translatedLabel = field.getLabel(); // fallback
String translatedLabel = field.getLabel();
String translatedPlaceHolder = field.getPlaceholder();

if (t != null) {
if (label != null) {
if ("hi".equalsIgnoreCase(lang)) {
translatedLabel = t.getHindiTranslation();
translatedLabel = label.getHindiTranslation();
} else if ("as".equalsIgnoreCase(lang)) {
translatedLabel = t.getAssameseTranslation();
translatedLabel = label.getAssameseTranslation();
} else if ("en".equalsIgnoreCase(lang)) {
translatedLabel = t.getEnglish();
translatedLabel = label.getEnglish();

}
}

if (placeHolder != null) {
if ("hi".equalsIgnoreCase(lang)) {
translatedPlaceHolder= placeHolder.getHindiTranslation();
} else if ("as".equalsIgnoreCase(lang)) {
translatedPlaceHolder = placeHolder.getAssameseTranslation();
} else if ("en".equalsIgnoreCase(lang)) {
translatedPlaceHolder = placeHolder.getEnglish();

}
}


FieldResponseDTO dto = new FieldResponseDTO();
dto.setId(field.getId());
dto.setIsEditable(field.getIsEditable());
Expand All @@ -165,27 +187,32 @@
dto.setType(field.getType());
dto.setIsRequired(field.getIsRequired());
dto.setDefaultValue(field.getDefaultValue());
dto.setPlaceholder(field.getPlaceholder());
dto.setPlaceholder(translatedPlaceHolder);
dto.setSequence(field.getSequence());


try {
// Handle options
if (field.getOptions() != null && !field.getOptions().isBlank()) {
JsonNode node = objectMapper.readTree(field.getOptions());
List<String> options = null;
if (node.isArray()) {
options = objectMapper.convertValue(node, new TypeReference<>() {
});
} else if (node.has("options")) {
options = objectMapper.convertValue(node.get("options"), new TypeReference<>() {
});
}
dto.setOptions(options == null || options.isEmpty() ? null : options);
if (field.getOptionKey() != null && !field.getOptionKey().isBlank()) {
List<FormFieldOption> dbOptions = formFieldOptionRepo
.findByOptionKeyOrderBySortOrderAsc(field.getOptionKey());

List<Map<String, Object>> translatedOptions = dbOptions.stream()
.map(opt -> {
Map<String, Object> map = new LinkedHashMap<>();
map.put("id", opt.getId());
map.put("value", opt.getValue());
if ("hi".equalsIgnoreCase(lang)) map.put("label", opt.getLabelHi());

Check failure on line 204 in src/main/java/com/iemr/common/service/dynamicForm/FormMasterServiceImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "label" 3 times.

See more on https://sonarcloud.io/project/issues?id=PSMRI_Common-API&issues=AZ38AprptsfJDtCC-uLs&open=AZ38AprptsfJDtCC-uLs&pullRequest=405
else if ("as".equalsIgnoreCase(lang)) map.put("label", opt.getLabelAs());
else map.put("label", opt.getLabelEn());
return map;
})
.collect(Collectors.toList());

Check warning on line 209 in src/main/java/com/iemr/common/service/dynamicForm/FormMasterServiceImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this usage of 'Stream.collect(Collectors.toList())' with 'Stream.toList()' and ensure that the list is unmodified.

See more on https://sonarcloud.io/project/issues?id=PSMRI_Common-API&issues=AZ38AprptsfJDtCC-uLt&open=AZ38AprptsfJDtCC-uLt&pullRequest=405

dto.setOptions(translatedOptions.isEmpty() ? null : translatedOptions);

} else {
dto.setOptions(null);
}

// Handle validation
if (field.getValidation() != null && !field.getValidation().isBlank()) {
Map<String, Object> validation = objectMapper.readValue(field.getValidation(), new TypeReference<>() {
});
Expand All @@ -194,7 +221,6 @@
dto.setValidation(null);
}

// Handle conditional
if (field.getConditional() != null && !field.getConditional().isBlank()) {
Map<String, Object> conditional = objectMapper.readValue(field.getConditional(), new TypeReference<>() {
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

Expand Down Expand Up @@ -46,58 +47,57 @@ public class WelcomeBenificarySmsServiceImpl implements WelcomeBenificarySmsServ

private String smsTemplateName = "welcome_sms";

private String smsTemplate;
private String smsTemplate =null;

@Override
@Async
public String sendWelcomeSMStoBenificiary(String contactNo, String beneficiaryName, String beneficiaryId) {
final RestTemplate restTemplate = new RestTemplate();

Optional<SMSTemplate> smsTemplateData = smsTemplateRepository.findBySmsTemplateName(smsTemplateName);
if (smsTemplateData.isPresent()) {
smsTemplate = smsTemplateRepository.findBySmsTemplateID(smsTemplateData.get().getSmsTemplateID()).getSmsTemplate();

}

logger.info("sms template" + smsTemplate);


String sendSMSAPI = SMS_GATEWAY_URL;

try {
String sendSMSAPI = SMS_GATEWAY_URL;

String message = smsTemplate.replace("$$BENE_NAME$$", beneficiaryName).replace("$$BEN_ID$$", beneficiaryId);
// Build payload
Map<String, Object> payload = new HashMap<>();
payload.put("customerId", smsUserName);
payload.put("destinationAddress", contactNo);
payload.put("message", message);
payload.put("sourceAddress", smsSourceAddress);
payload.put("messageType", "SERVICE_IMPLICIT");
payload.put("dltTemplateId", smsTemplateData.get().getDltTemplateId());
payload.put("entityId", smsEntityId);
// 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<Map<String, Object>> request = new HttpEntity<>(payload, headers);

// Call API
ResponseEntity<String> response = restTemplate.postForEntity(sendSMSAPI, request, String.class);
logger.info("sms-response:" + response.getBody());
if (response.getStatusCode().value() == 200) {
return "OTP sent successfully on register mobile number";
} else {
return "Fail";
final RestTemplate restTemplate = new RestTemplate();

Optional<SMSTemplate> smsTemplateData = smsTemplateRepository.findBySmsTemplateName(smsTemplateName);
if (smsTemplateData.isPresent()) {
smsTemplate = smsTemplateRepository.findBySmsTemplateID(smsTemplateData.get().getSmsTemplateID()).getSmsTemplate();
}
if(smsTemplate!=null){
String message = smsTemplate.replace("$$BENE_NAME$$", beneficiaryName).replace("$$BEN_ID$$", beneficiaryId);
// Build payload
Map<String, Object> payload = new HashMap<>();
payload.put("customerId", smsUserName);
payload.put("destinationAddress", contactNo);
payload.put("message", message);
payload.put("sourceAddress", smsSourceAddress);
payload.put("messageType", "SERVICE_IMPLICIT");
payload.put("dltTemplateId", smsTemplateData.get().getDltTemplateId());
payload.put("entityId", smsEntityId);
// 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<Map<String, Object>> request = new HttpEntity<>(payload, headers);

// Call API
ResponseEntity<String> response = restTemplate.postForEntity(sendSMSAPI, request, String.class);
logger.info("sms-response:" + response.getBody());
if (response.getStatusCode().value() == 200) {
return "OTP sent successfully on register mobile number";
} else {
return "Fail";

}
}


} catch (Exception e) {
return "Error sending SMS: " + e.getMessage().toString();
}
return null;

}
}
Loading