diff --git a/backend/attendance/pom.xml b/backend/attendance/pom.xml index 4d39ba210f..1110668e8b 100644 --- a/backend/attendance/pom.xml +++ b/backend/attendance/pom.xml @@ -77,7 +77,7 @@ org.egov.common health-services-models - 1.0.6-SNAPSHOT + 1.0.19-SNAPSHOT compile @@ -114,17 +114,23 @@ javax.validation validation-api + + org.egov.common + health-services-common + 1.0.15-SNAPSHOT + compile + - repo.digit.org - eGov ERP Releases Repository - https://nexus-repo.digit.org/nexus/content/repositories/releases/ + repo.digit.org.snapshots + eGov ERP SNAPSHOT Repository + https://nexus-repo.digit.org/nexus/content/repositories/snapshots/ - repo.digit.org.snapshots + repo.digit.org eGov ERP Releases Repository - https://nexus-repo.digit.org/nexus/content/repositories/snapshots/ + https://nexus-repo.digit.org/nexus/content/repositories/releases/ repo.digit.org.public diff --git a/backend/attendance/src/main/java/org/egov/config/AttendanceLogConfiguration.java b/backend/attendance/src/main/java/org/egov/config/AttendanceLogConfiguration.java new file mode 100644 index 0000000000..5c392dec8f --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/config/AttendanceLogConfiguration.java @@ -0,0 +1,28 @@ +package org.egov.config; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.egov.tracer.config.TracerConfiguration; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Import; +import org.springframework.stereotype.Component; + +@Import({TracerConfiguration.class}) +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Component +public class AttendanceLogConfiguration { + + @Value("${attendance.log.kafka.consumer.bulk.create.topic}") + private String createAttendanceLogBulkTopic; + + @Value("${attendance.log.kafka.consumer.bulk.update.topic}") + private String updateAttendanceLogBulkTopic; + +} diff --git a/backend/attendance/src/main/java/org/egov/config/AttendanceServiceConfiguration.java b/backend/attendance/src/main/java/org/egov/config/AttendanceServiceConfiguration.java index ede3010f45..85b5043d5c 100644 --- a/backend/attendance/src/main/java/org/egov/config/AttendanceServiceConfiguration.java +++ b/backend/attendance/src/main/java/org/egov/config/AttendanceServiceConfiguration.java @@ -1,5 +1,8 @@ package org.egov.config; +import java.util.TimeZone; +import javax.annotation.PostConstruct; + import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -8,8 +11,7 @@ import org.springframework.context.annotation.Import; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; -import java.util.TimeZone; +import java.util.List; @Component @Data @@ -102,6 +104,35 @@ public void initialize() { @Value("${works.individual.search.endpoint}") private String individualSearchEndpoint; + @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 projectSupervisorRoles; + + @Value("${project.attendee.roles}") + private List projectAttendeeRoles; + + @Value("${project.staff.attendance.topic}") + private String projectStaffAttendanceTopic; + } diff --git a/backend/attendance/src/main/java/org/egov/config/MainConfiguration.java b/backend/attendance/src/main/java/org/egov/config/MainConfiguration.java index e4d1cb86e3..9e1c5cb638 100644 --- a/backend/attendance/src/main/java/org/egov/config/MainConfiguration.java +++ b/backend/attendance/src/main/java/org/egov/config/MainConfiguration.java @@ -1,19 +1,35 @@ package org.egov.config; +import java.util.TimeZone; +import javax.annotation.PostConstruct; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.egov.tracer.config.TracerConfiguration; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import javax.annotation.PostConstruct; -import java.util.TimeZone; - @Import({TracerConfiguration.class}) +@Configuration +@ComponentScan(basePackages = {"org.egov"}) public class MainConfiguration { @Value("${app.timezone}") @@ -24,9 +40,14 @@ public void initialize() { TimeZone.setDefault(TimeZone.getTimeZone(timeZone)); } - @Bean - public ObjectMapper objectMapper() { - return new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES).setTimeZone(TimeZone.getTimeZone(timeZone)); + @Value("${spring.redis.host}") + private String redisHost; + @Bean(name = "objectMapper") + public ObjectMapper objectMapper(){ + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES).setTimeZone(TimeZone.getTimeZone(timeZone)); + objectMapper.registerModule(new JavaTimeModule()); + return objectMapper; } @Bean @@ -36,4 +57,37 @@ public MappingJackson2HttpMessageConverter jacksonConverter(ObjectMapper objectM converter.setObjectMapper(objectMapper); return converter; } + @Bean + @Qualifier("redisObjectMapper") + public ObjectMapper redisObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, + ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY); + objectMapper.registerModule(new JavaTimeModule()); + return objectMapper; + } + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); + redisStandaloneConfiguration.setHostName(redisHost); + return new JedisConnectionFactory(redisStandaloneConfiguration); + } + + + @Bean + public RedisTemplate redisTemplate(@Qualifier("redisObjectMapper") ObjectMapper redisObjectMapper, + RedisConnectionFactory redisConnectionFactory) { + Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class); + serializer.setObjectMapper(redisObjectMapper); + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(serializer); + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashValueSerializer(serializer); + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } } \ No newline at end of file diff --git a/backend/attendance/src/main/java/org/egov/enrichment/AttendanceLogEnrichment.java b/backend/attendance/src/main/java/org/egov/enrichment/AttendanceLogEnrichment.java index 64f9e785ce..4495897ed6 100644 --- a/backend/attendance/src/main/java/org/egov/enrichment/AttendanceLogEnrichment.java +++ b/backend/attendance/src/main/java/org/egov/enrichment/AttendanceLogEnrichment.java @@ -11,7 +11,9 @@ import org.egov.web.models.Document; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import java.util.Collections; import java.util.List; import java.util.UUID; @@ -34,8 +36,10 @@ public void enrichAttendanceLogCreateRequest(AttendanceLogRequest attendanceLogR String attendanceLogId = String.valueOf(UUID.randomUUID()); attendanceLog.setId(attendanceLogId); List documentIds = attendanceLog.getDocumentIds(); - for (Document documentId : documentIds) { - documentId.setId(String.valueOf(UUID.randomUUID())); + if(!CollectionUtils.isEmpty(documentIds)) { + for (Document documentId : documentIds) { + documentId.setId(String.valueOf(UUID.randomUUID())); + } } } log.info("Enriched attendance log create request for register ["+registerId+"]"); diff --git a/backend/attendance/src/main/java/org/egov/enrichment/RegisterEnrichment.java b/backend/attendance/src/main/java/org/egov/enrichment/RegisterEnrichment.java index c848e02b15..da7a1a1a5c 100644 --- a/backend/attendance/src/main/java/org/egov/enrichment/RegisterEnrichment.java +++ b/backend/attendance/src/main/java/org/egov/enrichment/RegisterEnrichment.java @@ -65,7 +65,7 @@ public void enrichRegisterOnCreate(AttendanceRegisterRequest attendanceRegisterR attendanceRegisters.get(i).setAuditDetails(auditDetails); log.info("Enriched register " + attendanceRegisters.get(i).getId() + " with Audit details"); // User who creates the register, by default gets enrolled as the first staff for that register. - enrichRegisterFirstStaff(attendanceRegisters.get(i), requestInfo, auditDetails); + if(config.getRegisterFirstStaffInsertEnabled()) enrichRegisterFirstStaff(attendanceRegisters.get(i), requestInfo, auditDetails); } } diff --git a/backend/attendance/src/main/java/org/egov/kafka/AttendanceLogConsumer.java b/backend/attendance/src/main/java/org/egov/kafka/AttendanceLogConsumer.java new file mode 100644 index 0000000000..b404119d20 --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/kafka/AttendanceLogConsumer.java @@ -0,0 +1,55 @@ +package org.egov.kafka; + +import java.util.Map; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.egov.service.AttendanceLogService; +import org.egov.tracer.model.CustomException; +import org.egov.web.models.AttendanceLogRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.kafka.support.KafkaHeaders; +import org.springframework.messaging.handler.annotation.Header; +import org.springframework.stereotype.Component; + + +@Component +@Slf4j +public class AttendanceLogConsumer { + + @Autowired + private AttendanceLogService attendanceLogService; + + @Autowired + private ObjectMapper objectMapper; + + @KafkaListener(topics = "${attendance.log.kafka.consumer.bulk.create.topic}") + public void bulkCreate(Map consumerRecord, + @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) { + try { + AttendanceLogRequest request = objectMapper.convertValue(consumerRecord, AttendanceLogRequest.class); + attendanceLogService.createAttendanceLog(request); + } catch (Exception exception) { + log.error("Error in Attendance Log consumer bulk create", exception); + log.error("Exception trace: ", ExceptionUtils.getStackTrace(exception)); + throw new CustomException("HCM_ATTENDANCE_LOG_CREATE", exception.getMessage()); + } + } + + @KafkaListener(topics = "${attendance.log.kafka.consumer.bulk.update.topic}") + public void bulkUpdate(Map consumerRecord, + @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) { + try { + AttendanceLogRequest request = objectMapper.convertValue(consumerRecord, AttendanceLogRequest.class); + attendanceLogService.updateAttendanceLog(request); + } catch (Exception exception) { + log.error("Error in Attendance Log consumer bulk update", exception); + log.error("Exception trace: ", ExceptionUtils.getStackTrace(exception)); + throw new CustomException("HCM_ATTENDANCE_LOG_UPDATE", exception.getMessage()); + } + } + +} diff --git a/backend/attendance/src/main/java/org/egov/kafka/AttendanceRegisterConsumer.java b/backend/attendance/src/main/java/org/egov/kafka/AttendanceRegisterConsumer.java new file mode 100644 index 0000000000..a58dc64a3a --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/kafka/AttendanceRegisterConsumer.java @@ -0,0 +1,40 @@ +package org.egov.kafka; + +import java.util.Map; + +import com.fasterxml.jackson.databind.ObjectMapper; +import digit.models.coremodels.RequestInfoWrapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.egov.common.models.project.ProjectRequest; +import org.egov.service.AttendanceRegisterService; +import org.egov.tracer.model.CustomException; +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; + +@Component +@Slf4j +public class AttendanceRegisterConsumer { + @Autowired + private AttendanceRegisterService attendanceRegisterService; + + @Autowired + private ObjectMapper objectMapper; + + @KafkaListener(topics = "${project.management.system.kafka.update.topic}") + public void projectUpdate(Map consumerRecord, + @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) { + try { + log.info("Attendance Register Consumer Started for project update."); + ProjectRequest projectRequest = objectMapper.convertValue(consumerRecord, ProjectRequest.class); + attendanceRegisterService.updateAttendanceRegister(RequestInfoWrapper.builder().requestInfo(projectRequest.getRequestInfo()).build(), projectRequest.getProjects()); + } catch (Exception exception) { + log.error("Error in Attendance Register consumer update", exception); + log.error("Exception trace: ", ExceptionUtils.getStackTrace(exception)); + throw new CustomException("HCM_ATTENDANCE_REGISTER_UPDATE", exception.getMessage()); + } + } +} diff --git a/backend/attendance/src/main/java/org/egov/kafka/Consumer.java b/backend/attendance/src/main/java/org/egov/kafka/Consumer.java index 8b5094ede0..7e91c71ab9 100644 --- a/backend/attendance/src/main/java/org/egov/kafka/Consumer.java +++ b/backend/attendance/src/main/java/org/egov/kafka/Consumer.java @@ -33,10 +33,10 @@ public class Consumer { private AttendanceRegisterService attendanceRegisterService; @KafkaListener(topics = "${organisation.contact.details.update.topic}") - public void updateAttendanceStaff(String consumerRecord, + public void updateAttendanceStaff(Map consumerRecord, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic){ try { - OrgContactUpdateDiff orgContactUpdateDiff = objectMapper.readValue(consumerRecord, OrgContactUpdateDiff.class); + OrgContactUpdateDiff orgContactUpdateDiff = objectMapper.convertValue(consumerRecord, OrgContactUpdateDiff.class); organisationContactDetailsStaffUpdateService.updateStaffPermissionsForContactDetails(orgContactUpdateDiff); } catch(Exception e){ log.error("Error updating staff permissions for update in organisation contact details", e); @@ -49,9 +49,9 @@ public void updateAttendanceStaff(String consumerRecord, * @param topic */ @KafkaListener(topics = "${contracts.revision.topic}") - public void updateEndDate(String consumerRecord, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) { + public void updateEndDate(Map consumerRecord, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) { try { - JsonNode attendanceContractRevisionRequest = objectMapper.readValue(consumerRecord, JsonNode.class); + JsonNode attendanceContractRevisionRequest = objectMapper.convertValue(consumerRecord, JsonNode.class); RequestInfo requestInfo = objectMapper.convertValue(attendanceContractRevisionRequest.get("RequestInfo"), RequestInfo.class); String tenantId = attendanceContractRevisionRequest.get("tenantId").asText(); String referenceId = attendanceContractRevisionRequest.get("referenceId").asText(); diff --git a/backend/attendance/src/main/java/org/egov/kafka/Producer.java b/backend/attendance/src/main/java/org/egov/kafka/Producer.java index b226368be0..e13cd3d7fa 100644 --- a/backend/attendance/src/main/java/org/egov/kafka/Producer.java +++ b/backend/attendance/src/main/java/org/egov/kafka/Producer.java @@ -4,7 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -@Component +//@Component public class Producer { @Autowired diff --git a/backend/attendance/src/main/java/org/egov/kafka/ProjectStaffConsumer.java b/backend/attendance/src/main/java/org/egov/kafka/ProjectStaffConsumer.java new file mode 100644 index 0000000000..3d93d29339 --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/kafka/ProjectStaffConsumer.java @@ -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 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(); + + List staffUserUuids = Collections.singletonList(projectStaff.getUserId()); + String tenantId = projectStaff.getTenantId(); + + // Search for the individual details using the user UUID + IndividualSearch individualSearch = IndividualSearch.builder().userUuid(staffUserUuids).build(); + List individualList = individualServiceUtil.getIndividualDetailsFromSearchCriteria(individualSearch, requestInfo, tenantId); + + if (individualList.isEmpty()) + throw new CustomException("INVALID_STAFF_ID", "No Individual found for the given staff Uuid - " + staffUserUuids); + Individual individual = individualList.get(0); + + List roleList = individual.getUserDetails().getRoles(); + List 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); + } + } + + +} diff --git a/backend/attendance/src/main/java/org/egov/repository/AttendanceLogRepository.java b/backend/attendance/src/main/java/org/egov/repository/AttendanceLogRepository.java index 13f19c885e..42e52bf780 100644 --- a/backend/attendance/src/main/java/org/egov/repository/AttendanceLogRepository.java +++ b/backend/attendance/src/main/java/org/egov/repository/AttendanceLogRepository.java @@ -1,36 +1,55 @@ package org.egov.repository; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.egov.common.data.query.builder.SelectQueryBuilder; +import org.egov.common.data.repository.GenericRepository; +import org.egov.common.producer.Producer; import org.egov.repository.querybuilder.AttendanceLogQueryBuilder; import org.egov.repository.rowmapper.AttendanceLogRowMapper; import org.egov.web.models.AttendanceLog; import org.egov.web.models.AttendanceLogSearchCriteria; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; - -import java.util.ArrayList; -import java.util.List; +import org.springframework.util.CollectionUtils; @Repository @Slf4j -public class AttendanceLogRepository { - @Autowired - private AttendanceLogRowMapper rowMapper; +public class AttendanceLogRepository extends GenericRepository { + private final AttendanceLogRowMapper rowMapper; + private final AttendanceLogQueryBuilder queryBuilder; + private final JdbcTemplate jdbcTemplate; @Autowired - private AttendanceLogQueryBuilder queryBuilder; + protected AttendanceLogRepository( + Producer producer, + NamedParameterJdbcTemplate namedParameterJdbcTemplate, + RedisTemplate redisTemplate, + SelectQueryBuilder selectQueryBuilder, + AttendanceLogRowMapper rowMapper, + JdbcTemplate jdbcTemplate) { + super(producer, namedParameterJdbcTemplate, redisTemplate, selectQueryBuilder, null, Optional.of("abc")); + this.rowMapper = rowMapper; + this.queryBuilder = new AttendanceLogQueryBuilder(); + this.jdbcTemplate = jdbcTemplate; + } - @Autowired - private JdbcTemplate jdbcTemplate; public List getAttendanceLogs(AttendanceLogSearchCriteria searchCriteria) { List preparedStmtList = new ArrayList<>(); - log.info("Fetching Attendance Log list. RegisterId ["+searchCriteria.getRegisterId()+"]"); + if(!StringUtils.isBlank(searchCriteria.getRegisterId())) log.info("Fetching Attendance Log list. RegisterId ["+searchCriteria.getRegisterId()+"]"); + if(!CollectionUtils.isEmpty(searchCriteria.getClientReferenceId())) log.info("Fetching Attendance Log list. ClientReferenceIds "+searchCriteria.getClientReferenceId()); String query = queryBuilder.getAttendanceLogSearchQuery(searchCriteria, preparedStmtList); - log.info("Query build successfully. RegisterId ["+searchCriteria.getRegisterId()+"]"); + log.info("Query build successfully"); List attendanceLogList = jdbcTemplate.query(query, rowMapper, preparedStmtList.toArray()); - log.info("Fetched Attendance Log list. RegisterId ["+searchCriteria.getRegisterId()+"]"); + log.info("Fetched Attendance Log list"); return attendanceLogList; } } diff --git a/backend/attendance/src/main/java/org/egov/repository/ServiceRequestRepository.java b/backend/attendance/src/main/java/org/egov/repository/ServiceRequestRepository.java index a0c8261080..644e99c7df 100644 --- a/backend/attendance/src/main/java/org/egov/repository/ServiceRequestRepository.java +++ b/backend/attendance/src/main/java/org/egov/repository/ServiceRequestRepository.java @@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j; import org.egov.tracer.model.ServiceCallException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Repository; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; @@ -16,6 +17,7 @@ public class ServiceRequestRepository { @Autowired + @Qualifier("objectMapper") private ObjectMapper mapper; @Autowired diff --git a/backend/attendance/src/main/java/org/egov/repository/StaffRepository.java b/backend/attendance/src/main/java/org/egov/repository/StaffRepository.java index 6d83e146dc..5436c7ab11 100644 --- a/backend/attendance/src/main/java/org/egov/repository/StaffRepository.java +++ b/backend/attendance/src/main/java/org/egov/repository/StaffRepository.java @@ -37,4 +37,17 @@ public List getAllStaff(StaffSearchCriteria searchCriteria) { List 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 getFirstStaff(StaffSearchCriteria searchCriteria) { + List preparedStmtList = new ArrayList<>(); + String query = queryBuilder.appendOrderLimit(queryBuilder.getAttendanceStaffSearchQuery(searchCriteria, preparedStmtList)); + List attendanceStaffList = jdbcTemplate.query(query, rowMapper, preparedStmtList.toArray()); + return attendanceStaffList; + } } diff --git a/backend/attendance/src/main/java/org/egov/repository/querybuilder/AttendanceLogQueryBuilder.java b/backend/attendance/src/main/java/org/egov/repository/querybuilder/AttendanceLogQueryBuilder.java index 2a678b23dc..ad659d8e2c 100644 --- a/backend/attendance/src/main/java/org/egov/repository/querybuilder/AttendanceLogQueryBuilder.java +++ b/backend/attendance/src/main/java/org/egov/repository/querybuilder/AttendanceLogQueryBuilder.java @@ -15,6 +15,7 @@ public class AttendanceLogQueryBuilder { private static final String ATTENDANCE_LOG_SELECT_QUERY = " SELECT log.id as logid, " + "log.individual_id as logIndividualId, " + + "log.clientreferenceid as logClientReferenceId, " + "log.tenantId as logTenantId, " + "log.register_id as logRegisterId, " + "log.status as logStatus, " + @@ -25,6 +26,10 @@ public class AttendanceLogQueryBuilder { "log.lastmodifiedby as logLastModifiedBy, " + "log.createdtime as logCreatedTime, " + "log.lastmodifiedtime as logLastModifiedTime, " + + "log.clientcreatedby as logClientCreatedBy, " + + "log.clientlastmodifiedby as logClientLastModifiedBy, " + + "log.clientcreatedtime as logClientCreatedTime, " + + "log.clientlastmodifiedtime as logClientLastModifiedTime, " + "doc.id as docId, " + "doc.filestore_id as docFileStoreId, " + "doc.document_type as docDocumentType, " + @@ -52,6 +57,13 @@ public String getAttendanceLogSearchQuery(AttendanceLogSearchCriteria criteria, addToPreparedStatement(preparedStmtList, ids); } + List clientReferenceIds = criteria.getClientReferenceId(); + if (clientReferenceIds != null && !clientReferenceIds.isEmpty()) { + addClauseIfRequired(query, preparedStmtList); + query.append(" log.clientreferenceid IN (").append(createQuery(clientReferenceIds)).append(")"); + addToPreparedStatement(preparedStmtList, clientReferenceIds); + } + if (StringUtils.isNotBlank(criteria.getTenantId())) { addClauseIfRequired(query, preparedStmtList); query.append(" log.tenantid=? "); diff --git a/backend/attendance/src/main/java/org/egov/repository/querybuilder/StaffQueryBuilder.java b/backend/attendance/src/main/java/org/egov/repository/querybuilder/StaffQueryBuilder.java index 7e093724b6..db82f3d573 100644 --- a/backend/attendance/src/main/java/org/egov/repository/querybuilder/StaffQueryBuilder.java +++ b/backend/attendance/src/main/java/org/egov/repository/querybuilder/StaffQueryBuilder.java @@ -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"; + } } diff --git a/backend/attendance/src/main/java/org/egov/repository/rowmapper/AttendanceLogRowMapper.java b/backend/attendance/src/main/java/org/egov/repository/rowmapper/AttendanceLogRowMapper.java index f009b03d33..98ec0fe582 100644 --- a/backend/attendance/src/main/java/org/egov/repository/rowmapper/AttendanceLogRowMapper.java +++ b/backend/attendance/src/main/java/org/egov/repository/rowmapper/AttendanceLogRowMapper.java @@ -11,6 +11,7 @@ import org.egov.web.models.Status; import org.postgresql.util.PGobject; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.stereotype.Component; @@ -26,6 +27,7 @@ public class AttendanceLogRowMapper implements ResultSetExtractor> { @Autowired + @Qualifier("objectMapper") private ObjectMapper mapper; @Override @@ -35,6 +37,7 @@ public List extractData(ResultSet rs) throws SQLException, DataAc while (rs.next()) { String id = rs.getString("logid"); + String clientReferenceId = rs.getString("logClientReferenceId"); String individualId = rs.getString("logIndividualId"); String tenantId = rs.getString("logTenantId"); String registerId = rs.getString("logRegisterId"); @@ -45,15 +48,21 @@ public List extractData(ResultSet rs) throws SQLException, DataAc String lastmodifiedby = rs.getString("logLastModifiedBy"); Long createdtime = rs.getLong("logCreatedTime"); Long lastmodifiedtime = rs.getLong("logLastModifiedTime"); - + String clientcreatedby = rs.getString("logClientCreatedBy"); + String clientlastmodifiedby = rs.getString("logClientLastModifiedBy"); + Long clientcreatedtime = rs.getLong("logClientCreatedTime"); + Long clientlastmodifiedtime = rs.getLong("logClientLastModifiedTime"); AuditDetails auditDetails = AuditDetails.builder().createdBy(createdby).createdTime(createdtime) .lastModifiedBy(lastmodifiedby).lastModifiedTime(lastmodifiedtime) .build(); - + AuditDetails clientAuditDetails = AuditDetails.builder().createdBy(clientcreatedby).createdTime(clientcreatedtime) + .lastModifiedBy(clientlastmodifiedby).lastModifiedTime(clientlastmodifiedtime) + .build(); JsonNode additionalDetails = getAdditionalDetail("logAdditionalDetails", rs); AttendanceLog attendanceLog = AttendanceLog.builder() .id(id) + .clientReferenceId(clientReferenceId) .individualId(individualId) .tenantId(tenantId) .registerId(registerId) @@ -62,6 +71,7 @@ public List extractData(ResultSet rs) throws SQLException, DataAc .type(eventType) .additionalDetails(additionalDetails) .auditDetails(auditDetails) + .clientAuditDetails(clientAuditDetails) .build(); if (!attendanceLogMap.containsKey(id)) { diff --git a/backend/attendance/src/main/java/org/egov/repository/rowmapper/AttendeeRowMapper.java b/backend/attendance/src/main/java/org/egov/repository/rowmapper/AttendeeRowMapper.java index 5d5c23ea42..b6c0bcdbd0 100644 --- a/backend/attendance/src/main/java/org/egov/repository/rowmapper/AttendeeRowMapper.java +++ b/backend/attendance/src/main/java/org/egov/repository/rowmapper/AttendeeRowMapper.java @@ -7,6 +7,7 @@ import org.egov.web.models.IndividualEntry; import org.postgresql.util.PGobject; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.stereotype.Component; @@ -21,6 +22,7 @@ public class AttendeeRowMapper implements ResultSetExtractor> { @Autowired + @Qualifier("objectMapper") private ObjectMapper mapper; @Override diff --git a/backend/attendance/src/main/java/org/egov/repository/rowmapper/RegisterRowMapper.java b/backend/attendance/src/main/java/org/egov/repository/rowmapper/RegisterRowMapper.java index e6ffb4090a..90e44065b7 100644 --- a/backend/attendance/src/main/java/org/egov/repository/rowmapper/RegisterRowMapper.java +++ b/backend/attendance/src/main/java/org/egov/repository/rowmapper/RegisterRowMapper.java @@ -8,6 +8,7 @@ import org.egov.web.models.Status; import org.postgresql.util.PGobject; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.stereotype.Component; @@ -25,6 +26,7 @@ public class RegisterRowMapper implements ResultSetExtractor> { @Autowired + @Qualifier("objectMapper") private ObjectMapper mapper; @Override diff --git a/backend/attendance/src/main/java/org/egov/repository/rowmapper/StaffRowMapper.java b/backend/attendance/src/main/java/org/egov/repository/rowmapper/StaffRowMapper.java index 60851bc94c..38b99cad25 100644 --- a/backend/attendance/src/main/java/org/egov/repository/rowmapper/StaffRowMapper.java +++ b/backend/attendance/src/main/java/org/egov/repository/rowmapper/StaffRowMapper.java @@ -7,6 +7,7 @@ import org.egov.web.models.StaffPermission; import org.postgresql.util.PGobject; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.stereotype.Component; @@ -24,6 +25,7 @@ public class StaffRowMapper implements ResultSetExtractor> { @Autowired + @Qualifier("objectMapper") private ObjectMapper mapper; @Override diff --git a/backend/attendance/src/main/java/org/egov/service/AttendanceLogService.java b/backend/attendance/src/main/java/org/egov/service/AttendanceLogService.java index 136e4ec3a0..a55dd69aeb 100644 --- a/backend/attendance/src/main/java/org/egov/service/AttendanceLogService.java +++ b/backend/attendance/src/main/java/org/egov/service/AttendanceLogService.java @@ -4,7 +4,7 @@ import org.egov.common.contract.response.ResponseInfo; import org.egov.config.AttendanceServiceConfiguration; import org.egov.enrichment.AttendanceLogEnrichment; -import org.egov.kafka.Producer; +import org.egov.common.producer.Producer; import org.egov.web.models.AttendanceLogSearchCriteria; import org.egov.repository.AttendanceLogRepository; import org.egov.util.ResponseInfoFactory; @@ -99,4 +99,10 @@ public AttendanceLogResponse updateAttendanceLog(AttendanceLogRequest attendance log.info("Attendance logs updated successfully for register ["+registerId+"]"); return attendanceLogResponse; } + + public void putInCache(List attendanceLogs) { + log.info("putting {} Attendance Logs in cache", attendanceLogs.size()); + attendanceLogRepository.putInCache(attendanceLogs); + log.info("successfully put Attendance Logs in cache"); + } } diff --git a/backend/attendance/src/main/java/org/egov/service/AttendanceRegisterService.java b/backend/attendance/src/main/java/org/egov/service/AttendanceRegisterService.java index ce0bc9457f..5c2c621bae 100644 --- a/backend/attendance/src/main/java/org/egov/service/AttendanceRegisterService.java +++ b/backend/attendance/src/main/java/org/egov/service/AttendanceRegisterService.java @@ -1,14 +1,16 @@ package org.egov.service; +import ch.qos.logback.core.BasicStatusManager; import digit.models.coremodels.RequestInfoWrapper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.egov.common.contract.request.RequestInfo; import org.egov.common.contract.request.Role; +import org.egov.common.models.project.Project; import org.egov.config.AttendanceServiceConfiguration; import org.egov.enrichment.RegisterEnrichment; import org.egov.enrichment.StaffEnrichmentService; -import org.egov.kafka.Producer; +import org.egov.common.producer.Producer; import org.egov.repository.AttendeeRepository; import org.egov.repository.RegisterRepository; import org.egov.tracer.model.CustomException; @@ -18,6 +20,7 @@ import org.egov.web.models.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.util.*; @@ -285,7 +288,7 @@ public AttendanceRegisterRequest updateAttendanceRegister(AttendanceRegisterRequ log.info("Fetched attendance registers for update request"); //Validate Update attendance register request against attendance registers fetched from database - attendanceServiceValidator.validateUpdateAgainstDB(attendanceRegisterRequest, attendanceRegistersFromDB); + attendanceServiceValidator.validateUpdateAgainstDB(attendanceRegisterRequest, attendanceRegistersFromDB, attendanceServiceConfiguration.getRegisterFirstStaffInsertEnabled()); registerEnrichment.enrichRegisterOnUpdate(attendanceRegisterRequest, attendanceRegistersFromDB); log.info("Enriched with register Number, Ids and AuditDetails"); @@ -295,6 +298,42 @@ public AttendanceRegisterRequest updateAttendanceRegister(AttendanceRegisterRequ return attendanceRegisterRequest; } + public void updateAttendanceRegister(RequestInfoWrapper requestInfoWrapper, List projects) { + if(!CollectionUtils.isEmpty(projects)) { + List updatedRegisters = new ArrayList<>(); + projects.forEach(project -> { + BigDecimal projectStartDate = BigDecimal.valueOf(project.getStartDate()); + BigDecimal projectEndDate = BigDecimal.valueOf(project.getEndDate()); + log.info("Fetching register from db for project : " + project.getId()); + List registers = searchAttendanceRegister( + requestInfoWrapper, + AttendanceRegisterSearchCriteria.builder().referenceId(project.getId()).tenantId(project.getTenantId()).build() + ); + if(CollectionUtils.isEmpty(registers)) return; + + registers.forEach(attendanceRegister -> { + Boolean isUpdated = false; + if(attendanceRegister.getEndDate().compareTo(projectEndDate) < 0) { + // update register end date to project end date + attendanceRegister.setEndDate(projectEndDate); + isUpdated = true; + } + if(isUpdated) updatedRegisters.add(attendanceRegister); + }); + if(!updatedRegisters.isEmpty()) { + AttendanceRegisterRequest attendanceRegisterRequest = AttendanceRegisterRequest.builder() + .attendanceRegister(updatedRegisters) + .requestInfo(requestInfoWrapper.getRequestInfo()) + .build(); + registerEnrichment.enrichRegisterOnUpdate(attendanceRegisterRequest, updatedRegisters); + log.info("Pushing update attendance register request to kafka"); + producer.push(attendanceServiceConfiguration.getUpdateAttendanceRegisterTopic(), attendanceRegisterRequest); + log.info("Pushed update attendance register request to kafka"); + } + }); + } + } + public List getAttendanceRegisters(RequestInfoWrapper requestInfoWrapper, List registerIds, String tenantId) { //Search criteria for attendance register search request diff --git a/backend/attendance/src/main/java/org/egov/service/AttendeeService.java b/backend/attendance/src/main/java/org/egov/service/AttendeeService.java index 72f9e0a588..6198b4578b 100644 --- a/backend/attendance/src/main/java/org/egov/service/AttendeeService.java +++ b/backend/attendance/src/main/java/org/egov/service/AttendeeService.java @@ -4,8 +4,9 @@ import lombok.extern.slf4j.Slf4j; import org.egov.config.AttendanceServiceConfiguration; import org.egov.enrichment.AttendeeEnrichmentService; -import org.egov.kafka.Producer; +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; @@ -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 attendeeIds = extractAttendeeIdsFromCreateRequest(attendeeCreateRequest); diff --git a/backend/attendance/src/main/java/org/egov/service/StaffService.java b/backend/attendance/src/main/java/org/egov/service/StaffService.java index a20bc3898c..7e3144f43a 100644 --- a/backend/attendance/src/main/java/org/egov/service/StaffService.java +++ b/backend/attendance/src/main/java/org/egov/service/StaffService.java @@ -4,7 +4,7 @@ import lombok.extern.slf4j.Slf4j; import org.egov.config.AttendanceServiceConfiguration; import org.egov.enrichment.StaffEnrichmentService; -import org.egov.kafka.Producer; +import org.egov.common.producer.Producer; import org.egov.repository.RegisterRepository; import org.egov.repository.StaffRepository; import org.egov.util.ResponseInfoFactory; @@ -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 @@ -176,4 +175,28 @@ private List extractStaffIdsFromRequest(StaffPermissionRequest staffPerm return staffIds; } + /** + * Creates a map of attendance registerId and its first staff enrolled. + * + * @param tenantId + * @param registerIds + * @return + */ + public Map fetchRegisterIdtoFirstStaffMap(String tenantId, List registerIds) { + Map 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 staffPermissionList = staffRepository.getFirstStaff(staffSearchCriteria); + + if (!staffPermissionList.isEmpty()) { + registerIdToFirstStaffMap.put(registerId, staffPermissionList.get(0)); + } + } + } + return registerIdToFirstStaffMap; + } + } diff --git a/backend/attendance/src/main/java/org/egov/util/AttendanceServiceConstants.java b/backend/attendance/src/main/java/org/egov/util/AttendanceServiceConstants.java index 702bc4ba0b..9e33ade2d4 100644 --- a/backend/attendance/src/main/java/org/egov/util/AttendanceServiceConstants.java +++ b/backend/attendance/src/main/java/org/egov/util/AttendanceServiceConstants.java @@ -3,4 +3,6 @@ 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"; + public static final String TWO_SESSIONS = "TWO_SESSIONS"; } diff --git a/backend/attendance/src/main/java/org/egov/util/HRMSUtil.java b/backend/attendance/src/main/java/org/egov/util/HRMSUtil.java new file mode 100644 index 0000000000..37c32d0601 --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/util/HRMSUtil.java @@ -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 getEmployee(String tenantId, List uuids, RequestInfo requestInfo){ + + StringBuilder url = getHRMSURI(tenantId, uuids); + + EmployeeResponse employeeResponse = serviceRequestClient.fetchResult(url, RequestInfoWrapper.builder().requestInfo(requestInfo).build(), EmployeeResponse.class); + List 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 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; + } + +} diff --git a/backend/attendance/src/main/java/org/egov/util/IndividualServiceUtil.java b/backend/attendance/src/main/java/org/egov/util/IndividualServiceUtil.java index b668b46a19..a1fbb2816d 100644 --- a/backend/attendance/src/main/java/org/egov/util/IndividualServiceUtil.java +++ b/backend/attendance/src/main/java/org/egov/util/IndividualServiceUtil.java @@ -12,6 +12,7 @@ import org.egov.repository.ServiceRequestRepository; import org.egov.tracer.model.CustomException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import org.springframework.web.client.HttpClientErrorException; @@ -35,6 +36,7 @@ public class IndividualServiceUtil { private AttendanceServiceConfiguration config; @Autowired + @Qualifier("objectMapper") private ObjectMapper mapper; @Autowired @@ -112,4 +114,33 @@ public List 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 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(); + } } diff --git a/backend/attendance/src/main/java/org/egov/util/ProjectStaffUtil.java b/backend/attendance/src/main/java/org/egov/util/ProjectStaffUtil.java new file mode 100644 index 0000000000..3e48270305 --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/util/ProjectStaffUtil.java @@ -0,0 +1,285 @@ +package org.egov.util; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.egov.common.contract.request.RequestInfo; +import org.egov.common.http.client.ServiceRequestClient; +import org.egov.common.models.individual.Individual; +import org.egov.common.models.individual.IndividualSearch; +import org.egov.common.models.project.*; +import org.egov.config.AttendanceServiceConfiguration; +import org.egov.repository.RegisterRepository; + +import org.egov.service.AttendanceRegisterService; +import org.egov.service.AttendeeService; +import org.egov.service.StaffService; +import org.egov.tracer.model.CustomException; +import org.egov.web.models.*; + +import org.egov.web.models.Hrms.Employee; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; + +import static org.egov.util.AttendanceServiceConstants.LIMIT_OFFSET; +import static org.egov.util.AttendanceServiceConstants.TWO_SESSIONS; + +@Component +@Slf4j +public class ProjectStaffUtil { + + @Autowired + private AttendanceServiceConfiguration config; + + @Autowired + private RegisterRepository registerRepository; + + @Autowired + private ServiceRequestClient serviceRequestClient; + + @Autowired + private IndividualServiceUtil individualServiceUtil; + + @Autowired + private AttendanceRegisterService attendanceRegisterService; + + @Autowired + private StaffService staffService; + + @Autowired + private HRMSUtil hrmsUtil; + + @Autowired + private AttendeeService attendeeService; + + @Autowired + @Qualifier("objectMapper") + private ObjectMapper mapper; + + /** + * Creates a registry for a supervisor based on the provided project staff, request info, and individual. + * Enrolls the first staff member in the registry. + * + * @param projectStaff The project staff information + * @param requestInfo The request information + * @param individual The individual information + */ + public void createRegistryForSupervisor(ProjectStaff projectStaff, RequestInfo requestInfo, Individual individual) { + String tenantId = projectStaff.getTenantId(); + ObjectMapper objectMapper = new ObjectMapper(); + String numberOfSessions = null; + + log.info("Match Found for Supervisor Role"); + + // Get the project details + Project projectsearch = Project.builder().id(projectStaff.getProjectId()).tenantId(tenantId).build(); + List projectList = getProject(tenantId,projectsearch,requestInfo); + if(projectList.isEmpty()) + throw new CustomException("INVALID_PROJECT_ID","No Project found for the given project ID - "+projectStaff.getProjectId()); + + Project project = projectList.get(0); + + JsonNode additionalDetails = null; + try { + Object additionalDetailsObj = project.getAdditionalDetails(); + String additionalDetailsStr = objectMapper.writeValueAsString(additionalDetailsObj); + additionalDetails = objectMapper.readTree(additionalDetailsStr); + + JsonNode numberOfSessionsNode = additionalDetails.get("numberOfSessions"); + if (numberOfSessionsNode != null && numberOfSessionsNode.isTextual()) { + numberOfSessions = numberOfSessionsNode.asText(); + log.info("Number of sessions: " + numberOfSessions); + } else { + numberOfSessions = TWO_SESSIONS; + log.info("numberOfSessions field not found in project's additonal Details"); + } + }catch (ClassCastException e) { + log.error("Not able to parse additional details object", e); + } catch (Exception e) { + log.error("An unexpected error occurred while getting AdditionalDetails", e); + } + + Map additionalDetailsMap = new HashMap<>(); + additionalDetailsMap.put("eventType", "Attendance"); + additionalDetailsMap.put("campaignName", project.getName()); + + if(numberOfSessions.equals(TWO_SESSIONS)) + additionalDetailsMap.put("sessions", 2); + else + additionalDetailsMap.put("sessions", 0); + + JsonNode additionalDetailsNode=null; + try { + String additionalDetailsJson = mapper.writeValueAsString(additionalDetailsMap); + additionalDetailsNode = mapper.readTree(additionalDetailsJson); + + } + catch (Exception e) + { + throw new CustomException("UNABLE_TO_CREATE_ADDITIONAL_DETAILS_OBJECT", "Unable to create Additional Details Object "); + } + + // Create an attendance register for the project + AttendanceRegister attendanceRegister = AttendanceRegister.builder().tenantId(tenantId) + .name(project.getName()) + .referenceId(projectStaff.getProjectId()) + .serviceCode(String.valueOf(UUID.randomUUID())) + .startDate(BigDecimal.valueOf(project.getStartDate())) + .endDate(BigDecimal.valueOf(project.getEndDate())) + .additionalDetails(additionalDetailsNode) + .status(Status.ACTIVE) + .build(); + AttendanceRegisterRequest request = AttendanceRegisterRequest.builder().attendanceRegister(Collections.singletonList(attendanceRegister)).requestInfo(requestInfo).build(); + AttendanceRegisterRequest enrichedAttendanceRegisterRequest = attendanceRegisterService.createAttendanceRegister(request); + + // Enroll the first staff member in the registry + if (enrichedAttendanceRegisterRequest.getAttendanceRegister().isEmpty()) + throw new CustomException("UNABLE_TO_CREATE_REGISTER", "Unable to create Register with Project ID - " + projectStaff.getProjectId()); + + String attendanceRegisterId = enrichedAttendanceRegisterRequest.getAttendanceRegister().get(0).getId(); + StaffPermission staffPermission = StaffPermission.builder().registerId(attendanceRegisterId).userId(individual.getId()).tenantId(tenantId).build(); + StaffPermissionRequest staffPermissionRequest = StaffPermissionRequest.builder().staff(Collections.singletonList(staffPermission)).requestInfo(requestInfo).build(); + + StaffPermissionRequest enrichedRequest = staffService.createAttendanceStaff(staffPermissionRequest, false); + if (enrichedRequest.getStaff().isEmpty()) + throw new CustomException("UNABLE_TO_ENROLL_FIRST_STAFF", "Unable to enroll first staff with Staff ID - " + individual.getId()); + log.info("Staff Successfully enrolled with Staff Id - " + individual.getId()); + } + + /** + * Enrolls an attendee to a register based on the provided project staff, request info, and individual. + * + * @param projectStaff The project staff information + * @param requestInfo The request information + * @param individual The individual information + */ + public void enrollAttendeetoRegister(ProjectStaff projectStaff, RequestInfo requestInfo, Individual individual) { + log.info("Match Found for Attendee Role"); + String tenantId = projectStaff.getTenantId(); + + // Get the employee details for the individual + List employeeList = hrmsUtil.getEmployee(tenantId, Collections.singletonList(individual.getId()), requestInfo); + if (employeeList.isEmpty()) + throw new CustomException("NO_EMPLOYEE_FOUND", "No Employee found for Individual Id - " + individual.getId()); + + // Get the reportingToUuid for the employee + String reportingToUuid; + if (!employeeList.get(0).getAssignments().isEmpty()) + reportingToUuid = employeeList.get(0).getAssignments().get(0).getReportingTo(); + else + throw new CustomException("INDIVIDUAL_REPORTING_TO_INVALID", "Did not find reportingTo Uuid in HRMS Employee object"); + + // Get the individual details for the reportingToUuid + IndividualSearch individualSearch = IndividualSearch.builder().userUuid(Collections.singletonList(reportingToUuid)).build(); + List individualList = individualServiceUtil.getIndividualDetailsFromSearchCriteria(individualSearch, requestInfo, tenantId); + + if (individualList.isEmpty()) + throw new CustomException("INVALID_STAFF_ID", "No Individual found for the reportingTo Uuid - " + reportingToUuid); + + Individual reportingToIndividual = individualList.get(0); + + // Get the attendance registers for the project and staff + AttendanceRegisterSearchCriteria searchCriteria = AttendanceRegisterSearchCriteria.builder().staffId(reportingToIndividual.getId()).referenceId(projectStaff.getProjectId()).build(); + List attendanceRegisters = registerRepository.getRegister(searchCriteria); + + if (attendanceRegisters.isEmpty()) + throw new CustomException("NO_REGISTER_FOUND", "No Register found with project Id - " + projectStaff.getProjectId() + "and Staff Id - " + reportingToIndividual.getId()); + + String registerId = attendanceRegisters.get(0).getId(); + + // Enroll the attendee to the register + IndividualEntry individualEntry = IndividualEntry.builder().individualId(individual.getId()).registerId(registerId).tenantId(projectStaff.getTenantId()).build(); + AttendeeCreateRequest attendeeCreateRequest = AttendeeCreateRequest.builder().attendees(Collections.singletonList(individualEntry)).requestInfo(requestInfo).build(); + AttendeeCreateRequest enrichedAttendeeCreateRequest = attendeeService.createAttendee(attendeeCreateRequest); + + if (enrichedAttendeeCreateRequest.getAttendees().isEmpty()) + throw new CustomException("UNABLE_TO_ENROLL_ATTENDEE", "Unable to enroll attendee with the given criteria"); + + log.info("Successfully created Attendee with Attendee Id - " + individual.getId()); + } + + + /** + * Gets the Employee for the given list of uuids and tenantId of employees + * @param tenantId + * @param project + * @param requestInfo + * @return + */ + public List getProject(String tenantId, Project project, RequestInfo requestInfo){ + + StringBuilder url = getProjectURL(tenantId); + ProjectRequest projectRequest = ProjectRequest.builder().projects(Collections.singletonList(project)).requestInfo(requestInfo).build(); + ProjectResponse projectResponse = serviceRequestClient.fetchResult(url,projectRequest,ProjectResponse.class); + + return projectResponse.getProject(); + + } + + /** + * Gets the Employee for the given list of uuids and tenantId of employees + * @param tenantId + * @param projectStaffSearch + * @param requestInfo + * @return + */ + public List getProjectStaff(String tenantId, ProjectStaffSearch projectStaffSearch, RequestInfo requestInfo){ + + StringBuilder url = getProjectStaffURL(tenantId); + ProjectStaffSearchRequest projectStaffSearchRequest = ProjectStaffSearchRequest.builder().projectStaff(projectStaffSearch).requestInfo(requestInfo).build(); + ProjectStaffBulkResponse projectStaffBulkResponse = serviceRequestClient.fetchResult(url, projectStaffSearchRequest, ProjectStaffBulkResponse.class); + + return projectStaffBulkResponse.getProjectStaff(); + + } + + /** + * Gets the Employee for the given list of uuids and tenantId of employees + * @param tenantId + * @param registerIds + * @param requestInfo + * @return + */ + public Map getregisterIdVsProjectIdMap(String tenantId, List registerIds, RequestInfo requestInfo){ + + AttendanceRegisterSearchCriteria searchCriteria = AttendanceRegisterSearchCriteria.builder().ids(registerIds).build(); + List attendanceRegisters = registerRepository.getRegister(searchCriteria); + Map registerIdVsProjectId = attendanceRegisters.stream() + .collect(Collectors.toMap(AttendanceRegister::getId, AttendanceRegister::getReferenceId)); + + return registerIdVsProjectId; + } + + + /** + * Builds Project Staff search URL + * @param tenantId + * @return URL + */ + public StringBuilder getProjectStaffURL(String tenantId) + { + StringBuilder builder = new StringBuilder(config.getProjectHost()); + builder.append(config.getProjectStaffSearchEndpoint()).append(LIMIT_OFFSET); + builder.append("&tenantId=").append(tenantId); + return builder; + } + + /** + * Builds Project search URL + * @param tenantId + * @return URL + */ + public StringBuilder getProjectURL(String tenantId) + { + StringBuilder builder = new StringBuilder(config.getProjectHost()); + builder.append(config.getProjectSearchEndpoint()).append(LIMIT_OFFSET); + builder.append("&tenantId=").append(tenantId); + return builder; + } + +} \ No newline at end of file diff --git a/backend/attendance/src/main/java/org/egov/validator/AttendanceLogServiceValidator.java b/backend/attendance/src/main/java/org/egov/validator/AttendanceLogServiceValidator.java index 756daa3651..4d38d5c2c5 100644 --- a/backend/attendance/src/main/java/org/egov/validator/AttendanceLogServiceValidator.java +++ b/backend/attendance/src/main/java/org/egov/validator/AttendanceLogServiceValidator.java @@ -17,6 +17,7 @@ import org.egov.web.models.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; import java.time.Instant; import java.util.*; @@ -364,20 +365,22 @@ public void validateSearchAttendanceLogRequest(RequestInfoWrapper requestInfoWra // Verify given parameters validateSearchAttendanceLogParameters(requestInfoWrapper, searchCriteria); - // Fetch register for given Id - List attendanceRegisters = fetchRegisterWithId(searchCriteria.getRegisterId()); + if(!StringUtils.isBlank(searchCriteria.getRegisterId())) { + // Fetch register for given Id + List attendanceRegisters = fetchRegisterWithId(searchCriteria.getRegisterId()); - if (attendanceRegisters == null || attendanceRegisters.isEmpty()) { - throw new CustomException("INVALID_REGISTERID", "Register Not found "); - } + if (attendanceRegisters == null || attendanceRegisters.isEmpty()) { + throw new CustomException("INVALID_REGISTERID", "Register Not found "); + } - // Verify TenantId association with register - validateTenantIdAssociationWithRegisterId(attendanceRegisters.get(0), searchCriteria.getTenantId()); + // Verify TenantId association with register + validateTenantIdAssociationWithRegisterId(attendanceRegisters.get(0), searchCriteria.getTenantId()); - // Verify the Logged-in user is associated to the given register. - String individualId = individualServiceUtil.getIndividualDetailsFromUserId(requestInfoWrapper.getRequestInfo().getUserInfo().getId(), requestInfoWrapper.getRequestInfo(), searchCriteria.getTenantId()).get(0).getId(); - validateLoggedInUser(individualId, searchCriteria.getRegisterId()); + // Verify the Logged-in user is associated to the given register. + String individualId = individualServiceUtil.getIndividualDetailsFromUserId(requestInfoWrapper.getRequestInfo().getUserInfo().getId(), requestInfoWrapper.getRequestInfo(), searchCriteria.getTenantId()).get(0).getId(); + validateLoggedInUser(individualId, searchCriteria.getRegisterId()); + } log.info("Attendance log search request validated successfully"); } @@ -395,9 +398,9 @@ private void validateSearchAttendanceLogParameters(RequestInfoWrapper requestInf log.error("Attendance log search, Tenant is mandatory"); throw new CustomException("TENANT_ID", "Tenant is mandatory"); } - if (StringUtils.isBlank(searchCriteria.getRegisterId())) { - log.error("Attendance log search, RegisterId is mandatory"); - throw new CustomException("REGISTER_ID", "RegisterId is mandatory"); + if (StringUtils.isBlank(searchCriteria.getRegisterId()) && CollectionUtils.isEmpty(searchCriteria.getClientReferenceId())) { + log.error("Attendance log search, RegisterId or ClientReferenceId is mandatory"); + throw new CustomException("REGISTER_ID_OR_CLIENT_REFERENCE_ID", "RegisterId or ClientReferenceId is mandatory"); } // Throw exception if required parameters are missing diff --git a/backend/attendance/src/main/java/org/egov/validator/AttendanceServiceValidator.java b/backend/attendance/src/main/java/org/egov/validator/AttendanceServiceValidator.java index 3d0d5e7508..37ea4e14d9 100644 --- a/backend/attendance/src/main/java/org/egov/validator/AttendanceServiceValidator.java +++ b/backend/attendance/src/main/java/org/egov/validator/AttendanceServiceValidator.java @@ -118,7 +118,7 @@ public void validateUpdateAttendanceRegisterRequest(AttendanceRegisterRequest re } /* Validates attendance register data in update request against attendance register data fetched from database */ - public void validateUpdateAgainstDB(AttendanceRegisterRequest attendanceRegisterRequest, List attendanceRegistersFromDB) { + public void validateUpdateAgainstDB(AttendanceRegisterRequest attendanceRegisterRequest, List attendanceRegistersFromDB, Boolean registerFirstStaffInsertEnabled) { if (CollectionUtils.isEmpty(attendanceRegistersFromDB)) { log.error("The record that you are trying to update does not exists in the system"); throw new CustomException("INVALID_REGISTER_MODIFY", "The record that you are trying to update does not exists in the system"); @@ -140,7 +140,7 @@ public void validateUpdateAgainstDB(AttendanceRegisterRequest attendanceRegister log.error("The user " + attendanceRegisterRequest.getRequestInfo().getUserInfo().getUuid() + " does not have permission to modify the register " + registerFromDB.getId()); throw new CustomException("INVALID_REGISTER_MODIFY", "The user " + attendanceRegisterRequest.getRequestInfo().getUserInfo().getUuid() + " does not have permission to modify the register " + registerFromDB.getId()); } - } else { + } else if(registerFirstStaffInsertEnabled) { log.error("The user " + attendanceRegisterRequest.getRequestInfo().getUserInfo().getUuid() + " does not have permission to modify the register " + registerFromDB.getId()); throw new CustomException("INVALID_REGISTER_MODIFY", "The user " + attendanceRegisterRequest.getRequestInfo().getUserInfo().getUuid() + " does not have permission to modify the register " + registerFromDB.getId()); } diff --git a/backend/attendance/src/main/java/org/egov/validator/AttendeeServiceValidator.java b/backend/attendance/src/main/java/org/egov/validator/AttendeeServiceValidator.java index 3427c1c6d6..253251c5ae 100644 --- a/backend/attendance/src/main/java/org/egov/validator/AttendeeServiceValidator.java +++ b/backend/attendance/src/main/java/org/egov/validator/AttendeeServiceValidator.java @@ -4,13 +4,19 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.egov.common.contract.request.RequestInfo; +import org.egov.common.models.project.ProjectStaff; +import org.egov.common.models.project.ProjectStaffSearch; +import org.egov.config.AttendanceServiceConfiguration; +import org.egov.repository.RegisterRepository; +import org.egov.service.StaffService; import org.egov.tracer.model.CustomException; +import org.egov.util.HRMSUtil; import org.egov.util.IndividualServiceUtil; import org.egov.util.MDMSUtils; -import org.egov.web.models.AttendanceRegister; -import org.egov.web.models.AttendeeCreateRequest; -import org.egov.web.models.AttendeeDeleteRequest; -import org.egov.web.models.IndividualEntry; +import org.egov.util.ProjectStaffUtil; +import org.egov.web.models.*; +import org.egov.web.models.Hrms.Assignment; +import org.egov.web.models.Hrms.Employee; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; @@ -19,8 +25,7 @@ import java.util.*; import java.util.stream.Collectors; -import static org.egov.util.AttendanceServiceConstants.MASTER_TENANTS; -import static org.egov.util.AttendanceServiceConstants.MDMS_TENANT_MODULE_NAME; +import static org.egov.util.AttendanceServiceConstants.*; @Component @Slf4j @@ -32,6 +37,17 @@ public class AttendeeServiceValidator { @Autowired private IndividualServiceUtil individualServiceUtil; + @Autowired + private HRMSUtil hrmsUtil; + @Autowired + private StaffService staffService; + + @Autowired + private AttendanceServiceConfiguration config; + + @Autowired + private ProjectStaffUtil projectStaffUtil; + public void validateAttendeeCreateRequestParameters(AttendeeCreateRequest attendeeCreateRequest) { List attendeeList = attendeeCreateRequest.getAttendees(); Map errorMap = new HashMap<>(); @@ -370,6 +386,75 @@ private void validateMDMSData(String tenantId, Object mdmsData, Map validIndividualEntries = new ArrayList<>(); + + //extracting all registerIDs coming in the request + List registerIds = attendeeCreateRequest.getAttendees().stream() + .map(IndividualEntry::getRegisterId) + .collect(Collectors.toList()); + + //creating a register Id to First Staff Map + Map registerIdToFirstStaffMap = staffService.fetchRegisterIdtoFirstStaffMap(tenantId,registerIds); + + //fetching a register Id to Project Id Map + Map registerIdVsProjectIdMap = projectStaffUtil.getregisterIdVsProjectIdMap(tenantId, registerIds, requestInfo); + + //Fetching all the attendees's uuids for hrms search + List userUuids = attendeeCreateRequest.getAttendees().stream() + .map(IndividualEntry::getIndividualId) + .collect(Collectors.toList()); + + //getting the employee List from HRMS Search based on the attendee's uuids + List employeeList = hrmsUtil.getEmployee(tenantId, userUuids, requestInfo); + + Map individualIdVsEmployeeMap = employeeList.stream() + .collect(Collectors.toMap(Employee::getUuid, emp -> emp)); + + //looping through attendees for validating their details + for (IndividualEntry entry : attendeeCreateRequest.getAttendees()) { + try { + + if (!individualIdVsEmployeeMap.containsKey(entry.getIndividualId())) { + throw new CustomException("HRMS_EMPLOYEE_NOT_FOUND", "Employee not present in HRMS for the individual ID - " + entry.getIndividualId()); + } + + //fetch reportingTo uuids from employees assignments + List reportingToList = individualIdVsEmployeeMap.get(entry.getIndividualId()).getAssignments().stream() + .map(Assignment::getReportingTo) + .filter(reportingTo -> reportingTo != null && !reportingTo.isEmpty()) + .collect(Collectors.toList()); + + //fetch the first staff's User Id + String reportersUuid = registerIdToFirstStaffMap.get(entry.getRegisterId()).getUserId(); + + List reportersEmployeeList = hrmsUtil.getEmployee(tenantId, Collections.singletonList(reportersUuid), requestInfo); + if(reportersEmployeeList.isEmpty()) + throw new CustomException("FAILED_TO_FETCH_REPORTERS_UUID", "Failed to fetch reporters hrms uuid for userserviceId - " + reportersUuid); + + if (!reportingToList.contains(reportersEmployeeList.get(0).getUser().getUserServiceUuid())) { + //throw validation error if attendee's reportingTo is not First Staff of the Register + throw new CustomException("REPORTING_STAFF_INCORRECT_FOR_ATTENDEE", "Attendees reporting uuid does not match with for attendee uuid - " + entry.getIndividualId()); + } + validIndividualEntries.add(entry); + } + catch (Exception e) + { + log.error(e.toString()); + } + } + attendeeCreateRequest.setAttendees(validIndividualEntries); + } } diff --git a/backend/attendance/src/main/java/org/egov/web/controllers/AttendanceLogApiController.java b/backend/attendance/src/main/java/org/egov/web/controllers/AttendanceLogApiController.java index 102be7397d..4f881f8f0d 100644 --- a/backend/attendance/src/main/java/org/egov/web/controllers/AttendanceLogApiController.java +++ b/backend/attendance/src/main/java/org/egov/web/controllers/AttendanceLogApiController.java @@ -2,10 +2,15 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.annotations.ApiParam; +import org.egov.common.contract.response.ResponseInfo; +import org.egov.config.AttendanceLogConfiguration; +import org.egov.common.producer.Producer; import org.egov.service.AttendanceLogService; +import org.egov.util.ResponseInfoFactory; import org.egov.web.models.AttendanceLogRequest; import org.egov.web.models.AttendanceLogResponse; import org.egov.web.models.AttendanceLogSearchCriteria; +import org.egov.web.models.AttendanceLogSearchRequest; import org.egov.web.models.RequestInfoWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -30,15 +35,41 @@ public class AttendanceLogApiController { @Autowired private AttendanceLogService attendanceLogService; + @Autowired + private ResponseInfoFactory responseInfoFactory; + + @Autowired + private AttendanceLogConfiguration attendanceLogConfiguration; + + @Autowired + private HttpServletRequest httpServletRequest; + + @Autowired + private Producer producer; + @RequestMapping(value = "/_create", method = RequestMethod.POST) public ResponseEntity attendanceLogV1CreatePOST(@ApiParam(value = "", allowableValues = "application/json") @RequestHeader(value = "Content-Type", required = false) String contentType, @ApiParam(value = "") @Valid @RequestBody AttendanceLogRequest attendanceLogRequest) { AttendanceLogResponse attendanceLogResponse = attendanceLogService.createAttendanceLog(attendanceLogRequest); return new ResponseEntity(attendanceLogResponse, HttpStatus.OK); } + @RequestMapping(value = "/bulk/_create", method = RequestMethod.POST) + public ResponseEntity attendanceLogV1BulkCreatePost(@ApiParam(value = "", allowableValues = "application/json") @RequestHeader(value = "Content-Type", required = false) String contentType, @ApiParam(value = "") @Valid @RequestBody AttendanceLogRequest attendanceLogRequest) { + attendanceLogRequest.getRequestInfo().setApiId(httpServletRequest.getRequestURI()); + attendanceLogService.putInCache(attendanceLogRequest.getAttendance()); + producer.push(attendanceLogConfiguration.getCreateAttendanceLogBulkTopic(), attendanceLogRequest); + return ResponseEntity.status(HttpStatus.ACCEPTED).body(responseInfoFactory.createResponseInfoFromRequestInfo(attendanceLogRequest.getRequestInfo(), true)); + } @RequestMapping(value = "/_search", method = RequestMethod.POST) - public ResponseEntity attendanceLogV1SearchPOST(@Valid @ModelAttribute AttendanceLogSearchCriteria searchCriteria, @ApiParam(value = "") @Valid @RequestBody RequestInfoWrapper requestInfoWrapper) { - AttendanceLogResponse attendanceLogResponse = attendanceLogService.searchAttendanceLog(requestInfoWrapper, searchCriteria); + public ResponseEntity attendanceLogV1SearchPOST(@Valid @ModelAttribute AttendanceLogSearchCriteria searchCriteria, @ApiParam(value = "") @Valid @RequestBody AttendanceLogSearchRequest attendanceLogSearchRequest) { + AttendanceLogResponse attendanceLogResponse = attendanceLogService.searchAttendanceLog( + RequestInfoWrapper.builder() + .requestInfo(attendanceLogSearchRequest.getRequestInfo()) + .build(), + attendanceLogSearchRequest.getAttendanceLogSearchCriteria() != null + ? attendanceLogSearchRequest.getAttendanceLogSearchCriteria() + : searchCriteria + ); return new ResponseEntity(attendanceLogResponse, HttpStatus.OK); } @@ -48,4 +79,12 @@ public ResponseEntity attendanceLogV1UpdatePOST(@ApiParam return new ResponseEntity(attendanceLogResponse, HttpStatus.OK); } + @RequestMapping(value = "/bulk/_update", method = RequestMethod.POST) + public ResponseEntity attendanceLogV1BulkUpdatePost(@ApiParam(value = "", allowableValues = "application/json") @RequestHeader(value = "Content-Type", required = false) String contentType, @ApiParam(value = "") @Valid @RequestBody AttendanceLogRequest attendanceLogRequest) { + attendanceLogRequest.getRequestInfo().setApiId(httpServletRequest.getRequestURI()); + attendanceLogService.putInCache(attendanceLogRequest.getAttendance()); + producer.push(attendanceLogConfiguration.getUpdateAttendanceLogBulkTopic(), attendanceLogRequest); + return ResponseEntity.status(HttpStatus.ACCEPTED).body(responseInfoFactory.createResponseInfoFromRequestInfo(attendanceLogRequest.getRequestInfo(), true)); + } + } diff --git a/backend/attendance/src/main/java/org/egov/web/models/AttendanceLog.java b/backend/attendance/src/main/java/org/egov/web/models/AttendanceLog.java index 0deeac5eca..1ece72e839 100644 --- a/backend/attendance/src/main/java/org/egov/web/models/AttendanceLog.java +++ b/backend/attendance/src/main/java/org/egov/web/models/AttendanceLog.java @@ -26,6 +26,9 @@ public class AttendanceLog { @JsonProperty("id") private String id = null; + @JsonProperty("clientReferenceId") + private String clientReferenceId = null; + @JsonProperty("registerId") private String registerId = null; @@ -51,6 +54,9 @@ public class AttendanceLog { @JsonProperty("auditDetails") private AuditDetails auditDetails = null; + @JsonProperty("clientAuditDetails") + private AuditDetails clientAuditDetails = null; + @JsonProperty("additionalDetails") private Object additionalDetails = null; diff --git a/backend/attendance/src/main/java/org/egov/web/models/AttendanceLogSearchCriteria.java b/backend/attendance/src/main/java/org/egov/web/models/AttendanceLogSearchCriteria.java index 9c225a3afe..51d2073cbb 100644 --- a/backend/attendance/src/main/java/org/egov/web/models/AttendanceLogSearchCriteria.java +++ b/backend/attendance/src/main/java/org/egov/web/models/AttendanceLogSearchCriteria.java @@ -17,6 +17,9 @@ public class AttendanceLogSearchCriteria { @JsonProperty("ids") private List ids; + @JsonProperty("clientReferenceId") + private List clientReferenceId; + @JsonProperty("tenantId") private String tenantId; diff --git a/backend/attendance/src/main/java/org/egov/web/models/AttendanceLogSearchRequest.java b/backend/attendance/src/main/java/org/egov/web/models/AttendanceLogSearchRequest.java new file mode 100644 index 0000000000..eecb7dc653 --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/web/models/AttendanceLogSearchRequest.java @@ -0,0 +1,29 @@ +package org.egov.web.models; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.egov.common.contract.request.RequestInfo; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@JsonIgnoreProperties(ignoreUnknown = true) +public class AttendanceLogSearchRequest { + + @JsonProperty("RequestInfo") + @NotNull + @Valid + private RequestInfo requestInfo = null; + + @JsonProperty("attendance") + @Valid + private AttendanceLogSearchCriteria attendanceLogSearchCriteria = null; +} diff --git a/backend/attendance/src/main/java/org/egov/web/models/Hrms/Assignment.java b/backend/attendance/src/main/java/org/egov/web/models/Hrms/Assignment.java new file mode 100644 index 0000000000..36ba14c4e9 --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/web/models/Hrms/Assignment.java @@ -0,0 +1,97 @@ +/* + * eGov suite of products aim to improve the internal efficiency,transparency, + * accountability and the service delivery of the government organizations. + * + * Copyright (C) 2016 eGovernments Foundation + * + * The updated version of eGov suite of products as by eGovernments Foundation + * is available at http://www.egovernments.org + * + * 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 + * 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 http://www.gnu.org/licenses/ or + * http://www.gnu.org/licenses/gpl.html . + * + * In addition to the terms of the GPL license to be adhered to in using this + * program, the following additional terms are to be complied with: + * + * 1) All versions of this program, verbatim or modified must carry this + * Legal Notice. + * + * 2) Any misrepresentation of the origin of the material is prohibited. It + * is required that all modified versions of this material be marked in + * reasonable ways as different from the original version. + * + * 3) This license does not grant any rights to any user of the program + * with regards to rights under trademark law for use of the trade names + * or trademarks of eGovernments Foundation. + * + * In case of any queries, you can reach eGovernments Foundation at contact@egovernments.org. + */ + +package org.egov.web.models.Hrms; + +import com.fasterxml.jackson.annotation.JsonProperty; +import digit.models.coremodels.AuditDetails; +import lombok.*; +import org.hibernate.validator.constraints.SafeHtml; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotNull; + +@Validated +@EqualsAndHashCode(exclude = {"auditDetails"}) +@AllArgsConstructor +@Builder +@Getter +@NoArgsConstructor +@Setter +@ToString +public class Assignment { + + @SafeHtml + private String id; + + private Long position; + + @SafeHtml + @NotNull + private String designation; + + @SafeHtml + @NotNull + private String department; + + @NotNull + private Long fromDate; + + private Long toDate; + + @SafeHtml + private String govtOrderNumber; + + @SafeHtml + private String tenantid; + + @SafeHtml + private String reportingTo; + + @JsonProperty("isHOD") + private Boolean isHOD=false; + + @NotNull + @JsonProperty("isCurrentAssignment") + private Boolean isCurrentAssignment; + + private AuditDetails auditDetails; + +} \ No newline at end of file diff --git a/backend/attendance/src/main/java/org/egov/web/models/Hrms/DeactivationDetails.java b/backend/attendance/src/main/java/org/egov/web/models/Hrms/DeactivationDetails.java new file mode 100644 index 0000000000..793504a87e --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/web/models/Hrms/DeactivationDetails.java @@ -0,0 +1,46 @@ +package org.egov.web.models.Hrms; + +import digit.models.coremodels.AuditDetails; +import lombok.*; +import org.hibernate.validator.constraints.SafeHtml; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotNull; + +@Validated +@EqualsAndHashCode(exclude = {"auditDetails"}) +@AllArgsConstructor +@Getter +@NoArgsConstructor +@Setter +@ToString +@Builder +public class DeactivationDetails { + + @SafeHtml + private String id; + + @SafeHtml + @NotNull + private String reasonForDeactivation; + + @SafeHtml + private String orderNo; + + @SafeHtml + private String remarks; + + @NotNull + private Long effectiveFrom; + + @SafeHtml + private String tenantId; + + private AuditDetails auditDetails; + + + + +} + + diff --git a/backend/attendance/src/main/java/org/egov/web/models/Hrms/DepartmentalTest.java b/backend/attendance/src/main/java/org/egov/web/models/Hrms/DepartmentalTest.java new file mode 100644 index 0000000000..b8480038d2 --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/web/models/Hrms/DepartmentalTest.java @@ -0,0 +1,80 @@ +/* + * eGov suite of products aim to improve the internal efficiency,transparency, + * accountability and the service delivery of the government organizations. + * + * Copyright (C) 2016 eGovernments Foundation + * + * The updated version of eGov suite of products as by eGovernments Foundation + * is available at http://www.egovernments.org + * + * 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 + * 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 http://www.gnu.org/licenses/ or + * http://www.gnu.org/licenses/gpl.html . + * + * In addition to the terms of the GPL license to be adhered to in using this + * program, the following additional terms are to be complied with: + * + * 1) All versions of this program, verbatim or modified must carry this + * Legal Notice. + * + * 2) Any misrepresentation of the origin of the material is prohibited. It + * is required that all modified versions of this material be marked in + * reasonable ways as different from the original version. + * + * 3) This license does not grant any rights to any user of the program + * with regards to rights under trademark law for use of the trade names + * or trademarks of eGovernments Foundation. + * + * In case of any queries, you can reach eGovernments Foundation at contact@egovernments.org. + */ + +package org.egov.web.models.Hrms; + +import digit.models.coremodels.AuditDetails; +import lombok.*; +import org.hibernate.validator.constraints.SafeHtml; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotNull; + +@Validated +@EqualsAndHashCode(exclude = {"auditDetails"}) +@Builder +@AllArgsConstructor +@Getter +@NoArgsConstructor +@Setter +@ToString +public class DepartmentalTest { + + @SafeHtml + private String id; + + @SafeHtml + @NotNull + private String test; + + @NotNull + private Long yearOfPassing; + + @SafeHtml + private String remarks; + + @SafeHtml + private String tenantId; + + private AuditDetails auditDetails; + + private Boolean isActive; + +} \ No newline at end of file diff --git a/backend/attendance/src/main/java/org/egov/web/models/Hrms/EducationalQualification.java b/backend/attendance/src/main/java/org/egov/web/models/Hrms/EducationalQualification.java new file mode 100644 index 0000000000..ece8bf6942 --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/web/models/Hrms/EducationalQualification.java @@ -0,0 +1,88 @@ +/* + * eGov suite of products aim to improve the internal efficiency,transparency, + * accountability and the service delivery of the government organizations. + * + * Copyright (C) 2016 eGovernments Foundation + * + * The updated version of eGov suite of products as by eGovernments Foundation + * is available at http://www.egovernments.org + * + * 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 + * 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 http://www.gnu.org/licenses/ or + * http://www.gnu.org/licenses/gpl.html . + * + * In addition to the terms of the GPL license to be adhered to in using this + * program, the following additional terms are to be complied with: + * + * 1) All versions of this program, verbatim or modified must carry this + * Legal Notice. + * + * 2) Any misrepresentation of the origin of the material is prohibited. It + * is required that all modified versions of this material be marked in + * reasonable ways as different from the original version. + * + * 3) This license does not grant any rights to any user of the program + * with regards to rights under trademark law for use of the trade names + * or trademarks of eGovernments Foundation. + * + * In case of any queries, you can reach eGovernments Foundation at contact@egovernments.org. + */ + +package org.egov.web.models.Hrms; + +import digit.models.coremodels.AuditDetails; +import lombok.*; +import org.hibernate.validator.constraints.SafeHtml; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotNull; + +@Validated +@EqualsAndHashCode(exclude = {"auditDetails"}) +@Builder +@AllArgsConstructor +@Getter +@NoArgsConstructor +@Setter +@ToString +public class EducationalQualification { + + @SafeHtml + private String id; + + @SafeHtml + @NotNull + private String qualification; + + @SafeHtml + @NotNull + private String stream; + + @NotNull + private Long yearOfPassing; + + @SafeHtml + private String university; + + @SafeHtml + private String remarks; + + @SafeHtml + private String tenantId; + + private AuditDetails auditDetails; + + private Boolean isActive; + + +} \ No newline at end of file diff --git a/backend/attendance/src/main/java/org/egov/web/models/Hrms/Employee.java b/backend/attendance/src/main/java/org/egov/web/models/Hrms/Employee.java new file mode 100644 index 0000000000..71e5a333c3 --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/web/models/Hrms/Employee.java @@ -0,0 +1,133 @@ +/* + * eGov suite of products aim to improve the internal efficiency,transparency, + * accountability and the service delivery of the government organizations. + * + * Copyright (C) 2016 eGovernments Foundation + * + * The updated version of eGov suite of products as by eGovernments Foundation + * is available at http://www.egovernments.org + * + * 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 + * 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 http://www.gnu.org/licenses/ or + * http://www.gnu.org/licenses/gpl.html . + * + * In addition to the terms of the GPL license to be adhered to in using this + * program, the following additional terms are to be complied with: + * + * 1) All versions of this program, verbatim or modified must carry this + * Legal Notice. + * + * 2) Any misrepresentation of the origin of the material is prohibited. It + * is required that all modified versions of this material be marked in + * reasonable ways as different from the original version. + * + * 3) This license does not grant any rights to any user of the program + * with regards to rights under trademark law for use of the trade names + * or trademarks of eGovernments Foundation. + * + * In case of any queries, you can reach eGovernments Foundation at contact@egovernments.org. + */ + +package org.egov.web.models.Hrms; + +import digit.models.coremodels.AuditDetails; +import lombok.*; +import org.hibernate.validator.constraints.NotEmpty; +import org.hibernate.validator.constraints.SafeHtml; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.util.ArrayList; +import java.util.List; + +@Validated +@AllArgsConstructor +@EqualsAndHashCode +@Getter +@NoArgsConstructor +@Setter +@ToString +@Builder +public class Employee { + + private Long id; + + @SafeHtml + @Size(max = 1024) + private String uuid; + + @SafeHtml + @Size(min = 1, max = 256) + private String code; + + @SafeHtml + @Size(max = 250) + private String employeeStatus; + + @SafeHtml + @NotNull + @Size(max = 250) + private String employeeType; + + private Long dateOfAppointment; + + @Valid + @NotEmpty + @Size(min = 1,max = 50) + private List jurisdictions = new ArrayList<>(); + + + @Valid + private List assignments = new ArrayList<>(); + + @Valid + @Size(max=25) + private List serviceHistory = new ArrayList<>(); + + + private Boolean IsActive; + + @Valid + @Size(max=25) + private List education = new ArrayList<>(); + + @Valid + @Size(max=25) + private List tests = new ArrayList<>(); + + @SafeHtml + @NotNull + @Size(max = 250) + private String tenantId; + + @Valid + @Size(max=50) + private List documents = new ArrayList<>(); + + @Valid + private List deactivationDetails = new ArrayList<>(); + + private List reactivationDetails = new ArrayList<>(); + + private AuditDetails auditDetails; + + private Boolean reActivateEmployee; + + @Valid + @NotNull + private User user; + + +} \ No newline at end of file diff --git a/backend/attendance/src/main/java/org/egov/web/models/Hrms/EmployeeDocument.java b/backend/attendance/src/main/java/org/egov/web/models/Hrms/EmployeeDocument.java new file mode 100644 index 0000000000..af32d2fede --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/web/models/Hrms/EmployeeDocument.java @@ -0,0 +1,78 @@ +/* + * eGov suite of products aim to improve the internal efficiency,transparency, + * accountability and the service delivery of the government organizations. + * + * Copyright (C) 2016 eGovernments Foundation + * + * The updated version of eGov suite of products as by eGovernments Foundation + * is available at http://www.egovernments.org + * + * 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 + * 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 http://www.gnu.org/licenses/ or + * http://www.gnu.org/licenses/gpl.html . + * + * In addition to the terms of the GPL license to be adhered to in using this + * program, the following additional terms are to be complied with: + * + * 1) All versions of this program, verbatim or modified must carry this + * Legal Notice. + * + * 2) Any misrepresentation of the origin of the material is prohibited. It + * is required that all modified versions of this material be marked in + * reasonable ways as different from the original version. + * + * 3) This license does not grant any rights to any user of the program + * with regards to rights under trademark law for use of the trade names + * or trademarks of eGovernments Foundation. + * + * In case of any queries, you can reach eGovernments Foundation at contact@egovernments.org. + */ + +package org.egov.web.models.Hrms; + +import digit.models.coremodels.AuditDetails; +import lombok.*; +import org.hibernate.validator.constraints.SafeHtml; +import org.springframework.validation.annotation.Validated; + +@Validated +@EqualsAndHashCode(exclude = {"auditDetails"}) +@AllArgsConstructor +@Getter +@NoArgsConstructor +@Setter +@ToString +@Builder +public class EmployeeDocument { + + @SafeHtml + private String id; + + @SafeHtml + private String documentName; + + @SafeHtml + private String documentId; + + private EmployeeDocumentReferenceType referenceType; + + @SafeHtml + private String referenceId; + + @SafeHtml + private String tenantId; + + private AuditDetails auditDetails; + + +} \ No newline at end of file diff --git a/backend/attendance/src/main/java/org/egov/web/models/Hrms/EmployeeDocumentReferenceType.java b/backend/attendance/src/main/java/org/egov/web/models/Hrms/EmployeeDocumentReferenceType.java new file mode 100644 index 0000000000..f175ffa538 --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/web/models/Hrms/EmployeeDocumentReferenceType.java @@ -0,0 +1,31 @@ +package org.egov.web.models.Hrms; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +public enum EmployeeDocumentReferenceType { + HEADER("HEADER"), ASSIGNMENT("ASSIGNMENT"), JURISDICTION("JURISDICTION"), SERVICE("SERVICE"), + EDUCATION("EDUCATION"), TEST("TEST"), DEACTIVATION("DEACTIVATION"); + + private String value; + + EmployeeDocumentReferenceType(String value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return name(); + } + + @JsonCreator + public static EmployeeDocumentReferenceType fromValue(String passedValue) { + for (EmployeeDocumentReferenceType obj : EmployeeDocumentReferenceType.values()) { + if (String.valueOf(obj.value).equals(passedValue.toUpperCase())) { + return obj; + } + } + return null; + } +} diff --git a/backend/attendance/src/main/java/org/egov/web/models/Hrms/EmployeeResponse.java b/backend/attendance/src/main/java/org/egov/web/models/Hrms/EmployeeResponse.java new file mode 100644 index 0000000000..6415b7bb84 --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/web/models/Hrms/EmployeeResponse.java @@ -0,0 +1,71 @@ +/* + * eGov suite of products aim to improve the internal efficiency,transparency, + * accountability and the service delivery of the government organizations. + * + * Copyright (C) 2016 eGovernments Foundation + * + * The updated version of eGov suite of products as by eGovernments Foundation + * is available at http://www.egovernments.org + * + * 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 + * 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 http://www.gnu.org/licenses/ or + * http://www.gnu.org/licenses/gpl.html . + * + * In addition to the terms of the GPL license to be adhered to in using this + * program, the following additional terms are to be complied with: + * + * 1) All versions of this program, verbatim or modified must carry this + * Legal Notice. + * + * 2) Any misrepresentation of the origin of the material is prohibited. It + * is required that all modified versions of this material be marked in + * reasonable ways as different from the original version. + * + * 3) This license does not grant any rights to any user of the program + * with regards to rights under trademark law for use of the trade names + * or trademarks of eGovernments Foundation. + * + * In case of any queries, you can reach eGovernments Foundation at contact@egovernments.org. + */ + +package org.egov.web.models.Hrms; + +import java.util.List; + +import org.egov.common.contract.response.ResponseInfo; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +@Builder +@AllArgsConstructor +@EqualsAndHashCode +@Getter +@NoArgsConstructor +@Setter +@ToString +public class EmployeeResponse { + + @JsonProperty("ResponseInfo") + private ResponseInfo responseInfo; + + @JsonProperty("Employees") + private List employees; + +} \ No newline at end of file diff --git a/backend/attendance/src/main/java/org/egov/web/models/Hrms/Jurisdiction.java b/backend/attendance/src/main/java/org/egov/web/models/Hrms/Jurisdiction.java new file mode 100644 index 0000000000..0fb94e138a --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/web/models/Hrms/Jurisdiction.java @@ -0,0 +1,86 @@ +/* + * eGov suite of products aim to improve the internal efficiency,transparency, + * accountability and the service delivery of the government organizations. + * + * Copyright (C) 2016 eGovernments Foundation + * + * The updated version of eGov suite of products as by eGovernments Foundation + * is available at http://www.egovernments.org + * + * 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 + * 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 http://www.gnu.org/licenses/ or + * http://www.gnu.org/licenses/gpl.html . + * + * In addition to the terms of the GPL license to be adhered to in using this + * program, the following additional terms are to be complied with: + * + * 1) All versions of this program, verbatim or modified must carry this + * Legal Notice. + * + * 2) Any misrepresentation of the origin of the material is prohibited. It + * is required that all modified versions of this material be marked in + * reasonable ways as different from the original version. + * + * 3) This license does not grant any rights to any user of the program + * with regards to rights under trademark law for use of the trade names + * or trademarks of eGovernments Foundation. + * + * In case of any queries, you can reach eGovernments Foundation at contact@egovernments.org. + */ + +package org.egov.web.models.Hrms; + +import digit.models.coremodels.AuditDetails; +import lombok.*; +import org.hibernate.validator.constraints.SafeHtml; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +@Validated +@EqualsAndHashCode(exclude = {"auditDetails"}) +@Builder +@AllArgsConstructor +@Getter +@NoArgsConstructor +@Setter +@ToString +public class Jurisdiction { + + @SafeHtml + private String id; + + @SafeHtml + @NotNull + @Size(min=2, max=100) + private String hierarchy; + + @SafeHtml + @NotNull + @Size(min=2, max=100) + private String boundary; + + @SafeHtml + @NotNull + @Size(max=256) + private String boundaryType; + + @SafeHtml + private String tenantId; + + private AuditDetails auditDetails; + + private Boolean isActive; + +} \ No newline at end of file diff --git a/backend/attendance/src/main/java/org/egov/web/models/Hrms/ReactivationDetails.java b/backend/attendance/src/main/java/org/egov/web/models/Hrms/ReactivationDetails.java new file mode 100644 index 0000000000..406dc46739 --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/web/models/Hrms/ReactivationDetails.java @@ -0,0 +1,46 @@ +package org.egov.web.models.Hrms; + +import digit.models.coremodels.AuditDetails; +import lombok.*; +import org.hibernate.validator.constraints.SafeHtml; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotNull; + +@Validated +@EqualsAndHashCode(exclude = {"auditDetails"}) +@AllArgsConstructor +@Getter +@NoArgsConstructor +@Setter +@ToString +@Builder +public class ReactivationDetails { + + @SafeHtml + private String id; + + @SafeHtml + @NotNull + private String reasonForReactivation; + + @SafeHtml + private String orderNo; + + @SafeHtml + private String remarks; + + @NotNull + private Long effectiveFrom; + + @SafeHtml + private String tenantId; + + private AuditDetails auditDetails; + + + + +} + + diff --git a/backend/attendance/src/main/java/org/egov/web/models/Hrms/ServiceHistory.java b/backend/attendance/src/main/java/org/egov/web/models/Hrms/ServiceHistory.java new file mode 100644 index 0000000000..7e96c802a7 --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/web/models/Hrms/ServiceHistory.java @@ -0,0 +1,83 @@ +/* + * eGov suite of products aim to improve the internal efficiency,transparency, + * accountability and the service delivery of the government organizations. + * + * Copyright (C) 2016 eGovernments Foundation + * + * The updated version of eGov suite of products as by eGovernments Foundation + * is available at http://www.egovernments.org + * + * 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 + * 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 http://www.gnu.org/licenses/ or + * http://www.gnu.org/licenses/gpl.html . + * + * In addition to the terms of the GPL license to be adhered to in using this + * program, the following additional terms are to be complied with: + * + * 1) All versions of this program, verbatim or modified must carry this + * Legal Notice. + * + * 2) Any misrepresentation of the origin of the material is prohibited. It + * is required that all modified versions of this material be marked in + * reasonable ways as different from the original version. + * + * 3) This license does not grant any rights to any user of the program + * with regards to rights under trademark law for use of the trade names + * or trademarks of eGovernments Foundation. + * + * In case of any queries, you can reach eGovernments Foundation at contact@egovernments.org. + */ + +package org.egov.web.models.Hrms; + +import digit.models.coremodels.AuditDetails; +import lombok.*; +import org.hibernate.validator.constraints.SafeHtml; +import org.springframework.validation.annotation.Validated; + +@Validated +@EqualsAndHashCode(exclude = {"auditDetails"}) +@Builder +@AllArgsConstructor +@Getter +@NoArgsConstructor +@Setter +@ToString +public class ServiceHistory { + + @SafeHtml + private String id; + + @SafeHtml + private String serviceStatus; + + private Long serviceFrom; + + private Long serviceTo; + + @SafeHtml + private String orderNo; + + @SafeHtml + private String location; + + @SafeHtml + private String tenantId; + + private Boolean isCurrentPosition; + + private AuditDetails auditDetails; + + + +} \ No newline at end of file diff --git a/backend/attendance/src/main/java/org/egov/web/models/Hrms/User.java b/backend/attendance/src/main/java/org/egov/web/models/Hrms/User.java new file mode 100644 index 0000000000..e91d43c27f --- /dev/null +++ b/backend/attendance/src/main/java/org/egov/web/models/Hrms/User.java @@ -0,0 +1,185 @@ +package org.egov.web.models.Hrms; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import org.egov.common.models.core.Role; +import org.egov.common.models.user.GuardianRelation; +import org.springframework.validation.annotation.Validated; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.util.List; + +@Validated +@AllArgsConstructor +@EqualsAndHashCode +@Getter +@NoArgsConstructor +@Setter +@ToString +@Builder +@JsonIgnoreProperties( + ignoreUnknown = true +) +public class User { + + @JsonProperty("id") + private Long id; + + @Size(max=64) + @JsonProperty("uuid") + private String uuid; + + @Size(max=64) + @JsonProperty("userServiceUuid") + private String userServiceUuid; + + @Size(max=180) + @JsonProperty("userName") + private String userName; + + @Size(max=64) + @JsonProperty("password") + private String password; + + @Size(max = 5) + @JsonProperty("salutation") + private String salutation; + + @NotNull + @Size(max=250) + @JsonProperty("name") + private String name; + + @JsonProperty("gender") + private String gender; + + @Pattern(regexp = "^[0-9]{9,10}$", message = "MobileNumber should be either 9 or 10 digit number") + @JsonProperty("mobileNumber") + private String mobileNumber; + + @Size(max=128) + @JsonProperty("emailId") + private String emailId; + + @Size(max=50) + @JsonProperty("altContactNumber") + private String altContactNumber; + + @Size(max=10) + @JsonProperty("pan") + private String pan; + + @Pattern(regexp = "^[0-9]{12}$", message = "AdharNumber should be 12 digit number") + @JsonProperty("aadhaarNumber") + private String aadhaarNumber; + + @Size(max=300) + @JsonProperty("permanentAddress") + private String permanentAddress; + + @Size(max=300) + @JsonProperty("permanentCity") + private String permanentCity; + + @Size(max=10) + @JsonProperty("permanentPinCode") + private String permanentPincode; + + @Size(max=300) + @JsonProperty("correspondenceCity") + private String correspondenceCity; + + @Size(max=10) + @JsonProperty("correspondencePinCode") + private String correspondencePincode; + + @Size(max=300) + @JsonProperty("correspondenceAddress") + private String correspondenceAddress; + + @JsonProperty("active") + private Boolean active; + + @NotNull + @JsonProperty("dob") + private Long dob; + + @JsonProperty("pwdExpiryDate") + private Long pwdExpiryDate; + + @Size(max=16) + @JsonProperty("locale") + private String locale; + + @Size(max=50) + @JsonProperty("type") + private String type; + + @Size(max=36) + @JsonProperty("signature") + private String signature; + + @JsonProperty("accountLocked") + private Boolean accountLocked; + + @JsonProperty("roles") + @Valid + private List roles; + + @Size(max=100) + @JsonProperty("fatherOrHusbandName") + private String fatherOrHusbandName; + + @JsonProperty("relationship") + private GuardianRelation relationship; + + @Size(max=32) + @JsonProperty("bloodGroup") + private String bloodGroup; + + @Size(max=300) + @JsonProperty("identificationMark") + private String identificationMark; + + @Size(max=36) + @JsonProperty("photo") + private String photo; + + @Size(max=64) + @JsonProperty("createdBy") + private String createdBy; + + @JsonProperty("createdDate") + private Long createdDate; + + @Size(max=64) + @JsonProperty("lastModifiedBy") + private String lastModifiedBy; + + @JsonProperty("lastModifiedDate") + private Long lastModifiedDate; + + @JsonProperty("otpReference") + private String otpReference; + + @Size(max=256) + @JsonProperty("tenantId") + private String tenantId; + + @JsonProperty("rowVersion") + private Integer rowVersion; + + +} diff --git a/backend/attendance/src/main/resources/application.properties b/backend/attendance/src/main/resources/application.properties index 685170e8e4..7465297d3c 100644 --- a/backend/attendance/src/main/resources/application.properties +++ b/backend/attendance/src/main/resources/application.properties @@ -5,22 +5,27 @@ app.timezone=UTC org.egov.detailed.tracing.enabled=true #-----------------KAFKA SERVER CONFIGURATIONS--------------------------------# +# KAFKA SERVER CONFIGURATIONS kafka.config.bootstrap_server_config=localhost:9092 -spring.kafka.consumer.properties.spring.deserializer.value.delegate.class=org.springframework.kafka.support.serializer.JsonDeserializer +spring.kafka.consumer.value-deserializer=org.egov.tracer.kafka.deserializer.HashMapDeserializer spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer -spring.kafka.consumer.group-id=egov-attendance-service +spring.kafka.consumer.group-id=health-attendance spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer -#-----------------KAFKA CONSUMER CONFIGURATIONS--------------------------------# +# KAFKA CONSUMER CONFIGURATIONS kafka.consumer.config.auto_commit=true kafka.consumer.config.auto_commit_interval=100 kafka.consumer.config.session_timeout=15000 kafka.consumer.config.auto_offset_reset=earliest -#-----------------KAFKA PRODUCER CONFIGURATIONS--------------------------------# +spring.kafka.listener.missing-topics-fatal=false +spring.kafka.consumer.properties.spring.json.use.type.headers=false +# KAFKA PRODUCER CONFIGURATIONS kafka.producer.config.retries_config=0 kafka.producer.config.batch_size_config=16384 kafka.producer.config.linger_ms_config=1 kafka.producer.config.buffer_memory_config=33554432 +#org.egov.detailed.tracing.enabled = false + #----------------Postgres Configurations----------------# spring.datasource.driver-class-name=org.postgresql.Driver @@ -45,7 +50,21 @@ egov.idgen.attendance.register.number.name=attendance.register.number #---------------Individual service----------------# works.individual.host=https://unified-dev.digit.org #works.individual.host=http://localhost:9090 -works.individual.search.endpoint=/individual/v1/_search +works.individual.search.endpoint=individual/v1/_search + +#---------------HRMS service----------------# +egov.hrms.host=https://unified-dev.digit.org +egov.hrms.search.endpoint=/health-hrms/employees/_search + +#---------------------Project----------------------------# +egov.project.host=http://unified-dev.digit.org +egov.project.staff.search.endpoint=/health-project/staff/v1/_search +egov.project.search.endpoint=/health-project/v1/_search + +project.staff.attendance.topic=project-staff-attendance-health-topic + +project.supervisor.roles=NATIONAL_SUPERVISOR,PROVINCIAL_SUPERVISOR,DISTRICT_SUPERVISOR,FIELD_SUPERVISOR,SUPERVISOR +project.attendee.roles=REGISTRAR,DISTRIBUTOR #----------Individual/Staff service integration--------------# @@ -63,6 +82,8 @@ attendance.document.id.verification.required=false #---------------- Attendance log Topic Config----------------# attendance.log.kafka.create.topic=save-attendance-log attendance.log.kafka.update.topic=update-attendance-log +attendance.log.kafka.consumer.bulk.create.topic=save-attendance-log-bulk-health +attendance.log.kafka.consumer.bulk.update.topic=update-attendance-log-bulk-health #--------------Attendance Register Topic Config------------------# attendance.register.kafka.create.topic=save-attendance @@ -79,6 +100,9 @@ attendance.staff.kafka.update.topic=update-staff attendance.attendee.kafka.create.topic=save-attendee attendance.attendee.kafka.update.topic=update-attendee +# The value of the following field should be changed to service specific name +kafka.topics.consumer=health-attendance-consumer-topic + #-------------- Update staff for change in contact detail of an organisation------------------# organisation.contact.details.update.topic=organisation.contact.details.update @@ -88,4 +112,15 @@ contracts.revision.topic=contracts-revision #------------------------------------------------------------------------------------------------# #---Attendance Register Search : Comma separated roles that can do open search ------------------# #------------------------------------------------------------------------------------------------# -attendance.register.open.search.enabled.roles=SUPERUSER,EMPLOYEE \ No newline at end of file +attendance.register.open.search.enabled.roles=SUPERUSER,EMPLOYEE + +#-------------- Redis Config ------------------# +spring.redis.host=radis.backbone +spring.redis.port=6379 +spring.cache.type=redis +spring.cache.redis.time-to-live=60 +spring.cache.autoexpiry=true + + +project.management.system.kafka.update.topic=update-project-health +attendance.register.first.staff.insert.enabled=true \ No newline at end of file diff --git a/backend/attendance/src/main/resources/db/migration/main/V20240124104400__alter_attendance_log_table.sql b/backend/attendance/src/main/resources/db/migration/main/V20240124104400__alter_attendance_log_table.sql new file mode 100644 index 0000000000..4505dbdb1c --- /dev/null +++ b/backend/attendance/src/main/resources/db/migration/main/V20240124104400__alter_attendance_log_table.sql @@ -0,0 +1,5 @@ +ALTER TABLE eg_wms_attendance_log ADD COLUMN IF NOT EXISTS clientreferenceid character varying(256); +ALTER TABLE eg_wms_attendance_log ADD COLUMN IF NOT EXISTS clientcreatedby character varying(256); +ALTER TABLE eg_wms_attendance_log ADD COLUMN IF NOT EXISTS clientlastmodifiedby character varying(256); +ALTER TABLE eg_wms_attendance_log ADD COLUMN IF NOT EXISTS clientcreatedtime bigint; +ALTER TABLE eg_wms_attendance_log ADD COLUMN IF NOT EXISTS clientlastmodifiedtime bigint; \ No newline at end of file diff --git a/backend/attendance/src/test/java/org/egov/service/AttendanceLogServiceTest.java b/backend/attendance/src/test/java/org/egov/service/AttendanceLogServiceTest.java index 1e275c093a..2acd6629f4 100644 --- a/backend/attendance/src/test/java/org/egov/service/AttendanceLogServiceTest.java +++ b/backend/attendance/src/test/java/org/egov/service/AttendanceLogServiceTest.java @@ -4,7 +4,7 @@ import org.egov.config.AttendanceServiceConfiguration; import org.egov.enrichment.AttendanceLogEnrichment; import org.egov.helper.AttendanceLogRequestTestBuilder; -import org.egov.kafka.Producer; +import org.egov.common.producer.Producer; import org.egov.repository.AttendanceLogRepository; import org.egov.tracer.model.CustomException; import org.egov.util.ResponseInfoFactory; diff --git a/backend/attendance/src/test/java/org/egov/validator/AttendanceLogServiceValidatorTest.java b/backend/attendance/src/test/java/org/egov/validator/AttendanceLogServiceValidatorTest.java index 251766c061..fe4403af13 100644 --- a/backend/attendance/src/test/java/org/egov/validator/AttendanceLogServiceValidatorTest.java +++ b/backend/attendance/src/test/java/org/egov/validator/AttendanceLogServiceValidatorTest.java @@ -130,7 +130,7 @@ public void validateCreateAttendanceLogRequest_validateAttendanceLogRequest_10() @DisplayName("Method validateAttendanceLogRequest: RequestInfo object with UserInfo but without Attendance Log Time") @Test public void validateCreateAttendanceLogRequest_validateAttendanceLogRequest_11(){ - AttendanceLogRequest attendanceLogRequest = AttendanceLogRequestTestBuilder.builder().withRequestInfo().attendanceLogWithoutTime().build();; + AttendanceLogRequest attendanceLogRequest = AttendanceLogRequestTestBuilder.builder().withRequestInfo().attendanceLogWithoutTime().build(); CustomException exception = assertThrows(CustomException.class, ()-> ReflectionTestUtils.invokeMethod(attendanceLogServiceValidator, "validateAttendanceLogRequest", attendanceLogRequest)); assertTrue(exception.toString().contains("Attendance time is mandatory")); } diff --git a/backend/attendance/src/test/java/org/egov/web/controllers/AttendanceLogApiControllerTest.java b/backend/attendance/src/test/java/org/egov/web/controllers/AttendanceLogApiControllerTest.java index 605a943624..6fd284bce9 100644 --- a/backend/attendance/src/test/java/org/egov/web/controllers/AttendanceLogApiControllerTest.java +++ b/backend/attendance/src/test/java/org/egov/web/controllers/AttendanceLogApiControllerTest.java @@ -6,7 +6,7 @@ import org.egov.TestConfiguration; import org.egov.common.contract.response.ResponseInfo; import org.egov.helper.AttendanceLogRequestTestBuilder; -import org.egov.kafka.Producer; +import org.egov.common.producer.Producer; import org.egov.repository.AttendanceLogRepository; import org.egov.service.AttendanceLogService; import org.egov.util.ResponseInfoFactory;