Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HLM-4894 Changes for managing staff in attendance module #627

Merged
merged 43 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
e890e85
HLM-4894 adding hrms related flag to Individual object, adding anothe…
Priyanka-eGov Feb 5, 2024
20149b2
HLM-4894 adding hrms related flag to Individual object, adding anothe…
Priyanka-eGov Feb 6, 2024
217c2ef
HLM-4894 adding changes related to linking of HRMS Employee with Indi…
Priyanka-eGov Feb 6, 2024
5398a0d
HLM-4894 adding changes related to linking of HRMS Employee with Indi…
Priyanka-eGov Feb 6, 2024
70beffa
HLM-4894 reverting changes related to linking of HRMS Employee with I…
Priyanka-eGov Feb 7, 2024
484acf8
HLM-4894 reverting changes related to linking of HRMS Employee with I…
Priyanka-eGov Feb 7, 2024
1e5a3bc
HLM-4894 adding changes for managing attendees while enrollment
Priyanka-eGov Feb 7, 2024
0323475
HLM-4894 updating build config
Priyanka-eGov Feb 8, 2024
17d2591
HLM-4894 adding changes for project staff validation
Priyanka-eGov Feb 8, 2024
e09485e
Merge branch 'hlm-4496-attendance-module' of https://github.com/egove…
Priyanka-eGov Feb 9, 2024
3d5eddd
HLM-4894 adding @Qualifier annotation for object mapper
Priyanka-eGov Feb 9, 2024
659085c
HLM-4894 fixing hrms url
Priyanka-eGov Feb 9, 2024
66e66f4
Merge branch 'hlm-4496-attendance-module' of https://github.com/egove…
Priyanka-eGov Feb 13, 2024
3dcdc20
HLM-4894 updating environment variables.
Priyanka-eGov Feb 13, 2024
5e23b8f
HLM-4894 updating code changes
Priyanka-eGov Feb 13, 2024
4457086
HLM-4894 adding code changes
Priyanka-eGov Feb 13, 2024
51cb04c
HLM-4894 adding code changes
Priyanka-eGov Feb 13, 2024
eb14bf1
HLM-4894 adding code changes
Priyanka-eGov Feb 13, 2024
48606bc
HLM-4894 adding useruuid as search param in individual search
Priyanka-eGov Feb 13, 2024
9d6afb5
HLM-4894 adding useruuid as search param in individual search
Priyanka-eGov Feb 13, 2024
af0b1be
HLM-4894 adding useruuid as search param in individual search
Priyanka-eGov Feb 13, 2024
ad05191
HLM-4894 adding changes for registry creation when supervisor enrolls
Priyanka-eGov Feb 13, 2024
c38976d
Merge branch 'hlm-4496-attendance-module' of https://github.com/egove…
Priyanka-eGov Feb 13, 2024
45bad0a
HLM-4894 adding changes attendee enrollment
Priyanka-eGov Feb 14, 2024
f972556
Merge branch 'hlm-4496-attendance-module' of https://github.com/egove…
Priyanka-eGov Feb 14, 2024
db5417a
HLM-4894 adding changes for making staffId as list of staffId in Proj…
Priyanka-eGov Feb 14, 2024
5e570a2
HLM-4894 adding changes for making staffId as list of staffId in Proj…
Priyanka-eGov Feb 14, 2024
e1b3b87
HLM-4894 adding changes for making staffId as list of staffId in Proj…
Priyanka-eGov Feb 14, 2024
e2e307e
HLM-4894 removing staff-bulk-create-topic
Priyanka-eGov Feb 14, 2024
cbed04f
HLM-4894 removing staff-bulk-create-topic
Priyanka-eGov Feb 14, 2024
39afd9b
HLM-4894 removing staff-bulk-create-topic
Priyanka-eGov Feb 14, 2024
070ed3a
HLM-4894 removing staff-bulk-create-topic
Priyanka-eGov Feb 14, 2024
fb8b1da
HLM-4894 changing health-attendance consumer group-id
Priyanka-eGov Feb 15, 2024
7fed5e8
HLM-4894 adding changes for projectstaff consumer
Priyanka-eGov Feb 15, 2024
c9060fb
HLM-4894 adding changes for projectstaff consumer
Priyanka-eGov Feb 15, 2024
6a80066
HLM-4894 adding changes for projectstaff consumer
Priyanka-eGov Feb 15, 2024
8772b71
HLM-4894 adding changes for projectstaff consumer
Priyanka-eGov Feb 15, 2024
7f1e892
HLM-4894 adding changes for projectstaff consumer
Priyanka-eGov Feb 15, 2024
0ee5698
HLM-4894 adding comments
Priyanka-eGov Feb 16, 2024
aaf9df9
HLM-4894 adding additional Details during attendance register creation
Priyanka-eGov Feb 19, 2024
fda2b2b
HLM-4894 adding additional Details during attendance register creation
Priyanka-eGov Feb 19, 2024
e8d303e
Merge branch 'hlm-4496-attendance-module' of https://github.com/egove…
Priyanka-eGov Feb 20, 2024
494ba0f
HLM-4894 increasing limit to 1000
Priyanka-eGov Feb 21, 2024
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
7 changes: 7 additions & 0 deletions build/build-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,10 @@ config:
dockerfile: "build/maven/Dockerfile"
- work-dir: "core-services/attendance/src/main/resources/db"
image-name: "attendance-db"
- name: "builds/health-campaign-services/core-services/health-hrms"
build:
- work-dir: "core-services/egov-hrms"
image-name: "health-hrms"
dockerfile: "build/maven/Dockerfile"
- work-dir: "core-services/egov-hrms/src/main/resources/db"
image-name: "health-hrms-db"
2 changes: 1 addition & 1 deletion health-services/attendance/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
<dependency>
<groupId>org.egov.common</groupId>
<artifactId>health-services-models</artifactId>
<version>1.0.6-SNAPSHOT</version>
<version>1.0.19-SNAPSHOT-dev</version>
<scope>compile</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@Data
@Import({TracerConfiguration.class})
Expand Down Expand Up @@ -105,6 +107,32 @@ public void initialize() {
@Value("${attendance.register.first.staff.insert.enabled:true}")
private Boolean registerFirstStaffInsertEnabled;

//HRMS Service
@Value("${egov.hrms.host}")
private String hrmsHost;

@Value("${egov.hrms.search.endpoint}")
private String hrmsEndPoint;

//Project Service
@Value("${egov.project.host}")
private String projectHost;

@Value("${egov.project.staff.search.endpoint}")
private String projectStaffSearchEndpoint;

@Value("${egov.project.search.endpoint}")
private String projectSearchEndpoint;

@Value("${project.supervisor.roles}")
private List<String> projectSupervisorRoles;

@Value("${project.attendee.roles}")
private List<String> projectAttendeeRoles;

@Value("${project.staff.attendance.topic}")
private String projectStaffAttendanceTopic;

}


Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package org.egov.kafka;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.egov.common.contract.request.RequestInfo;
import org.egov.common.models.core.Role;
import org.egov.common.models.individual.Individual;
import org.egov.common.models.individual.IndividualSearch;
import org.egov.common.models.project.ProjectStaff;
import org.egov.common.models.project.ProjectStaffBulkRequest;
import org.egov.common.models.project.ProjectStaffRequest;
import org.egov.config.AttendanceServiceConfiguration;
import org.egov.tracer.model.CustomException;
import org.egov.util.IndividualServiceUtil;
import org.egov.util.ProjectStaffUtil;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.KafkaHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Component
@Slf4j
public class ProjectStaffConsumer {

@Autowired
private ObjectMapper objectMapper;

@Autowired
private ProjectStaffUtil projectStaffUtil;

@Autowired
private IndividualServiceUtil individualServiceUtil;

@Autowired
private AttendanceServiceConfiguration config;

@KafkaListener(topics = "${project.staff.attendance.topic}")
public void bulkStaffCreate(Map<String, Object> consumerRecord,
@Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
try {
// Convert the received Kafka message into a ProjectStaffBulkRequest object
ProjectStaffBulkRequest request = objectMapper.convertValue(consumerRecord, ProjectStaffBulkRequest.class);

// Iterate over the ProjectStaff objects in the request
for (ProjectStaff projectStaff : request.getProjectStaff()) {
try {
RequestInfo requestInfo = request.getRequestInfo();

String staffUserUuid = projectStaff.getUserId();
String tenantId = projectStaff.getTenantId();

// Search for the individual details using the user UUID
IndividualSearch individualSearch = IndividualSearch.builder().userUuid(staffUserUuid).build();
List<Individual> individualList = individualServiceUtil.getIndividualDetailsFromSearchCriteria(individualSearch, requestInfo, tenantId);

if (individualList.isEmpty())
throw new CustomException("INVALID_STAFF_ID", "No Individual found for the given staff Uuid - " + staffUserUuid);
Individual individual = individualList.get(0);

List<Role> roleList = individual.getUserDetails().getRoles();
List<String> roleCodeList = roleList.stream()
.map(Role::getCode)
.collect(Collectors.toList());

// Check if the individual has any supervisor roles
boolean matchFoundForSupervisorRoles = roleCodeList.stream()
.anyMatch(config.getProjectSupervisorRoles()::contains);

// Check if the individual has any attendee roles
boolean matchFoundForAttendeeRoles = roleCodeList.stream()
.anyMatch(config.getProjectAttendeeRoles()::contains);

// If the individual has supervisor roles, create a registry for supervisor
if (matchFoundForSupervisorRoles)
projectStaffUtil.createRegistryForSupervisor(projectStaff, requestInfo, individual);

// If the individual has attendee roles, enroll the attendee to register
if (matchFoundForAttendeeRoles)
projectStaffUtil.enrollAttendeetoRegister(projectStaff, requestInfo, individual);
}
catch (Exception e)
{
log.error(e.toString());
}
}

} catch (Exception exception) {
log.error("error in project staff consumer bulk create", exception);
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,17 @@ public List<StaffPermission> getAllStaff(StaffSearchCriteria searchCriteria) {
List<StaffPermission> attendanceStaffList = jdbcTemplate.query(query, rowMapper, preparedStmtList.toArray());
return attendanceStaffList;
}

/**
* Retrieves a list of staff permissions based on the provided search criteria.
*
* @param searchCriteria The criteria to use for searching staff permissions
* @return A list of staff permissions
*/
public List<StaffPermission> getFirstStaff(StaffSearchCriteria searchCriteria) {
List<Object> preparedStmtList = new ArrayList<>();
String query = queryBuilder.appendOrderLimit(queryBuilder.getAttendanceStaffSearchQuery(searchCriteria, preparedStmtList));
List<StaffPermission> attendanceStaffList = jdbcTemplate.query(query, rowMapper, preparedStmtList.toArray());
return attendanceStaffList;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,8 @@ private void addLimitAndOffset(StringBuilder query, StaffSearchCriteria criteria
preparedStmtList.add(criteria.getLimit());

}

public static String appendOrderLimit(String query) {
return query + " ORDER BY stf.enrollment_date ASC LIMIT 1";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.egov.enrichment.AttendeeEnrichmentService;
import org.egov.common.producer.Producer;
import org.egov.repository.AttendeeRepository;
import org.egov.tracer.model.CustomException;
import org.egov.util.ResponseInfoFactory;
import org.egov.validator.AttendanceServiceValidator;
import org.egov.validator.AttendeeServiceValidator;
Expand Down Expand Up @@ -57,6 +58,11 @@ public AttendeeCreateRequest createAttendee(AttendeeCreateRequest attendeeCreate
log.info("validating create attendee request parameters");
attendeeServiceValidator.validateAttendeeCreateRequestParameters(attendeeCreateRequest);

//validate whether attendees are project staff and whether attendees have the correct reporting staff
attendeeServiceValidator.validateAttendeeDetails(attendeeCreateRequest);
if(attendeeCreateRequest.getAttendees().isEmpty())
throw new CustomException("NO_VALID_ATTENDEES","No Valid attendees provided in this request.");

//extract registerIds and attendee IndividualIds from client request
String tenantId = attendeeCreateRequest.getAttendees().get(0).getTenantId();
List<String> attendeeIds = extractAttendeeIdsFromCreateRequest(attendeeCreateRequest);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.*;

@Service
@Slf4j
Expand Down Expand Up @@ -176,4 +175,28 @@ private List<String> extractStaffIdsFromRequest(StaffPermissionRequest staffPerm
return staffIds;
}

/**
* Creates a map of attendance registerId and its first staff enrolled.
*
* @param tenantId
* @param registerIds
* @return
*/
public Map<String, StaffPermission> fetchRegisterIdtoFirstStaffMap(String tenantId, List<String> registerIds) {
Map<String, StaffPermission> registerIdToFirstStaffMap = new HashMap<>(); //mapping of registerId to the first StaffPermission for each unique registerId

for ( String registerId : registerIds) {
if (!registerIdToFirstStaffMap.containsKey(registerId)) {
StaffSearchCriteria staffSearchCriteria = StaffSearchCriteria.builder().tenantId(tenantId).registerIds(Collections.singletonList(registerId)).build();

List<StaffPermission> staffPermissionList = staffRepository.getFirstStaff(staffSearchCriteria);

if (!staffPermissionList.isEmpty()) {
registerIdToFirstStaffMap.put(registerId, staffPermissionList.get(0));
}
}
}
return registerIdToFirstStaffMap;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
public class AttendanceServiceConstants {
public static final String MASTER_TENANTS = "tenants";
public static final String MDMS_TENANT_MODULE_NAME = "tenant";
public static final String LIMIT_OFFSET = "?limit=1000&offset=0";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package org.egov.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.egov.common.contract.request.RequestInfo;
import org.egov.common.http.client.ServiceRequestClient;
import org.egov.config.AttendanceServiceConfiguration;
import org.egov.repository.ServiceRequestRepository;
import org.egov.tracer.model.CustomException;
import org.egov.web.models.Hrms.Employee;
import org.egov.web.models.Hrms.EmployeeResponse;
import org.egov.web.models.RequestInfoWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class HRMSUtil {


@Autowired
private ServiceRequestRepository serviceRequestRepository;

@Autowired
private AttendanceServiceConfiguration config;

@Autowired
private ServiceRequestClient serviceRequestClient;

@Autowired
@Qualifier("objectMapper")
private ObjectMapper mapper;

private String HRMS_EMPLOYEE_JSONPATH = "$.Employees.*";
/**
* Gets the Employee for the given list of uuids and tenantId of employees
* @param tenantId
* @param uuids
* @param requestInfo
* @return
*/
public List<Employee> getEmployee(String tenantId, List<String> uuids, RequestInfo requestInfo){

StringBuilder url = getHRMSURI(tenantId, uuids);

EmployeeResponse employeeResponse = serviceRequestClient.fetchResult(url, RequestInfoWrapper.builder().requestInfo(requestInfo).build(), EmployeeResponse.class);
List<Employee> employeeList = employeeResponse.getEmployees();
if(employeeList.isEmpty())
throw new CustomException("NO_EMPLOYEE_FOUND_FOR_INDIVIDUALID","The Employees with uuid: "+uuids.toString()+" is not found");

return employeeList;

}

/**
* Builds HRMS search URL
* @param uuids
* @param tenantId
* @return URL
*/

public StringBuilder getHRMSURI(String tenantId, List<String> uuids){

StringBuilder builder = new StringBuilder(config.getHrmsHost());
builder.append(config.getHrmsEndPoint());
builder.append("?tenantId=").append(tenantId);
builder.append("&uuids=");
builder.append(StringUtils.join(uuids, ","));

return builder;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,33 @@ public List<Individual> getIndividualDetailsFromUserId(Long userId, RequestInfo

return response.getIndividual();
}

/**
* Retrieves individual details based on the provided search criteria and request information.
*
* @param individualSearch The search criteria for retrieving individual details
* @param requestInfo The request information
* @param tenantId The ID of the tenant
* @return A list of individual details matching the search criteria
*/
public List<Individual> getIndividualDetailsFromSearchCriteria(IndividualSearch individualSearch, RequestInfo requestInfo, String tenantId) {
String uri = getSearchURLWithParams(multiStateInstanceUtil.getStateLevelTenant(tenantId)).toUriString();
IndividualSearchRequest individualSearchRequest = IndividualSearchRequest.builder()
.requestInfo(requestInfo).individual(individualSearch).build();

IndividualBulkResponse response = null;
log.info("call individual search with tenantId::" + tenantId + "::indidividual search criteria::" + individualSearch.toString());

try {
response = restTemplate.postForObject(uri, individualSearchRequest, IndividualBulkResponse.class);
} catch (HttpClientErrorException | HttpServerErrorException httpClientOrServerExc) {
log.error("Error thrown from individual search service::" + httpClientOrServerExc.getStatusCode());
throw new CustomException("INDIVIDUAL_SEARCH_SERVICE_EXCEPTION", "Error thrown from individual search service::" + httpClientOrServerExc.getStatusCode());
}
if (response == null || CollectionUtils.isEmpty(response.getIndividual())) {
throw new CustomException("INDIVIDUAL_SEARCH_RESPONSE_IS_EMPTY", "Individuals not found");
}

return response.getIndividual();
}
}
Loading