diff --git a/build/build-config.yml b/build/build-config.yml
index dec24965782..2002805a366 100644
--- a/build/build-config.yml
+++ b/build/build-config.yml
@@ -250,15 +250,22 @@ config:
dockerfile: "build/17/maven/Dockerfile"
- work-dir: "health-services/plan-service/src/main/resources/db"
image-name: "plan-service-db"
- - name: "builds/health-campaign-services/health-services/resource-estimation-service"
+ - name: "builds/health-campaign-services/health-services/resource-generator"
build:
- - work-dir: "health-services/resource-estimation-service"
- image-name: "resource-estimation-service"
+ - work-dir: "health-services/resource-generator"
+ image-name: "resource-generator"
dockerfile: "build/17/maven/Dockerfile"
- name: "builds/health-campaign-services/analytics/auth-proxy"
build:
- work-dir: "analytics/auth-proxy"
image-name: "auth-proxy"
+ - name: "builds/health-campaign-services/health-services/census-service"
+ build:
+ - work-dir: "health-services/census-service"
+ image-name: "census-service"
+ dockerfile: "build/17/maven/Dockerfile"
+ - work-dir: "health-services/census-service/src/main/resources/db"
+ image-name: "census-service-db"
# frontend
- name: builds/health-campaign-services/frontend/workbench-ui
diff --git a/health-services/census-service/CHANGELOG.md b/health-services/census-service/CHANGELOG.md
new file mode 100644
index 00000000000..38562489c90
--- /dev/null
+++ b/health-services/census-service/CHANGELOG.md
@@ -0,0 +1,13 @@
+# Changelog
+All notable changes to this module will be documented in this file.
+
+## 1.0.0 - 2024-11-28
+#### Census Service
+The Census Service introduces core functionalities for managing census data:
+
+1. Validation of Census: Ensures data integrity by validating all census requests before processing.
+2. Census Create: Creates new census records after validation and enrichment, publishing request to the designated Kafka topic to handle the creation process asynchronously.
+3. Census Update: Updates existing records post-validation and enrichment by sending request to the designated Kafka update topic.
+4. Census Bulk Update: Updates multiple census records in one operation after successful validation.
+5. Census Search: Enables searching for census records with the provided search criteria.
+6. Plan Facility Consumer: Listens to Plan Facility Update topic to assign facility to a boundary in census.
\ No newline at end of file
diff --git a/health-services/census-service/README.md b/health-services/census-service/README.md
new file mode 100644
index 00000000000..a2e8a9f7b84
--- /dev/null
+++ b/health-services/census-service/README.md
@@ -0,0 +1,18 @@
+# Swagger generated server
+
+Spring Boot Server
+
+
+## Overview
+This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project.
+By using the [OpenAPI-Spec](https://github.com/swagger-api/swagger-core), you can easily generate a server stub.
+This is an example of building a swagger-enabled server in Java using the SpringBoot framework.
+
+The underlying library integrating swagger to SpringBoot is [springfox](https://github.com/springfox/springfox)
+
+Start your server as an simple java application
+
+You can view the api documentation in swagger-ui by pointing to
+http://localhost:8080/
+
+Change default port value in application.properties
\ No newline at end of file
diff --git a/health-services/census-service/pom.xml b/health-services/census-service/pom.xml
new file mode 100644
index 00000000000..7e6f7adc8fb
--- /dev/null
+++ b/health-services/census-service/pom.xml
@@ -0,0 +1,141 @@
+
+ 4.0.0
+ org.egov
+ census-service
+ jar
+ census-service
+ 1.0.0
+
+ 17
+ ${java.version}
+ ${java.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.2
+
+
+ src/main/java
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ repackage
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.egov.common
+ health-services-models
+ 1.0.21-SNAPSHOT
+ compile
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ org.flywaydb
+ flyway-core
+ 9.22.3
+
+
+ org.postgresql
+ postgresql
+ 42.7.1
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ io.swagger
+ swagger-core
+ 1.5.18
+
+
+ io.swagger.core.v3
+ swagger-annotations
+ 2.2.8
+
+
+ net.minidev
+ json-smart
+ 2.5.0
+
+
+
+ org.egov.services
+ tracer
+ 2.9.0-SNAPSHOT
+
+
+
+
+
+
+
+ org.egov
+ mdms-client
+ 2.9.0-SNAPSHOT
+ compile
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+
+ repo.egovernments.org
+ eGov ERP Releases Repository
+ https://nexus-repo.egovernments.org/nexus/content/repositories/releases/
+
+
+ repo.egovernments.org.snapshots
+ eGov ERP Releases Repository
+ https://nexus-repo.egovernments.org/nexus/content/repositories/snapshots/
+
+
+ repo.egovernments.org.public
+ eGov Public Repository Group
+ https://nexus-repo.egovernments.org/nexus/content/groups/public/
+
+
+ repo.digit.org
+ eGov DIGIT Releases Repository
+ https://nexus-repo.digit.org/nexus/content/repositories/snapshots/
+
+
+
diff --git a/health-services/census-service/src/main/java/digit/Main.java b/health-services/census-service/src/main/java/digit/Main.java
new file mode 100644
index 00000000000..6e3d79db11c
--- /dev/null
+++ b/health-services/census-service/src/main/java/digit/Main.java
@@ -0,0 +1,20 @@
+package digit;
+
+
+import org.egov.tracer.config.TracerConfiguration;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Import;
+
+@Import({ TracerConfiguration.class })
+@SpringBootApplication
+@ComponentScan(basePackages = { "digit", "digit.web.controllers" , "digit.config"})
+public class Main {
+
+
+ public static void main(String[] args) throws Exception {
+ SpringApplication.run(Main.class, args);
+ }
+
+}
diff --git a/health-services/census-service/src/main/java/digit/config/Configuration.java b/health-services/census-service/src/main/java/digit/config/Configuration.java
new file mode 100644
index 00000000000..8459885357e
--- /dev/null
+++ b/health-services/census-service/src/main/java/digit/config/Configuration.java
@@ -0,0 +1,86 @@
+package digit.config;
+
+import lombok.*;
+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 java.util.List;
+
+@Component
+@Data
+@Import({TracerConfiguration.class})
+@NoArgsConstructor
+@AllArgsConstructor
+@Setter
+@Getter
+public class Configuration {
+
+ // Allowed roles for census
+ @Value("#{${allowed.census.roles}}")
+ private List allowedCensusRoles;
+
+ @Value("#{${workflow.restricted.roles}}")
+ private List workflowRestrictedRoles;
+
+ // Persister Topic
+ @Value("${census.create.topic}")
+ private String censusCreateTopic;
+
+ @Value("${census.update.topic}")
+ private String censusUpdateTopic;
+
+ @Value("${census.bulk.update.topic}")
+ private String censusBulkUpdateTopic;
+
+ @Value("${plan.facility.update.topic}")
+ private String planFcailityUpdateTopic;
+
+ // Boundary Service
+ @Value("${egov.boundary.service.host}")
+ private String boundaryServiceHost;
+
+ @Value("${egov.boundary.relationship.search.endpoint}")
+ private String boundaryRelationshipSearchEndpoint;
+
+ @Value("${egov.boundary.hierarchy.search.endpoint}")
+ private String boundaryHierarchySearchEndpoint;
+
+ // Plan Service
+ @Value("${egov.plan.service.host}")
+ private String planServiceHost;
+
+ @Value("${egov.plan.employee.assignment.search.endpoint}")
+ private String planEmployeeAssignmentSearchEndpoint;
+
+ //Workflow
+ @Value("${egov.workflow.host}")
+ private String wfHost;
+
+ @Value("${egov.workflow.transition.path}")
+ private String wfTransitionPath;
+
+ @Value("${egov.business.service.search.endpoint}")
+ private String businessServiceSearchEndpoint;
+
+ @Value("${workflow.initiate.action}")
+ private List wfInitiateActions;
+
+ @Value("${workflow.intermediate.action}")
+ private List wfIntermediateActions;
+
+ @Value("${workflow.send.back.actions}")
+ private List wfSendBackActions;
+
+ //SMSNotification
+ @Value("${egov.sms.notification.topic}")
+ private String smsNotificationTopic;
+
+ //Pagination
+ @Value("${census.default.offset}")
+ private Integer defaultOffset;
+
+ @Value("${census.default.limit}")
+ private Integer defaultLimit;
+}
diff --git a/health-services/census-service/src/main/java/digit/config/MainConfiguration.java b/health-services/census-service/src/main/java/digit/config/MainConfiguration.java
new file mode 100644
index 00000000000..239331c9cd8
--- /dev/null
+++ b/health-services/census-service/src/main/java/digit/config/MainConfiguration.java
@@ -0,0 +1,41 @@
+package digit.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+
+import java.util.TimeZone;
+
+import jakarta.annotation.PostConstruct;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.egov.tracer.config.TracerConfiguration;
+
+
+@Import({TracerConfiguration.class})
+public class MainConfiguration {
+
+ @Value("${app.timezone}")
+ private String timeZone;
+
+ @PostConstruct
+ 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));
+ }
+
+ @Bean
+ @Autowired
+ public MappingJackson2HttpMessageConverter jacksonConverter(ObjectMapper objectMapper) {
+ MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
+ converter.setObjectMapper(objectMapper);
+ return converter;
+ }
+}
\ No newline at end of file
diff --git a/health-services/census-service/src/main/java/digit/config/ServiceConstants.java b/health-services/census-service/src/main/java/digit/config/ServiceConstants.java
new file mode 100644
index 00000000000..5d944060848
--- /dev/null
+++ b/health-services/census-service/src/main/java/digit/config/ServiceConstants.java
@@ -0,0 +1,114 @@
+package digit.config;
+
+
+import org.springframework.stereotype.Component;
+
+
+@Component
+public class ServiceConstants {
+
+ public static final String EXTERNAL_SERVICE_EXCEPTION = "External Service threw an Exception: ";
+ public static final String SEARCHER_SERVICE_EXCEPTION = "Exception while fetching from searcher: ";
+
+ public static final String IDGEN_ERROR = "IDGEN ERROR";
+ public static final String NO_IDS_FOUND_ERROR = "No ids returned from idgen Service";
+
+ public static final String ERROR_WHILE_FETCHING_FROM_MDMS = "Exception occurred while fetching category lists from mdms: ";
+
+ public static final String ERROR_WHILE_FETCHING_BOUNDARY_DETAILS = "Exception occurred while fetching boundary relationship from boundary service: ";
+
+ public static final String ERROR_WHILE_FETCHING_BOUNDARY_HIERARCHY_DETAILS = "Exception occurred while fetching boundary hierarchy details from boundary service: ";
+
+ public static final String ERROR_WHILE_FETCHING_EMPLOYEE_ASSIGNMENT_DETAILS = "Exception occurred while fetching plan employee assignment details from plan service: ";
+
+ public static final String ERROR_WHILE_FETCHING_BUSINESS_SERVICE_DETAILS = "Exception occurred while fetching business service details: ";
+
+ public static final String RES_MSG_ID = "uief87324";
+ public static final String SUCCESSFUL = "successful";
+ public static final String FAILED = "failed";
+
+ public static final String URL = "url";
+ public static final String URL_SHORTENING_ERROR_CODE = "URL_SHORTENING_ERROR";
+ public static final String URL_SHORTENING_ERROR_MESSAGE = "Unable to shorten url: ";
+
+ public static final String DOB_FORMAT_Y_M_D = "yyyy-MM-dd";
+ public static final String DOB_FORMAT_D_M_Y = "dd/MM/yyyy";
+ public static final String ILLEGAL_ARGUMENT_EXCEPTION_CODE = "IllegalArgumentException";
+ public static final String OBJECTMAPPER_UNABLE_TO_CONVERT = "ObjectMapper not able to convertValue in userCall";
+ public static final String DOB_FORMAT_D_M_Y_H_M_S = "dd-MM-yyyy HH:mm:ss";
+ public static final String CREATED_DATE = "createdDate";
+ public static final String LAST_MODIFIED_DATE = "lastModifiedDate";
+ public static final String DOB = "dob";
+ public static final String PWD_EXPIRY_DATE = "pwdExpiryDate";
+ public static final String INVALID_DATE_FORMAT_CODE = "INVALID_DATE_FORMAT";
+ public static final String INVALID_DATE_FORMAT_MESSAGE = "Failed to parse date format in user";
+ public static final String CITIZEN_UPPER = "CITIZEN";
+ public static final String CITIZEN_LOWER = "Citizen";
+ public static final String USER = "user";
+ public static final String PIPE_REGEX = "\\|";
+ public static final String FACILITY_ID_FIELD = "facilityId";
+ public static final String FACILITY_NAME_FIELD = "facilityName";
+
+ public static final String PARSING_ERROR_CODE = "PARSING ERROR";
+ public static final String PARSING_ERROR_MESSAGE = "Failed to parse JSON data from PGobject";
+
+ public static final String FAILED_TO_PARSE_BUSINESS_SERVICE_SEARCH = "Failed to parse response of workflow business service search";
+ public static final String BUSINESS_SERVICE_NOT_FOUND = "BUSINESSSERVICE_NOT_FOUND";
+ public static final String THE_BUSINESS_SERVICE = "The businessService ";
+ public static final String NOT_FOUND = " is not found";
+ public static final String TENANTID = "?tenantId=";
+ public static final String BUSINESS_SERVICES = "&businessServices=";
+
+ public static final String NO_BOUNDARY_DATA_FOUND_FOR_GIVEN_BOUNDARY_CODE_CODE = "NO_BOUNDARY_DATA_FOUND_FOR_GIVEN_BOUNDARY_CODE";
+ public static final String NO_BOUNDARY_DATA_FOUND_FOR_GIVEN_BOUNDARY_CODE_MESSAGE = "Invalid or incorrect boundaryCode. No boundary data found.";
+
+ public static final String NO_BUSINESS_SERVICE_DATA_FOUND_CODE = "NO_BUSINESS_SERVICE_DATA_FOUND";
+ public static final String NO_BUSINESS_SERVICE_DATA_FOUND_MESSAGE = "Invalid or incorrect businessService. No business service data found.";
+
+ public static final String USERINFO_MISSING_CODE = "USERINFO_MISSING";
+ public static final String USERINFO_MISSING_MESSAGE = "UserInfo is missing in Request Info ";
+
+ public static final String ERROR_WHILE_UPDATING_ADDITIONAL_DETAILS_CODE = "ERROR_WHILE_UPDATING_ADDITIONAL_DETAILS";
+ public static final String ERROR_WHILE_UPDATING_ADDITIONAL_DETAILS_MESSAGE = "Exception occurred while updating additional details : ";
+
+ public static final String WORKFLOW_INTEGRATION_ERROR_CODE = "WORKFLOW_INTEGRATION_ERROR";
+ public static final String WORKFLOW_INTEGRATION_ERROR_MESSAGE = "Exception occured while integrating with workflow : ";
+
+ public static final String INVALID_PARTNER_CODE = "INVALID_PARTNER";
+ public static final String INVALID_PARTNER_MESSAGE = "Invalid partner assignment or invalid jurisdiction of the assigned partner";
+
+ public static final String INVALID_CENSUS_CODE = "INVALID_CENSUS";
+ public static final String INVALID_CENSUS_MESSAGE = "Provided census does not exist";
+
+ public static final String DUPLICATE_CENSUS_ID_IN_BULK_UPDATE_CODE = "DUPLICATE_CENSUS_ID_IN_BULK_UPDATE";
+ public static final String DUPLICATE_CENSUS_ID_IN_BULK_UPDATE_MESSAGE = "Census provided in the bulk update request are not unique.";
+
+ public static final String INVALID_SOURCE_OR_TENANT_ID_FOR_BULK_UPDATE_CODE = "INVALID_SOURCE_OR_TENANT_ID_FOR_BULK_UPDATE";
+ public static final String INVALID_SOURCE_OR_TENANT_ID_FOR_BULK_UPDATE_MESSAGE = "Tenant id and source should be same across all entries for bulk update.";
+
+ public static final String WORKFLOW_NOT_FOUND_FOR_BULK_UPDATE_CODE = "WORKFLOW_NOT_FOUND_FOR_BULK_UPDATE";
+ public static final String WORKFLOW_NOT_FOUND_FOR_BULK_UPDATE_MESSAGE = "Workflow information is mandatory for each entry for bulk update";
+
+ public static final String DUPLICATE_KEY_IN_ADDITIONAL_FIELD_CODE = "DUPLICATE_KEY_IN_ADDITIONAL_FIELD";
+ public static final String DUPLICATE_KEY_IN_ADDITIONAL_FIELD_MESSGAE = "Duplicate key found in additional field : ";
+
+ public static final String CENSUS_ALREADY_EXISTS_CODE = "CENSUS_ALREADY_EXISTS";
+ public static final String CENSUS_ALREADY_EXISTS_MESSAGE = "Census with the given boundary and source already exists.";
+
+ public static final String DIFFERENT_WORKFLOW_FOR_BULK_UPDATE_CODE = "DIFFERENT_WORKFLOW_FOR_BULK_UPDATE";
+ public static final String DIFFERENT_WORKFLOW_FOR_BULK_UPDATE_MESSAGE = "All entries should be in the same state for bulk transitioning census records.";
+
+ public static final String UNAUTHORIZED_WORKFLOW_ACCESS_CODE = "UNAUTHORIZED_WORKFLOW_ACCESS";
+ public static final String UNAUTHORIZED_WORKFLOW_ACCESS_MESSAGE = "User with provided roles cannot have an active workflow. Please remove the workflow or update user roles.";
+
+ public static final String SEARCH_CRITERIA_EMPTY_CODE = "SEARCH_CRITERIA_EMPTY";
+ public static final String SEARCH_CRITERIA_EMPTY_MESSAGE = "Search criteria cannot be empty";
+
+ public static final String TENANT_ID_EMPTY_CODE = "TENANT_ID_EMPTY";
+ public static final String TENANT_ID_EMPTY_MESSAGE = "Tenant Id cannot be empty, TenantId should be present";
+
+ //Workflow constants
+ public static final String MODULE_NAME_VALUE = "census-service";
+
+ public static final String CENSUS_BUSINESS_SERVICE = "CENSUS";
+}
diff --git a/health-services/census-service/src/main/java/digit/kafka/FacilityCatchmentConsumer.java b/health-services/census-service/src/main/java/digit/kafka/FacilityCatchmentConsumer.java
new file mode 100644
index 00000000000..d5be4b7458c
--- /dev/null
+++ b/health-services/census-service/src/main/java/digit/kafka/FacilityCatchmentConsumer.java
@@ -0,0 +1,99 @@
+package digit.kafka;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import digit.repository.CensusRepository;
+import digit.service.CensusService;
+import digit.service.enrichment.CensusEnrichment;
+import digit.util.BoundaryUtil;
+import digit.util.CommonUtil;
+import digit.web.models.BulkCensusRequest;
+import digit.web.models.Census;
+import digit.web.models.CensusResponse;
+import digit.web.models.boundary.BoundaryTypeHierarchyResponse;
+import digit.web.models.plan.PlanFacilityDTO;
+import digit.web.models.plan.PlanFacilityRequestDTO;
+import lombok.extern.slf4j.Slf4j;
+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.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static digit.config.ServiceConstants.FACILITY_ID_FIELD;
+import static digit.config.ServiceConstants.FACILITY_NAME_FIELD;
+
+@Component
+@Slf4j
+public class FacilityCatchmentConsumer {
+
+ private ObjectMapper objectMapper;
+
+ private CensusService service;
+
+ private CensusRepository repository;
+
+ private CommonUtil commonUtil;
+
+ private BoundaryUtil boundaryUtil;
+
+ private CensusEnrichment enrichment;
+
+ public FacilityCatchmentConsumer(ObjectMapper objectMapper, CensusService service, CommonUtil commonUtil, CensusRepository repository, BoundaryUtil boundaryUtil, CensusEnrichment enrichment) {
+ this.objectMapper = objectMapper;
+ this.service = service;
+ this.commonUtil = commonUtil;
+ this.repository = repository;
+ this.boundaryUtil = boundaryUtil;
+ this.enrichment = enrichment;
+ }
+
+ @KafkaListener(topics = {"${plan.facility.update.topic}"})
+ public void listen(Map consumerRecord, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
+ try {
+ PlanFacilityRequestDTO planFacilityRequestDTO = objectMapper.convertValue(consumerRecord, PlanFacilityRequestDTO.class);
+ PlanFacilityDTO planFacilityDTO = planFacilityRequestDTO.getPlanFacilityDTO();
+
+ CensusResponse censusResponse = service.search(commonUtil.getCensusSearchRequest(planFacilityDTO.getTenantId(), planFacilityDTO.getPlanConfigurationId(), planFacilityDTO.getServiceBoundaries(), planFacilityDTO.getInitiallySetServiceBoundaries(), planFacilityRequestDTO.getRequestInfo()));
+ List censusFromSearch = censusResponse.getCensus();
+
+ BoundaryTypeHierarchyResponse boundaryTypeHierarchyResponse = boundaryUtil.fetchBoundaryHierarchy(planFacilityRequestDTO.getRequestInfo(), censusFromSearch.get(0).getTenantId(), censusFromSearch.get(0).getHierarchyType());
+ String facilityId = planFacilityRequestDTO.getPlanFacilityDTO().getFacilityId();
+ String facilityName = planFacilityRequestDTO.getPlanFacilityDTO().getFacilityName();
+
+ Set boundariesWithFacility = new HashSet<>(List.of(planFacilityDTO.getServiceBoundaries().split(",")));
+ Set boundariesWithNoFacility = new HashSet<>(planFacilityDTO.getInitiallySetServiceBoundaries());
+
+ censusFromSearch.forEach(census -> {
+ String boundaryCode = census.getBoundaryCode();
+
+ if (!boundariesWithFacility.contains(boundaryCode)) {
+
+ // Unassigning facilities to the boundaries which were initially assigned that facility
+ census.setAdditionalDetails(commonUtil.removeFieldFromAdditionalDetails(census.getAdditionalDetails(), FACILITY_ID_FIELD));
+ census.setAdditionalDetails(commonUtil.removeFieldFromAdditionalDetails(census.getAdditionalDetails(), FACILITY_NAME_FIELD));
+ census.setFacilityAssigned(Boolean.FALSE);
+ census.setPartnerAssignmentValidationEnabled(Boolean.FALSE);
+
+ } else if (!boundariesWithNoFacility.contains(boundaryCode)) {
+
+ // Assigning facilities to the newly added boundaries in the update request.
+ census.setAdditionalDetails(commonUtil.updateFieldInAdditionalDetails(census.getAdditionalDetails(), FACILITY_ID_FIELD, facilityId));
+ census.setAdditionalDetails(commonUtil.updateFieldInAdditionalDetails(census.getAdditionalDetails(), FACILITY_NAME_FIELD, facilityName));
+ census.setFacilityAssigned(Boolean.TRUE);
+ census.setPartnerAssignmentValidationEnabled(Boolean.FALSE);
+ }
+ });
+
+ // Enrich jurisdiction mapping in census for indexer
+ enrichment.enrichJurisdictionMapping(censusFromSearch, boundaryTypeHierarchyResponse.getBoundaryHierarchy().get(0));
+ repository.bulkUpdate(BulkCensusRequest.builder().requestInfo(planFacilityRequestDTO.getRequestInfo()).census(censusFromSearch).build());
+
+ } catch (Exception exception) {
+ log.error("Error in census consumer", exception);
+ }
+ }
+}
diff --git a/health-services/census-service/src/main/java/digit/kafka/Producer.java b/health-services/census-service/src/main/java/digit/kafka/Producer.java
new file mode 100644
index 00000000000..542f4f686c0
--- /dev/null
+++ b/health-services/census-service/src/main/java/digit/kafka/Producer.java
@@ -0,0 +1,20 @@
+package digit.kafka;
+
+import lombok.extern.slf4j.Slf4j;
+import org.egov.tracer.kafka.CustomKafkaTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+// NOTE: If tracer is disabled change CustomKafkaTemplate to KafkaTemplate in autowiring
+
+@Service
+@Slf4j
+public class Producer {
+
+ @Autowired
+ private CustomKafkaTemplate kafkaTemplate;
+
+ public void push(String topic, Object value) {
+ kafkaTemplate.send(topic, value);
+ }
+}
diff --git a/health-services/census-service/src/main/java/digit/kafka/ResourceCensusConsumer.java b/health-services/census-service/src/main/java/digit/kafka/ResourceCensusConsumer.java
new file mode 100644
index 00000000000..e161225b23a
--- /dev/null
+++ b/health-services/census-service/src/main/java/digit/kafka/ResourceCensusConsumer.java
@@ -0,0 +1,37 @@
+package digit.kafka;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import digit.service.CensusService;
+import digit.web.models.CensusRequest;
+import lombok.extern.slf4j.Slf4j;
+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.Map;
+
+@Component
+@Slf4j
+public class ResourceCensusConsumer {
+
+ private CensusService censusService;
+
+ private ObjectMapper mapper;
+
+ public ResourceCensusConsumer(CensusService censusService, ObjectMapper mapper) {
+ this.censusService = censusService;
+ this.mapper = mapper;
+ }
+
+ @KafkaListener(topics = {"${resource.config.consumer.census.create.topic}"})
+ public void listen(Map consumerRecord, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
+ try {
+ CensusRequest censusRequest = mapper.convertValue(consumerRecord, CensusRequest.class);
+ censusRequest.getCensus().setPartnerAssignmentValidationEnabled(Boolean.FALSE);
+ censusService.create(censusRequest);
+ } catch (Exception exception) {
+ log.error("Error in resource census consumer", exception);
+ }
+ }
+}
diff --git a/health-services/census-service/src/main/java/digit/repository/CensusRepository.java b/health-services/census-service/src/main/java/digit/repository/CensusRepository.java
new file mode 100644
index 00000000000..4a9f159e7e9
--- /dev/null
+++ b/health-services/census-service/src/main/java/digit/repository/CensusRepository.java
@@ -0,0 +1,21 @@
+package digit.repository;
+
+import digit.web.models.*;
+
+import java.util.List;
+import java.util.Map;
+
+public interface CensusRepository {
+
+ public void create(CensusRequest censusRequest);
+
+ public List search(CensusSearchCriteria censusSearchCriteria);
+
+ public void update(CensusRequest censusRequest);
+
+ public void bulkUpdate(BulkCensusRequest request);
+
+ public Integer count(CensusSearchCriteria censusSearchCriteria);
+
+ public Map statusCount(CensusSearchRequest censusSearchRequest);
+}
diff --git a/health-services/census-service/src/main/java/digit/repository/ServiceRequestRepository.java b/health-services/census-service/src/main/java/digit/repository/ServiceRequestRepository.java
new file mode 100644
index 00000000000..d09d230e4fa
--- /dev/null
+++ b/health-services/census-service/src/main/java/digit/repository/ServiceRequestRepository.java
@@ -0,0 +1,45 @@
+package digit.repository;
+
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import lombok.extern.slf4j.Slf4j;
+import org.egov.tracer.model.ServiceCallException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+
+import static digit.config.ServiceConstants.*;
+
+@Repository
+@Slf4j
+public class ServiceRequestRepository {
+
+ private ObjectMapper mapper;
+
+ private RestTemplate restTemplate;
+
+ public ServiceRequestRepository(ObjectMapper mapper, RestTemplate restTemplate) {
+ this.mapper = mapper;
+ this.restTemplate = restTemplate;
+ }
+
+
+ public Object fetchResult(StringBuilder uri, Object request) {
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ Object response = null;
+ try {
+ response = restTemplate.postForObject(uri.toString(), request, Map.class);
+ } catch (HttpClientErrorException e) {
+ log.error(EXTERNAL_SERVICE_EXCEPTION, e);
+ throw new ServiceCallException(e.getResponseBodyAsString());
+ } catch (Exception e) {
+ log.error(SEARCHER_SERVICE_EXCEPTION, e);
+ }
+
+ return response;
+ }
+}
\ No newline at end of file
diff --git a/health-services/census-service/src/main/java/digit/repository/impl/CensusRepositoryImpl.java b/health-services/census-service/src/main/java/digit/repository/impl/CensusRepositoryImpl.java
new file mode 100644
index 00000000000..c6dec4b4d11
--- /dev/null
+++ b/health-services/census-service/src/main/java/digit/repository/impl/CensusRepositoryImpl.java
@@ -0,0 +1,219 @@
+package digit.repository.impl;
+
+import digit.config.Configuration;
+import digit.kafka.Producer;
+import digit.repository.CensusRepository;
+import digit.repository.querybuilder.CensusQueryBuilder;
+import digit.repository.rowmapper.CensusRowMapper;
+import digit.repository.rowmapper.StatusCountRowMapper;
+import digit.util.CommonUtil;
+import digit.web.models.*;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.SingleColumnRowMapper;
+import org.springframework.stereotype.Repository;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static digit.config.ServiceConstants.CENSUS_BUSINESS_SERVICE;
+
+@Slf4j
+@Repository
+public class CensusRepositoryImpl implements CensusRepository {
+
+ private Producer producer;
+
+ private Configuration config;
+
+ private CensusQueryBuilder queryBuilder;
+
+ private CensusRowMapper censusRowMapper;
+
+ private JdbcTemplate jdbcTemplate;
+
+ private StatusCountRowMapper statusCountRowMapper;
+
+ private CommonUtil commonUtil;
+
+ public CensusRepositoryImpl(Producer producer, Configuration config, CensusQueryBuilder queryBuilder, CensusRowMapper censusRowMapper, JdbcTemplate jdbcTemplate, StatusCountRowMapper statusCountRowMapper,CommonUtil commonUtil) {
+ this.producer = producer;
+ this.config = config;
+ this.queryBuilder = queryBuilder;
+ this.censusRowMapper = censusRowMapper;
+ this.jdbcTemplate = jdbcTemplate;
+ this.statusCountRowMapper = statusCountRowMapper;
+ this.commonUtil = commonUtil;
+ }
+
+ /**
+ * Pushes a new census record to persister kafka topic.
+ *
+ * @param censusRequest The request containing the census details
+ */
+ @Override
+ public void create(CensusRequest censusRequest) {
+ CensusRequestDTO requestDTO = convertToReqDTO(censusRequest);
+ producer.push(config.getCensusCreateTopic(), requestDTO);
+ }
+
+ /**
+ * Searches for census records based on the provided search criteria.
+ *
+ * @param censusSearchCriteria The criteria to use for searching census records.
+ * @return A list of census records that match the search criteria.
+ */
+ @Override
+ public List search(CensusSearchCriteria censusSearchCriteria) {
+
+ if(censusSearchCriteria.getAreaCodes() != null && censusSearchCriteria.getAreaCodes().isEmpty())
+ return new ArrayList<>();
+
+ // Fetch census ids from database
+ List censusIds = queryDatabaseForCensusIds(censusSearchCriteria);
+
+ // Return empty list back as response if no census ids are found
+ if(CollectionUtils.isEmpty(censusIds)) {
+ log.info("No census ids found for provided census search criteria.");
+ return new ArrayList<>();
+ }
+
+ // Fetch census from database based on the acquired ids
+ return searchCensusByIds(censusIds);
+ }
+
+ private List searchCensusByIds(List censusIds) {
+
+ List