diff --git a/pom.xml b/pom.xml index 84eb1596..416e042f 100644 --- a/pom.xml +++ b/pom.xml @@ -73,6 +73,16 @@ 1.3.2 + org.springframework.boot + spring-boot-starter-data-elasticsearch + + + co.elastic.clients + elasticsearch-java + 8.11.0 + + + org.springframework.boot spring-boot-devtools runtime diff --git a/src/main/java/com/iemr/common/identity/ScheduledSyncJob.java b/src/main/java/com/iemr/common/identity/ScheduledSyncJob.java new file mode 100644 index 00000000..82120338 --- /dev/null +++ b/src/main/java/com/iemr/common/identity/ScheduledSyncJob.java @@ -0,0 +1,76 @@ +package com.iemr.common.identity; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import com.iemr.common.identity.data.elasticsearch.ElasticsearchSyncJob; +import com.iemr.common.identity.service.elasticsearch.SyncJobService; + +/** + * Scheduled jobs for Elasticsearch sync + * + * To enable scheduled sync, set: + * elasticsearch.sync.scheduled.enabled=true in application.properties + */ +@Component +public class ScheduledSyncJob { + + private static final Logger logger = LoggerFactory.getLogger(ScheduledSyncJob.class); + + @Autowired + private SyncJobService syncJobService; + + @Value("${elasticsearch.sync.scheduled.enabled:true}") + private boolean scheduledSyncEnabled; + + /** + * Run full sync every day at 2 AM + * Cron: second, minute, hour, day, month, weekday + */ + @Scheduled(cron = "${elasticsearch.sync.scheduled.cron:0 0 2 * * ?}") + public void scheduledFullSync() { + if (!scheduledSyncEnabled) { + logger.debug("Scheduled sync is disabled"); + return; + } + + logger.info("========================================"); + logger.info("Starting scheduled full sync job"); + logger.info("========================================"); + + try { + // Check if there's already a sync running + if (syncJobService.isFullSyncRunning()) { + logger.warn("Full sync already running. Skipping scheduled sync."); + return; + } + + // Start async sync + ElasticsearchSyncJob job = syncJobService.startFullSyncJob("SCHEDULER"); + logger.info("Scheduled sync job started: jobId={}", job.getJobId()); + + } catch (Exception e) { + logger.error("Error starting scheduled sync: {}", e.getMessage(), e); + } + } + + /** + * Clean up old completed jobs (keep last 30 days) + * Runs every Sunday at 3 AM + */ + @Scheduled(cron = "0 0 3 * * SUN") + public void cleanupOldJobs() { + if (!scheduledSyncEnabled) { + return; + } + + logger.info("Running cleanup of old sync jobs..."); + + // TODO: Implement cleanup logic + // Delete jobs older than 30 days with status COMPLETED or FAILED + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/config/ElasticsearchConfig.java b/src/main/java/com/iemr/common/identity/config/ElasticsearchConfig.java new file mode 100644 index 00000000..a908b646 --- /dev/null +++ b/src/main/java/com/iemr/common/identity/config/ElasticsearchConfig.java @@ -0,0 +1,100 @@ +package com.iemr.common.identity.config; + +import java.io.IOException; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.elasticsearch.client.RestClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ElasticsearchConfig { + + private static final Logger logger = LoggerFactory.getLogger(ElasticsearchConfig.class); + + @Value("${elasticsearch.host}") + private String esHost; + + @Value("${elasticsearch.port}") + private int esPort; + + @Value("${elasticsearch.username}") + private String esUsername; + + @Value("${elasticsearch.password}") + private String esPassword; + + @Value("${elasticsearch.index.beneficiary}") + private String indexName; + + @Bean + public ElasticsearchClient elasticsearchClient() { + BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials( + AuthScope.ANY, + new UsernamePasswordCredentials(esUsername, esPassword) + ); + + RestClient restClient = RestClient.builder( + new HttpHost(esHost, esPort, "http") + ).setHttpClientConfigCallback(httpClientBuilder -> + httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider) + ).build(); + + ElasticsearchTransport transport = new RestClientTransport( + restClient, + new JacksonJsonpMapper() + ); + + return new ElasticsearchClient(transport); + } + + @Bean + public Boolean createIndexMapping(ElasticsearchClient client) throws IOException { + + // Check if index exists + boolean exists = client.indices().exists(e -> e.index(indexName)).value(); + + if (!exists) { + client.indices().create(c -> c + .index(indexName) + .mappings(m -> m + .properties("beneficiaryRegID", p -> p.keyword(k -> k)) + .properties("firstName", p -> p.text(t -> t + .fields("keyword", f -> f.keyword(k -> k)) + .analyzer("standard") + )) + .properties("lastName", p -> p.text(t -> t + .fields("keyword", f -> f.keyword(k -> k)) + .analyzer("standard") + )) + .properties("phoneNum", p -> p.keyword(k -> k)) + .properties("fatherName", p -> p.text(t -> t.analyzer("standard"))) + .properties("spouseName", p -> p.text(t -> t.analyzer("standard"))) + .properties("aadharNo", p -> p.keyword(k -> k)) + .properties("govtIdentityNo", p -> p.keyword(k -> k)) + ) + .settings(s -> s + .numberOfShards("3") + .numberOfReplicas("1") + .refreshInterval(t -> t.time("1s")) + ) + ); + + logger.info("Created Elasticsearch index with proper mappings"); + } + return true; + + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/config/ElasticsearchSyncConfig.java b/src/main/java/com/iemr/common/identity/config/ElasticsearchSyncConfig.java new file mode 100644 index 00000000..bb72f91a --- /dev/null +++ b/src/main/java/com/iemr/common/identity/config/ElasticsearchSyncConfig.java @@ -0,0 +1,56 @@ +package com.iemr.common.identity.config; + +import java.util.concurrent.Executor; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +/** + * Configuration for async processing and scheduling + */ +@Configuration +@EnableAsync +@EnableScheduling +public class ElasticsearchSyncConfig { + + /** + * Thread pool for Elasticsearch sync operations + * Configured for long-running background jobs + */ + @Bean(name = "elasticsearchSyncExecutor") + public Executor elasticsearchSyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + + // Only 1-2 sync jobs should run at a time to avoid overwhelming DB/ES + executor.setCorePoolSize(5); + executor.setMaxPoolSize(10); + executor.setQueueCapacity(100); + executor.setThreadNamePrefix("es-sync-"); + executor.setKeepAliveSeconds(60); + + // Handle rejected tasks + executor.setRejectedExecutionHandler((r, executor1) -> { + throw new RuntimeException("Elasticsearch sync queue is full. Please wait for current job to complete."); + }); + + executor.initialize(); + return executor; + } + + /** + * General purpose async executor + */ + @Bean(name = "taskExecutor") + public Executor taskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(5); + executor.setMaxPoolSize(10); + executor.setQueueCapacity(100); + executor.setThreadNamePrefix("async-"); + executor.initialize(); + return executor; + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/controller/IdentityController.java b/src/main/java/com/iemr/common/identity/controller/IdentityController.java index 16995734..c90b06ca 100644 --- a/src/main/java/com/iemr/common/identity/controller/IdentityController.java +++ b/src/main/java/com/iemr/common/identity/controller/IdentityController.java @@ -99,7 +99,7 @@ public String getBeneficiaries( JsonElement json = JsonParser.parseString(searchFilter); IdentitySearchDTO searchParams = InputMapper.getInstance().gson().fromJson(json, IdentitySearchDTO.class); - List list = svc.getBeneficiaries(searchParams); + List list = svc.getBeneficiarieswithES(searchParams); list.removeIf(Objects::isNull); Collections.sort(list); response = getSuccessResponseString(list, 200, "success", "getBeneficiariesByAdvanceSearch"); diff --git a/src/main/java/com/iemr/common/identity/controller/IdentityESController.java b/src/main/java/com/iemr/common/identity/controller/IdentityESController.java new file mode 100644 index 00000000..4e4fbedf --- /dev/null +++ b/src/main/java/com/iemr/common/identity/controller/IdentityESController.java @@ -0,0 +1,69 @@ +package com.iemr.common.identity.controller; + + +import java.util.HashMap; +import java.util.*; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import com.iemr.common.identity.service.elasticsearch.ElasticsearchService; +import com.iemr.common.identity.utils.CookieUtil; +import com.iemr.common.identity.utils.JwtUtil; + +import jakarta.servlet.http.HttpServletRequest; + +/** + * Elasticsearch-enabled Beneficiary Search Controller + * All search endpoints with ES support + */ +@RestController +@RequestMapping("/beneficiary") +public class IdentityESController { + + private static final Logger logger = LoggerFactory.getLogger(IdentityESController.class); + + @Autowired + private ElasticsearchService elasticsearchService; + + @Autowired + private JwtUtil jwtUtil; + + /** + * MAIN UNIVERSAL SEARCH ENDPOINT + * Searches across all fields - name, phone, ID, etc. + * + * Usage: GET /beneficiary/search?query=vani + * Usage: GET /beneficiary/search?query=9876543210 + */ + @GetMapping("/search") + public ResponseEntity> search(@RequestParam String query, HttpServletRequest request) { + try { + String jwtToken = CookieUtil.getJwtTokenFromCookie(request); + String userId = jwtUtil.getUserIdFromToken(jwtToken); + int userID=Integer.parseInt(userId); + List> results = elasticsearchService.universalSearch(query, userID); + + Map response = new HashMap<>(); + response.put("data", results); + response.put("statusCode", 200); + response.put("errorMessage", "Success"); + response.put("status", "Success"); + + return ResponseEntity.ok(response); + + } catch (Exception e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("data", new ArrayList<>()); + errorResponse.put("statusCode", 500); + errorResponse.put("errorMessage", e.getMessage()); + errorResponse.put("status", "Error"); + + return ResponseEntity.status(500).body(errorResponse); + } + } + + +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/controller/elasticsearch/ElasticsearchSyncController.java b/src/main/java/com/iemr/common/identity/controller/elasticsearch/ElasticsearchSyncController.java new file mode 100644 index 00000000..075e7239 --- /dev/null +++ b/src/main/java/com/iemr/common/identity/controller/elasticsearch/ElasticsearchSyncController.java @@ -0,0 +1,432 @@ +package com.iemr.common.identity.controller.elasticsearch; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; + +import com.iemr.common.identity.data.elasticsearch.ElasticsearchSyncJob; +import com.iemr.common.identity.repo.BenMappingRepo; +import com.iemr.common.identity.service.elasticsearch.ElasticsearchSyncService; +import com.iemr.common.identity.service.elasticsearch.SyncJobService; +import com.iemr.common.identity.service.elasticsearch.ElasticsearchSyncService.SyncStatus; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.springframework.http.ResponseEntity; +import com.iemr.common.identity.utils.response.OutputResponse; +import com.iemr.common.identity.domain.MBeneficiarymapping; +import com.iemr.common.identity.service.elasticsearch.ElasticsearchIndexingService; + +/** + * Controller to manage Elasticsearch synchronization operations + * Supports both synchronous and asynchronous sync jobs + */ +@RestController +@RequestMapping("/elasticsearch") +public class ElasticsearchSyncController { + + private static final Logger logger = LoggerFactory.getLogger(ElasticsearchSyncController.class); + + @Autowired + private ElasticsearchSyncService syncService; + + @Autowired + private SyncJobService syncJobService; + + @Autowired + private BenMappingRepo mappingRepo; + + @Autowired + private ElasticsearchIndexingService indexingService; + + /** + * Start async full sync (RECOMMENDED for millions of records) + * Returns immediately with job ID for tracking + * + * Usage: POST http://localhost:8080/elasticsearch/sync/start + */ + @PostMapping("/start") + public ResponseEntity> startAsyncFullSync( + @RequestParam(required = false, defaultValue = "API") String triggeredBy) { + + logger.info("Received request to start ASYNC full sync"); + + Map response = new HashMap<>(); + + try { + ElasticsearchSyncJob job = syncJobService.startFullSyncJob(triggeredBy); + + response.put("status", "success"); + response.put("message", "Sync job started in background"); + response.put("jobId", job.getJobId()); + response.put("jobStatus", job.getStatus()); + response.put("checkStatusUrl", "/elasticsearch/status/" + job.getJobId()); + + return ResponseEntity.ok(response); + + } catch (RuntimeException e) { + logger.error("Error starting async sync: {}", e.getMessage()); + response.put("status", "error"); + response.put("message", e.getMessage()); + return ResponseEntity.status(HttpStatus.CONFLICT).body(response); + + } catch (Exception e) { + logger.error("Unexpected error: {}", e.getMessage(), e); + response.put("status", "error"); + response.put("message", "Unexpected error: " + e.getMessage()); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response); + } + } + + /** + * Get job status by ID + * + * Usage: GET http://localhost:8080/elasticsearch/sync/status/1 + */ + @GetMapping("/status/{jobId}") + public ResponseEntity> getAsyncJobStatus(@PathVariable Long jobId) { + logger.info("Checking status for job: {}", jobId); + + try { + ElasticsearchSyncJob job = syncJobService.getJobStatus(jobId); + + Map response = new HashMap<>(); + response.put("jobId", job.getJobId()); + response.put("jobType", job.getJobType()); + response.put("status", job.getStatus()); + response.put("totalRecords", job.getTotalRecords()); + response.put("processedRecords", job.getProcessedRecords()); + response.put("successCount", job.getSuccessCount()); + response.put("failureCount", job.getFailureCount()); + response.put("progressPercentage", String.format("%.2f", job.getProgressPercentage())); + response.put("processingSpeed", job.getProcessingSpeed()); + response.put("estimatedTimeRemaining", job.getEstimatedTimeRemaining()); + response.put("startedAt", job.getStartedAt()); + response.put("completedAt", job.getCompletedAt()); + response.put("errorMessage", job.getErrorMessage()); + + return ResponseEntity.ok(response); + + } catch (RuntimeException e) { + Map response = new HashMap<>(); + response.put("status", "error"); + response.put("message", e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response); + } + } + + /** + * Get all active jobs + * + * Usage: GET http://localhost:8080/elasticsearch/sync/active + */ + @GetMapping("/active") + public ResponseEntity> getActiveJobs() { + logger.info("Fetching active jobs"); + return ResponseEntity.ok(syncJobService.getActiveJobs()); + } + + /** + * Get recent jobs + * + * Usage: GET http://localhost:8080/elasticsearch/sync/recent + */ + @GetMapping("/recent") + public ResponseEntity> getRecentJobs() { + logger.info("Fetching recent jobs"); + return ResponseEntity.ok(syncJobService.getRecentJobs()); + } + + /** + * Resume a failed job + * + * Usage: POST http://localhost:8080/elasticsearch/sync/resume/1 + */ + @PostMapping("/resume/{jobId}") + public ResponseEntity> resumeJob( + @PathVariable Long jobId, + @RequestParam(required = false, defaultValue = "API") String triggeredBy) { + + logger.info("Resuming job: {}", jobId); + + Map response = new HashMap<>(); + + try { + ElasticsearchSyncJob job = syncJobService.resumeJob(jobId, triggeredBy); + + response.put("status", "success"); + response.put("message", "Job resumed"); + response.put("jobId", job.getJobId()); + response.put("resumedFromOffset", job.getCurrentOffset()); + + return ResponseEntity.ok(response); + + } catch (RuntimeException e) { + response.put("status", "error"); + response.put("message", e.getMessage()); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response); + } + } + + /** + * Cancel a running job + * + * Usage: POST http://localhost:8080/elasticsearch/sync/cancel/1 + */ + @PostMapping("/cancel/{jobId}") + public ResponseEntity> cancelJob(@PathVariable Long jobId) { + logger.info("Cancelling job: {}", jobId); + + Map response = new HashMap<>(); + boolean cancelled = syncJobService.cancelJob(jobId); + + if (cancelled) { + response.put("status", "success"); + response.put("message", "Job cancelled"); + return ResponseEntity.ok(response); + } else { + response.put("status", "error"); + response.put("message", "Could not cancel job. It may not be active."); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response); + } + } + + /** + * LEGACY: Synchronous full sync (NOT recommended for large datasets) + * Use /start instead + * + * Usage: POST http://localhost:8080/elasticsearch/sync/all + */ + @PostMapping("/all") + public ResponseEntity> syncAllBeneficiaries() { + logger.warn("LEGACY sync endpoint called. Consider using /start instead."); + logger.info("Received request to sync all beneficiaries (BLOCKING)"); + + Map response = new HashMap<>(); + + try { + ElasticsearchSyncService.SyncResult result = syncService.syncAllBeneficiaries(); + + response.put("status", "completed"); + response.put("successCount", result.getSuccessCount()); + response.put("failureCount", result.getFailureCount()); + response.put("error", result.getError()); + response.put("warning", "This is a blocking operation. For large datasets, use /start"); + + if (result.getError() != null) { + return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT).body(response); + } + + return ResponseEntity.ok(response); + + } catch (Exception e) { + logger.error("Error in sync all endpoint: {}", e.getMessage(), e); + response.put("status", "error"); + response.put("message", e.getMessage()); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response); + } + } + + /** + * Sync a single beneficiary by BenRegId + * + * Usage: POST http://localhost:8080/elasticsearch/sync/single/123456 + */ + @PostMapping("/single/{benRegId}") + public ResponseEntity> syncSingleBeneficiary( + @PathVariable String benRegId) { + logger.info("Received request to sync single beneficiary: {}", benRegId); + + Map response = new HashMap<>(); + + try { + boolean success = syncService.syncSingleBeneficiary(benRegId); + + response.put("status", success ? "success" : "failed"); + response.put("benRegId", benRegId); + response.put("synced", success); + + if (!success) { + response.put("message", "Beneficiary not found in database or sync failed. Check logs for details."); + } else { + response.put("message", "Beneficiary successfully synced to Elasticsearch"); + } + + return ResponseEntity.ok(response); + + } catch (Exception e) { + logger.error("Error syncing single beneficiary: {}", e.getMessage(), e); + response.put("status", "error"); + response.put("benRegId", benRegId); + response.put("synced", false); + response.put("message", "Exception occurred: " + e.getMessage()); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response); + } + } + + /** + * Check sync status - compare DB count vs ES count + * + * Usage: GET http://localhost:8080/elasticsearch/sync/status + */ + @GetMapping("/status") + public ResponseEntity checkSyncStatus() { + logger.info("Received request to check sync status"); + + try { + SyncStatus status = syncService.checkSyncStatus(); + return ResponseEntity.ok(status); + + } catch (Exception e) { + logger.error("Error checking sync status: {}", e.getMessage(), e); + SyncStatus errorStatus = new SyncStatus(); + errorStatus.setError(e.getMessage()); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorStatus); + } + } + + /** + * Health check endpoint + * + * Usage: GET http://localhost:8080/elasticsearch/sync/health + */ + @GetMapping("/health") + public ResponseEntity> healthCheck() { + Map response = new HashMap<>(); + response.put("status", "UP"); + response.put("service", "Elasticsearch Sync Service"); + response.put("asyncJobsRunning", syncJobService.isFullSyncRunning()); + response.put("activeJobs", syncJobService.getActiveJobs().size()); + return ResponseEntity.ok(response); + } + + /** + * Debug endpoint to check if a beneficiary exists in database + * + * Usage: GET http://localhost:8080/elasticsearch/sync/debug/check/123456 + */ + @GetMapping("/debug/check/{benRegId}") + public ResponseEntity> checkBeneficiaryExists( + @PathVariable String benRegId) { + logger.info("Checking if beneficiary exists: {}", benRegId); + + Map response = new HashMap<>(); + + try { + java.math.BigInteger benRegIdBig = new java.math.BigInteger(benRegId); + + boolean exists = mappingRepo.existsByBenRegId(benRegIdBig); + + response.put("benRegId", benRegId); + response.put("existsInDatabase", exists); + + if (exists) { + response.put("message", "Beneficiary found in database"); + + MBeneficiarymapping mapping = + mappingRepo.findByBenRegId(benRegIdBig); + + if (mapping != null) { + response.put("benMapId", mapping.getBenMapId()); + response.put("deleted", mapping.getDeleted()); + response.put("hasDetails", mapping.getMBeneficiarydetail() != null); + response.put("hasContact", mapping.getMBeneficiarycontact() != null); + } + } else { + response.put("message", "Beneficiary NOT found in database"); + } + + return ResponseEntity.ok(response); + + } catch (Exception e) { + logger.error("Error checking beneficiary: {}", e.getMessage(), e); + response.put("status", "error"); + response.put("message", e.getMessage()); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response); + } + } + + /** + * Create or recreate the Elasticsearch index with proper mapping + * This will DELETE the existing index and create a new one + * + * POST /elasticsearch/index/create + */ + @PostMapping("/index/create") + public ResponseEntity createIndex() { + logger.info("API: Create Elasticsearch index request received"); + OutputResponse response = new OutputResponse(); + + try { + indexingService.createIndexWithMapping(); + + response.setResponse("Index created successfully. Ready for data sync."); + logger.info("Index created successfully"); + + return ResponseEntity.ok(response); + + } catch (Exception e) { + logger.error("Error creating index: {}", e.getMessage(), e); + response.setError(5000, "Error creating index: " + e.getMessage()); + return ResponseEntity.status(500).body(response); + } + } + + /** + * Recreate index and immediately start syncing data + * This is a convenience endpoint that does both operations + * + * POST /elasticsearch/index/recreate-and-sync + */ + @PostMapping("/index/recreate-and-sync") + public ResponseEntity recreateAndSync() { + logger.info("API: Recreate index and sync request received"); + OutputResponse response = new OutputResponse(); + + try { + // Step 1: Recreate index + logger.info("Step 1: Recreating index..."); + indexingService.createIndexWithMapping(); + logger.info("Index recreated successfully"); + + // Step 2: Start sync + logger.info("Step 2: Starting data sync..."); + Map syncResult = indexingService.indexAllBeneficiaries(); + + response.setResponse("Index recreated and sync started. Success: " + + syncResult.get("success") + ", Failed: " + syncResult.get("failed")); + + return ResponseEntity.ok(response); + + } catch (Exception e) { + logger.error("Error in recreate and sync: {}", e.getMessage(), e); + response.setError(5000, "Error: " + e.getMessage()); + return ResponseEntity.status(500).body(response); + } + } + + /** + * Get information about the current index + * Shows mapping, document count, etc. + * + * GET /elasticsearch/index/info + */ + @GetMapping("/index/info") + public ResponseEntity getIndexInfo() { + logger.info("API: Get index info request received"); + OutputResponse response = new OutputResponse(); + + try { + // You can add code here to get index stats using esClient + response.setResponse("Index info endpoint - implementation pending"); + return ResponseEntity.ok(response); + + } catch (Exception e) { + logger.error("Error getting index info: {}", e.getMessage(), e); + response.setError(5000, "Error: " + e.getMessage()); + return ResponseEntity.status(500).body(response); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/data/elasticsearch/BeneficiaryDocument.java b/src/main/java/com/iemr/common/identity/data/elasticsearch/BeneficiaryDocument.java new file mode 100644 index 00000000..d8b3b01c --- /dev/null +++ b/src/main/java/com/iemr/common/identity/data/elasticsearch/BeneficiaryDocument.java @@ -0,0 +1,138 @@ +package com.iemr.common.identity.data.elasticsearch; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import java.util.Date; + +@Data +public class BeneficiaryDocument { + + @JsonProperty("benId") + private String benId; + + @JsonProperty("benRegId") + private Long benRegId; + + @JsonProperty("beneficiaryID") + private String beneficiaryID; + + @JsonProperty("firstName") + private String firstName; + + @JsonProperty("lastName") + private String lastName; + + @JsonProperty("fatherName") + private String fatherName; + + @JsonProperty("spouseName") + private String spouseName; + + @JsonProperty("age") + private Integer age; + + @JsonProperty("dOB") + private Date dOB; + + @JsonProperty("gender") + private String gender; + + @JsonProperty("genderID") + private Integer genderID; + + @JsonProperty("genderName") + private String genderName; + + @JsonProperty("phoneNum") + private String phoneNum; + + @JsonProperty("aadharNo") + private String aadharNo; + + @JsonProperty("govtIdentityNo") + private String govtIdentityNo; + + @JsonProperty("healthID") + private String healthID; + + @JsonProperty("abhaID") + private String abhaID; + + @JsonProperty("familyID") + private String familyID; + + @JsonProperty("stateID") + private Integer stateID; + + @JsonProperty("stateName") + private String stateName; + + @JsonProperty("districtID") + private Integer districtID; + + @JsonProperty("districtName") + private String districtName; + + @JsonProperty("blockID") + private Integer blockID; + + @JsonProperty("blockName") + private String blockName; + + @JsonProperty("villageID") + private Integer villageID; + + @JsonProperty("villageName") + private String villageName; + + @JsonProperty("pinCode") + private String pinCode; + + @JsonProperty("servicePointID") + private Integer servicePointID; + + @JsonProperty("servicePointName") + private String servicePointName; + + @JsonProperty("parkingPlaceID") + private Integer parkingPlaceID; + + @JsonProperty("permStateID") + private Integer permStateID; + + @JsonProperty("permStateName") + private String permStateName; + + @JsonProperty("permDistrictID") + private Integer permDistrictID; + + @JsonProperty("permDistrictName") + private String permDistrictName; + + @JsonProperty("permBlockID") + private Integer permBlockID; + + @JsonProperty("permBlockName") + private String permBlockName; + + @JsonProperty("permVillageID") + private Integer permVillageID; + + @JsonProperty("permVillageName") + private String permVillageName; + + @JsonProperty("createdBy") + private String createdBy; + + @JsonProperty("createdDate") + private Date createdDate; + + @JsonProperty("lastModDate") + private Long lastModDate; + + @JsonProperty("benAccountID") + private Long benAccountID; + + @JsonProperty("isHIVPos") + private String isHIVPos; +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/data/elasticsearch/ElasticsearchSyncJob.java b/src/main/java/com/iemr/common/identity/data/elasticsearch/ElasticsearchSyncJob.java new file mode 100644 index 00000000..11a854bc --- /dev/null +++ b/src/main/java/com/iemr/common/identity/data/elasticsearch/ElasticsearchSyncJob.java @@ -0,0 +1,95 @@ +package com.iemr.common.identity.data.elasticsearch; + +import java.sql.Timestamp; +import java.math.BigInteger; +import jakarta.persistence.*; +import lombok.Data; + +/** + * Entity to track Elasticsearch sync job status + */ +@Entity +@Table(name = "t_elasticsearch_sync_job") +@Data +public class ElasticsearchSyncJob { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "job_id") + private Long jobId; + + @Column(name = "job_type", length = 50, nullable = false) + private String jobType; // FULL_SYNC, INCREMENTAL_SYNC, SINGLE_BENEFICIARY + + @Column(name = "status", length = 50, nullable = false) + private String status; // PENDING, RUNNING, COMPLETED, FAILED, CANCELLED + + @Column(name = "total_records") + private Long totalRecords; + + @Column(name = "processed_records") + private Long processedRecords; + + @Column(name = "success_count") + private Long successCount; + + @Column(name = "failure_count") + private Long failureCount; + + @Column(name = "current_offset") + private Integer currentOffset; + + @Column(name = "started_at") + private Timestamp startedAt; + + @Column(name = "completed_at") + private Timestamp completedAt; + + @Column(name = "error_message", columnDefinition = "TEXT") + private String errorMessage; + + @Column(name = "triggered_by", length = 100) + private String triggeredBy; // User who triggered the job + + @Column(name = "created_date", nullable = false, updatable = false) + private Timestamp createdDate; + + @Column(name = "last_updated") + private Timestamp lastUpdated; + + @Column(name = "estimated_time_remaining") + private Long estimatedTimeRemaining; // in seconds + + @Column(name = "processing_speed") + private Double processingSpeed; // records per second + + @PrePersist + protected void onCreate() { + createdDate = new Timestamp(System.currentTimeMillis()); + lastUpdated = createdDate; + } + + @PreUpdate + protected void onUpdate() { + lastUpdated = new Timestamp(System.currentTimeMillis()); + } + + /** + * Calculate progress percentage + */ + @Transient + public double getProgressPercentage() { + if (totalRecords == null || totalRecords == 0) { + return 0.0; + } + return (processedRecords * 100.0) / totalRecords; + } + + /** + * Check if job is active (running) + */ + @Transient + public boolean isActive() { + return "RUNNING".equals(status) || "PENDING".equals(status); + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/domain/User.java b/src/main/java/com/iemr/common/identity/domain/User.java index 916709f3..f35a5607 100644 --- a/src/main/java/com/iemr/common/identity/domain/User.java +++ b/src/main/java/com/iemr/common/identity/domain/User.java @@ -15,7 +15,8 @@ import jakarta.persistence.Table; import lombok.Data; @Entity -@Table(name = "m_User",schema = "db_iemr") +@Table(schema = "db_iemr", name = "m_user") +@JsonIgnoreProperties(ignoreUnknown = true) @Data public class User { @Id diff --git a/src/main/java/com/iemr/common/identity/dto/BeneficiariesESDTO.java b/src/main/java/com/iemr/common/identity/dto/BeneficiariesESDTO.java new file mode 100644 index 00000000..b8d92536 --- /dev/null +++ b/src/main/java/com/iemr/common/identity/dto/BeneficiariesESDTO.java @@ -0,0 +1,172 @@ +package com.iemr.common.identity.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; +import java.util.Date; +import java.util.List; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class BeneficiariesESDTO { + + @JsonProperty("benRegId") + private Long benRegId; + + @JsonProperty("beneficiaryID") + private String beneficiaryID; + + @JsonProperty("firstName") + private String firstName; + + @JsonProperty("lastName") + private String lastName; + + @JsonProperty("genderID") + private Integer genderID; + + @JsonProperty("genderName") + private String genderName; + + @JsonProperty("dOB") + private Date dOB; + + @JsonProperty("age") + private Integer age; + + @JsonProperty("phoneNum") + private String phoneNum; + + // @JsonProperty("aadharNo") + // private String aadharNo; + + // @JsonProperty("govtIdentityNo") + // private String govtIdentityNo; + + @JsonProperty("fatherName") + private String fatherName; + + @JsonProperty("spouseName") + private String spouseName; + + @JsonProperty("createdBy") + private String createdBy; + + @JsonProperty("createdDate") + private Date createdDate; + + @JsonProperty("lastModDate") + private Long lastModDate; + + @JsonProperty("benAccountID") + private Long benAccountID; + + @JsonProperty("isHIVPos") + private String isHIVPos; + + @JsonProperty("healthID") + private String healthID; + + @JsonProperty("abhaID") + private String abhaID; + + @JsonProperty("familyID") + private String familyID; + + @JsonProperty("stateID") + private Integer stateID; + + @JsonProperty("stateName") + private String stateName; + + @JsonProperty("stateCode") + private String stateCode; + + @JsonProperty("districtID") + private Integer districtID; + + @JsonProperty("districtName") + private String districtName; + + @JsonProperty("blockID") + private Integer blockID; + + @JsonProperty("blockName") + private String blockName; + + @JsonProperty("villageID") + private Integer villageID; + + @JsonProperty("villageName") + private String villageName; + + @JsonProperty("districtBranchID") + private Integer districtBranchID; + + @JsonProperty("districtBranchName") + private String districtBranchName; + + @JsonProperty("parkingPlaceID") + private Integer parkingPlaceID; + + @JsonProperty("servicePointID") + private Integer servicePointID; + + @JsonProperty("servicePointName") + private String servicePointName; + + @JsonProperty("pinCode") + private String pinCode; + + @JsonProperty("permStateID") + private Integer permStateID; + + @JsonProperty("permStateName") + private String permStateName; + + @JsonProperty("permDistrictID") + private Integer permDistrictID; + + @JsonProperty("permDistrictName") + private String permDistrictName; + + @JsonProperty("permBlockID") + private Integer permBlockID; + + @JsonProperty("permBlockName") + private String permBlockName; + + @JsonProperty("permVillageID") + private Integer permVillageID; + + @JsonProperty("permVillageName") + private String permVillageName; + + @JsonProperty("phoneNumbers") + private List phoneNumbers; + + @Data + @NoArgsConstructor + @AllArgsConstructor + @JsonIgnoreProperties(ignoreUnknown = true) + public static class PhoneNumberDTO { + @JsonProperty("benPhMapID") + private Long benPhMapID; + + @JsonProperty("phoneNo") + private String phoneNo; + + @JsonProperty("parentBenRegID") + private Long parentBenRegID; + + @JsonProperty("benRelationshipID") + private Integer benRelationshipID; + + @JsonProperty("benRelationshipType") + private String benRelationshipType; + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/dto/IdentitySearchDTO.java b/src/main/java/com/iemr/common/identity/dto/IdentitySearchDTO.java index db4bf011..855f8dba 100644 --- a/src/main/java/com/iemr/common/identity/dto/IdentitySearchDTO.java +++ b/src/main/java/com/iemr/common/identity/dto/IdentitySearchDTO.java @@ -30,6 +30,7 @@ import lombok.Data; @Data +@lombok.Builder public class IdentitySearchDTO { private BigInteger beneficiaryId; diff --git a/src/main/java/com/iemr/common/identity/mapper/BeneficiaryESMapper.java b/src/main/java/com/iemr/common/identity/mapper/BeneficiaryESMapper.java new file mode 100644 index 00000000..4cec8d2e --- /dev/null +++ b/src/main/java/com/iemr/common/identity/mapper/BeneficiaryESMapper.java @@ -0,0 +1,136 @@ +package com.iemr.common.identity.mapper; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.stereotype.Component; + +import java.util.*; + +@Component +public class BeneficiaryESMapper { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + public Map transformESResponse(List> esResults) { + List> transformedData = new ArrayList<>(); + + for (Map esDoc : esResults) { + Map beneficiary = new HashMap<>(); + + beneficiary.put("beneficiaryRegID", esDoc.get("beneficiaryRegID")); + beneficiary.put("beneficiaryID", esDoc.get("beneficiaryID")); + beneficiary.put("firstName", esDoc.get("firstName")); + beneficiary.put("lastName", esDoc.get("lastName")); + beneficiary.put("genderID", esDoc.get("genderID")); + beneficiary.put("genderName", esDoc.get("genderName")); + beneficiary.put("dOB", esDoc.get("dOB")); + beneficiary.put("dob", esDoc.get("dOB")); + beneficiary.put("age", esDoc.get("age")); + beneficiary.put("actualAge", esDoc.get("age")); + beneficiary.put("ageUnits", "Years"); + beneficiary.put("fatherName", esDoc.getOrDefault("fatherName", "")); + beneficiary.put("spouseName", esDoc.getOrDefault("spouseName", "")); + beneficiary.put("isHIVPos", esDoc.getOrDefault("isHIVPos", "")); + beneficiary.put("createdBy", esDoc.get("createdBy")); + beneficiary.put("createdDate", esDoc.get("createdDate")); + beneficiary.put("lastModDate", esDoc.get("lastModDate")); + beneficiary.put("benAccountID", esDoc.get("benAccountID")); + + Map mGender = new HashMap<>(); + mGender.put("genderID", esDoc.get("genderID")); + mGender.put("genderName", esDoc.get("genderName")); + beneficiary.put("m_gender", mGender); + + Map demographics = (Map) esDoc.get("demographics"); + if (demographics != null) { + Map benDemographics = new HashMap<>(demographics); + benDemographics.put("beneficiaryRegID", esDoc.get("beneficiaryRegID")); + + benDemographics.put("m_state", createStateObject(demographics)); + benDemographics.put("m_district", createDistrictObject(demographics)); + benDemographics.put("m_districtblock", createBlockObject(demographics)); + benDemographics.put("m_districtbranchmapping", createBranchObject(demographics)); + + beneficiary.put("i_bendemographics", benDemographics); + } + + List> phoneMaps = new ArrayList<>(); + List> phoneNumbers = (List>) esDoc.get("phoneNumbers"); + if (phoneNumbers != null && !phoneNumbers.isEmpty()) { + for (Map phone : phoneNumbers) { + Map phoneMap = new HashMap<>(phone); + phoneMap.put("benificiaryRegID", esDoc.get("beneficiaryRegID")); + + Map relationType = new HashMap<>(); + relationType.put("benRelationshipID", phone.get("benRelationshipID")); + relationType.put("benRelationshipType", phone.get("benRelationshipType")); + phoneMap.put("benRelationshipType", relationType); + + phoneMaps.add(phoneMap); + } + } + beneficiary.put("benPhoneMaps", phoneMaps); + + beneficiary.put("isConsent", false); + beneficiary.put("m_title", new HashMap<>()); + beneficiary.put("maritalStatus", new HashMap<>()); + beneficiary.put("changeInSelfDetails", false); + beneficiary.put("changeInAddress", false); + beneficiary.put("changeInContacts", false); + beneficiary.put("changeInIdentities", false); + beneficiary.put("changeInOtherDetails", false); + beneficiary.put("changeInFamilyDetails", false); + beneficiary.put("changeInAssociations", false); + beneficiary.put("changeInBankDetails", false); + beneficiary.put("changeInBenImage", false); + beneficiary.put("is1097", false); + beneficiary.put("emergencyRegistration", false); + beneficiary.put("passToNurse", false); + beneficiary.put("beneficiaryIdentities", new ArrayList<>()); + + transformedData.add(beneficiary); + } + + Map response = new HashMap<>(); + response.put("data", transformedData); + response.put("statusCode", 200); + response.put("errorMessage", "Success"); + response.put("status", "Success"); + + return response; + } + + private Map createStateObject(Map demographics) { + Map state = new HashMap<>(); + state.put("stateID", demographics.get("stateID")); + state.put("stateName", demographics.get("stateName")); + state.put("stateCode", demographics.get("stateCode")); + state.put("countryID", 1); + return state; + } + + private Map createDistrictObject(Map demographics) { + Map district = new HashMap<>(); + district.put("districtID", demographics.get("districtID")); + district.put("districtName", demographics.get("districtName")); + district.put("stateID", demographics.get("stateID")); + return district; + } + + private Map createBlockObject(Map demographics) { + Map block = new HashMap<>(); + block.put("blockID", demographics.get("blockID")); + block.put("blockName", demographics.get("blockName")); + block.put("districtID", demographics.get("districtID")); + block.put("stateID", demographics.get("stateID")); + return block; + } + + private Map createBranchObject(Map demographics) { + Map branch = new HashMap<>(); + branch.put("districtBranchID", demographics.get("districtBranchID")); + branch.put("blockID", demographics.get("blockID")); + branch.put("villageName", demographics.get("districtBranchName")); + branch.put("pinCode", demographics.get("pinCode")); + return branch; + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/repo/BenAddressRepo.java b/src/main/java/com/iemr/common/identity/repo/BenAddressRepo.java index d9339ab2..5d79f8ae 100644 --- a/src/main/java/com/iemr/common/identity/repo/BenAddressRepo.java +++ b/src/main/java/com/iemr/common/identity/repo/BenAddressRepo.java @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see https://www.gnu.org/licenses/. -*/ + */ package com.iemr.common.identity.repo; import java.math.BigInteger; @@ -36,42 +36,59 @@ @Repository public interface BenAddressRepo extends CrudRepository { - List findByBenAddressIDOrderByBenAddressIDAsc(BigInteger benAddressID); - List findByCurrPinCodeOrderByBenAddressIDAsc(String currPinCode); + List findByBenAddressIDOrderByBenAddressIDAsc(BigInteger benAddressID); - List findByPermPinCodeOrderByBenAddressIDAsc(String permPinCode); + List findByCurrPinCodeOrderByBenAddressIDAsc(String currPinCode); - List findByCurrStateAndCurrDistrictOrderByBenAddressIDAsc(String currState, String currDist); + List findByPermPinCodeOrderByBenAddressIDAsc(String permPinCode); - List findByCurrStateIdAndCurrDistrictIdOrderByBenAddressIDAsc(Integer currStateID, - Integer currDistID); + List findByCurrStateAndCurrDistrictOrderByBenAddressIDAsc(String currState, String currDist); - List findByPermStateAndPermDistrictOrderByBenAddressIDAsc(String permState, String permDist); + List findByCurrStateIdAndCurrDistrictIdOrderByBenAddressIDAsc(Integer currStateID, + Integer currDistID); - List findByPermStateIdAndPermDistrictIdOrderByBenAddressIDAsc(Integer permStateID, - Integer permDistID); + List findByPermStateAndPermDistrictOrderByBenAddressIDAsc(String permState, String permDist); - List findByEmerStateAndEmerDistrictOrderByBenAddressIDAsc(String emerState, String emerDist); + List findByPermStateIdAndPermDistrictIdOrderByBenAddressIDAsc(Integer permStateID, + Integer permDistID); - List findByEmerStateIdAndEmerDistrictIdOrderByBenAddressIDAsc(Integer emerStateID, - Integer emerDistID); + List findByEmerStateAndEmerDistrictOrderByBenAddressIDAsc(String emerState, String emerDist); - List findByCreatedDateBetweenOrderByBenAddressIDAsc(Timestamp fromDate, Timestamp toDate); + List findByEmerStateIdAndEmerDistrictIdOrderByBenAddressIDAsc(Integer emerStateID, + Integer emerDistID); - @Query("select a from MBeneficiaryaddress a where a.currAddressValue = :address or " - + "a.emerAddressValue = :address or a.permAddressValue = :address order by a.benAddressID asc") - List findByAddress(String address); + List findByCreatedDateBetweenOrderByBenAddressIDAsc(Timestamp fromDate, Timestamp toDate); - @Transactional - @Modifying - @Query(" UPDATE MBeneficiaryaddress set vanSerialNo = :benAddressID WHERE benAddressID = :benAddressID") - int updateVanSerialNo(@Param("benAddressID") BigInteger benAddressID); + @Query("select a from MBeneficiaryaddress a where a.currAddressValue = :address or " + + "a.emerAddressValue = :address or a.permAddressValue = :address order by a.benAddressID asc") + List findByAddress(String address); - @Query("SELECT benAddressID FROM MBeneficiaryaddress WHERE vanSerialNo =:vanSerialNo AND vanID =:vanID ") - BigInteger findIdByVanSerialNoAndVanID(@Param("vanSerialNo") BigInteger vanSerialNo, @Param("vanID") Integer vanID); + @Transactional + @Modifying + @Query(" UPDATE MBeneficiaryaddress set vanSerialNo = :benAddressID WHERE benAddressID = :benAddressID") + int updateVanSerialNo(@Param("benAddressID") BigInteger benAddressID); + + @Query("SELECT benAddressID FROM MBeneficiaryaddress WHERE vanSerialNo =:vanSerialNo AND vanID =:vanID ") + BigInteger findIdByVanSerialNoAndVanID(@Param("vanSerialNo") BigInteger vanSerialNo, @Param("vanID") Integer vanID); + + @Query("SELECT a FROM MBeneficiaryaddress a WHERE a.vanSerialNo =:vanSerialNo AND a.vanID =:vanID ") + MBeneficiaryaddress getWithVanSerialNoVanID(@Param("vanSerialNo") BigInteger vanSerialNo, + @Param("vanID") Integer vanID); + + /** + * Get user location details from m_userservicerolemapping + */ + @Query(value = "SELECT " + + "ProviderServiceMapID, " + + "Blockid, " + + "Villageid, " + + "WorkingLocationID " + + "FROM db_iemr.m_userservicerolemapping " + + "WHERE UserID = :userId " + + "AND Deleted = false " + + "LIMIT 1", + nativeQuery = true) + List getUserLocation(@Param("userId") Integer userId); - @Query("SELECT a FROM MBeneficiaryaddress a WHERE a.vanSerialNo =:vanSerialNo AND a.vanID =:vanID ") - MBeneficiaryaddress getWithVanSerialNoVanID(@Param("vanSerialNo") BigInteger vanSerialNo, - @Param("vanID") Integer vanID); } diff --git a/src/main/java/com/iemr/common/identity/repo/BenDetailRepo.java b/src/main/java/com/iemr/common/identity/repo/BenDetailRepo.java index 3a8be24f..c7f0bbfa 100644 --- a/src/main/java/com/iemr/common/identity/repo/BenDetailRepo.java +++ b/src/main/java/com/iemr/common/identity/repo/BenDetailRepo.java @@ -147,4 +147,134 @@ int untagFamily(@Param("modifiedBy") String modifiedBy, @Param("vanSerialNo") Bi @Query("SELECT b FROM MBeneficiarydetail b WHERE b.familyId =:familyid ") List searchByFamilyId(@Param("familyid") String familyid); + /** + * Find complete beneficiary data by IDs from Elasticsearch + */ + @Query(value = "SELECT " + + "m.BenRegId, " + // 0 + "d.BeneficiaryRegID, " + // 1 + "d.FirstName, " + // 2 + "d.LastName, " + // 3 + "d.GenderID, " + // 4 + "g.GenderName, " + // 5 + "d.DOB, " + // 6 + "TIMESTAMPDIFF(YEAR, d.DOB, CURDATE()) as Age, " + // 7 + "d.FatherName, " + // 8 + "d.SpouseName, " + // 9 + "d.IsHIVPositive, " + // 10 + "m.CreatedBy, " + // 11 + "m.CreatedDate, " + // 12 + "UNIX_TIMESTAMP(m.LastModDate) * 1000, " + // 13 + "m.BenAccountID, " + // 14 + "addr.CurrStateId, " + // 15 + "addr.CurrState, " + // 16 + "addr.CurrDistrictId, " + // 17 + "addr.CurrDistrict, " + // 18 + "addr.CurrSubDistrictId, " + // 19 + "addr.CurrSubDistrict, " + // 20 + "addr.CurrPinCode, " + // 21 + "addr.CurrServicePointId, " + // 22 + "addr.CurrServicePoint, " + // 23 + "addr.ParkingPlaceID, " + // 24 + "contact.PreferredPhoneNum " + // 25 + "FROM i_beneficiarymapping m " + + "LEFT JOIN i_beneficiarydetails d ON m.BenDetailsId = d.BeneficiaryDetailsID " + + "LEFT JOIN db_iemr.m_gender g ON d.GenderID = g.GenderID " + + "LEFT JOIN i_beneficiaryaddress addr ON m.BenAddressId = addr.BenAddressID " + + "LEFT JOIN i_beneficiarycontacts contact ON m.BenContactsId = contact.BenContactsID " + + "WHERE m.BenRegId IN (:ids) AND m.Deleted = false", + nativeQuery = true) + List findCompleteDataByIds(@Param("ids") List ids); + + /** + * Direct search in database (fallback) + */ + @Query(value = "SELECT " + + "m.BenRegId, " + + "d.BeneficiaryRegID, " + + "d.FirstName, " + + "d.LastName, " + + "d.GenderID, " + + "g.GenderName, " + + "d.DOB, " + + "TIMESTAMPDIFF(YEAR, d.DOB, CURDATE()) as Age, " + + "d.FatherName, " + + "d.SpouseName, " + + "d.IsHIVPositive, " + + "m.CreatedBy, " + + "m.CreatedDate, " + + "UNIX_TIMESTAMP(m.LastModDate) * 1000, " + + "m.BenAccountID, " + + "addr.CurrStateId, " + + "addr.CurrState, " + + "addr.CurrDistrictId, " + + "addr.CurrDistrict, " + + "addr.CurrSubDistrictId, " + + "addr.CurrSubDistrict, " + + "addr.CurrPinCode, " + + "addr.CurrServicePointId, " + + "addr.CurrServicePoint, " + + "addr.ParkingPlaceID, " + + "contact.PreferredPhoneNum " + + "FROM i_beneficiarymapping m " + + "LEFT JOIN i_beneficiarydetails d ON m.BenDetailsId = d.BeneficiaryDetailsID " + + "LEFT JOIN db_iemr.m_gender g ON d.GenderID = g.GenderID " + + "LEFT JOIN i_beneficiaryaddress addr ON m.BenAddressId = addr.BenAddressID " + + "LEFT JOIN i_beneficiarycontacts contact ON m.BenContactsId = contact.BenContactsID " + + "WHERE (d.FirstName LIKE CONCAT('%', :query, '%') " + + " OR d.LastName LIKE CONCAT('%', :query, '%') " + + " OR d.FatherName LIKE CONCAT('%', :query, '%') " + + " OR d.BeneficiaryRegID = :query " + + " OR contact.PreferredPhoneNum = :query " + + " OR contact.PhoneNum1 = :query " + + " OR contact.PhoneNum2 = :query " + + " OR contact.PhoneNum3 = :query " + + " OR contact.PhoneNum4 = :query " + + " OR contact.PhoneNum5 = :query) " + + "AND m.Deleted = false " + + "LIMIT 20", + nativeQuery = true) + List searchBeneficiaries(@Param("query") String query); + + /** + * Get all phone numbers for a beneficiary + */ + @Query(value = "SELECT " + + "contact.PreferredPhoneNum as phoneNo, " + + "'Preferred' as phoneType, " + + "1 as priority " + + "FROM i_beneficiarymapping m " + + "LEFT JOIN i_beneficiarycontacts contact ON m.BenContactsId = contact.BenContactsID " + + "WHERE m.BenRegId = :beneficiaryId AND contact.PreferredPhoneNum IS NOT NULL " + + "UNION ALL " + + "SELECT contact.PhoneNum1, contact.PhoneTyp1, 2 " + + "FROM i_beneficiarymapping m " + + "LEFT JOIN i_beneficiarycontacts contact ON m.BenContactsId = contact.BenContactsID " + + "WHERE m.BenRegId = :beneficiaryId AND contact.PhoneNum1 IS NOT NULL " + + "UNION ALL " + + "SELECT contact.PhoneNum2, contact.PhoneTyp2, 3 " + + "FROM i_beneficiarymapping m " + + "LEFT JOIN i_beneficiarycontacts contact ON m.BenContactsId = contact.BenContactsID " + + "WHERE m.BenRegId = :beneficiaryId AND contact.PhoneNum2 IS NOT NULL " + + "UNION ALL " + + "SELECT contact.PhoneNum3, contact.PhoneTyp3, 4 " + + "FROM i_beneficiarymapping m " + + "LEFT JOIN i_beneficiarycontacts contact ON m.BenContactsId = contact.BenContactsID " + + "WHERE m.BenRegId = :beneficiaryId AND contact.PhoneNum3 IS NOT NULL " + + "UNION ALL " + + "SELECT contact.PhoneNum4, contact.PhoneTyp4, 5 " + + "FROM i_beneficiarymapping m " + + "LEFT JOIN i_beneficiarycontacts contact ON m.BenContactsId = contact.BenContactsID " + + "WHERE m.BenRegId = :beneficiaryId AND contact.PhoneNum4 IS NOT NULL " + + "UNION ALL " + + "SELECT contact.PhoneNum5, contact.PhoneTyp5, 6 " + + "FROM i_beneficiarymapping m " + + "LEFT JOIN i_beneficiarycontacts contact ON m.BenContactsId = contact.BenContactsID " + + "WHERE m.BenRegId = :beneficiaryId AND contact.PhoneNum5 IS NOT NULL " + + "ORDER BY priority", + nativeQuery = true) + List findPhoneNumbersByBeneficiaryId(@Param("beneficiaryId") Long beneficiaryId); + + + } diff --git a/src/main/java/com/iemr/common/identity/repo/BenMappingRepo.java b/src/main/java/com/iemr/common/identity/repo/BenMappingRepo.java index e3080a5d..58d32861 100644 --- a/src/main/java/com/iemr/common/identity/repo/BenMappingRepo.java +++ b/src/main/java/com/iemr/common/identity/repo/BenMappingRepo.java @@ -142,4 +142,103 @@ Long getBeneficiaryCountsByVillageIDAndLastModifyDate(@Param("villageIDs") List< @Query("SELECT a FROM MBeneficiarymapping a WHERE a.vanSerialNo =:vanSerialNo AND a.vanID =:vanID ") MBeneficiarymapping getWithVanSerialNoVanID(@Param("vanSerialNo") BigInteger vanSerialNo, @Param("vanID") Integer vanID); + + @Query("SELECT b.benRegId, b.benMapId FROM MBeneficiarymapping b WHERE benRegId IS NOT NULL AND deleted = false") + List getAllBeneficiaryIds(); + + /** + * Get beneficiary IDs in batches for efficient processing + */ + @Query(value = "SELECT BenRegId FROM i_beneficiarymapping " + + "WHERE Deleted = false ORDER BY BenRegId LIMIT :limit OFFSET :offset", + nativeQuery = true) + List getBeneficiaryIdsBatch(@Param("offset") int offset, @Param("limit") int limit); + + /** + * Count total non-deleted beneficiaries + */ + @Query(value = "SELECT COUNT(*) FROM i_beneficiarymapping WHERE Deleted = false", nativeQuery = true) + long countActiveBeneficiaries(); + /** + * COMPLETE DATA FETCH - Single query with all joins + * This is the key query that fetches everything needed for ES indexing + */ + @Query(value = "SELECT " + + "m.BenRegId, " + // 0 + "d.BeneficiaryRegID, " + // 1 + "d.FirstName, " + // 2 + "d.LastName, " + // 3 + "d.GenderID, " + // 4 + "g.GenderName, " + // 5 + "d.DOB, " + // 6 + "TIMESTAMPDIFF(YEAR, d.DOB, CURDATE()), " + // 7 - age + "d.FatherName, " + // 8 + "d.SpouseName, " + // 9 + "d.IsHIVPositive, " + // 10 + "m.CreatedBy, " + // 11 + "m.CreatedDate, " + // 12 + "UNIX_TIMESTAMP(m.LastModDate) * 1000, " + // 13 + "m.BenAccountID, " + // 14 + "contact.PreferredPhoneNum, " + // 15 + "h.HealthID, " + "h.HealthIDNumber, " + "fam.BenFamilyMapId, " + + "addr.CurrStateId, " + // 19 + "addr.CurrState, " + // 20 + "addr.CurrDistrictId, " + // 21 + "addr.CurrDistrict, " + // 22 + "addr.CurrSubDistrictId, " + // 23 + "addr.CurrSubDistrict, " + // 24 + "addr.CurrVillageId, " + // 25 + "addr.CurrVillage, " + // 26 + "addr.CurrPinCode, " + // 27 + "addr.CurrServicePointId, " + // 28 + "addr.CurrServicePoint, " + // 29 + "addr.ParkingPlaceID, " + // 30 + "addr.PermStateId, " + // 31 + "addr.PermState, " + // 32 + "addr.PermDistrictId, " + // 33 + "addr.PermDistrict, " + // 34 + "addr.PermSubDistrictId, " + // 35 + "addr.PermSubDistrict, " + // 36 + "addr.PermVillageId, " + // 37 + "addr.PermVillage " + // 38 + // "id.GovtIdentityNo, " + // 39 - Aadhar/Govt ID + // "id.IdentityNo " + // 40 - Another identity + "FROM i_beneficiarymapping m " + + "LEFT JOIN i_beneficiarydetails d ON m.BenDetailsId = d.BeneficiaryDetailsID " + + "LEFT JOIN db_iemr.m_gender g ON d.GenderID = g.GenderID " + + "LEFT JOIN i_beneficiaryaddress addr ON m.BenAddressId = addr.BenAddressID " + + "LEFT JOIN i_beneficiarycontacts contact ON m.BenContactsId = contact.BenContactsID " + + "LEFT JOIN db_iemr.m_benhealthidmapping h ON m.BenRegId = h.BeneficiaryRegID " + + "LEFT JOIN i_beneficiaryfamilymapping fam " + + " ON m.BenRegId = fam.AssociatedBenRegID " + + " AND fam.Deleted = false " + + "WHERE m.BenRegId IN :benRegIds " + + "AND m.Deleted = false", + nativeQuery = true) + + List findCompleteDataByBenRegIds(@Param("benRegIds") List benRegIds); + + /** + * Find with all details (JPA approach - for single beneficiary) + */ + @Query("SELECT m FROM MBeneficiarymapping m " + + "LEFT JOIN FETCH m.mBeneficiarydetail " + + "LEFT JOIN FETCH m.mBeneficiarycontact " + + "LEFT JOIN FETCH m.mBeneficiaryaddress " + + "WHERE m.benRegId = :benRegId AND m.deleted = false") + MBeneficiarymapping findByBenRegIdWithDetails(@Param("benRegId") BigInteger benRegId); + + /** + * Simple find by benRegId + */ + @Query("SELECT m FROM MBeneficiarymapping m WHERE m.benRegId = :benRegId AND m.deleted = false") + MBeneficiarymapping findByBenRegId(@Param("benRegId") BigInteger benRegId); + + /** + * Check if beneficiary exists + */ + @Query(value = "SELECT COUNT(*) > 0 FROM i_beneficiarymapping WHERE BenRegId = :benRegId AND Deleted = false", nativeQuery = true) + boolean existsByBenRegId(@Param("benRegId") BigInteger benRegId); + + } diff --git a/src/main/java/com/iemr/common/identity/repo/elasticsearch/SyncJobRepo.java b/src/main/java/com/iemr/common/identity/repo/elasticsearch/SyncJobRepo.java new file mode 100644 index 00000000..79bc0432 --- /dev/null +++ b/src/main/java/com/iemr/common/identity/repo/elasticsearch/SyncJobRepo.java @@ -0,0 +1,43 @@ +package com.iemr.common.identity.repo.elasticsearch; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import com.iemr.common.identity.data.elasticsearch.ElasticsearchSyncJob; + +@Repository +public interface SyncJobRepo extends JpaRepository { + + /** + * Find all active (running or pending) jobs + */ + @Query("SELECT j FROM ElasticsearchSyncJob j WHERE j.status IN ('RUNNING', 'PENDING') ORDER BY j.createdDate DESC") + List findActiveJobs(); + + /** + * Check if there's any active full sync job + */ + @Query("SELECT COUNT(j) > 0 FROM ElasticsearchSyncJob j WHERE j.jobType = 'FULL_SYNC' AND j.status IN ('RUNNING', 'PENDING')") + boolean hasActiveFullSyncJob(); + + /** + * Find latest job of a specific type + */ + @Query("SELECT j FROM ElasticsearchSyncJob j WHERE j.jobType = :jobType ORDER BY j.createdDate DESC") + List findLatestJobsByType(String jobType); + + /** + * Find recent jobs (last 10) + */ + @Query("SELECT j FROM ElasticsearchSyncJob j ORDER BY j.createdDate DESC") + List findRecentJobs(); + + /** + * Find job by ID + */ + Optional findByJobId(Long jobId); +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/service/IdentityService.java b/src/main/java/com/iemr/common/identity/service/IdentityService.java index 029b60a4..305ec307 100644 --- a/src/main/java/com/iemr/common/identity/service/IdentityService.java +++ b/src/main/java/com/iemr/common/identity/service/IdentityService.java @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see https://www.gnu.org/licenses/. -*/ + */ package com.iemr.common.identity.service; import java.math.BigDecimal; @@ -90,673 +90,942 @@ import com.iemr.common.identity.repo.MBeneficiaryImageRepo; import com.iemr.common.identity.repo.V_BenAdvanceSearchRepo; import com.iemr.common.identity.repo.rmnch.RMNCHBeneficiaryDetailsRmnchRepo; +import com.iemr.common.identity.service.elasticsearch.ElasticsearchService; import com.iemr.common.identity.utils.mapper.OutputMapper; import com.iemr.common.identity.utils.response.OutputResponse; +import org.springframework.beans.factory.annotation.Value; + +import com.iemr.common.identity.service.elasticsearch.BeneficiaryElasticsearchIndexUpdater; + import jakarta.persistence.NoResultException; import jakarta.persistence.QueryTimeoutException; - @Service public class IdentityService { - private static final Logger logger = LoggerFactory.getLogger(IdentityService.class); - public static final String CREATED_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS"; - @Autowired - private DataSource dataSource; - - private JdbcTemplate jdbcTemplate; - - private JdbcTemplate getJdbcTemplate() { - return new JdbcTemplate(dataSource); - - } - - @Autowired - private RMNCHBeneficiaryDetailsRmnchRepo rMNCHBeneficiaryDetailsRmnchRepo; - - @Autowired - IdentityMapper mapper; - @Autowired - IdentityEditMapper editMapper; - @Autowired - IdentitySearchMapper searchMapper; - @Autowired - private IdentityPartialMapper partialMapper; - @Autowired - BenAddressRepo addressRepo; - @Autowired - BenConsentRepo consentRepo; - @Autowired - BenContactRepo contactRepo; - @Autowired - BenDataAccessRepo accessRepo; - @Autowired - BenDetailRepo detailRepo; - @Autowired - BenFamilyMappingRepo familyMapRepo; - @Autowired - BenIdentityRepo identityRepo; - @Autowired - BenMappingRepo mappingRepo; - @Autowired - BenRegIdMappingRepo regIdRepo; - @Autowired - BenServiceMappingRepo serviceMapRepo; - @Autowired - MBeneficiaryAccountRepo accountRepo; - @Autowired - MBeneficiaryImageRepo imageRepo; - @Autowired - private BenIdImportMapper benIdImportMapper; - @Autowired - private V_BenAdvanceSearchRepo v_BenAdvanceSearchRepo; - - public void getBenAdress() { - logger.debug("Address count: " + addressRepo.count()); - logger.debug( - "Address By Address: " + addressRepo.findByBenAddressIDOrderByBenAddressIDAsc(new BigInteger("12"))); - logger.debug("Consent count: " + consentRepo.count()); - logger.debug("Consent By Id: " + consentRepo.findByBenConsentIDOrderByBenConsentIDAsc(new BigInteger("12"))); - logger.debug("Contact count: " + contactRepo.count()); - logger.debug("Contact By Id: " + contactRepo.findByBenContactsIDOrderByBenContactsIDAsc(new BigInteger("12"))); - logger.debug("Data Access count: " + accessRepo.count()); - logger.debug("Data Access By Id: " + accessRepo.findByAccessIdOrderByAccessIdAsc(new BigInteger("12"))); - logger.debug("Detail count: " + detailRepo.count()); - logger.debug("Detail By Address: " - + detailRepo.findByBeneficiaryDetailsIdOrderByBeneficiaryDetailsIdAsc(new BigInteger("12"))); - logger.debug("FamilyMap count: " + familyMapRepo.count()); - logger.debug( - "FamilyMap By Id: " + familyMapRepo.findByBenFamilyMapIdOrderByBenFamilyMapIdAsc(new BigInteger("12"))); - logger.debug("Identity count: " + identityRepo.count()); - logger.debug("Identity By Id: " + identityRepo.findByBenIdentityId(new BigInteger("12"))); - logger.debug("Mapping count: " + mappingRepo.count()); - logger.debug("Mapping By Id: " + mappingRepo.findByBenMapIdOrderByBenMapIdAsc(new BigInteger("12"))); - } - - /** - * - * @param searchDTO - * @return - */ - public List getBeneficiaries(IdentitySearchDTO searchDTO) - throws NoResultException, QueryTimeoutException, Exception { - List list = new ArrayList(); - - /** - * if beneficiary Id present - */ - if (searchDTO.getBeneficiaryId() != null) { - logger.info("getting beneficiaries by ID for " + searchDTO.getBeneficiaryId()); - return this.getBeneficiariesByBenId(searchDTO.getBeneficiaryId()); - } - - /** - * if beneficiary Reg Id present - */ - if (searchDTO.getBeneficiaryRegId() != null) { - logger.info("getting beneficiaries by reg ID for " + searchDTO.getBeneficiaryRegId()); - return this.getBeneficiariesByBenRegId(searchDTO.getBeneficiaryRegId()); - } - - /** - * if beneficiary Reg Id present - */ - if (searchDTO.getContactNumber() != null) { - logger.info("getting beneficiaries by contact no for " + searchDTO.getContactNumber()); - List list3 = this.getBeneficiariesByPhoneNum(searchDTO.getContactNumber()); - if (!list3.isEmpty() && searchDTO.getIsD2D() != null && Boolean.TRUE.equals(searchDTO.getIsD2D())) { - - for (int i = 0; i < list3.size(); i++) { - if (searchDTO.getFirstName() != null) { - if (list3.get(i) == null || list3.get(i).getBeneficiaryDetails() == null - || list3.get(i).getBeneficiaryDetails().getFirstName() == null - || !list3.get(i).getBeneficiaryDetails().getFirstName() - .equalsIgnoreCase(searchDTO.getFirstName())) { - list3.remove(i); - i--; - - continue; - } - - } - if (searchDTO.getLastName() != null) { - if (list3.get(i) == null || list3.get(i).getBeneficiaryDetails() == null - || list3.get(i).getBeneficiaryDetails().getLastName() == null - || !list3.get(i).getBeneficiaryDetails().getLastName() - .equalsIgnoreCase(searchDTO.getLastName())) { - list3.remove(i); - i--; - - continue; - } - } - - if (searchDTO.getGenderId() != null) { - if (list3.get(i) == null || list3.get(i).getBeneficiaryDetails() == null - || list3.get(i).getBeneficiaryDetails().getGenderId() == null || !list3.get(i) - .getBeneficiaryDetails().getGenderId().equals(searchDTO.getGenderId())) { - - list3.remove(i); - i--; - continue; - } - } - if (searchDTO.getHouseHoldID() != null) { - if (list3.get(i) == null || list3.get(i).getBeneficiaryDetails() == null - || list3.get(i).getBeneficiaryDetails().getHouseHoldID() == null || !list3.get(i) - .getBeneficiaryDetails().getHouseHoldID().equals(searchDTO.getHouseHoldID())) { - - list3.remove(i); - i--; - continue; - } - } - - if (searchDTO.getCurrentAddress().getStateId() != null) { - if (list3.get(i) == null || list3.get(i).getCurrentAddress() == null - || list3.get(i).getCurrentAddress().getStateId() == null - || !list3.get(i).getCurrentAddress().getStateId() - .equals(searchDTO.getCurrentAddress().getStateId())) { - - list3.remove(i); - i--; - continue; - } - } - - if (searchDTO.getCurrentAddress().getDistrictId() != null) { - if (list3.get(i) == null || list3.get(i).getCurrentAddress() == null - || list3.get(i).getCurrentAddress().getDistrictId() == null - || !list3.get(i).getCurrentAddress().getDistrictId() - .equals(searchDTO.getCurrentAddress().getDistrictId())) { - - list3.remove(i); - i--; - continue; - } - } - - if (searchDTO.getCurrentAddress().getVillageId() != null) { - if (list3.get(i) == null || list3.get(i).getCurrentAddress() == null - || list3.get(i).getCurrentAddress().getVillageId() == null - || !list3.get(i).getCurrentAddress().getVillageId() - .equals(searchDTO.getCurrentAddress().getVillageId())) { - - list3.remove(i); - i--; - continue; - } - } - - } - } - return list3; - } - - /** - * New logic for advance search, 03-10-2018 - */ - List tmpList = mappingRepo.dynamicFilterSearchNew(searchDTO); - for (VBenAdvanceSearch obj : tmpList) { - list.add(this.getBeneficiariesDTO(this.getBeneficiariesDTONew1(obj))); - logger.debug("benMapId: " + obj.getBenMapID()); - } - /** - * End - */ - - return list; - } - - /** - * - * Check which parameters available Get BenMapID based on the parameter/set of - * parameters Use BenMapID to retrieve all data for a Beneficiary - * - * @param benId - * @return - */ - public List getBeneficiariesByBenId(BigInteger benId) - throws NoResultException, QueryTimeoutException, Exception { - logger.info("IdentityService.getBeneficiariesByBenId - start, beneficiaryID : " + benId); - List list = new ArrayList(); - - MBeneficiaryregidmapping regId = regIdRepo.findByBeneficiaryID(benId); - if (regId != null && regId.getBenRegId() != null) { - List benMapObjArr = mappingRepo.getBenMappingByRegID(regId.getBenRegId()); - - // new logic, 27-08-2018 - if (benMapObjArr != null && benMapObjArr.size() > 0) { - MBeneficiarymapping benMap = this.getBeneficiariesDTONew(benMapObjArr.get(0)); - list.add(this.getBeneficiariesDTO(benMap)); - } - } - logger.info("benMap size " + (list.size() == 0 ? "No Beneficiary Found" : list.size())); - // end new logic - - logger.info("IdentityService.getBeneficiariesByBenId - end - beneficiaryID : " + benId); - - return list; - } - - /** - * - * @param BenRegId - * @return - */ - public List getBeneficiariesByBenRegId(BigInteger benRegId) - throws NoResultException, QueryTimeoutException, Exception { - List list = new ArrayList(); - logger.info("IdentityService.getBeneficiariesByBenRegId - start for benRegId " + benRegId); - try { - // new logic, 27-09-2018 - List benMapObjArr = mappingRepo.getBenMappingByRegID(benRegId); - - // new logic, 27-08-2018 - if (benMapObjArr != null && !benMapObjArr.isEmpty()) { - MBeneficiarymapping benMap = this.getBeneficiariesDTONew(benMapObjArr.get(0)); - list.add(this.getBeneficiariesDTO(benMap)); - } - logger.info("benMap size" + (list.isEmpty() ? "No Beneficiary Found" : list.size())); - // end new logic - - logger.info("IdentityService.getBeneficiariesByBenRegId - end for benRegId " + benRegId); - } catch (Exception e) { - logger.error("error in beneficiary search for beneficiary reg id : " + benRegId + " error : " - + e.getLocalizedMessage()); - } - - return list; - } - - /** - * - * Check which parameters available Get BenMapID based on the parameter/set of - * parameters Use BenMapID to retrieve all data for a Beneficiary - * - * @param phoneNum - * @return - */ - - public List getBeneficiariesByPhoneNum(String phoneNum) - throws NoResultException, QueryTimeoutException { - // new logic, 27-09-2018 - List list = new ArrayList<>(); - try { - List benContact = contactRepo.findByAnyPhoneNum(phoneNum); - - logger.info(benContact.size() + " contacts found for phone number " + phoneNum); - - List benMapObjArr = new ArrayList<>(); - - for (MBeneficiarycontact benContactOBJ : benContact) { - benMapObjArr.addAll(mappingRepo.getBenMappingByBenContactIdListNew(benContactOBJ.getVanSerialNo(), - benContactOBJ.getVanID())); - } - - for (Object[] benMapOBJ : benMapObjArr) { - list.add(this.getBeneficiariesDTO(this.getBeneficiariesDTONew(benMapOBJ))); - } - - } catch (Exception e) { - logger.error( - "error in beneficiary search for phone no : " + phoneNum + " error : " + e.getLocalizedMessage()); - } - - logger.info("IdentityService.getBeneficiariesByPhoneNum - end"); - // end - return list; - } - - /*** - * - * Search beneficiary by healthID / ABHA address - * - * @param healthID - * @return - * @throws NoResultException - * @throws QueryTimeoutException - * @throws Exception - */ - - public List getBeneficiaryByHealthIDAbhaAddress(String healthID) - throws NoResultException, QueryTimeoutException, Exception { - List beneficiaryList = new ArrayList<>(); - try { - List regIDList = v_BenAdvanceSearchRepo.getBenRegIDByHealthIDAbhaAddress(healthID); - if (regIDList != null && !regIDList.isEmpty()) { - for (BigInteger benRegID : regIDList) { - if (benRegID != null) { - List searchList = this.getBeneficiariesByBenRegId(benRegID); - beneficiaryList.addAll(searchList); - } - } - } - } catch (Exception e) { - logger.error("error in beneficiary search for health ID / ABHA Address : " + healthID + " error : " - + e.getLocalizedMessage()); - } - return beneficiaryList; - } - - /*** - * - * Search beneficiary by healthIDNo / ABHA ID No - * - * @param healthIDNo - * @return - * @throws NoResultException - * @throws QueryTimeoutException - * @throws Exception - */ - - public List getBeneficiaryByHealthIDNoAbhaIdNo(String healthIDNo) - throws NoResultException, QueryTimeoutException, Exception { - List beneficiaryList = new ArrayList<>(); - try { - List regIDList = v_BenAdvanceSearchRepo.getBenRegIDByHealthIDNoAbhaIdNo(healthIDNo); - if (regIDList != null && !regIDList.isEmpty()) { - for (BigInteger benRegID : regIDList) { - if (benRegID != null) { - List searchList = this.getBeneficiariesByBenRegId(benRegID); - beneficiaryList.addAll(searchList); - } - } - } - } catch (Exception e) { - logger.error("error in beneficiary search for health ID No / ABHA ID No : " + healthIDNo + " error : " - + e.getLocalizedMessage()); - } - return beneficiaryList; - } - - public List searhBeneficiaryByFamilyId(String familyId) - throws NoResultException, QueryTimeoutException { - List beneficiaryList = new ArrayList<>(); - try { - - // find benmap ids - List benMapObjArr = null; - List benDetailsVanSerialNoList = new ArrayList<>(); - int vanID = 0; - - List benDetailsList = detailRepo.searchByFamilyId(familyId); - - if (benDetailsList == null || benDetailsList.isEmpty()) - return beneficiaryList; - else { - // considering as of now family creation is possible through facility modules - // only - vanID = benDetailsList.get(0).getVanID(); - - for (MBeneficiarydetail benDetails : benDetailsList) { - benDetailsVanSerialNoList.add(benDetails.getVanSerialNo()); - } - - benMapObjArr = mappingRepo.getBenMappingByBenDetailsIds(benDetailsVanSerialNoList, vanID); - - for (Object[] benMapOBJ : benMapObjArr) { - beneficiaryList.add(this.getBeneficiariesDTO(this.getBeneficiariesDTONew(benMapOBJ))); - } - - } - - } catch (Exception e) { - logger.error( - "error in beneficiary search for familyId : " + familyId + " error : " + e.getLocalizedMessage()); - } - return beneficiaryList; - } - - public List searchBeneficiaryByVillageIdAndLastModifyDate(List villageIDs, - Timestamp lastModifiedDate) { - - List beneficiaryList = new ArrayList<>(); - try { - // find benmap ids - List benMappingsList = mappingRepo - .findByBeneficiaryDetailsByVillageIDAndLastModifyDate(villageIDs, lastModifiedDate); - if (benMappingsList != null && !benMappingsList.isEmpty()) { - for (MBeneficiarymapping benMapOBJ : benMappingsList) { - beneficiaryList.add(this.getBeneficiariesDTO(benMapOBJ)); - } - } - - } catch (Exception e) { - logger.error("error in beneficiary search to sync to CHO App with villageIDs: {} ", - villageIDs + " error : " + e.getLocalizedMessage()); - } - return beneficiaryList; - } - - public Long countBeneficiaryByVillageIdAndLastModifyDate(List villageIDs, Timestamp lastModifiedDate) { - Long beneficiaryCount = 0L; - try { - beneficiaryCount = mappingRepo.getBeneficiaryCountsByVillageIDAndLastModifyDate(villageIDs, - lastModifiedDate); - } catch (Exception e) { - logger.error("error in getting beneficiary count to sync to CHO App with villageIDs: {},error :{} ", - villageIDs, e.getLocalizedMessage()); - } - return beneficiaryCount; - } - - public List searhBeneficiaryByGovIdentity(String identity) - throws NoResultException, QueryTimeoutException { - List beneficiaryList = new ArrayList<>(); - try { - - List benMapObjArr = new ArrayList<>(); - - // find identity no - List benIdentityList = identityRepo.searchByIdentityNo(identity); - - // find benmap ids - if (benIdentityList == null || benIdentityList.isEmpty()) - return beneficiaryList; - else { - for (MBeneficiaryidentity identityObj : benIdentityList) { - benMapObjArr.addAll( - mappingRepo.getBenMappingByVanSerialNo(identityObj.getBenMapId(), identityObj.getVanID())); - } - - for (Object[] benMapOBJ : benMapObjArr) { - beneficiaryList.add(this.getBeneficiariesDTO(this.getBeneficiariesDTONew(benMapOBJ))); - } - - } - - } catch (Exception e) { - logger.error("error in beneficiary search for gov identity : " + identity + " error : " - + e.getLocalizedMessage()); - } - return beneficiaryList; - } - - private MBeneficiarymapping getBeneficiariesDTONew(Object[] benMapArr) { - MBeneficiarymapping mapping = new MBeneficiarymapping(); - if (benMapArr != null && benMapArr.length == 12 && benMapArr[8] != null && benMapArr[9] != null) { - mapping.setBenMapId(getBigIntegerValueFromObject(benMapArr[0])); - mapping.setCreatedBy(String.valueOf(benMapArr[10])); - mapping.setCreatedDate((Timestamp) benMapArr[11]); - mapping = mappingRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[9]), (Integer) benMapArr[8]); - MBeneficiaryaddress address = addressRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[1]), (Integer) benMapArr[8]); - MBeneficiaryconsent consent = consentRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[2]), (Integer) benMapArr[8]); - MBeneficiarycontact contact = contactRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[3]), (Integer) benMapArr[8]); - MBeneficiarydetail details = detailRepo.getWith_vanSerialNo_vanID(getBigIntegerValueFromObject(benMapArr[4]), (Integer) benMapArr[8]); - MBeneficiaryregidmapping regidmapping = regIdRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[5]), (Integer) benMapArr[8]); - MBeneficiaryAccount account = accountRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[7]), (Integer) benMapArr[8]); - MBeneficiaryImage image = imageRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[6]), (Integer) benMapArr[8]); - List servicemap = serviceMapRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[0]), (Integer) benMapArr[8]); - List identity = identityRepo.findByBenMapIdAndVanID(getBigIntegerValueFromObject(benMapArr[0]), (Integer) benMapArr[8]); - List familymapping = familyMapRepo.findByBenMapIdAndVanIDOrderByBenFamilyMapIdAsc(getBigIntegerValueFromObject(benMapArr[0]), (Integer) benMapArr[8]); - - mapping.setMBeneficiaryaddress(address); - mapping.setMBeneficiaryconsent(consent); - mapping.setMBeneficiarycontact(contact); - mapping.setMBeneficiarydetail(details); - mapping.setMBeneficiaryfamilymappings(familymapping); - mapping.setMBeneficiaryidentities(identity); - mapping.setMBeneficiaryImage(image); - mapping.setMBeneficiaryregidmapping(regidmapping); - mapping.setMBeneficiaryservicemappings(servicemap); - mapping.setMBeneficiaryAccount(account); - //benMapOBJ = mappingRepo.getMapping(getBigIntegerValueFromObject(benMapArr[9]), (Integer) benMapArr[8]); - - - - BigInteger benRegId = new BigInteger(benMapArr[5].toString()); - RMNCHBeneficiaryDetailsRmnch obj = rMNCHBeneficiaryDetailsRmnchRepo - .getByRegID(benRegId); - - if (obj != null) { - if (obj.getHouseoldId() != null) - mapping.setHouseHoldID(obj.getHouseoldId()); - if (obj.getGuidelineId() != null) - mapping.setGuideLineID(obj.getGuidelineId()); - if (obj.getRchid() != null) - mapping.setRchID(obj.getRchid()); - } - - } - return mapping; - } - private MBeneficiarymapping getBeneficiariesDTONewPartial(Object[] benMapArr) { - MBeneficiarymapping benMapOBJ = new MBeneficiarymapping(); - - benMapOBJ.setBenMapId(getBigIntegerValueFromObject(benMapArr[0])); - benMapOBJ.setCreatedBy(String.valueOf(benMapArr[10])); - benMapOBJ.setCreatedDate((Timestamp) benMapArr[11]); - - if (benMapArr.length == 12 && benMapArr[8] != null && benMapArr[9] != null) { - - benMapOBJ.setMBeneficiarydetail(detailRepo - .getWith_vanSerialNo_vanID(getBigIntegerValueFromObject(benMapArr[4]), (Integer) benMapArr[8])); - benMapOBJ.setMBeneficiaryregidmapping(regIdRepo - .getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[5]), (Integer) benMapArr[8])); - } - return benMapOBJ; - } - - // 03-10-2018 - // get ben mapping object from v_benadvancesearch - private MBeneficiarymapping getBeneficiariesDTONew1(VBenAdvanceSearch benAdvanceSearchOBJ) { - MBeneficiarymapping benMapOBJ = new MBeneficiarymapping(); - - // for createdBy & createdDate - if (benAdvanceSearchOBJ != null) { - MBeneficiarydetail benDetailsOBJ = detailRepo - .getWith_vanSerialNo_vanID(benAdvanceSearchOBJ.getBenDetailsID(), benAdvanceSearchOBJ.getVanID()); - - if (benAdvanceSearchOBJ.getHouseHoldID() != null) - benMapOBJ.setHouseHoldID(benAdvanceSearchOBJ.getHouseHoldID()); - if (benAdvanceSearchOBJ.getGuideLineID() != null) - benMapOBJ.setGuideLineID(benAdvanceSearchOBJ.getGuideLineID()); - if (benAdvanceSearchOBJ.getRchID() != null) - benMapOBJ.setRchID(benAdvanceSearchOBJ.getRchID()); - - benMapOBJ.setBenMapId(benAdvanceSearchOBJ.getBenMapID()); - benMapOBJ.setCreatedBy(benDetailsOBJ.getCreatedBy()); - benMapOBJ.setCreatedDate(benDetailsOBJ.getCreatedDate()); - - benMapOBJ.setMBeneficiaryaddress(addressRepo.getWithVanSerialNoVanID(benAdvanceSearchOBJ.getBenAddressID(), - benAdvanceSearchOBJ.getVanID())); - benMapOBJ.setMBeneficiaryconsent(consentRepo.getWithVanSerialNoVanID(benAdvanceSearchOBJ.getBenConsentID(), - benAdvanceSearchOBJ.getVanID())); - benMapOBJ.setMBeneficiarycontact(contactRepo.getWithVanSerialNoVanID(benAdvanceSearchOBJ.getBenContactID(), - benAdvanceSearchOBJ.getVanID())); - benMapOBJ.setMBeneficiarydetail(benDetailsOBJ); - benMapOBJ.setMBeneficiaryregidmapping(regIdRepo.getWithVanSerialNoVanID(benAdvanceSearchOBJ.getBenRegID(), - benAdvanceSearchOBJ.getVanID())); - benMapOBJ.setMBeneficiaryImage(imageRepo.getWithVanSerialNoVanID(benAdvanceSearchOBJ.getBenImageID(), - benAdvanceSearchOBJ.getVanID())); - benMapOBJ.setMBeneficiaryAccount(accountRepo.getWithVanSerialNoVanID(benAdvanceSearchOBJ.getBenAccountID(), - benAdvanceSearchOBJ.getVanID())); - - benMapOBJ.setMBeneficiaryfamilymappings( - familyMapRepo.findByBenMapIdOrderByBenFamilyMapIdAsc(benAdvanceSearchOBJ.getVanSerialNo())); - benMapOBJ.setMBeneficiaryidentities(identityRepo.findByBenMapId(benAdvanceSearchOBJ.getVanSerialNo())); - } - - return benMapOBJ; - } - - private BigInteger getBigIntegerValueFromObject(Object value) { - BigInteger ret = null; - if (value != null) { - if (value instanceof BigInteger) { - ret = (BigInteger) value; - } else if (value instanceof String) { - ret = new BigInteger((String) value); - } else if (value instanceof BigDecimal) { - ret = ((BigDecimal) value).toBigInteger(); - } else if (value instanceof Number) { - ret = BigInteger.valueOf(((Number) value).longValue()); - } else { - throw new ClassCastException("Not possible to coerce [" + value + "] from class " + value.getClass() - + " into a BigInteger."); - } - } else - throw new ClassCastException("given value is null"); - return ret; - } - - /** - * The following parameters can be changed/edited once created: - First Name - - * Middle Name - Last Name - DOB/Age - Address (Current, Permanent, Emergency) - - * Contact Numbers/Email Ids - Spouse Name - Preferred Num - Preferred SMS Num - - * Email Id - Identity - * - * Following changes need Additional Authorization - First Name - Middle Name - - * Last Name - Father Name - Spouse Name - Identity - * - * @param identity - * @return - * @throws MissingMandatoryFieldsException - */ - public void editIdentity(IdentityEditDTO identity) throws MissingMandatoryFieldsException { - logger.info("IdentityService.editIdentity - start"); - if (identity.getBeneficiaryRegId() == null && null == identity.getBeneficaryId()) { - throw new MissingMandatoryFieldsException("Either of BeneficiaryID or Beneficiary Reg Id is mandatory."); - } - - MBeneficiarymapping benMapping = mappingRepo.findByBenRegIdOrderByBenMapIdAsc(identity.getBeneficiaryRegId()); - - // change in self details is implement here and other details here - logger.debug("identity.getChangeInSelfDetails = " + identity.getChangeInSelfDetails()); - logger.debug("identity.getChangeInOtherDetails = " + identity.getChangeInOtherDetails()); - logger.debug("identity.getChangeInAssociations = " + identity.getChangeInAssociations()); - if (Boolean.TRUE.equals(identity.getChangeInSelfDetails()) - || Boolean.TRUE.equals(identity.getChangeInOtherDetails()) - || Boolean.TRUE.equals(identity.getChangeInAssociations())) { - - // MBeneficiarydetail mbDetl = - // editMapper.identityEditDTOToMBeneficiarydetail(identity); - // MBeneficiarydetail mbDetl = - // convertIdentityEditDTOToMBeneficiarydetail(identity); - /** - * new logic for data sync, 26-09-2018 - */ - // getting correct beneficiaryDetailsId by passing vanSerialNo & vanID - MBeneficiarydetail benDetails = detailRepo.findBenDetailsByVanSerialNoAndVanID( - benMapping.getMBeneficiarydetail().getBeneficiaryDetailsId(), benMapping.getVanID()); - // next statement is new one, setting correct beneficiaryDetailsId - if (benDetails != null) { - // Create a new instance of MBeneficiarydetail or use the existing one - MBeneficiarydetail mbDetl = convertIdentityEditDTOToMBeneficiarydetail(identity); - - // Set fields from the existing benDetails to mbDetl - mbDetl.setBeneficiaryDetailsId(benDetails.getBeneficiaryDetailsId()); - if (benDetails.getFamilyId() != null) - mbDetl.setFamilyId(benDetails.getFamilyId()); - if (benDetails.getHeadOfFamily_RelationID() != null) - mbDetl.setHeadOfFamily_RelationID(benDetails.getHeadOfFamily_RelationID()); - if (benDetails.getHeadOfFamily_Relation() != null) - mbDetl.setHeadOfFamily_Relation(benDetails.getHeadOfFamily_Relation()); - if (benDetails.getOther() != null) - mbDetl.setOther(benDetails.getOther()); - - // Extract and set extra fields + + private static final Logger logger = LoggerFactory.getLogger(IdentityService.class); + public static final String CREATED_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS"; + @Autowired + private DataSource dataSource; + + private JdbcTemplate jdbcTemplate; + + private JdbcTemplate getJdbcTemplate() { + return new JdbcTemplate(dataSource); + + } + + @Autowired + private RMNCHBeneficiaryDetailsRmnchRepo rMNCHBeneficiaryDetailsRmnchRepo; + + @Autowired + private ElasticsearchService elasticsearchService; + + @Autowired + private BeneficiaryElasticsearchIndexUpdater syncService; + + @Autowired + IdentityMapper mapper; + @Autowired + IdentityEditMapper editMapper; + @Autowired + IdentitySearchMapper searchMapper; + @Autowired + private IdentityPartialMapper partialMapper; + @Autowired + BenAddressRepo addressRepo; + @Autowired + BenConsentRepo consentRepo; + @Autowired + BenContactRepo contactRepo; + @Autowired + BenDataAccessRepo accessRepo; + @Autowired + BenDetailRepo detailRepo; + @Autowired + BenFamilyMappingRepo familyMapRepo; + @Autowired + BenIdentityRepo identityRepo; + @Autowired + BenMappingRepo mappingRepo; + @Autowired + BenRegIdMappingRepo regIdRepo; + @Autowired + BenServiceMappingRepo serviceMapRepo; + @Autowired + MBeneficiaryAccountRepo accountRepo; + @Autowired + MBeneficiaryImageRepo imageRepo; + @Autowired + private BenIdImportMapper benIdImportMapper; + @Autowired + private V_BenAdvanceSearchRepo v_BenAdvanceSearchRepo; + + @Value("${elasticsearch.enabled}") + private boolean esEnabled; + + public void getBenAdress() { + logger.debug("Address count: " + addressRepo.count()); + logger.debug( + "Address By Address: " + addressRepo.findByBenAddressIDOrderByBenAddressIDAsc(new BigInteger("12"))); + logger.debug("Consent count: " + consentRepo.count()); + logger.debug("Consent By Id: " + consentRepo.findByBenConsentIDOrderByBenConsentIDAsc(new BigInteger("12"))); + logger.debug("Contact count: " + contactRepo.count()); + logger.debug("Contact By Id: " + contactRepo.findByBenContactsIDOrderByBenContactsIDAsc(new BigInteger("12"))); + logger.debug("Data Access count: " + accessRepo.count()); + logger.debug("Data Access By Id: " + accessRepo.findByAccessIdOrderByAccessIdAsc(new BigInteger("12"))); + logger.debug("Detail count: " + detailRepo.count()); + logger.debug("Detail By Address: " + + detailRepo.findByBeneficiaryDetailsIdOrderByBeneficiaryDetailsIdAsc(new BigInteger("12"))); + logger.debug("FamilyMap count: " + familyMapRepo.count()); + logger.debug( + "FamilyMap By Id: " + familyMapRepo.findByBenFamilyMapIdOrderByBenFamilyMapIdAsc(new BigInteger("12"))); + logger.debug("Identity count: " + identityRepo.count()); + logger.debug("Identity By Id: " + identityRepo.findByBenIdentityId(new BigInteger("12"))); + logger.debug("Mapping count: " + mappingRepo.count()); + logger.debug("Mapping By Id: " + mappingRepo.findByBenMapIdOrderByBenMapIdAsc(new BigInteger("12"))); + } + + /** + * + * @param searchDTO + * @return + */ + public List getBeneficiaries(IdentitySearchDTO searchDTO) + throws NoResultException, QueryTimeoutException, Exception { + List list = new ArrayList(); + + /** + * if beneficiary Id present + */ + if (searchDTO.getBeneficiaryId() != null) { + logger.info("getting beneficiaries by ID for " + searchDTO.getBeneficiaryId()); + return this.getBeneficiariesByBenId(searchDTO.getBeneficiaryId()); + } + + /** + * if beneficiary Reg Id present + */ + if (searchDTO.getBeneficiaryRegId() != null) { + logger.info("getting beneficiaries by reg ID for " + searchDTO.getBeneficiaryRegId()); + return this.getBeneficiariesByBenRegId(searchDTO.getBeneficiaryRegId()); + } + + /** + * if beneficiary Reg Id present + */ + if (searchDTO.getContactNumber() != null) { + logger.info("getting beneficiaries by contact no for " + searchDTO.getContactNumber()); + List list3 = this.getBeneficiariesByPhoneNum(searchDTO.getContactNumber()); + if (!list3.isEmpty() && searchDTO.getIsD2D() != null && Boolean.TRUE.equals(searchDTO.getIsD2D())) { + + for (int i = 0; i < list3.size(); i++) { + if (searchDTO.getFirstName() != null) { + if (list3.get(i) == null || list3.get(i).getBeneficiaryDetails() == null + || list3.get(i).getBeneficiaryDetails().getFirstName() == null + || !list3.get(i).getBeneficiaryDetails().getFirstName() + .equalsIgnoreCase(searchDTO.getFirstName())) { + list3.remove(i); + i--; + + continue; + } + + } + if (searchDTO.getLastName() != null) { + if (list3.get(i) == null || list3.get(i).getBeneficiaryDetails() == null + || list3.get(i).getBeneficiaryDetails().getLastName() == null + || !list3.get(i).getBeneficiaryDetails().getLastName() + .equalsIgnoreCase(searchDTO.getLastName())) { + list3.remove(i); + i--; + + continue; + } + } + + if (searchDTO.getGenderId() != null) { + if (list3.get(i) == null || list3.get(i).getBeneficiaryDetails() == null + || list3.get(i).getBeneficiaryDetails().getGenderId() == null || !list3.get(i) + .getBeneficiaryDetails().getGenderId().equals(searchDTO.getGenderId())) { + + list3.remove(i); + i--; + continue; + } + } + if (searchDTO.getHouseHoldID() != null) { + if (list3.get(i) == null || list3.get(i).getBeneficiaryDetails() == null + || list3.get(i).getBeneficiaryDetails().getHouseHoldID() == null || !list3.get(i) + .getBeneficiaryDetails().getHouseHoldID().equals(searchDTO.getHouseHoldID())) { + + list3.remove(i); + i--; + continue; + } + } + + if (searchDTO.getCurrentAddress().getStateId() != null) { + if (list3.get(i) == null || list3.get(i).getCurrentAddress() == null + || list3.get(i).getCurrentAddress().getStateId() == null + || !list3.get(i).getCurrentAddress().getStateId() + .equals(searchDTO.getCurrentAddress().getStateId())) { + + list3.remove(i); + i--; + continue; + } + } + + if (searchDTO.getCurrentAddress().getDistrictId() != null) { + if (list3.get(i) == null || list3.get(i).getCurrentAddress() == null + || list3.get(i).getCurrentAddress().getDistrictId() == null + || !list3.get(i).getCurrentAddress().getDistrictId() + .equals(searchDTO.getCurrentAddress().getDistrictId())) { + + list3.remove(i); + i--; + continue; + } + } + + if (searchDTO.getCurrentAddress().getVillageId() != null) { + if (list3.get(i) == null || list3.get(i).getCurrentAddress() == null + || list3.get(i).getCurrentAddress().getVillageId() == null + || !list3.get(i).getCurrentAddress().getVillageId() + .equals(searchDTO.getCurrentAddress().getVillageId())) { + + list3.remove(i); + i--; + continue; + } + } + + } + } + return list3; + } + + /** + * New logic for advance search, 03-10-2018 + */ + List tmpList = mappingRepo.dynamicFilterSearchNew(searchDTO); + for (VBenAdvanceSearch obj : tmpList) { + list.add(this.getBeneficiariesDTO(this.getBeneficiariesDTONew1(obj))); + logger.debug("benMapId: " + obj.getBenMapID()); + } + /** + * End + */ + + return list; + } + + public List getBeneficiarieswithES(IdentitySearchDTO searchDTO) + throws NoResultException, QueryTimeoutException, Exception { + List list = new ArrayList(); + + /** + * Try Elasticsearch first if enabled + */ + // if (esEnabled) { + // try { + // logger.info("Attempting Elasticsearch search"); + // // Search by beneficiary Id + // if (searchDTO.getBeneficiaryId() != null) { + // logger.info("Elasticsearch: searching by beneficiaryId: {}", searchDTO.getBeneficiaryId()); + // list = elasticsearchService.searchByBenId(searchDTO.getBeneficiaryId()); + // if (!list.isEmpty()) { + // logger.info("Found {} results from Elasticsearch", list.size()); + // return enrichBeneficiariesFromDatabase(list); + // } + // } + // // Search by beneficiary Reg Id + // if (searchDTO.getBeneficiaryRegId() != null) { + // logger.info("Elasticsearch: searching by beneficiaryRegId: {}", searchDTO.getBeneficiaryRegId()); + // list = elasticsearchService.searchByBenRegId(searchDTO.getBeneficiaryRegId()); + // if (!list.isEmpty()) { + // logger.info("Found {} results from Elasticsearch", list.size()); + // return enrichBeneficiariesFromDatabase(list); + // } + // } + // // Search by contact number + // if (searchDTO.getContactNumber() != null) { + // logger.info("Elasticsearch: searching by phoneNum: {}", searchDTO.getContactNumber()); + // list = elasticsearchService.searchByPhoneNum(searchDTO.getContactNumber()); + // if (!list.isEmpty()) { + // logger.info("Found {} results from Elasticsearch", list.size()); + // // Apply D2D filters if needed + // if (searchDTO.getIsD2D() != null && Boolean.TRUE.equals(searchDTO.getIsD2D())) { + // list = applyD2DFilters(list, searchDTO); + // } + // return enrichBeneficiariesFromDatabase(list); + // } + // } + // // Advanced search (multiple criteria) + // if (hasMultipleCriteria(searchDTO)) { + // logger.info("Elasticsearch: advanced search"); + // list = elasticsearchService.advancedSearch( + // searchDTO.getFirstName(), + // searchDTO.getLastName(), + // searchDTO.getContactNumber(), + // null, // gender from searchDTO if available + // null // age from searchDTO if available + // ); + // if (!list.isEmpty()) { + // logger.info("Found {} results from Elasticsearch", list.size()); + // return enrichBeneficiariesFromDatabase(list); + // } + // } + // logger.info("No results from Elasticsearch, falling back to database"); + // } catch (Exception e) { + // logger.error("Elasticsearch search failed, falling back to database: {}", e.getMessage()); + // } + // } + /** + * Fallback to MySQL database search + */ + logger.info("Searching in MySQL database"); + + // if beneficiary Id present + if (searchDTO.getBeneficiaryId() != null) { + logger.info("getting beneficiaries by ID for " + searchDTO.getBeneficiaryId()); + return this.getBeneficiariesByBenId(searchDTO.getBeneficiaryId()); + } + + // if beneficiary Reg Id present + if (searchDTO.getBeneficiaryRegId() != null) { + logger.info("getting beneficiaries by reg ID for " + searchDTO.getBeneficiaryRegId()); + return this.getBeneficiariesByBenRegId(searchDTO.getBeneficiaryRegId()); + } + + // if beneficiary Reg Id present + if (searchDTO.getContactNumber() != null) { + logger.info("getting beneficiaries by contact no for " + searchDTO.getContactNumber()); + List list3 = this.getBeneficiariesByPhoneNum(searchDTO.getContactNumber()); + if (!list3.isEmpty() && searchDTO.getIsD2D() != null && Boolean.TRUE.equals(searchDTO.getIsD2D())) { + list3 = applyD2DFilters(list3, searchDTO); + } + return list3; + } + + // Advanced search from database + List tmpList = mappingRepo.dynamicFilterSearchNew(searchDTO); + for (VBenAdvanceSearch obj : tmpList) { + list.add(this.getBeneficiariesDTO(this.getBeneficiariesDTONew1(obj))); + logger.debug("benMapId: " + obj.getBenMapID()); + } + + return list; + } + + /** + * Check if search has multiple criteria (for advanced search) + */ + private boolean hasMultipleCriteria(IdentitySearchDTO searchDTO) { + int criteriaCount = 0; + + if (searchDTO.getFirstName() != null && !searchDTO.getFirstName().trim().isEmpty()) { + criteriaCount++; + } + if (searchDTO.getLastName() != null && !searchDTO.getLastName().trim().isEmpty()) { + criteriaCount++; + } + if (searchDTO.getContactNumber() != null && !searchDTO.getContactNumber().trim().isEmpty()) { + criteriaCount++; + } + + return criteriaCount >= 2; + } + + /** + * Enrich Elasticsearch results with complete data from database ES returns + * only basic fields, fetch complete data from DB + */ + private List enrichBeneficiariesFromDatabase(List esResults) { + List enrichedList = new ArrayList<>(); + + for (BeneficiariesDTO esResult : esResults) { + try { + if (esResult.getBenRegId() != null) { + // Fetch complete data from database + List fullData = this.getBeneficiariesByBenRegId(esResult.getBenRegId()); + if (!fullData.isEmpty()) { + enrichedList.add(fullData.get(0)); + } else { + // If not in DB anymore, return ES data + enrichedList.add(esResult); + } + } + } catch (Exception e) { + logger.error("Error enriching beneficiary data: {}", e.getMessage()); + // Return ES data if enrichment fails + enrichedList.add(esResult); + } + } + + return enrichedList; + } + + /** + * Apply D2D filters to search results + */ + private List applyD2DFilters(List list, IdentitySearchDTO searchDTO) { + List filtered = new ArrayList<>(); + + for (BeneficiariesDTO dto : list) { + boolean matches = true; + + if (searchDTO.getFirstName() != null) { + if (dto.getBeneficiaryDetails() == null + || dto.getBeneficiaryDetails().getFirstName() == null + || !dto.getBeneficiaryDetails().getFirstName().equalsIgnoreCase(searchDTO.getFirstName())) { + matches = false; + } + } + + if (matches && searchDTO.getLastName() != null) { + if (dto.getBeneficiaryDetails() == null + || dto.getBeneficiaryDetails().getLastName() == null + || !dto.getBeneficiaryDetails().getLastName().equalsIgnoreCase(searchDTO.getLastName())) { + matches = false; + } + } + + if (matches && searchDTO.getGenderId() != null) { + if (dto.getBeneficiaryDetails() == null + || dto.getBeneficiaryDetails().getGenderId() == null + || !dto.getBeneficiaryDetails().getGenderId().equals(searchDTO.getGenderId())) { + matches = false; + } + } + + if (matches && searchDTO.getHouseHoldID() != null) { + if (dto.getBeneficiaryDetails() == null + || dto.getBeneficiaryDetails().getHouseHoldID() == null + || !dto.getBeneficiaryDetails().getHouseHoldID().equals(searchDTO.getHouseHoldID())) { + matches = false; + } + } + + if (matches && searchDTO.getCurrentAddress() != null && searchDTO.getCurrentAddress().getStateId() != null) { + if (dto.getCurrentAddress() == null + || dto.getCurrentAddress().getStateId() == null + || !dto.getCurrentAddress().getStateId().equals(searchDTO.getCurrentAddress().getStateId())) { + matches = false; + } + } + + if (matches && searchDTO.getCurrentAddress() != null && searchDTO.getCurrentAddress().getDistrictId() != null) { + if (dto.getCurrentAddress() == null + || dto.getCurrentAddress().getDistrictId() == null + || !dto.getCurrentAddress().getDistrictId().equals(searchDTO.getCurrentAddress().getDistrictId())) { + matches = false; + } + } + + if (matches && searchDTO.getCurrentAddress() != null && searchDTO.getCurrentAddress().getVillageId() != null) { + if (dto.getCurrentAddress() == null + || dto.getCurrentAddress().getVillageId() == null + || !dto.getCurrentAddress().getVillageId().equals(searchDTO.getCurrentAddress().getVillageId())) { + matches = false; + } + } + + if (matches) { + filtered.add(dto); + } + } + + return filtered; + } + + /** + * + * Check which parameters available Get BenMapID based on the parameter/set + * of parameters Use BenMapID to retrieve all data for a Beneficiary + * + * @param benId + * @return + */ + public List getBeneficiariesByBenId(BigInteger benId) + throws NoResultException, QueryTimeoutException, Exception { + logger.info("IdentityService.getBeneficiariesByBenId - start, beneficiaryID : " + benId); + List list = new ArrayList(); + + // // Try Elasticsearch first if enabled + // if (esEnabled) { + // try { + // list = elasticsearchService.searchByBenId(benId); + // if (!list.isEmpty()) { + // logger.info("Found " + list.size() + " results from Elasticsearch for BenId: " + benId); + // return list; + // } + // logger.info("No results from Elasticsearch, falling back to database"); + // } catch (Exception e) { + // logger.error("Elasticsearch search failed, falling back to database: " + e.getMessage()); + // } + // } + MBeneficiaryregidmapping regId = regIdRepo.findByBeneficiaryID(benId); + if (regId != null && regId.getBenRegId() != null) { + List benMapObjArr = mappingRepo.getBenMappingByRegID(regId.getBenRegId()); + + // new logic, 27-08-2018 + if (benMapObjArr != null && benMapObjArr.size() > 0) { + MBeneficiarymapping benMap = this.getBeneficiariesDTONew(benMapObjArr.get(0)); + list.add(this.getBeneficiariesDTO(benMap)); + } + } + logger.info("benMap size " + (list.size() == 0 ? "No Beneficiary Found" : list.size())); + // end new logic + + logger.info("IdentityService.getBeneficiariesByBenId - end - beneficiaryID : " + benId); + + return list; + } + + /** + * + * @param BenRegId + * @return + */ + public List getBeneficiariesByBenRegId(BigInteger benRegId) + throws NoResultException, QueryTimeoutException, Exception { + List list = new ArrayList(); + logger.info("IdentityService.getBeneficiariesByBenRegId - start for benRegId " + benRegId); + try { + // new logic, 27-09-2018 + List benMapObjArr = mappingRepo.getBenMappingByRegID(benRegId); + + // new logic, 27-08-2018 + if (benMapObjArr != null && !benMapObjArr.isEmpty()) { + MBeneficiarymapping benMap = this.getBeneficiariesDTONew(benMapObjArr.get(0)); + list.add(this.getBeneficiariesDTO(benMap)); + } + logger.info("benMap size" + (list.isEmpty() ? "No Beneficiary Found" : list.size())); + // end new logic + + logger.info("IdentityService.getBeneficiariesByBenRegId - end for benRegId " + benRegId); + } catch (Exception e) { + logger.error("error in beneficiary search for beneficiary reg id : " + benRegId + " error : " + + e.getLocalizedMessage()); + } + + return list; + } + + /** + * + * Check which parameters available Get BenMapID based on the parameter/set + * of parameters Use BenMapID to retrieve all data for a Beneficiary + * + * @param phoneNum + * @return + */ + public List getBeneficiariesByPhoneNum(String phoneNum) + throws NoResultException, QueryTimeoutException { + // new logic, 27-09-2018 + List list = new ArrayList<>(); + + // Try Elasticsearch first if enabled + // if (esEnabled) { + // try { + // list = elasticsearchService.searchByPhoneNum(phoneNum); + // if (!list.isEmpty()) { + // logger.info("Found " + list.size() + " results from Elasticsearch for PhoneNum: " + phoneNum); + // return list; + // } + // logger.info("No results from Elasticsearch, falling back to database"); + // } catch (Exception e) { + // logger.error("Elasticsearch search failed, falling back to database: " + e.getMessage()); + // } + // } + try { + List benContact = contactRepo.findByAnyPhoneNum(phoneNum); + + logger.info(benContact.size() + " contacts found for phone number " + phoneNum); + + List benMapObjArr = new ArrayList<>(); + + for (MBeneficiarycontact benContactOBJ : benContact) { + benMapObjArr.addAll(mappingRepo.getBenMappingByBenContactIdListNew(benContactOBJ.getVanSerialNo(), + benContactOBJ.getVanID())); + } + + for (Object[] benMapOBJ : benMapObjArr) { + list.add(this.getBeneficiariesDTO(this.getBeneficiariesDTONew(benMapOBJ))); + } + + } catch (Exception e) { + logger.error( + "error in beneficiary search for phone no : " + phoneNum + " error : " + e.getLocalizedMessage()); + } + + logger.info("IdentityService.getBeneficiariesByPhoneNum - end"); + // end + return list; + } + + /** + * * + * + * Search beneficiary by healthID / ABHA address + * + * @param healthID + * @return + * @throws NoResultException + * @throws QueryTimeoutException + * @throws Exception + */ + public List getBeneficiaryByHealthIDAbhaAddress(String healthID) + throws NoResultException, QueryTimeoutException, Exception { + List beneficiaryList = new ArrayList<>(); + try { + List regIDList = v_BenAdvanceSearchRepo.getBenRegIDByHealthIDAbhaAddress(healthID); + if (regIDList != null && !regIDList.isEmpty()) { + for (BigInteger benRegID : regIDList) { + if (benRegID != null) { + List searchList = this.getBeneficiariesByBenRegId(benRegID); + beneficiaryList.addAll(searchList); + } + } + } + } catch (Exception e) { + logger.error("error in beneficiary search for health ID / ABHA Address : " + healthID + " error : " + + e.getLocalizedMessage()); + } + return beneficiaryList; + } + + /** + * * + * + * Search beneficiary by healthIDNo / ABHA ID No + * + * @param healthIDNo + * @return + * @throws NoResultException + * @throws QueryTimeoutException + * @throws Exception + */ + public List getBeneficiaryByHealthIDNoAbhaIdNo(String healthIDNo) + throws NoResultException, QueryTimeoutException, Exception { + List beneficiaryList = new ArrayList<>(); + try { + List regIDList = v_BenAdvanceSearchRepo.getBenRegIDByHealthIDNoAbhaIdNo(healthIDNo); + if (regIDList != null && !regIDList.isEmpty()) { + for (BigInteger benRegID : regIDList) { + if (benRegID != null) { + List searchList = this.getBeneficiariesByBenRegId(benRegID); + beneficiaryList.addAll(searchList); + } + } + } + } catch (Exception e) { + logger.error("error in beneficiary search for health ID No / ABHA ID No : " + healthIDNo + " error : " + + e.getLocalizedMessage()); + } + return beneficiaryList; + } + + public List searhBeneficiaryByFamilyId(String familyId) + throws NoResultException, QueryTimeoutException { + List beneficiaryList = new ArrayList<>(); + try { + + // find benmap ids + List benMapObjArr = null; + List benDetailsVanSerialNoList = new ArrayList<>(); + int vanID = 0; + + List benDetailsList = detailRepo.searchByFamilyId(familyId); + + if (benDetailsList == null || benDetailsList.isEmpty()) { + return beneficiaryList; + }else { + // considering as of now family creation is possible through facility modules + // only + vanID = benDetailsList.get(0).getVanID(); + + for (MBeneficiarydetail benDetails : benDetailsList) { + benDetailsVanSerialNoList.add(benDetails.getVanSerialNo()); + } + + benMapObjArr = mappingRepo.getBenMappingByBenDetailsIds(benDetailsVanSerialNoList, vanID); + + for (Object[] benMapOBJ : benMapObjArr) { + beneficiaryList.add(this.getBeneficiariesDTO(this.getBeneficiariesDTONew(benMapOBJ))); + } + + } + + } catch (Exception e) { + logger.error( + "error in beneficiary search for familyId : " + familyId + " error : " + e.getLocalizedMessage()); + } + return beneficiaryList; + } + + public List searchBeneficiaryByVillageIdAndLastModifyDate(List villageIDs, + Timestamp lastModifiedDate) { + + List beneficiaryList = new ArrayList<>(); + try { + // find benmap ids + List benMappingsList = mappingRepo + .findByBeneficiaryDetailsByVillageIDAndLastModifyDate(villageIDs, lastModifiedDate); + if (benMappingsList != null && !benMappingsList.isEmpty()) { + for (MBeneficiarymapping benMapOBJ : benMappingsList) { + beneficiaryList.add(this.getBeneficiariesDTO(benMapOBJ)); + } + } + + } catch (Exception e) { + logger.error("error in beneficiary search to sync to CHO App with villageIDs: {} ", + villageIDs + " error : " + e.getLocalizedMessage()); + } + return beneficiaryList; + } + + public Long countBeneficiaryByVillageIdAndLastModifyDate(List villageIDs, Timestamp lastModifiedDate) { + Long beneficiaryCount = 0L; + try { + beneficiaryCount = mappingRepo.getBeneficiaryCountsByVillageIDAndLastModifyDate(villageIDs, + lastModifiedDate); + } catch (Exception e) { + logger.error("error in getting beneficiary count to sync to CHO App with villageIDs: {},error :{} ", + villageIDs, e.getLocalizedMessage()); + } + return beneficiaryCount; + } + + public List searhBeneficiaryByGovIdentity(String identity) + throws NoResultException, QueryTimeoutException { + List beneficiaryList = new ArrayList<>(); + try { + + List benMapObjArr = new ArrayList<>(); + + // find identity no + List benIdentityList = identityRepo.searchByIdentityNo(identity); + + // find benmap ids + if (benIdentityList == null || benIdentityList.isEmpty()) { + return beneficiaryList; + }else { + for (MBeneficiaryidentity identityObj : benIdentityList) { + benMapObjArr.addAll( + mappingRepo.getBenMappingByVanSerialNo(identityObj.getBenMapId(), identityObj.getVanID())); + } + + for (Object[] benMapOBJ : benMapObjArr) { + beneficiaryList.add(this.getBeneficiariesDTO(this.getBeneficiariesDTONew(benMapOBJ))); + } + + } + + } catch (Exception e) { + logger.error("error in beneficiary search for gov identity : " + identity + " error : " + + e.getLocalizedMessage()); + } + return beneficiaryList; + } + + private MBeneficiarymapping getBeneficiariesDTONew(Object[] benMapArr) { + MBeneficiarymapping mapping = new MBeneficiarymapping(); + if (benMapArr != null && benMapArr.length == 12 && benMapArr[8] != null && benMapArr[9] != null) { + mapping.setBenMapId(getBigIntegerValueFromObject(benMapArr[0])); + mapping.setCreatedBy(String.valueOf(benMapArr[10])); + mapping.setCreatedDate((Timestamp) benMapArr[11]); + mapping = mappingRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[9]), (Integer) benMapArr[8]); + MBeneficiaryaddress address = addressRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[1]), (Integer) benMapArr[8]); + MBeneficiaryconsent consent = consentRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[2]), (Integer) benMapArr[8]); + MBeneficiarycontact contact = contactRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[3]), (Integer) benMapArr[8]); + MBeneficiarydetail details = detailRepo.getWith_vanSerialNo_vanID(getBigIntegerValueFromObject(benMapArr[4]), (Integer) benMapArr[8]); + MBeneficiaryregidmapping regidmapping = regIdRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[5]), (Integer) benMapArr[8]); + MBeneficiaryAccount account = accountRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[7]), (Integer) benMapArr[8]); + MBeneficiaryImage image = imageRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[6]), (Integer) benMapArr[8]); + List servicemap = serviceMapRepo.getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[0]), (Integer) benMapArr[8]); + List identity = identityRepo.findByBenMapIdAndVanID(getBigIntegerValueFromObject(benMapArr[0]), (Integer) benMapArr[8]); + List familymapping = familyMapRepo.findByBenMapIdAndVanIDOrderByBenFamilyMapIdAsc(getBigIntegerValueFromObject(benMapArr[0]), (Integer) benMapArr[8]); + + mapping.setMBeneficiaryaddress(address); + mapping.setMBeneficiaryconsent(consent); + mapping.setMBeneficiarycontact(contact); + mapping.setMBeneficiarydetail(details); + mapping.setMBeneficiaryfamilymappings(familymapping); + mapping.setMBeneficiaryidentities(identity); + mapping.setMBeneficiaryImage(image); + mapping.setMBeneficiaryregidmapping(regidmapping); + mapping.setMBeneficiaryservicemappings(servicemap); + mapping.setMBeneficiaryAccount(account); + //benMapOBJ = mappingRepo.getMapping(getBigIntegerValueFromObject(benMapArr[9]), (Integer) benMapArr[8]); + + BigInteger benRegId = new BigInteger(benMapArr[5].toString()); + RMNCHBeneficiaryDetailsRmnch obj = rMNCHBeneficiaryDetailsRmnchRepo + .getByRegID(benRegId); + + if (obj != null) { + if (obj.getHouseoldId() != null) { + mapping.setHouseHoldID(obj.getHouseoldId()); + } + if (obj.getGuidelineId() != null) { + mapping.setGuideLineID(obj.getGuidelineId()); + } + if (obj.getRchid() != null) { + mapping.setRchID(obj.getRchid()); + } + } + + } + return mapping; + } + + private MBeneficiarymapping getBeneficiariesDTONewPartial(Object[] benMapArr) { + MBeneficiarymapping benMapOBJ = new MBeneficiarymapping(); + + benMapOBJ.setBenMapId(getBigIntegerValueFromObject(benMapArr[0])); + benMapOBJ.setCreatedBy(String.valueOf(benMapArr[10])); + benMapOBJ.setCreatedDate((Timestamp) benMapArr[11]); + + if (benMapArr.length == 12 && benMapArr[8] != null && benMapArr[9] != null) { + + benMapOBJ.setMBeneficiarydetail(detailRepo + .getWith_vanSerialNo_vanID(getBigIntegerValueFromObject(benMapArr[4]), (Integer) benMapArr[8])); + benMapOBJ.setMBeneficiaryregidmapping(regIdRepo + .getWithVanSerialNoVanID(getBigIntegerValueFromObject(benMapArr[5]), (Integer) benMapArr[8])); + } + return benMapOBJ; + } + + // 03-10-2018 + // get ben mapping object from v_benadvancesearch + private MBeneficiarymapping getBeneficiariesDTONew1(VBenAdvanceSearch benAdvanceSearchOBJ) { + MBeneficiarymapping benMapOBJ = new MBeneficiarymapping(); + + // for createdBy & createdDate + if (benAdvanceSearchOBJ != null) { + MBeneficiarydetail benDetailsOBJ = detailRepo + .getWith_vanSerialNo_vanID(benAdvanceSearchOBJ.getBenDetailsID(), benAdvanceSearchOBJ.getVanID()); + + if (benAdvanceSearchOBJ.getHouseHoldID() != null) { + benMapOBJ.setHouseHoldID(benAdvanceSearchOBJ.getHouseHoldID()); + } + if (benAdvanceSearchOBJ.getGuideLineID() != null) { + benMapOBJ.setGuideLineID(benAdvanceSearchOBJ.getGuideLineID()); + } + if (benAdvanceSearchOBJ.getRchID() != null) { + benMapOBJ.setRchID(benAdvanceSearchOBJ.getRchID()); + } + + benMapOBJ.setBenMapId(benAdvanceSearchOBJ.getBenMapID()); + benMapOBJ.setCreatedBy(benDetailsOBJ.getCreatedBy()); + benMapOBJ.setCreatedDate(benDetailsOBJ.getCreatedDate()); + + benMapOBJ.setMBeneficiaryaddress(addressRepo.getWithVanSerialNoVanID(benAdvanceSearchOBJ.getBenAddressID(), + benAdvanceSearchOBJ.getVanID())); + benMapOBJ.setMBeneficiaryconsent(consentRepo.getWithVanSerialNoVanID(benAdvanceSearchOBJ.getBenConsentID(), + benAdvanceSearchOBJ.getVanID())); + benMapOBJ.setMBeneficiarycontact(contactRepo.getWithVanSerialNoVanID(benAdvanceSearchOBJ.getBenContactID(), + benAdvanceSearchOBJ.getVanID())); + benMapOBJ.setMBeneficiarydetail(benDetailsOBJ); + benMapOBJ.setMBeneficiaryregidmapping(regIdRepo.getWithVanSerialNoVanID(benAdvanceSearchOBJ.getBenRegID(), + benAdvanceSearchOBJ.getVanID())); + benMapOBJ.setMBeneficiaryImage(imageRepo.getWithVanSerialNoVanID(benAdvanceSearchOBJ.getBenImageID(), + benAdvanceSearchOBJ.getVanID())); + benMapOBJ.setMBeneficiaryAccount(accountRepo.getWithVanSerialNoVanID(benAdvanceSearchOBJ.getBenAccountID(), + benAdvanceSearchOBJ.getVanID())); + + benMapOBJ.setMBeneficiaryfamilymappings( + familyMapRepo.findByBenMapIdOrderByBenFamilyMapIdAsc(benAdvanceSearchOBJ.getVanSerialNo())); + benMapOBJ.setMBeneficiaryidentities(identityRepo.findByBenMapId(benAdvanceSearchOBJ.getVanSerialNo())); + } + + return benMapOBJ; + } + + private BigInteger getBigIntegerValueFromObject(Object value) { + BigInteger ret = null; + if (value != null) { + if (value instanceof BigInteger) { + ret = (BigInteger) value; + } else if (value instanceof String) { + ret = new BigInteger((String) value); + } else if (value instanceof BigDecimal) { + ret = ((BigDecimal) value).toBigInteger(); + } else if (value instanceof Number) { + ret = BigInteger.valueOf(((Number) value).longValue()); + } else { + throw new ClassCastException("Not possible to coerce [" + value + "] from class " + value.getClass() + + " into a BigInteger."); + } + } else { + throw new ClassCastException("given value is null"); + } + return ret; + } + + /** + * The following parameters can be changed/edited once created: - First Name + * - Middle Name - Last Name - DOB/Age - Address (Current, Permanent, + * Emergency) - Contact Numbers/Email Ids - Spouse Name - Preferred Num - + * Preferred SMS Num - Email Id - Identity + * + * Following changes need Additional Authorization - First Name - Middle + * Name - Last Name - Father Name - Spouse Name - Identity + * + * @param identity + * @return + * @throws MissingMandatoryFieldsException + */ + public void editIdentity(IdentityEditDTO identity) throws MissingMandatoryFieldsException { + logger.info("IdentityService.editIdentity - start"); + if (identity.getBeneficiaryRegId() == null && null == identity.getBeneficaryId()) { + throw new MissingMandatoryFieldsException("Either of BeneficiaryID or Beneficiary Reg Id is mandatory."); + } + + MBeneficiarymapping benMapping = mappingRepo.findByBenRegIdOrderByBenMapIdAsc(identity.getBeneficiaryRegId()); + + // change in self details is implement here and other details here + logger.debug("identity.getChangeInSelfDetails = " + identity.getChangeInSelfDetails()); + logger.debug("identity.getChangeInOtherDetails = " + identity.getChangeInOtherDetails()); + logger.debug("identity.getChangeInAssociations = " + identity.getChangeInAssociations()); + if (Boolean.TRUE.equals(identity.getChangeInSelfDetails()) + || Boolean.TRUE.equals(identity.getChangeInOtherDetails()) + || Boolean.TRUE.equals(identity.getChangeInAssociations())) { + + // MBeneficiarydetail mbDetl = + // editMapper.identityEditDTOToMBeneficiarydetail(identity); + // MBeneficiarydetail mbDetl = + // convertIdentityEditDTOToMBeneficiarydetail(identity); + /** + * new logic for data sync, 26-09-2018 + */ + // getting correct beneficiaryDetailsId by passing vanSerialNo & vanID + MBeneficiarydetail benDetails = detailRepo.findBenDetailsByVanSerialNoAndVanID( + benMapping.getMBeneficiarydetail().getBeneficiaryDetailsId(), benMapping.getVanID()); + // next statement is new one, setting correct beneficiaryDetailsId + if (benDetails != null) { + // Create a new instance of MBeneficiarydetail or use the existing one + MBeneficiarydetail mbDetl = convertIdentityEditDTOToMBeneficiarydetail(identity); + + // Set fields from the existing benDetails to mbDetl + mbDetl.setBeneficiaryDetailsId(benDetails.getBeneficiaryDetailsId()); + if (benDetails.getFamilyId() != null) { + mbDetl.setFamilyId(benDetails.getFamilyId()); + } + if (benDetails.getHeadOfFamily_RelationID() != null) { + mbDetl.setHeadOfFamily_RelationID(benDetails.getHeadOfFamily_RelationID()); + } + if (benDetails.getHeadOfFamily_Relation() != null) { + mbDetl.setHeadOfFamily_Relation(benDetails.getHeadOfFamily_Relation()); + } + if (benDetails.getOther() != null) { + mbDetl.setOther(benDetails.getOther()); + } + + // Extract and set extra fields // String identityJson = new Gson().toJson(json); // JsonObject identityJsonObject = new Gson().fromJson(identityJson, JsonObject.class); // JsonObject otherFieldsJson = new JsonObject(); @@ -778,1052 +1047,1088 @@ public void editIdentity(IdentityEditDTO identity) throws MissingMandatoryFields // } // } // String otherFieldsJsonString = otherFieldsJson.toString(); - // mbDetl.setOtherFields(benDetails.getOtherFields()); - logger.debug("Beneficiary details to update = " + new OutputMapper().gson().toJson(mbDetl)); - if (benDetails.getEmergencyRegistration() != null && benDetails.getEmergencyRegistration()) { - mbDetl.setEmergencyRegistration(true); - } else { - mbDetl.setEmergencyRegistration(false); - } - detailRepo.save(mbDetl); - } - } - // edition in current emergency and permanent is implement below - logger.debug("identity.getChangeInAddress = " + identity.getChangeInAddress()); - if (Boolean.TRUE.equals(identity.getChangeInAddress())) { - - MBeneficiaryaddress mbAddr = editMapper.identityEditDTOToMBeneficiaryaddress(identity); - - /** - * new logic for data sync, 26-09-2018 - */ - - // getting correct beneficiaryDetailsId by passing vanSerialNo & vanID - BigInteger benAddressID = addressRepo.findIdByVanSerialNoAndVanID( - benMapping.getMBeneficiaryaddress().getBenAddressID(), benMapping.getVanID()); - // next statement is new one, setting correct beneficiaryDetailsId - if (benAddressID != null) - mbAddr.setBenAddressID(benAddressID); - else - throw new MissingMandatoryFieldsException("Either of vanSerialNO or vanID is missing."); - - /** - * END - */ - - logger.debug("Beneficiary address to update = " + OutputMapper.gson().toJson(mbAddr)); - addressRepo.save(mbAddr); - } - - // edition in beneficiary contacts is updated here - logger.debug("identity.getChangeInContacts = " + identity.getChangeInContacts()); - if (Boolean.TRUE.equals(identity.getChangeInContacts())) { - - MBeneficiarycontact benCon = editMapper.identityEdiDTOToMBeneficiarycontact(identity); - - /** - * new logic for data sync, 26-09-2018 - */ - - // getting correct beneficiaryDetailsId by passing vanSerialNo & vanID - BigInteger benContactsID = contactRepo.findIdByVanSerialNoAndVanID( - benMapping.getMBeneficiarycontact().getBenContactsID(), benMapping.getVanID()); - // next statement is new one, setting correct beneficiaryDetailsId - if (benContactsID != null) - benCon.setBenContactsID(benContactsID); - else - throw new MissingMandatoryFieldsException("Either of vanSerialNO or vanID is missing."); - - /** - * END - */ - - logger.debug("Beneficiary contact to update = " + OutputMapper.gson().toJson(benCon)); - contactRepo.save(benCon); - } - - // change in identities are added here - logger.debug("identity.getChangeInIdentities = " + identity.getChangeInIdentities()); - if (Boolean.TRUE.equals(identity.getChangeInIdentities())) { - - MBeneficiaryidentity beneficiaryidentity; - List identities = editMapper - .identityEditDTOListToMBeneficiaryidentityList(identity.getIdentities()); - logger.debug("identities to upsert = " + OutputMapper.gson().toJson(identities)); - - // new logic for getting beneficiary identities, 26-09-2018 - List idList = identityRepo.findByBenMapId(benMapping.getVanSerialNo()); - - logger.debug("existing identies = " + OutputMapper.gson().toJson(idList)); - ListIterator iterator = identities.listIterator(); - int index = 0; - while (iterator.hasNext()) { - beneficiaryidentity = iterator.next(); - - // new logic, 26-09-2018 - beneficiaryidentity.setBenMapId(benMapping.getVanSerialNo()); - logger.debug("Beneficiary identity to update = " + OutputMapper.gson().toJson(beneficiaryidentity)); - if (index < idList.size() && beneficiaryidentity.getBenIdentityId() == null) { - beneficiaryidentity.setBenIdentityId(idList.get(index).getBenIdentityId()); - } - - // new code to set vanID & parkingPlaceID for new record, 26-09-2018 - if (index >= idList.size() && beneficiaryidentity.getBenIdentityId() == null) { - beneficiaryidentity.setVanID(benMapping.getVanID()); - beneficiaryidentity.setParkingPlaceID(benMapping.getParkingPlaceID()); - } - - // new logic, 26-09-2018 - MBeneficiaryidentity m = identityRepo.save(beneficiaryidentity); - - // new code, update van serial no for new entry, 26-09-2018 - if (index >= idList.size() && beneficiaryidentity.getBenIdentityId() == null) { - identityRepo.updateVanSerialNo(m.getBenIdentityId()); - } - - index++; - } - } - - // family detail changes are performing here - logger.debug("identity.getChangeInFamilyDetails = " + identity.getChangeInFamilyDetails()); - if (Boolean.TRUE.equals(identity.getChangeInFamilyDetails())) { - List fbMaps = editMapper - .identityEditDTOListToMBeneficiaryfamilymappingList(identity.getBenFamilyDTOs()); - - logger.debug("family map to upsert = " + OutputMapper.gson().toJson(fbMaps)); - - // new logic, 26-09-2018 - List fmList = familyMapRepo - .findByBenMapIdOrderByBenFamilyMapIdAsc(benMapping.getVanSerialNo()); - - logger.debug("family map stored = " + OutputMapper.gson().toJson(fmList)); - ListIterator iterator = fbMaps.listIterator(); - MBeneficiaryfamilymapping familymapping; - int index = 0; - while (iterator.hasNext()) { - - familymapping = iterator.next(); - // new logic, 26-09-2018 - familymapping.setBenMapId(benMapping.getVanSerialNo()); - - logger.debug("family mapping to update = " + OutputMapper.gson().toJson(familymapping)); - if (index < fmList.size()) { - familymapping.setBenFamilyMapId(fmList.get(index).getBenFamilyMapId()); - } - - if (index >= fmList.size() && familymapping.getBenFamilyMapId() == null) { - familymapping.setVanID(benMapping.getVanID()); - familymapping.setParkingPlaceID(benMapping.getParkingPlaceID()); - } - - // new logic, 26-09-2018 - MBeneficiaryfamilymapping m = familyMapRepo.save(familymapping); - - // new code, update van serial no for new entry, 26-09-2018 - if (familymapping.getBenFamilyMapId() == null) { - familyMapRepo.updateVanSerialNo(m.getBenFamilyMapId()); - } - - index++; - } - } - - // start - // Feature used in outreach - if (Boolean.TRUE.equals(identity.getChangeInBankDetails())) { - MBeneficiaryAccount beneficiaryAccount = editMapper.identityEditDTOToMBeneficiaryAccount(identity); - - /** - * new logic for data sync, 26-09-2018 - */ - // getting correct beneficiaryDetailsId by passing vanSerialNo & vanID - BigInteger benAccountID = accountRepo.findIdByVanSerialNoAndVanID( - benMapping.getMBeneficiaryAccount().getBenAccountID(), benMapping.getVanID()); - // next statement is new one, setting correct beneficiaryDetailsId - if (benAccountID != null) - beneficiaryAccount.setBenAccountID(benAccountID); - else - throw new MissingMandatoryFieldsException("Either of vanSerialNO or vanID is missing."); - - /** - * END - */ - - logger.debug("Account to upsert = " + OutputMapper.gson().toJson(beneficiaryAccount)); - accountRepo.save(beneficiaryAccount); - } - - if (Boolean.TRUE.equals(identity.getChangeInBenImage())) { - MBeneficiaryImage beneficiaryImage = editMapper.identityEditDTOToMBeneficiaryImage(identity); - - /** - * new logic for data sync, 26-09-2018 - */ - // getting correct beneficiaryDetailsId by passing vanSerialNo & vanID - BigInteger benImageId = imageRepo.findIdByVanSerialNoAndVanID( - benMapping.getMBeneficiaryImage().getBenImageId(), benMapping.getVanID()); - // next statement is new one, setting correct beneficiaryDetailsId - if (benImageId != null) - beneficiaryImage.setBenImageId(benImageId); - else - throw new MissingMandatoryFieldsException("Either of vanSerialNO or vanID is missing."); - - /** - * END - */ - - logger.debug("Image to upsert = " + OutputMapper.gson().toJson(beneficiaryImage)); - beneficiaryImage.setProcessed("N"); - imageRepo.save(beneficiaryImage); - } - - logger.info("IdentityService.editIdentity - end. id = " + benMapping.getBenMapId()); - } - - private MBeneficiarydetail convertIdentityEditDTOToMBeneficiarydetail(IdentityEditDTO dto) { - MBeneficiarydetail beneficiarydetail = new MBeneficiarydetail(); - - // Directly set values without using @Mapping - beneficiarydetail.setAreaId(dto.getAreaId()); - beneficiarydetail.setBeneficiaryRegID(dto.getBeneficiaryRegId()); - beneficiarydetail.setCommunity(dto.getCommunity()); - beneficiarydetail.setLiteracyStatus(dto.getLiteracyStatus()); - beneficiarydetail.setCommunityId(dto.getCommunityId()); - beneficiarydetail.setDob(dto.getDob()); - beneficiarydetail.setEducation(dto.getEducation()); - beneficiarydetail.setEducationId(dto.getEducationId()); - beneficiarydetail.setHealthCareWorkerId(dto.getHealthCareWorkerId()); - beneficiarydetail.setHealthCareWorker(dto.getHealthCareWorker()); - beneficiarydetail.setFatherName(dto.getFatherName()); - beneficiarydetail.setMotherName(dto.getMotherName()); - beneficiarydetail.setFirstName(dto.getFirstName()); - beneficiarydetail.setGender(dto.getGender()); - beneficiarydetail.setGenderId(dto.getGenderId()); - beneficiarydetail.setIncomeStatusId(dto.getIncomeStatusId()); - beneficiarydetail.setIncomeStatus(dto.getIncomeStatus()); - beneficiarydetail.setMonthlyFamilyIncome(dto.getMonthlyFamilyIncome()); - if (dto.getLastName() != null) - beneficiarydetail.setLastName(dto.getLastName()); - beneficiarydetail.setMaritalStatusId(dto.getMaritalStatusId()); - beneficiarydetail.setMaritalStatus(dto.getMaritalStatus()); - beneficiarydetail.setMiddleName(dto.getMiddleName()); - beneficiarydetail.setOccupation(dto.getOccupationName()); - beneficiarydetail.setOccupationId(dto.getOccupationId()); - beneficiarydetail.setPhcId(dto.getPhcId()); - beneficiarydetail.setPlaceOfWork(dto.getPlaceOfWork()); - beneficiarydetail.setPreferredLanguage(dto.getPreferredLanguage()); - beneficiarydetail.setReligion(dto.getReligion()); - if (dto.getReligionId() != null) - beneficiarydetail.setReligionId(BigInteger.valueOf(dto.getReligionId())); - beneficiarydetail.setRemarks(dto.getRemarks()); - beneficiarydetail.setServicePointId(dto.getServicePointId()); - beneficiarydetail.setSourceOfInfo(dto.getSourceOfInfo()); - beneficiarydetail.setSpouseName(dto.getSpouseName()); - beneficiarydetail.setStatus(dto.getStatus()); - beneficiarydetail.setTitle(dto.getTitle()); - beneficiarydetail.setTitleId(dto.getTitleId()); - beneficiarydetail.setZoneId(dto.getZoneId()); - beneficiarydetail.setCreatedBy(dto.getAgentName()); - beneficiarydetail.setCreatedDate(dto.getEventTypeDate()); - beneficiarydetail.setIsHIVPositive(MBeneficiarydetail.setIsHIVPositive(dto.getIsHIVPositive())); - beneficiarydetail.setAgeAtMarriage( - MBeneficiarydetail.getAgeAtMarriageCalc(dto.getDob(), dto.getMarriageDate(), dto.getAgeAtMarriage())); - beneficiarydetail.setMarriageDate( - MBeneficiarydetail.getMarriageDateCalc(dto.getDob(), dto.getMarriageDate(), dto.getAgeAtMarriage())); - if(dto.getOtherFields() != null) - beneficiarydetail.setOtherFields(dto.getOtherFields()); - - return beneficiarydetail; - } - - /** - * @param identity - * @return - */ - - ArrayDeque queue = new ArrayDeque<>(); - - public BeneficiaryCreateResp createIdentity(IdentityDTO identity) { - logger.info("IdentityService.createIdentity - start"); - - List list = null; - MBeneficiaryregidmapping regMap = null; - synchronized (queue) { - if (queue.isEmpty()) { - logger.info("fetching 10000 rows"); - list = regIdRepo.findTop10000ByProvisionedAndReserved(false, false); - logger.info("Adding SynchronousQueue start-- "); - for (MBeneficiaryregidmapping map : list) { - queue.add(map); - } - logger.info("Adding SynchronousQueue end-- "); - } - regMap = queue.removeFirst(); - } - regMap.setReserved(true); - if (regMap.getCreatedDate() == null) { - SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); - String dateToStoreInDataBase = sdf.format(new Date()); - Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); - regMap.setCreatedDate(ts); - } - - regIdRepo.save(regMap); - - regMap.setProvisioned(true); - - logger.info("IdentityService.createIdentity - saving Address"); - ObjectMapper objectMapper = new ObjectMapper(); - MBeneficiaryaddress mAddr = identityDTOToMBeneficiaryaddress(identity); - // MBeneficiaryaddress mAddr1 = - // mapper.identityDTOToMBeneficiaryaddress(identity); - logger.info("identity.getIsPermAddrSameAsCurrAddr = " + identity.getIsPermAddrSameAsCurrAddr()); - if (Boolean.TRUE.equals(identity.getIsPermAddrSameAsCurrAddr())) { - logger.debug("identity.getCurrentAddress = " + identity.getCurrentAddress()); - mAddr.setPermanentAddress(identity.getCurrentAddress()); - } - - logger.info("identity.getIsPermAddrSameAsEmerAddr = " + identity.getIsPermAddrSameAsEmerAddr()); - if (Boolean.TRUE.equals(identity.getIsPermAddrSameAsEmerAddr())) { - logger.debug("identity.getEmergencyAddress = " + identity.getEmergencyAddress()); - mAddr.setPermanentAddress(identity.getEmergencyAddress()); - } - - logger.info("identity.getIsEmerAddrSameAsCurrAddr = " + identity.getIsEmerAddrSameAsCurrAddr()); - if (Boolean.TRUE.equals(identity.getIsEmerAddrSameAsCurrAddr())) { - logger.debug("identity.getCurrentAddress = " + identity.getCurrentAddress()); - mAddr.setEmergencyAddress(identity.getCurrentAddress()); - } - - logger.info("identity.getIsEmerAddrSameAsPermAddr = " + identity.getIsEmerAddrSameAsPermAddr()); - if (Boolean.TRUE.equals(identity.getIsEmerAddrSameAsPermAddr())) { - logger.debug("identity.getPermanentAddress = " + identity.getPermanentAddress()); - mAddr.setEmergencyAddress(identity.getPermanentAddress()); - } - if (mAddr.getCreatedDate() == null) { - SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); - String dateToStoreInDataBase = sdf.format(new Date()); - Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); - mAddr.setCreatedDate(ts); - } - - mAddr = addressRepo.save(mAddr); - logger.info("IdentityService.createIdentity - Address saved - id = " + mAddr.getBenAddressID()); - - // Update van serial no for data sync - addressRepo.updateVanSerialNo(mAddr.getBenAddressID()); - - MBeneficiaryconsent mConsnt = mapper.identityDTOToDefaultMBeneficiaryconsent(identity, true, false); - logger.info("IdentityService.createIdentity - saving Consent"); - if (mConsnt.getCreatedDate() == null) { - SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); - String dateToStoreInDataBase = sdf.format(new Date()); - Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); - mConsnt.setCreatedDate(ts); - } - mConsnt = consentRepo.save(mConsnt); - logger.info("IdentityService.createIdentity - Consent saved - id = " + mConsnt.getBenConsentID()); - - // Update van serial no for data sync - consentRepo.updateVanSerialNo(mConsnt.getBenConsentID()); - - logger.info("IdentityService.createIdentity - saving Contacts"); - MBeneficiarycontact mContc = identityDTOToMBeneficiarycontact(identity); - - if (mContc.getEmergencyContactNum() != null) { - mContc.setEmergencyContactNum(cleanPhoneNumber(mContc.getEmergencyContactNum())); + // mbDetl.setOtherFields(benDetails.getOtherFields()); + logger.debug("Beneficiary details to update = " + new OutputMapper().gson().toJson(mbDetl)); + if (benDetails.getEmergencyRegistration() != null && benDetails.getEmergencyRegistration()) { + mbDetl.setEmergencyRegistration(true); + } else { + mbDetl.setEmergencyRegistration(false); + } + detailRepo.save(mbDetl); + } + } + // edition in current emergency and permanent is implement below + logger.debug("identity.getChangeInAddress = " + identity.getChangeInAddress()); + if (Boolean.TRUE.equals(identity.getChangeInAddress())) { + + MBeneficiaryaddress mbAddr = editMapper.identityEditDTOToMBeneficiaryaddress(identity); + + /** + * new logic for data sync, 26-09-2018 + */ + // getting correct beneficiaryDetailsId by passing vanSerialNo & vanID + BigInteger benAddressID = addressRepo.findIdByVanSerialNoAndVanID( + benMapping.getMBeneficiaryaddress().getBenAddressID(), benMapping.getVanID()); + // next statement is new one, setting correct beneficiaryDetailsId + if (benAddressID != null) { + mbAddr.setBenAddressID(benAddressID); + }else { + throw new MissingMandatoryFieldsException("Either of vanSerialNO or vanID is missing."); + } + + /** + * END + */ + logger.debug("Beneficiary address to update = " + OutputMapper.gson().toJson(mbAddr)); + addressRepo.save(mbAddr); + } + + // edition in beneficiary contacts is updated here + logger.debug("identity.getChangeInContacts = " + identity.getChangeInContacts()); + if (Boolean.TRUE.equals(identity.getChangeInContacts())) { + + MBeneficiarycontact benCon = editMapper.identityEdiDTOToMBeneficiarycontact(identity); + + /** + * new logic for data sync, 26-09-2018 + */ + // getting correct beneficiaryDetailsId by passing vanSerialNo & vanID + BigInteger benContactsID = contactRepo.findIdByVanSerialNoAndVanID( + benMapping.getMBeneficiarycontact().getBenContactsID(), benMapping.getVanID()); + // next statement is new one, setting correct beneficiaryDetailsId + if (benContactsID != null) { + benCon.setBenContactsID(benContactsID); + }else { + throw new MissingMandatoryFieldsException("Either of vanSerialNO or vanID is missing."); + } + + /** + * END + */ + logger.debug("Beneficiary contact to update = " + OutputMapper.gson().toJson(benCon)); + contactRepo.save(benCon); + } + + // change in identities are added here + logger.debug("identity.getChangeInIdentities = " + identity.getChangeInIdentities()); + if (Boolean.TRUE.equals(identity.getChangeInIdentities())) { + + MBeneficiaryidentity beneficiaryidentity; + List identities = editMapper + .identityEditDTOListToMBeneficiaryidentityList(identity.getIdentities()); + logger.debug("identities to upsert = " + OutputMapper.gson().toJson(identities)); + + // new logic for getting beneficiary identities, 26-09-2018 + List idList = identityRepo.findByBenMapId(benMapping.getVanSerialNo()); + + logger.debug("existing identies = " + OutputMapper.gson().toJson(idList)); + ListIterator iterator = identities.listIterator(); + int index = 0; + while (iterator.hasNext()) { + beneficiaryidentity = iterator.next(); + + // new logic, 26-09-2018 + beneficiaryidentity.setBenMapId(benMapping.getVanSerialNo()); + logger.debug("Beneficiary identity to update = " + OutputMapper.gson().toJson(beneficiaryidentity)); + if (index < idList.size() && beneficiaryidentity.getBenIdentityId() == null) { + beneficiaryidentity.setBenIdentityId(idList.get(index).getBenIdentityId()); + } + + // new code to set vanID & parkingPlaceID for new record, 26-09-2018 + if (index >= idList.size() && beneficiaryidentity.getBenIdentityId() == null) { + beneficiaryidentity.setVanID(benMapping.getVanID()); + beneficiaryidentity.setParkingPlaceID(benMapping.getParkingPlaceID()); + } + + // new logic, 26-09-2018 + MBeneficiaryidentity m = identityRepo.save(beneficiaryidentity); + + // new code, update van serial no for new entry, 26-09-2018 + if (index >= idList.size() && beneficiaryidentity.getBenIdentityId() == null) { + identityRepo.updateVanSerialNo(m.getBenIdentityId()); + } + + index++; + } + } + + // family detail changes are performing here + logger.debug("identity.getChangeInFamilyDetails = " + identity.getChangeInFamilyDetails()); + if (Boolean.TRUE.equals(identity.getChangeInFamilyDetails())) { + List fbMaps = editMapper + .identityEditDTOListToMBeneficiaryfamilymappingList(identity.getBenFamilyDTOs()); + + logger.debug("family map to upsert = " + OutputMapper.gson().toJson(fbMaps)); + + // new logic, 26-09-2018 + List fmList = familyMapRepo + .findByBenMapIdOrderByBenFamilyMapIdAsc(benMapping.getVanSerialNo()); + + logger.debug("family map stored = " + OutputMapper.gson().toJson(fmList)); + ListIterator iterator = fbMaps.listIterator(); + MBeneficiaryfamilymapping familymapping; + int index = 0; + while (iterator.hasNext()) { + + familymapping = iterator.next(); + // new logic, 26-09-2018 + familymapping.setBenMapId(benMapping.getVanSerialNo()); + + logger.debug("family mapping to update = " + OutputMapper.gson().toJson(familymapping)); + if (index < fmList.size()) { + familymapping.setBenFamilyMapId(fmList.get(index).getBenFamilyMapId()); + } + + if (index >= fmList.size() && familymapping.getBenFamilyMapId() == null) { + familymapping.setVanID(benMapping.getVanID()); + familymapping.setParkingPlaceID(benMapping.getParkingPlaceID()); + } + + // new logic, 26-09-2018 + MBeneficiaryfamilymapping m = familyMapRepo.save(familymapping); + + // new code, update van serial no for new entry, 26-09-2018 + if (familymapping.getBenFamilyMapId() == null) { + familyMapRepo.updateVanSerialNo(m.getBenFamilyMapId()); + } + + index++; + } + } + + // start + // Feature used in outreach + if (Boolean.TRUE.equals(identity.getChangeInBankDetails())) { + MBeneficiaryAccount beneficiaryAccount = editMapper.identityEditDTOToMBeneficiaryAccount(identity); + + /** + * new logic for data sync, 26-09-2018 + */ + // getting correct beneficiaryDetailsId by passing vanSerialNo & vanID + BigInteger benAccountID = accountRepo.findIdByVanSerialNoAndVanID( + benMapping.getMBeneficiaryAccount().getBenAccountID(), benMapping.getVanID()); + // next statement is new one, setting correct beneficiaryDetailsId + if (benAccountID != null) { + beneficiaryAccount.setBenAccountID(benAccountID); + }else { + throw new MissingMandatoryFieldsException("Either of vanSerialNO or vanID is missing."); + } + + /** + * END + */ + logger.debug("Account to upsert = " + OutputMapper.gson().toJson(beneficiaryAccount)); + accountRepo.save(beneficiaryAccount); + } + + if (Boolean.TRUE.equals(identity.getChangeInBenImage())) { + MBeneficiaryImage beneficiaryImage = editMapper.identityEditDTOToMBeneficiaryImage(identity); + + /** + * new logic for data sync, 26-09-2018 + */ + // getting correct beneficiaryDetailsId by passing vanSerialNo & vanID + BigInteger benImageId = imageRepo.findIdByVanSerialNoAndVanID( + benMapping.getMBeneficiaryImage().getBenImageId(), benMapping.getVanID()); + // next statement is new one, setting correct beneficiaryDetailsId + if (benImageId != null) { + beneficiaryImage.setBenImageId(benImageId); + }else { + throw new MissingMandatoryFieldsException("Either of vanSerialNO or vanID is missing."); + } + + /** + * END + */ + logger.debug("Image to upsert = " + OutputMapper.gson().toJson(beneficiaryImage)); + beneficiaryImage.setProcessed("N"); + imageRepo.save(beneficiaryImage); + } + + // Trigger async sync to Elasticsearch + if (identity.getBeneficiaryRegId() != null) { + logger.info("Triggering Elasticsearch sync for benRegId: {}", identity.getBeneficiaryRegId()); + syncService.syncBeneficiaryAsync(identity.getBeneficiaryRegId()); + } + logger.info("IdentityService.editIdentity - end. id = " + benMapping.getBenMapId()); } - - if (mContc.getPhoneNum1() != null) { - mContc.setPhoneNum1(cleanPhoneNumber(mContc.getPhoneNum1())); + + private MBeneficiarydetail convertIdentityEditDTOToMBeneficiarydetail(IdentityEditDTO dto) { + MBeneficiarydetail beneficiarydetail = new MBeneficiarydetail(); + + // Directly set values without using @Mapping + beneficiarydetail.setAreaId(dto.getAreaId()); + beneficiarydetail.setBeneficiaryRegID(dto.getBeneficiaryRegId()); + beneficiarydetail.setCommunity(dto.getCommunity()); + beneficiarydetail.setLiteracyStatus(dto.getLiteracyStatus()); + beneficiarydetail.setCommunityId(dto.getCommunityId()); + beneficiarydetail.setDob(dto.getDob()); + beneficiarydetail.setEducation(dto.getEducation()); + beneficiarydetail.setEducationId(dto.getEducationId()); + beneficiarydetail.setHealthCareWorkerId(dto.getHealthCareWorkerId()); + beneficiarydetail.setHealthCareWorker(dto.getHealthCareWorker()); + beneficiarydetail.setFatherName(dto.getFatherName()); + beneficiarydetail.setMotherName(dto.getMotherName()); + beneficiarydetail.setFirstName(dto.getFirstName()); + beneficiarydetail.setGender(dto.getGender()); + beneficiarydetail.setGenderId(dto.getGenderId()); + beneficiarydetail.setIncomeStatusId(dto.getIncomeStatusId()); + beneficiarydetail.setIncomeStatus(dto.getIncomeStatus()); + beneficiarydetail.setMonthlyFamilyIncome(dto.getMonthlyFamilyIncome()); + if (dto.getLastName() != null) { + beneficiarydetail.setLastName(dto.getLastName()); + } + beneficiarydetail.setMaritalStatusId(dto.getMaritalStatusId()); + beneficiarydetail.setMaritalStatus(dto.getMaritalStatus()); + beneficiarydetail.setMiddleName(dto.getMiddleName()); + beneficiarydetail.setOccupation(dto.getOccupationName()); + beneficiarydetail.setOccupationId(dto.getOccupationId()); + beneficiarydetail.setPhcId(dto.getPhcId()); + beneficiarydetail.setPlaceOfWork(dto.getPlaceOfWork()); + beneficiarydetail.setPreferredLanguage(dto.getPreferredLanguage()); + beneficiarydetail.setReligion(dto.getReligion()); + if (dto.getReligionId() != null) { + beneficiarydetail.setReligionId(BigInteger.valueOf(dto.getReligionId())); + } + beneficiarydetail.setRemarks(dto.getRemarks()); + beneficiarydetail.setServicePointId(dto.getServicePointId()); + beneficiarydetail.setSourceOfInfo(dto.getSourceOfInfo()); + beneficiarydetail.setSpouseName(dto.getSpouseName()); + beneficiarydetail.setStatus(dto.getStatus()); + beneficiarydetail.setTitle(dto.getTitle()); + beneficiarydetail.setTitleId(dto.getTitleId()); + beneficiarydetail.setZoneId(dto.getZoneId()); + beneficiarydetail.setCreatedBy(dto.getAgentName()); + beneficiarydetail.setCreatedDate(dto.getEventTypeDate()); + beneficiarydetail.setIsHIVPositive(MBeneficiarydetail.setIsHIVPositive(dto.getIsHIVPositive())); + beneficiarydetail.setAgeAtMarriage( + MBeneficiarydetail.getAgeAtMarriageCalc(dto.getDob(), dto.getMarriageDate(), dto.getAgeAtMarriage())); + beneficiarydetail.setMarriageDate( + MBeneficiarydetail.getMarriageDateCalc(dto.getDob(), dto.getMarriageDate(), dto.getAgeAtMarriage())); + if (dto.getOtherFields() != null) { + beneficiarydetail.setOtherFields(dto.getOtherFields()); + } + + return beneficiarydetail; } - - if (mContc.getPhoneNum2() != null) { - mContc.setPhoneNum2(cleanPhoneNumber(mContc.getPhoneNum2())); + + /** + * @param identity + * @return + */ + ArrayDeque queue = new ArrayDeque<>(); + + public BeneficiaryCreateResp createIdentity(IdentityDTO identity) { + logger.info("IdentityService.createIdentity - start"); + + List list = null; + MBeneficiaryregidmapping regMap = null; + synchronized (queue) { + if (queue.isEmpty()) { + logger.info("fetching 10000 rows"); + list = regIdRepo.findTop10000ByProvisionedAndReserved(false, false); + logger.info("Adding SynchronousQueue start-- "); + for (MBeneficiaryregidmapping map : list) { + queue.add(map); + } + logger.info("Adding SynchronousQueue end-- "); + } + regMap = queue.removeFirst(); + } + regMap.setReserved(true); + if (regMap.getCreatedDate() == null) { + SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); + String dateToStoreInDataBase = sdf.format(new Date()); + Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); + regMap.setCreatedDate(ts); + } + + regIdRepo.save(regMap); + + regMap.setProvisioned(true); + + logger.info("IdentityService.createIdentity - saving Address"); + ObjectMapper objectMapper = new ObjectMapper(); + MBeneficiaryaddress mAddr = identityDTOToMBeneficiaryaddress(identity); + // MBeneficiaryaddress mAddr1 = + // mapper.identityDTOToMBeneficiaryaddress(identity); + logger.info("identity.getIsPermAddrSameAsCurrAddr = " + identity.getIsPermAddrSameAsCurrAddr()); + if (Boolean.TRUE.equals(identity.getIsPermAddrSameAsCurrAddr())) { + logger.debug("identity.getCurrentAddress = " + identity.getCurrentAddress()); + mAddr.setPermanentAddress(identity.getCurrentAddress()); + } + + logger.info("identity.getIsPermAddrSameAsEmerAddr = " + identity.getIsPermAddrSameAsEmerAddr()); + if (Boolean.TRUE.equals(identity.getIsPermAddrSameAsEmerAddr())) { + logger.debug("identity.getEmergencyAddress = " + identity.getEmergencyAddress()); + mAddr.setPermanentAddress(identity.getEmergencyAddress()); + } + + logger.info("identity.getIsEmerAddrSameAsCurrAddr = " + identity.getIsEmerAddrSameAsCurrAddr()); + if (Boolean.TRUE.equals(identity.getIsEmerAddrSameAsCurrAddr())) { + logger.debug("identity.getCurrentAddress = " + identity.getCurrentAddress()); + mAddr.setEmergencyAddress(identity.getCurrentAddress()); + } + + logger.info("identity.getIsEmerAddrSameAsPermAddr = " + identity.getIsEmerAddrSameAsPermAddr()); + if (Boolean.TRUE.equals(identity.getIsEmerAddrSameAsPermAddr())) { + logger.debug("identity.getPermanentAddress = " + identity.getPermanentAddress()); + mAddr.setEmergencyAddress(identity.getPermanentAddress()); + } + if (mAddr.getCreatedDate() == null) { + SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); + String dateToStoreInDataBase = sdf.format(new Date()); + Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); + mAddr.setCreatedDate(ts); + } + + mAddr = addressRepo.save(mAddr); + logger.info("IdentityService.createIdentity - Address saved - id = " + mAddr.getBenAddressID()); + + // Update van serial no for data sync + addressRepo.updateVanSerialNo(mAddr.getBenAddressID()); + + MBeneficiaryconsent mConsnt = mapper.identityDTOToDefaultMBeneficiaryconsent(identity, true, false); + logger.info("IdentityService.createIdentity - saving Consent"); + if (mConsnt.getCreatedDate() == null) { + SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); + String dateToStoreInDataBase = sdf.format(new Date()); + Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); + mConsnt.setCreatedDate(ts); + } + mConsnt = consentRepo.save(mConsnt); + logger.info("IdentityService.createIdentity - Consent saved - id = " + mConsnt.getBenConsentID()); + + // Update van serial no for data sync + consentRepo.updateVanSerialNo(mConsnt.getBenConsentID()); + + logger.info("IdentityService.createIdentity - saving Contacts"); + MBeneficiarycontact mContc = identityDTOToMBeneficiarycontact(identity); + + if (mContc.getEmergencyContactNum() != null) { + mContc.setEmergencyContactNum(cleanPhoneNumber(mContc.getEmergencyContactNum())); + } + + if (mContc.getPhoneNum1() != null) { + mContc.setPhoneNum1(cleanPhoneNumber(mContc.getPhoneNum1())); + } + + if (mContc.getPhoneNum2() != null) { + mContc.setPhoneNum2(cleanPhoneNumber(mContc.getPhoneNum2())); + } + if (mContc.getPhoneNum3() != null) { + mContc.setPhoneNum3(cleanPhoneNumber(mContc.getPhoneNum3())); + } + + if (mContc.getPhoneNum4() != null) { + mContc.setPhoneNum4(cleanPhoneNumber(mContc.getPhoneNum4())); + } + if (mContc.getPhoneNum5() != null) { + mContc.setPhoneNum5(cleanPhoneNumber(mContc.getPhoneNum5())); + } + if (mContc.getPreferredSMSPhoneNum() != null) { + mContc.setPreferredSMSPhoneNum(cleanPhoneNumber(mContc.getPreferredSMSPhoneNum())); + } + if (mContc.getPreferredPhoneNum() != null) { + mContc.setPreferredPhoneNum(cleanPhoneNumber(mContc.getPreferredPhoneNum())); + } + + // MBeneficiarycontact mContc = + // mapper.identityDTOToMBeneficiarycontact(identity); + if (mContc.getCreatedDate() == null) { + SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); + String dateToStoreInDataBase = sdf.format(new Date()); + Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); + mContc.setCreatedDate(ts); + } + mContc = contactRepo.save(mContc); + logger.info("IdentityService.createIdentity - Contacts saved - id = " + mContc.getBenContactsID()); + + // Update van serial no for data sync + contactRepo.updateVanSerialNo(mContc.getBenContactsID()); + + logger.info("IdentityService.createIdentity - saving Details"); + // MBeneficiarydetail mDetl = mapper.identityDTOToMBeneficiarydetail(identity); + MBeneficiarydetail mDetl = convertIdentityDTOToMBeneficiarydetail(identity); + + if (mDetl.getCreatedDate() == null) { + SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); + String dateToStoreInDataBase = sdf.format(new Date()); + Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); + mDetl.setCreatedDate(ts); + } + mDetl = detailRepo.save(mDetl); + logger.info("IdentityService.createIdentity - Details saved - id = " + mDetl.getBeneficiaryDetailsId()); + + // Update van serial no for data sync + detailRepo.updateVanSerialNo(mDetl.getBeneficiaryDetailsId()); + + MBeneficiaryAccount bankOBJ = mapper.identityDTOToMBeneficiaryAccount(identity); + if (bankOBJ.getCreatedDate() == null) { + SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); + String dateToStoreInDataBase = sdf.format(new Date()); + Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); + bankOBJ.setCreatedDate(ts); + } + bankOBJ = accountRepo.save(bankOBJ); + // Update van serial no for data sync + accountRepo.updateVanSerialNo(bankOBJ.getBenAccountID()); + + // MBeneficiaryImage benImageOBJ = mapper.identityDTOToMBeneficiaryImage(identity); + MBeneficiaryImage benImageOBJ = identityDTOToMBeneficiaryImage(identity); + + if (benImageOBJ.getCreatedDate() == null) { + SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); + String dateToStoreInDataBase = sdf.format(new Date()); + Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); + benImageOBJ.setCreatedDate(ts); + } + benImageOBJ = imageRepo.save(benImageOBJ); + + // Update van serial no for data sync + imageRepo.updateVanSerialNo(benImageOBJ.getBenImageId()); + + logger.info("IdentityService.createIdentity - saving Mapping"); + MBeneficiarymapping benMapping = mapper.identityDTOToMBeneficiarymapping(identity); + + benMapping.setMBeneficiarycontact(mContc); + benMapping.setMBeneficiaryaddress(mAddr); + benMapping.setMBeneficiaryconsent(mConsnt); + benMapping.setMBeneficiarydetail(mDetl); + benMapping.setMBeneficiaryregidmapping(regMap); + benMapping.setMBeneficiaryImage(benImageOBJ); + benMapping.setMBeneficiaryAccount(bankOBJ); + + regMap.setProviderServiceMapID(identity.getProviderServiceMapId()); + // added columns for data sync + // 17-09-2018 + if (identity.getVanID() != null) { + regMap.setVanID(identity.getVanID()); + } + if (identity.getParkingPlaceId() != null) { + regMap.setParkingPlaceID(identity.getParkingPlaceId()); + } + regMap.setVanSerialNo(regMap.getBenRegId()); + // END + + regIdRepo.save(regMap); + if (benMapping.getCreatedDate() == null) { + SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); + String dateToStoreInDataBase = sdf.format(new Date()); + Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); + benMapping.setCreatedDate(ts); + } + + if (identity.getBenFamilyDTOs().get(0).getVanID() != null) { + benMapping.setVanID(identity.getBenFamilyDTOs().get(0).getVanID()); + } + + benMapping = mappingRepo.save(benMapping); + // Update van serial no for data sync + mappingRepo.updateVanSerialNo(benMapping.getBenMapId()); + + final MBeneficiarymapping benMapping2 = benMapping; + logger.info("IdentityService.createIdentity - saving FamilyMaps"); + List fIdenList = null; + List fList = null; + + // new logic (18-09-2018, Neeraj kumar) + if (null != identity.getBenFamilyDTOs()) { + fIdenList = mapper.identityDTOListToMBeneficiaryfamilymappingList(identity.getBenFamilyDTOs()); + if (fIdenList != null) { + for (MBeneficiaryfamilymapping bfMapping : fIdenList) { + bfMapping.setBenMapId(benMapping2.getBenMapId()); + + if (bfMapping.getVanID() == null && identity.getVanID() != null) { + bfMapping.setVanID(identity.getVanID()); + } + if (bfMapping.getVanID() == null && identity.getBenFamilyDTOs().get(0).getVanID() != null) { + bfMapping.setVanID(identity.getBenFamilyDTOs().get(0).getVanID()); + } + + if (bfMapping.getParkingPlaceID() == null && identity.getParkingPlaceId() != null) { + bfMapping.setParkingPlaceID(identity.getParkingPlaceId()); + } + + if (bfMapping.getAssociatedBenRegId() == null) { + bfMapping.setAssociatedBenRegId(benMapping2.getBenRegId()); + } + } + fList = (List) familyMapRepo.saveAll(fIdenList); + // Update van serial no for data sync + if (fList != null && !fList.isEmpty()) { + for (MBeneficiaryfamilymapping obj : fList) { + familyMapRepo.updateVanSerialNo(obj.getBenFamilyMapId()); + } + } + } + } + + logger.info("IdentityService.createIdentity - FamilyMap saved "); + logger.info("IdentityService.createIdentity - saving Service Map"); + MBeneficiaryservicemapping sMap = mapper.identityDTOToMBeneficiaryservicemapping(identity); + sMap.setBenMapId(benMapping.getBenMapId()); + if (sMap.getCreatedDate() == null) { + SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); + String dateToStoreInDataBase = sdf.format(new Date()); + Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); + sMap.setCreatedDate(ts); + } + sMap = serviceMapRepo.save(sMap); + logger.info("IdentityService.createIdentity - ServiceMap saved - id = " + sMap.getBenServiceMapID()); + + // Update van serial no for data sync + serviceMapRepo.updateVanSerialNo(sMap.getBenServiceMapID()); + + List sList = new ArrayList<>(); + sList.add(sMap); + logger.info("IdentityService.createIdentity - saving Identity"); + List mIdenList2 = new ArrayList<>(); + if (null != identity.getIdentities()) { + List mIdenList = mapper + .identityDTOListToMBeneficiaryidentityList(identity.getIdentities()); + mIdenList.forEach(mIden -> { + mIden.setBenMapId(benMapping2.getBenMapId()); + mIden.setCreatedBy(identity.getAgentName()); + mIden.setCreatedDate(identity.getEventTypeDate()); + + // set new column(vanID, parkingPlaceID) value for data sync + if (identity.getVanID() != null) { + mIden.setVanID(identity.getVanID()); + } + if (identity.getParkingPlaceId() != null) { + mIden.setParkingPlaceID(identity.getParkingPlaceId()); + } + + MBeneficiaryidentity m = identityRepo.save(mIden); + + // Update van serial no for data sync + identityRepo.updateVanSerialNo(m.getBenIdentityId()); + + mIdenList2.add(m); + logger.info("IdentityService.createIdentity - Identity saved - id = " + m.getBenIdentityId()); + }); + } + + // return partialMapper.mBeneficiarymappingToBeneficiaryCreateResp(benMapping); + logger.info("IdentityService.createIdentity - end. id = " + benMapping.getBenMapId()); + + BeneficiaryCreateResp response = partialMapper.mBeneficiarymappingToBeneficiaryCreateResp(benMapping); + +// Trigger async sync to Elasticsearch + if (regMap != null && regMap.getBenRegId() != null) { + logger.info("Triggering Elasticsearch sync for benRegId: {}", regMap.getBenRegId()); + syncService.syncBeneficiaryAsync(regMap.getBenRegId()); + } + + return response; } - if (mContc.getPhoneNum3() != null) { - mContc.setPhoneNum3(cleanPhoneNumber(mContc.getPhoneNum3())); + + private String cleanPhoneNumber(String phoneNumber) { + if (phoneNumber == null || phoneNumber.trim().isEmpty()) { + return phoneNumber; + } + + // Remove +91 prefix + String cleaned = phoneNumber.trim(); + if (cleaned.startsWith("+91")) { + cleaned = cleaned.substring(3); + } else if (cleaned.startsWith("91") && cleaned.length() == 12) { + // Handle case where + is already removed but 91 remains + cleaned = cleaned.substring(2); + } + + return cleaned.trim(); } - - if (mContc.getPhoneNum4() != null) { - mContc.setPhoneNum4(cleanPhoneNumber(mContc.getPhoneNum4())); + + private MBeneficiarydetail convertIdentityDTOToMBeneficiarydetail(IdentityDTO dto) { + MBeneficiarydetail beneficiarydetail = new MBeneficiarydetail(); + beneficiarydetail.setAreaId(dto.getAreaId()); + if (null != dto.getBeneficiaryRegId()) { + beneficiarydetail.setBeneficiaryRegID(BigInteger.valueOf(dto.getBeneficiaryRegId())); + } + beneficiarydetail.setCommunity(dto.getCommunity()); + beneficiarydetail.setCommunityId(dto.getCommunityId()); + beneficiarydetail.setDob(dto.getDob()); + beneficiarydetail.setEducation(dto.getEducation()); + beneficiarydetail.setEducationId(dto.getEducationId()); + beneficiarydetail.setEmergencyRegistration(dto.getEmergencyRegistration()); + beneficiarydetail.setHealthCareWorkerId(dto.getHealthCareWorkerId()); + beneficiarydetail.setHealthCareWorker(dto.getHealthCareWorker()); + beneficiarydetail.setFatherName(dto.getFatherName()); + beneficiarydetail.setMotherName(dto.getMotherName()); + beneficiarydetail.setFirstName(dto.getFirstName()); + beneficiarydetail.setGender(dto.getGender()); + beneficiarydetail.setGenderId(dto.getGenderId()); + beneficiarydetail.setIncomeStatus(dto.getIncomeStatus()); + beneficiarydetail.setMonthlyFamilyIncome(dto.getMonthlyFamilyIncome()); + beneficiarydetail.setIncomeStatusId(dto.getIncomeStatusId()); + beneficiarydetail.setLastName(dto.getLastName()); + beneficiarydetail.setMaritalStatusId(dto.getMaritalStatusId()); + beneficiarydetail.setMaritalStatus(dto.getMaritalStatus()); + beneficiarydetail.setMiddleName(dto.getMiddleName()); + beneficiarydetail.setOccupation(dto.getOccupationName()); + beneficiarydetail.setOccupationId(dto.getOccupationId()); + beneficiarydetail.setPhcId(dto.getPhcId()); + beneficiarydetail.setPlaceOfWork(dto.getPlaceOfWork()); + beneficiarydetail.setPreferredLanguageId(dto.getPreferredLanguageId()); + beneficiarydetail.setPreferredLanguage(dto.getPreferredLanguage()); + beneficiarydetail.setReligion(dto.getReligion()); + if (dto.getFaceEmbedding() != null) { + beneficiarydetail.setFaceEmbedding(dto.getFaceEmbedding().toString()); + } + if (dto.getReligionId() != null) { + beneficiarydetail.setReligionId(BigInteger.valueOf(dto.getReligionId())); + } + beneficiarydetail.setRemarks(dto.getRemarks()); + if (dto.getServicePointId() != null) { + beneficiarydetail.setServicePointId(BigInteger.valueOf(dto.getServicePointId())); + } + beneficiarydetail.setSourceOfInfo(dto.getSourceOfInfo()); + beneficiarydetail.setSpouseName(dto.getSpouseName()); + beneficiarydetail.setStatus(dto.getStatus()); + beneficiarydetail.setTitle(dto.getTitle()); + beneficiarydetail.setTitleId(dto.getTitleId()); + beneficiarydetail.setZoneId(dto.getZoneId()); + beneficiarydetail.setCreatedBy(dto.getAgentName()); + beneficiarydetail.setCreatedDate(dto.getCreatedDate()); + beneficiarydetail.setIsHIVPositive(MBeneficiarydetail.setIsHIVPositive(dto.getIsHIVPositive())); + beneficiarydetail.setAgeAtMarriage( + MBeneficiarydetail.getAgeAtMarriageCalc(dto.getDob(), dto.getMarriageDate(), dto.getAgeAtMarriage())); + beneficiarydetail.setMarriageDate( + MBeneficiarydetail.getMarriageDateCalc(dto.getDob(), dto.getMarriageDate(), dto.getAgeAtMarriage())); + beneficiarydetail.setVanID(dto.getVanID()); + beneficiarydetail.setParkingPlaceID(dto.getParkingPlaceId()); + if (dto.getOtherFields() != null) { + beneficiarydetail.setOtherFields(dto.getOtherFields()); + } + if (dto.getLiteracyStatus() != null) { + beneficiarydetail.setLiteracyStatus(dto.getLiteracyStatus()); + } + return beneficiarydetail; } - if (mContc.getPhoneNum5() != null) { - mContc.setPhoneNum5(cleanPhoneNumber(mContc.getPhoneNum5())); + + private MBeneficiaryImage identityDTOToMBeneficiaryImage(IdentityDTO identity) { + MBeneficiaryImage beneficiaryImage = new MBeneficiaryImage(); + + beneficiaryImage.setBenImage(identity.getBenImage()); + beneficiaryImage.setCreatedBy(identity.getAgentName()); + beneficiaryImage.setCreatedDate(identity.getCreatedDate()); + if (identity.getVanID() != null) { + beneficiaryImage.setVanID(identity.getVanID()); + } + if (identity.getBenFamilyDTOs() != null) { + beneficiaryImage.setVanID(identity.getBenFamilyDTOs().get(0).getVanID()); + } + + beneficiaryImage.setParkingPlaceID(identity.getParkingPlaceId()); + + return beneficiaryImage; } - if (mContc.getPreferredSMSPhoneNum() != null) { - mContc.setPreferredSMSPhoneNum(cleanPhoneNumber(mContc.getPreferredSMSPhoneNum())); - } if (mContc.getPreferredPhoneNum() != null) { - mContc.setPreferredPhoneNum(cleanPhoneNumber(mContc.getPreferredPhoneNum())); + + private MBeneficiarycontact identityDTOToMBeneficiarycontact(IdentityDTO dto) { + MBeneficiarycontact beneficiaryContact = new MBeneficiarycontact(); + if (dto.getContact() != null) { + beneficiaryContact.setPreferredPhoneNum(dto.getContact().getPreferredPhoneNum()); + beneficiaryContact.setPreferredPhoneTyp(dto.getContact().getPreferredPhoneTyp()); + beneficiaryContact.setPreferredSMSPhoneNum(dto.getContact().getPreferredSMSPhoneNum()); + beneficiaryContact.setPreferredSMSPhoneTyp(dto.getContact().getPreferredSMSPhoneTyp()); + beneficiaryContact.setEmergencyContactNum(dto.getContact().getEmergencyContactNum()); + beneficiaryContact.setPhoneNum1(dto.getContact().getPhoneNum1()); + beneficiaryContact.setPhoneTyp1(dto.getContact().getPhoneTyp1()); + beneficiaryContact.setPhoneNum2(dto.getContact().getPhoneNum2()); + beneficiaryContact.setPhoneTyp2(dto.getContact().getPhoneTyp2()); + beneficiaryContact.setPhoneNum3(dto.getContact().getPhoneNum3()); + beneficiaryContact.setPhoneTyp3(dto.getContact().getPhoneTyp3()); + beneficiaryContact.setPhoneNum4(dto.getContact().getPhoneNum4()); + beneficiaryContact.setPhoneTyp4(dto.getContact().getPhoneTyp4()); + beneficiaryContact.setPhoneNum5(dto.getContact().getPhoneNum5()); + beneficiaryContact.setPhoneTyp5(dto.getContact().getPhoneTyp5()); + } + beneficiaryContact.setEmailId(dto.getPreferredEmailId()); + beneficiaryContact.setCreatedBy(dto.getAgentName()); + beneficiaryContact.setCreatedDate(dto.getCreatedDate()); + beneficiaryContact.setVanID(dto.getVanID()); + beneficiaryContact.setParkingPlaceID(dto.getParkingPlaceId()); + return beneficiaryContact; } - - - - - // MBeneficiarycontact mContc = - // mapper.identityDTOToMBeneficiarycontact(identity); - if (mContc.getCreatedDate() == null) { - SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); - String dateToStoreInDataBase = sdf.format(new Date()); - Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); - mContc.setCreatedDate(ts); - } - mContc = contactRepo.save(mContc); - logger.info("IdentityService.createIdentity - Contacts saved - id = " + mContc.getBenContactsID()); - - // Update van serial no for data sync - contactRepo.updateVanSerialNo(mContc.getBenContactsID()); - - logger.info("IdentityService.createIdentity - saving Details"); - // MBeneficiarydetail mDetl = mapper.identityDTOToMBeneficiarydetail(identity); - MBeneficiarydetail mDetl = convertIdentityDTOToMBeneficiarydetail(identity); - - if (mDetl.getCreatedDate() == null) { - SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); - String dateToStoreInDataBase = sdf.format(new Date()); - Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); - mDetl.setCreatedDate(ts); - } - mDetl = detailRepo.save(mDetl); - logger.info("IdentityService.createIdentity - Details saved - id = " + mDetl.getBeneficiaryDetailsId()); - - // Update van serial no for data sync - detailRepo.updateVanSerialNo(mDetl.getBeneficiaryDetailsId()); - - MBeneficiaryAccount bankOBJ = mapper.identityDTOToMBeneficiaryAccount(identity); - if (bankOBJ.getCreatedDate() == null) { - SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); - String dateToStoreInDataBase = sdf.format(new Date()); - Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); - bankOBJ.setCreatedDate(ts); - } - bankOBJ = accountRepo.save(bankOBJ); - // Update van serial no for data sync - accountRepo.updateVanSerialNo(bankOBJ.getBenAccountID()); - - // MBeneficiaryImage benImageOBJ = mapper.identityDTOToMBeneficiaryImage(identity); - MBeneficiaryImage benImageOBJ = identityDTOToMBeneficiaryImage(identity); - - if (benImageOBJ.getCreatedDate() == null) { - SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); - String dateToStoreInDataBase = sdf.format(new Date()); - Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); - benImageOBJ.setCreatedDate(ts); - } - benImageOBJ = imageRepo.save(benImageOBJ); - - // Update van serial no for data sync - imageRepo.updateVanSerialNo(benImageOBJ.getBenImageId()); - - logger.info("IdentityService.createIdentity - saving Mapping"); - MBeneficiarymapping benMapping = mapper.identityDTOToMBeneficiarymapping(identity); - - benMapping.setMBeneficiarycontact(mContc); - benMapping.setMBeneficiaryaddress(mAddr); - benMapping.setMBeneficiaryconsent(mConsnt); - benMapping.setMBeneficiarydetail(mDetl); - benMapping.setMBeneficiaryregidmapping(regMap); - benMapping.setMBeneficiaryImage(benImageOBJ); - benMapping.setMBeneficiaryAccount(bankOBJ); - - regMap.setProviderServiceMapID(identity.getProviderServiceMapId()); - // added columns for data sync - // 17-09-2018 - if (identity.getVanID() != null) - regMap.setVanID(identity.getVanID()); - if (identity.getParkingPlaceId() != null) - regMap.setParkingPlaceID(identity.getParkingPlaceId()); - regMap.setVanSerialNo(regMap.getBenRegId()); - // END - - regIdRepo.save(regMap); - if (benMapping.getCreatedDate() == null) { - SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); - String dateToStoreInDataBase = sdf.format(new Date()); - Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); - benMapping.setCreatedDate(ts); - } - - if (identity.getBenFamilyDTOs().get(0).getVanID() != null) - benMapping.setVanID(identity.getBenFamilyDTOs().get(0).getVanID()); - - benMapping = mappingRepo.save(benMapping); - // Update van serial no for data sync - mappingRepo.updateVanSerialNo(benMapping.getBenMapId()); - - final MBeneficiarymapping benMapping2 = benMapping; - logger.info("IdentityService.createIdentity - saving FamilyMaps"); - List fIdenList = null; - List fList = null; - - // new logic (18-09-2018, Neeraj kumar) - if (null != identity.getBenFamilyDTOs()) { - fIdenList = mapper.identityDTOListToMBeneficiaryfamilymappingList(identity.getBenFamilyDTOs()); - if (fIdenList != null) { - for (MBeneficiaryfamilymapping bfMapping : fIdenList) { - bfMapping.setBenMapId(benMapping2.getBenMapId()); - - if (bfMapping.getVanID() == null && identity.getVanID() != null) - bfMapping.setVanID(identity.getVanID()); - if (bfMapping.getVanID() == null && identity.getBenFamilyDTOs().get(0).getVanID() != null) - bfMapping.setVanID(identity.getBenFamilyDTOs().get(0).getVanID()); - - if (bfMapping.getParkingPlaceID() == null && identity.getParkingPlaceId() != null) - bfMapping.setParkingPlaceID(identity.getParkingPlaceId()); - - if (bfMapping.getAssociatedBenRegId() == null) { - bfMapping.setAssociatedBenRegId(benMapping2.getBenRegId()); - } - } - fList = (List) familyMapRepo.saveAll(fIdenList); - // Update van serial no for data sync - if (fList != null && !fList.isEmpty()) { - for (MBeneficiaryfamilymapping obj : fList) { - familyMapRepo.updateVanSerialNo(obj.getBenFamilyMapId()); - } - } - } - } - - logger.info("IdentityService.createIdentity - FamilyMap saved "); - logger.info("IdentityService.createIdentity - saving Service Map"); - MBeneficiaryservicemapping sMap = mapper.identityDTOToMBeneficiaryservicemapping(identity); - sMap.setBenMapId(benMapping.getBenMapId()); - if (sMap.getCreatedDate() == null) { - SimpleDateFormat sdf = new SimpleDateFormat(CREATED_DATE_FORMAT); - String dateToStoreInDataBase = sdf.format(new Date()); - Timestamp ts = Timestamp.valueOf(dateToStoreInDataBase); - sMap.setCreatedDate(ts); - } - sMap = serviceMapRepo.save(sMap); - logger.info("IdentityService.createIdentity - ServiceMap saved - id = " + sMap.getBenServiceMapID()); - - // Update van serial no for data sync - serviceMapRepo.updateVanSerialNo(sMap.getBenServiceMapID()); - - List sList = new ArrayList<>(); - sList.add(sMap); - logger.info("IdentityService.createIdentity - saving Identity"); - List mIdenList2 = new ArrayList<>(); - if (null != identity.getIdentities()) { - List mIdenList = mapper - .identityDTOListToMBeneficiaryidentityList(identity.getIdentities()); - mIdenList.forEach(mIden -> { - mIden.setBenMapId(benMapping2.getBenMapId()); - mIden.setCreatedBy(identity.getAgentName()); - mIden.setCreatedDate(identity.getEventTypeDate()); - - // set new column(vanID, parkingPlaceID) value for data sync - if (identity.getVanID() != null) - mIden.setVanID(identity.getVanID()); - if (identity.getParkingPlaceId() != null) - mIden.setParkingPlaceID(identity.getParkingPlaceId()); - - MBeneficiaryidentity m = identityRepo.save(mIden); - - // Update van serial no for data sync - identityRepo.updateVanSerialNo(m.getBenIdentityId()); - - mIdenList2.add(m); - logger.info("IdentityService.createIdentity - Identity saved - id = " + m.getBenIdentityId()); - }); - } - - logger.info("IdentityService.createIdentity - end. id = " + benMapping.getBenMapId()); - return partialMapper.mBeneficiarymappingToBeneficiaryCreateResp(benMapping); - } -private String cleanPhoneNumber(String phoneNumber) { - if (phoneNumber == null || phoneNumber.trim().isEmpty()) { - return phoneNumber; + + private MBeneficiaryaddress identityDTOToMBeneficiaryaddress(IdentityDTO dto) { + MBeneficiaryaddress beneficiaryAddress = new MBeneficiaryaddress(); + if (dto.getCurrentAddress() != null) { + beneficiaryAddress.setCurrAddrLine1(dto.getCurrentAddress().getAddrLine1()); + beneficiaryAddress.setCurrAddrLine2(dto.getCurrentAddress().getAddrLine2()); + beneficiaryAddress.setCurrAddrLine3(dto.getCurrentAddress().getAddrLine3()); + beneficiaryAddress.setCurrCountryId(dto.getCurrentAddress().getCountryId()); + beneficiaryAddress.setCurrCountry(dto.getCurrentAddress().getCountry()); + beneficiaryAddress.setCurrStateId(dto.getCurrentAddress().getStateId()); + beneficiaryAddress.setCurrState(dto.getCurrentAddress().getState()); + beneficiaryAddress.setCurrDistrictId(dto.getCurrentAddress().getDistrictId()); + beneficiaryAddress.setCurrDistrict(dto.getCurrentAddress().getDistrict()); + beneficiaryAddress.setCurrSubDistrictId(dto.getCurrentAddress().getSubDistrictId()); + beneficiaryAddress.setCurrSubDistrict(dto.getCurrentAddress().getSubDistrict()); + beneficiaryAddress.setCurrVillageId(dto.getCurrentAddress().getVillageId()); + beneficiaryAddress.setCurrVillage(dto.getCurrentAddress().getVillage()); + beneficiaryAddress.setCurrAddressValue(dto.getCurrentAddress().getAddressValue()); + beneficiaryAddress.setCurrPinCode(dto.getCurrentAddress().getPinCode()); + beneficiaryAddress.setCurrZoneID(dto.getCurrentAddress().getZoneID()); + beneficiaryAddress.setCurrZone(dto.getCurrentAddress().getZoneName()); + beneficiaryAddress.setCurrAreaId(dto.getCurrentAddress().getParkingPlaceID()); + beneficiaryAddress.setCurrArea(dto.getCurrentAddress().getParkingPlaceName()); + beneficiaryAddress.setCurrServicePointId(dto.getCurrentAddress().getServicePointID()); + beneficiaryAddress.setCurrServicePoint(dto.getCurrentAddress().getServicePointName()); + beneficiaryAddress.setCurrHabitation(dto.getCurrentAddress().getHabitation()); + } + if (dto.getEmergencyAddress() != null) { + beneficiaryAddress.setEmerAddrLine1(dto.getEmergencyAddress().getAddrLine1()); + beneficiaryAddress.setEmerAddrLine2(dto.getEmergencyAddress().getAddrLine2()); + beneficiaryAddress.setEmerAddrLine3(dto.getEmergencyAddress().getAddrLine3()); + beneficiaryAddress.setEmerCountryId(dto.getEmergencyAddress().getCountryId()); + beneficiaryAddress.setEmerCountry(dto.getEmergencyAddress().getCountry()); + beneficiaryAddress.setEmerStateId(dto.getEmergencyAddress().getStateId()); + beneficiaryAddress.setEmerState(dto.getEmergencyAddress().getState()); + beneficiaryAddress.setEmerDistrictId(dto.getEmergencyAddress().getDistrictId()); + beneficiaryAddress.setEmerDistrict(dto.getEmergencyAddress().getDistrict()); + beneficiaryAddress.setEmerSubDistrictId(dto.getEmergencyAddress().getSubDistrictId()); + beneficiaryAddress.setEmerSubDistrict(dto.getEmergencyAddress().getSubDistrict()); + beneficiaryAddress.setEmerVillageId(dto.getEmergencyAddress().getVillageId()); + beneficiaryAddress.setEmerVillage(dto.getEmergencyAddress().getVillage()); + beneficiaryAddress.setEmerAddressValue(dto.getEmergencyAddress().getAddressValue()); + beneficiaryAddress.setEmerPinCode(dto.getEmergencyAddress().getPinCode()); + beneficiaryAddress.setEmerZoneID(dto.getEmergencyAddress().getZoneID()); + beneficiaryAddress.setEmerZone(dto.getEmergencyAddress().getZoneName()); + beneficiaryAddress.setEmerAreaId(dto.getEmergencyAddress().getParkingPlaceID()); + beneficiaryAddress.setEmerArea(dto.getEmergencyAddress().getParkingPlaceName()); + beneficiaryAddress.setEmerServicePointId(dto.getEmergencyAddress().getServicePointID()); + beneficiaryAddress.setEmerServicePoint(dto.getEmergencyAddress().getServicePointName()); + beneficiaryAddress.setEmerHabitation(dto.getEmergencyAddress().getHabitation()); + } + + if (dto.getPermanentAddress() != null) { + beneficiaryAddress.setPermAddrLine1(dto.getPermanentAddress().getAddrLine1()); + beneficiaryAddress.setPermAddrLine2(dto.getPermanentAddress().getAddrLine2()); + beneficiaryAddress.setPermAddrLine3(dto.getPermanentAddress().getAddrLine3()); + beneficiaryAddress.setPermCountryId(dto.getPermanentAddress().getCountryId()); + beneficiaryAddress.setPermCountry(dto.getPermanentAddress().getCountry()); + beneficiaryAddress.setPermStateId(dto.getPermanentAddress().getStateId()); + beneficiaryAddress.setPermState(dto.getPermanentAddress().getState()); + beneficiaryAddress.setPermDistrictId(dto.getPermanentAddress().getDistrictId()); + beneficiaryAddress.setPermDistrict(dto.getPermanentAddress().getDistrict()); + beneficiaryAddress.setPermSubDistrictId(dto.getPermanentAddress().getSubDistrictId()); + beneficiaryAddress.setPermSubDistrict(dto.getPermanentAddress().getSubDistrict()); + beneficiaryAddress.setPermVillageId(dto.getPermanentAddress().getVillageId()); + beneficiaryAddress.setPermVillage(dto.getPermanentAddress().getVillage()); + beneficiaryAddress.setPermAddressValue(dto.getPermanentAddress().getAddressValue()); + beneficiaryAddress.setPermPinCode(dto.getPermanentAddress().getPinCode()); + + beneficiaryAddress.setPermZoneID(dto.getPermanentAddress().getZoneID()); + beneficiaryAddress.setPermZone(dto.getPermanentAddress().getZoneName()); + beneficiaryAddress.setPermAreaId(dto.getPermanentAddress().getParkingPlaceID()); + beneficiaryAddress.setPermArea(dto.getPermanentAddress().getParkingPlaceName()); + beneficiaryAddress.setPermServicePointId(dto.getPermanentAddress().getServicePointID()); + beneficiaryAddress.setPermServicePoint(dto.getPermanentAddress().getServicePointName()); + beneficiaryAddress.setPermHabitation(dto.getPermanentAddress().getHabitation()); + } + if (dto.getAgentName() != null) { + beneficiaryAddress.setCreatedBy(dto.getAgentName()); + } + if (dto.getCreatedDate() != null) { + beneficiaryAddress.setCreatedDate(dto.getCreatedDate()); + } + if (dto.getVanID() != null) { + beneficiaryAddress.setVanID(dto.getVanID()); + } + if (dto.getParkingPlaceId() != null) { + beneficiaryAddress.setParkingPlaceID(dto.getParkingPlaceId()); + } + + return beneficiaryAddress; } - - // Remove +91 prefix - String cleaned = phoneNumber.trim(); - if (cleaned.startsWith("+91")) { - cleaned = cleaned.substring(3); - } else if (cleaned.startsWith("91") && cleaned.length() == 12) { - // Handle case where + is already removed but 91 remains - cleaned = cleaned.substring(2); + + public String getReservedIdList() { + + return "success"; + } + + /** + * + * @param reserveIdentityDTO + * @return + */ + public String reserveIdentity(ReserveIdentityDTO reserveIdentityDTO) { + + Long availableCount = regIdRepo.countByProviderServiceMapIDAndVehicalNoOrderByBenRegIdAsc( + reserveIdentityDTO.getProviderServiceMapID(), reserveIdentityDTO.getVehicalNo()); + + if (reserveIdentityDTO.getReserveCount() < availableCount) { + + MBeneficiaryregidmapping beneficiaryregidmapping; + Long countToBeAllocate = reserveIdentityDTO.getReserveCount() - availableCount; + countToBeAllocate++; + for (int index = 0; index < countToBeAllocate; index++) { + + beneficiaryregidmapping = regIdRepo.findFirstByProviderServiceMapIDAndVehicalNoOrderByBenRegIdAsc(null, + null); + beneficiaryregidmapping.setProviderServiceMapID(reserveIdentityDTO.getProviderServiceMapID()); + beneficiaryregidmapping.setVehicalNo(reserveIdentityDTO.getVehicalNo()); + regIdRepo.save(beneficiaryregidmapping); + } + } + + return "Successfully Completed"; + } + + public String unReserveIdentity(ReserveIdentityDTO unReserve) { + + regIdRepo.unreserveBeneficiaryIds(unReserve.getProviderServiceMapID(), unReserve.getVehicalNo()); + return "Successfully Completed"; + } + + /** + * Get partial details of beneficiaries (first name middle name and last + * name) list on benId's list + * + * @param BenRegIds + * @return {@link List} Beneficiaries + */ + public List getBeneficiariesPartialDeatilsByBenRegIdList(List benRegIds) { + + logger.info("IdentityService.getBeneficiariesPartialDeatilsByBenRegId - end"); + List list = new ArrayList<>(); + + // new logic, 19-12-2018 + List benMapObjArr = null; + if (benRegIds != null && !benRegIds.isEmpty()) { + benMapObjArr = mappingRepo.getBenMappingByRegIDList(benRegIds); + if (benMapObjArr != null && !benMapObjArr.isEmpty()) { + for (Object[] objArr : benMapObjArr) { + MBeneficiarymapping benMap = this.getBeneficiariesDTONewPartial(objArr); + + list.add(partialMapper.mBeneficiarymappingToBeneficiariesPartialDTO(benMap)); + } + } + logger.info("benMap size" + (list.isEmpty() ? "No Beneficiary Found" : list.size())); + + } + // end + logger.info("IdetityService.getBeneficiariesPartialDeatilsByBenRegId - end"); + + return list; + } + + /** + * Get partial details of beneficiaries (first name middle name and last + * name) list on benId's list + * + * @param benRegIds + * @return {@link List} Beneficiaries + */ + public List getBeneficiariesDeatilsByBenRegIdList(List benRegIds) { + + logger.info("IdentityService.getBeneficiariesDeatilsByBenRegIdList - end"); + List list = new ArrayList<>(); + + // new logic, 19-12-2018 + List benMapObjArr = null; + if (benRegIds != null && !benRegIds.isEmpty()) { + benMapObjArr = mappingRepo.getBenMappingByRegIDList(benRegIds); + if (benMapObjArr != null && !benMapObjArr.isEmpty()) { + for (Object[] objArr : benMapObjArr) { + MBeneficiarymapping benMap = this.getBeneficiariesDTONew(objArr); + list.add(this.getBeneficiariesDTO(benMap)); + } + } + logger.info("benMap size" + (list.isEmpty() ? "No Beneficiary Found" : list.size())); + } + // end + logger.info("IdetityService.getBeneficiariesPartialDeatilsByBenRegId - end"); + + return list; + } + + /** + * + * @param benMap + * @return + */ + private BeneficiariesDTO getBeneficiariesDTO(MBeneficiarymapping benMap) { + BeneficiariesDTO bdto = mapper.mBeneficiarymappingToBeneficiariesDTO(benMap); + if (null != benMap && null != benMap.getMBeneficiarydetail() + && !StringUtils.isEmpty(benMap.getMBeneficiarydetail().getFaceEmbedding())) { + String faceEmbedding = benMap.getMBeneficiarydetail().getFaceEmbedding(); + String trimmedInput = faceEmbedding.replaceAll("[\\[\\]]", ""); + List floatList = new ArrayList<>(); + if (!StringUtils.isEmpty(trimmedInput)) { + String[] stringNumbers = trimmedInput.split(",\\s*"); + for (String str : stringNumbers) { + floatList.add(Float.parseFloat(str)); + } + } + bdto.setFaceEmbedding(floatList); + } + // bdto.setOtherFields(benMap.getMBeneficiarydetail().getOtherFields()); + bdto.setBeneficiaryFamilyTags( + mapper.mapToMBeneficiaryfamilymappingWithBenFamilyDTOList(benMap.getMBeneficiaryfamilymappings())); + bdto.setBeneficiaryIdentites( + mapper.mBeneficiaryidentityListToBenIdentityDTOList(benMap.getMBeneficiaryidentities())); + + List abhaList = v_BenAdvanceSearchRepo.getBenAbhaDetailsByBenRegID(bdto.getBenRegId()); + if (abhaList != null && !abhaList.isEmpty()) { + List abhaDTOList = new ArrayList<>(); + AbhaAddressDTO abhaDTO; + for (Object[] objArr : abhaList) { + abhaDTO = new AbhaAddressDTO(); + abhaDTO.setBeneficiaryRegID(bdto.getBenRegId()); + if (objArr[1] != null) { + abhaDTO.setHealthID(objArr[1].toString()); + } + if (objArr[2] != null) { + abhaDTO.setHealthIDNumber(objArr[2].toString()); + } + if (objArr[3] != null) { + abhaDTO.setAuthenticationMode(objArr[3].toString()); + } + if (objArr[4] != null) { + abhaDTO.setCreatedDate((Timestamp) objArr[4]); + } + + abhaDTOList.add(abhaDTO); + + } + bdto.setAbhaDetails(abhaDTOList); + } + return bdto; + } + + private BeneficiariesDTO mBeneficiarymappingToBeneficiariesDTO(MBeneficiarymapping benMap) { + // TODO Auto-generated method stub + return null; + } + + /** + * finite search + * + * @param identityDTO + * @return + */ + public List getBeneficiaries(IdentityDTO identityDTO) { + List list = new ArrayList<>(); + + List benMapList = mappingRepo.finiteSearch(identityDTO); + for (MBeneficiarymapping benMap : benMapList) { + list.add(this.getBeneficiariesDTO(benMap)); + logger.info("benMapId: " + benMap.getBenMapId() + " :: BenId: " + + benMap.getMBeneficiaryregidmapping().getBeneficiaryID()); + } + + return list; + } + + /** + * * + * + * @return beneficiary image for beneficiary Reg ID. + */ + public String getBeneficiaryImage(String requestOBJ) { + OutputResponse response = new OutputResponse(); + try { + Map benImageMap = new HashMap<>(); + if (requestOBJ != null) { + + JsonElement jsnElmnt = JsonParser.parseString(requestOBJ); + JsonObject obj = jsnElmnt.getAsJsonObject(); + + if (obj != null && obj.has("beneficiaryRegID") && obj.get("beneficiaryRegID") != null) { + MBeneficiarymapping benMap = mappingRepo + .getBenImageIdByBenRegID(obj.get("beneficiaryRegID").getAsBigInteger()); + + if (benMap != null && benMap.getBenImageId() != null && benMap.getVanID() != null) { + MBeneficiaryImage benImageOBJ = imageRepo.getBenImageByBenImageID(benMap.getBenImageId(), + benMap.getVanID()); + benImageMap.put("benImage", benImageOBJ.getBenImage()); + benImageMap.put("createdDate", benImageOBJ.getCreatedDate()); + response.setResponse( + new GsonBuilder().setLongSerializationPolicy(LongSerializationPolicy.STRING).create() + .toJson(benImageMap)); + } else { + response.setResponse("Image not available"); + } + } else { + response.setError(5000, "Invalid request"); + } + } + } catch (Exception e) { + logger.error("Error while beneficiary image fetching" + e); + response.setError(e); + } + + return response.toString(); + } + + public void editIdentityEducationOrCommunity(IdentityEditDTO identity) throws MissingMandatoryFieldsException { + logger.info("IdentityService.editIdentityEducationorCommunity - start"); + if (identity.getBeneficiaryRegId() == null && null == identity.getBeneficaryId()) { + throw new MissingMandatoryFieldsException("Either of BeneficiaryID or Beneficiary Reg Id is mandatory."); + } + + // new logic : 13-11-2018 + MBeneficiarymapping benMapping = mappingRepo.findByBenRegIdOrderByBenMapIdAsc(identity.getBeneficiaryRegId()); + if (benMapping != null && benMapping.getBenDetailsId() != null && benMapping.getVanID() != null) { + if (identity.getCommunityId() != null) { + detailRepo.updateCommunity(benMapping.getBenDetailsId(), benMapping.getVanID(), + identity.getCommunityId()); + } + if (identity.getEducationId() != null) { + detailRepo.updateEducation(benMapping.getBenDetailsId(), benMapping.getVanID(), + identity.getEducationId()); + } + } + + } + + public int importBenIdToLocalServer(List benIdImportDTOList) { + logger.info("IdentityService.importBenIdToLocalServer - start"); + logger.info("IdentityService.importBenIdToLocalServer - benIdImportDTOList size : " + + (benIdImportDTOList == null ? "size:0" : benIdImportDTOList.size())); + if (!benIdImportDTOList.isEmpty()) { + ArrayList mBeneficiaryregidmappingList = benIdImportMapper + .benIdImportDTOToMBeneficiaryregidmappings(benIdImportDTOList); + logger.info("Inside if block of importBenIdToLocalServer"); + jdbcTemplate = getJdbcTemplate(); + List dataList = new ArrayList<>(); + Object[] objArr; + String query = " INSERT INTO m_beneficiaryregidmapping(BenRegId, BeneficiaryID, " + + " Provisioned, CreatedDate, CreatedBy, Reserved) VALUES (?,?,?,?,?,?) "; + logger.info("query : " + query); + for (MBeneficiaryregidmapping obj : mBeneficiaryregidmappingList) { + logger.info("inside for check->", obj); + + logger.info("In for loop of importBenIdToLocalServer" + obj.getVanID()); + objArr = new Object[7]; + + objArr[0] = obj.getBenRegId(); + objArr[1] = obj.getBeneficiaryID(); + objArr[2] = false; + objArr[3] = obj.getCreatedDate(); + objArr[4] = obj.getCreatedBy(); + objArr[5] = false; + objArr[6] = obj.getVanID(); + + dataList.add(objArr); + logger.info("regid :" + obj.getBenRegId() + " - benid :" + obj.getBeneficiaryID()); + } + + int[] i = jdbcTemplate.batchUpdate(query, dataList); + + return i.length; + } else { + return 0; + } + + } + + public Long checkBenIDAvailabilityLocal() { + return regIdRepo.countByProvisioned(false); + } - - return cleaned.trim(); -} - private MBeneficiarydetail convertIdentityDTOToMBeneficiarydetail(IdentityDTO dto) { - MBeneficiarydetail beneficiarydetail = new MBeneficiarydetail(); - beneficiarydetail.setAreaId(dto.getAreaId()); - if (null != dto.getBeneficiaryRegId()) - beneficiarydetail.setBeneficiaryRegID(BigInteger.valueOf(dto.getBeneficiaryRegId())); - beneficiarydetail.setCommunity(dto.getCommunity()); - beneficiarydetail.setCommunityId(dto.getCommunityId()); - beneficiarydetail.setDob(dto.getDob()); - beneficiarydetail.setEducation(dto.getEducation()); - beneficiarydetail.setEducationId(dto.getEducationId()); - beneficiarydetail.setEmergencyRegistration(dto.getEmergencyRegistration()); - beneficiarydetail.setHealthCareWorkerId(dto.getHealthCareWorkerId()); - beneficiarydetail.setHealthCareWorker(dto.getHealthCareWorker()); - beneficiarydetail.setFatherName(dto.getFatherName()); - beneficiarydetail.setMotherName(dto.getMotherName()); - beneficiarydetail.setFirstName(dto.getFirstName()); - beneficiarydetail.setGender(dto.getGender()); - beneficiarydetail.setGenderId(dto.getGenderId()); - beneficiarydetail.setIncomeStatus(dto.getIncomeStatus()); - beneficiarydetail.setMonthlyFamilyIncome(dto.getMonthlyFamilyIncome()); - beneficiarydetail.setIncomeStatusId(dto.getIncomeStatusId()); - beneficiarydetail.setLastName(dto.getLastName()); - beneficiarydetail.setMaritalStatusId(dto.getMaritalStatusId()); - beneficiarydetail.setMaritalStatus(dto.getMaritalStatus()); - beneficiarydetail.setMiddleName(dto.getMiddleName()); - beneficiarydetail.setOccupation(dto.getOccupationName()); - beneficiarydetail.setOccupationId(dto.getOccupationId()); - beneficiarydetail.setPhcId(dto.getPhcId()); - beneficiarydetail.setPlaceOfWork(dto.getPlaceOfWork()); - beneficiarydetail.setPreferredLanguageId(dto.getPreferredLanguageId()); - beneficiarydetail.setPreferredLanguage(dto.getPreferredLanguage()); - beneficiarydetail.setReligion(dto.getReligion()); - if (dto.getFaceEmbedding() != null) - beneficiarydetail.setFaceEmbedding(dto.getFaceEmbedding().toString()); - if (dto.getReligionId() != null) - beneficiarydetail.setReligionId(BigInteger.valueOf(dto.getReligionId())); - beneficiarydetail.setRemarks(dto.getRemarks()); - if (dto.getServicePointId() != null) - beneficiarydetail.setServicePointId(BigInteger.valueOf(dto.getServicePointId())); - beneficiarydetail.setSourceOfInfo(dto.getSourceOfInfo()); - beneficiarydetail.setSpouseName(dto.getSpouseName()); - beneficiarydetail.setStatus(dto.getStatus()); - beneficiarydetail.setTitle(dto.getTitle()); - beneficiarydetail.setTitleId(dto.getTitleId()); - beneficiarydetail.setZoneId(dto.getZoneId()); - beneficiarydetail.setCreatedBy(dto.getAgentName()); - beneficiarydetail.setCreatedDate(dto.getCreatedDate()); - beneficiarydetail.setIsHIVPositive(MBeneficiarydetail.setIsHIVPositive(dto.getIsHIVPositive())); - beneficiarydetail.setAgeAtMarriage( - MBeneficiarydetail.getAgeAtMarriageCalc(dto.getDob(), dto.getMarriageDate(), dto.getAgeAtMarriage())); - beneficiarydetail.setMarriageDate( - MBeneficiarydetail.getMarriageDateCalc(dto.getDob(), dto.getMarriageDate(), dto.getAgeAtMarriage())); - beneficiarydetail.setVanID(dto.getVanID()); - beneficiarydetail.setParkingPlaceID(dto.getParkingPlaceId()); - if(dto.getOtherFields() != null) - beneficiarydetail.setOtherFields(dto.getOtherFields()); - if(dto.getLiteracyStatus() != null) - beneficiarydetail.setLiteracyStatus(dto.getLiteracyStatus()); - return beneficiarydetail; - } - - private MBeneficiaryImage identityDTOToMBeneficiaryImage(IdentityDTO identity) { - MBeneficiaryImage beneficiaryImage = new MBeneficiaryImage(); - - beneficiaryImage.setBenImage(identity.getBenImage()); - beneficiaryImage.setCreatedBy(identity.getAgentName()); - beneficiaryImage.setCreatedDate(identity.getCreatedDate()); - if (identity.getVanID() != null) - beneficiaryImage.setVanID(identity.getVanID()); - if (identity.getBenFamilyDTOs() != null) - beneficiaryImage.setVanID(identity.getBenFamilyDTOs().get(0).getVanID()); - - beneficiaryImage.setParkingPlaceID(identity.getParkingPlaceId()); - - return beneficiaryImage; - } - - private MBeneficiarycontact identityDTOToMBeneficiarycontact(IdentityDTO dto) { - MBeneficiarycontact beneficiaryContact = new MBeneficiarycontact(); - if (dto.getContact() != null) { - beneficiaryContact.setPreferredPhoneNum(dto.getContact().getPreferredPhoneNum()); - beneficiaryContact.setPreferredPhoneTyp(dto.getContact().getPreferredPhoneTyp()); - beneficiaryContact.setPreferredSMSPhoneNum(dto.getContact().getPreferredSMSPhoneNum()); - beneficiaryContact.setPreferredSMSPhoneTyp(dto.getContact().getPreferredSMSPhoneTyp()); - beneficiaryContact.setEmergencyContactNum(dto.getContact().getEmergencyContactNum()); - beneficiaryContact.setPhoneNum1(dto.getContact().getPhoneNum1()); - beneficiaryContact.setPhoneTyp1(dto.getContact().getPhoneTyp1()); - beneficiaryContact.setPhoneNum2(dto.getContact().getPhoneNum2()); - beneficiaryContact.setPhoneTyp2(dto.getContact().getPhoneTyp2()); - beneficiaryContact.setPhoneNum3(dto.getContact().getPhoneNum3()); - beneficiaryContact.setPhoneTyp3(dto.getContact().getPhoneTyp3()); - beneficiaryContact.setPhoneNum4(dto.getContact().getPhoneNum4()); - beneficiaryContact.setPhoneTyp4(dto.getContact().getPhoneTyp4()); - beneficiaryContact.setPhoneNum5(dto.getContact().getPhoneNum5()); - beneficiaryContact.setPhoneTyp5(dto.getContact().getPhoneTyp5()); - } - beneficiaryContact.setEmailId(dto.getPreferredEmailId()); - beneficiaryContact.setCreatedBy(dto.getAgentName()); - beneficiaryContact.setCreatedDate(dto.getCreatedDate()); - beneficiaryContact.setVanID(dto.getVanID()); - beneficiaryContact.setParkingPlaceID(dto.getParkingPlaceId()); - return beneficiaryContact; - } - - private MBeneficiaryaddress identityDTOToMBeneficiaryaddress(IdentityDTO dto) { - MBeneficiaryaddress beneficiaryAddress = new MBeneficiaryaddress(); - if (dto.getCurrentAddress() != null) { - beneficiaryAddress.setCurrAddrLine1(dto.getCurrentAddress().getAddrLine1()); - beneficiaryAddress.setCurrAddrLine2(dto.getCurrentAddress().getAddrLine2()); - beneficiaryAddress.setCurrAddrLine3(dto.getCurrentAddress().getAddrLine3()); - beneficiaryAddress.setCurrCountryId(dto.getCurrentAddress().getCountryId()); - beneficiaryAddress.setCurrCountry(dto.getCurrentAddress().getCountry()); - beneficiaryAddress.setCurrStateId(dto.getCurrentAddress().getStateId()); - beneficiaryAddress.setCurrState(dto.getCurrentAddress().getState()); - beneficiaryAddress.setCurrDistrictId(dto.getCurrentAddress().getDistrictId()); - beneficiaryAddress.setCurrDistrict(dto.getCurrentAddress().getDistrict()); - beneficiaryAddress.setCurrSubDistrictId(dto.getCurrentAddress().getSubDistrictId()); - beneficiaryAddress.setCurrSubDistrict(dto.getCurrentAddress().getSubDistrict()); - beneficiaryAddress.setCurrVillageId(dto.getCurrentAddress().getVillageId()); - beneficiaryAddress.setCurrVillage(dto.getCurrentAddress().getVillage()); - beneficiaryAddress.setCurrAddressValue(dto.getCurrentAddress().getAddressValue()); - beneficiaryAddress.setCurrPinCode(dto.getCurrentAddress().getPinCode()); - beneficiaryAddress.setCurrZoneID(dto.getCurrentAddress().getZoneID()); - beneficiaryAddress.setCurrZone(dto.getCurrentAddress().getZoneName()); - beneficiaryAddress.setCurrAreaId(dto.getCurrentAddress().getParkingPlaceID()); - beneficiaryAddress.setCurrArea(dto.getCurrentAddress().getParkingPlaceName()); - beneficiaryAddress.setCurrServicePointId(dto.getCurrentAddress().getServicePointID()); - beneficiaryAddress.setCurrServicePoint(dto.getCurrentAddress().getServicePointName()); - beneficiaryAddress.setCurrHabitation(dto.getCurrentAddress().getHabitation()); - } - if (dto.getEmergencyAddress() != null) { - beneficiaryAddress.setEmerAddrLine1(dto.getEmergencyAddress().getAddrLine1()); - beneficiaryAddress.setEmerAddrLine2(dto.getEmergencyAddress().getAddrLine2()); - beneficiaryAddress.setEmerAddrLine3(dto.getEmergencyAddress().getAddrLine3()); - beneficiaryAddress.setEmerCountryId(dto.getEmergencyAddress().getCountryId()); - beneficiaryAddress.setEmerCountry(dto.getEmergencyAddress().getCountry()); - beneficiaryAddress.setEmerStateId(dto.getEmergencyAddress().getStateId()); - beneficiaryAddress.setEmerState(dto.getEmergencyAddress().getState()); - beneficiaryAddress.setEmerDistrictId(dto.getEmergencyAddress().getDistrictId()); - beneficiaryAddress.setEmerDistrict(dto.getEmergencyAddress().getDistrict()); - beneficiaryAddress.setEmerSubDistrictId(dto.getEmergencyAddress().getSubDistrictId()); - beneficiaryAddress.setEmerSubDistrict(dto.getEmergencyAddress().getSubDistrict()); - beneficiaryAddress.setEmerVillageId(dto.getEmergencyAddress().getVillageId()); - beneficiaryAddress.setEmerVillage(dto.getEmergencyAddress().getVillage()); - beneficiaryAddress.setEmerAddressValue(dto.getEmergencyAddress().getAddressValue()); - beneficiaryAddress.setEmerPinCode(dto.getEmergencyAddress().getPinCode()); - beneficiaryAddress.setEmerZoneID(dto.getEmergencyAddress().getZoneID()); - beneficiaryAddress.setEmerZone(dto.getEmergencyAddress().getZoneName()); - beneficiaryAddress.setEmerAreaId(dto.getEmergencyAddress().getParkingPlaceID()); - beneficiaryAddress.setEmerArea(dto.getEmergencyAddress().getParkingPlaceName()); - beneficiaryAddress.setEmerServicePointId(dto.getEmergencyAddress().getServicePointID()); - beneficiaryAddress.setEmerServicePoint(dto.getEmergencyAddress().getServicePointName()); - beneficiaryAddress.setEmerHabitation(dto.getEmergencyAddress().getHabitation()); - } - - if (dto.getPermanentAddress() != null) { - beneficiaryAddress.setPermAddrLine1(dto.getPermanentAddress().getAddrLine1()); - beneficiaryAddress.setPermAddrLine2(dto.getPermanentAddress().getAddrLine2()); - beneficiaryAddress.setPermAddrLine3(dto.getPermanentAddress().getAddrLine3()); - beneficiaryAddress.setPermCountryId(dto.getPermanentAddress().getCountryId()); - beneficiaryAddress.setPermCountry(dto.getPermanentAddress().getCountry()); - beneficiaryAddress.setPermStateId(dto.getPermanentAddress().getStateId()); - beneficiaryAddress.setPermState(dto.getPermanentAddress().getState()); - beneficiaryAddress.setPermDistrictId(dto.getPermanentAddress().getDistrictId()); - beneficiaryAddress.setPermDistrict(dto.getPermanentAddress().getDistrict()); - beneficiaryAddress.setPermSubDistrictId(dto.getPermanentAddress().getSubDistrictId()); - beneficiaryAddress.setPermSubDistrict(dto.getPermanentAddress().getSubDistrict()); - beneficiaryAddress.setPermVillageId(dto.getPermanentAddress().getVillageId()); - beneficiaryAddress.setPermVillage(dto.getPermanentAddress().getVillage()); - beneficiaryAddress.setPermAddressValue(dto.getPermanentAddress().getAddressValue()); - beneficiaryAddress.setPermPinCode(dto.getPermanentAddress().getPinCode()); - - beneficiaryAddress.setPermZoneID(dto.getPermanentAddress().getZoneID()); - beneficiaryAddress.setPermZone(dto.getPermanentAddress().getZoneName()); - beneficiaryAddress.setPermAreaId(dto.getPermanentAddress().getParkingPlaceID()); - beneficiaryAddress.setPermArea(dto.getPermanentAddress().getParkingPlaceName()); - beneficiaryAddress.setPermServicePointId(dto.getPermanentAddress().getServicePointID()); - beneficiaryAddress.setPermServicePoint(dto.getPermanentAddress().getServicePointName()); - beneficiaryAddress.setPermHabitation(dto.getPermanentAddress().getHabitation()); - } - if (dto.getAgentName() != null) { - beneficiaryAddress.setCreatedBy(dto.getAgentName()); - } - if (dto.getCreatedDate() != null) { - beneficiaryAddress.setCreatedDate(dto.getCreatedDate()); - } - if (dto.getVanID() != null) { - beneficiaryAddress.setVanID(dto.getVanID()); - } - if (dto.getParkingPlaceId() != null) { - beneficiaryAddress.setParkingPlaceID(dto.getParkingPlaceId()); - } - - return beneficiaryAddress; - } - - public String getReservedIdList() { - - return "success"; - } - - /** - * - * @param reserveIdentityDTO - * @return - */ - public String reserveIdentity(ReserveIdentityDTO reserveIdentityDTO) { - - Long availableCount = regIdRepo.countByProviderServiceMapIDAndVehicalNoOrderByBenRegIdAsc( - reserveIdentityDTO.getProviderServiceMapID(), reserveIdentityDTO.getVehicalNo()); - - if (reserveIdentityDTO.getReserveCount() < availableCount) { - - MBeneficiaryregidmapping beneficiaryregidmapping; - Long countToBeAllocate = reserveIdentityDTO.getReserveCount() - availableCount; - countToBeAllocate++; - for (int index = 0; index < countToBeAllocate; index++) { - - beneficiaryregidmapping = regIdRepo.findFirstByProviderServiceMapIDAndVehicalNoOrderByBenRegIdAsc(null, - null); - beneficiaryregidmapping.setProviderServiceMapID(reserveIdentityDTO.getProviderServiceMapID()); - beneficiaryregidmapping.setVehicalNo(reserveIdentityDTO.getVehicalNo()); - regIdRepo.save(beneficiaryregidmapping); - } - } - - return "Successfully Completed"; - } - - public String unReserveIdentity(ReserveIdentityDTO unReserve) { - - regIdRepo.unreserveBeneficiaryIds(unReserve.getProviderServiceMapID(), unReserve.getVehicalNo()); - return "Successfully Completed"; - } - - /** - * Get partial details of beneficiaries (first name middle name and last name) - * list on benId's list - * - * @param BenRegIds - * @return {@link List} Beneficiaries - */ - - public List getBeneficiariesPartialDeatilsByBenRegIdList(List benRegIds) { - - logger.info("IdentityService.getBeneficiariesPartialDeatilsByBenRegId - end"); - List list = new ArrayList<>(); - - // new logic, 19-12-2018 - List benMapObjArr = null; - if (benRegIds != null && !benRegIds.isEmpty()) { - benMapObjArr = mappingRepo.getBenMappingByRegIDList(benRegIds); - if (benMapObjArr != null && !benMapObjArr.isEmpty()) { - for (Object[] objArr : benMapObjArr) { - MBeneficiarymapping benMap = this.getBeneficiariesDTONewPartial(objArr); - - list.add(partialMapper.mBeneficiarymappingToBeneficiariesPartialDTO(benMap)); - } - } - logger.info("benMap size" + (list.isEmpty() ? "No Beneficiary Found" : list.size())); - - } - // end - logger.info("IdetityService.getBeneficiariesPartialDeatilsByBenRegId - end"); - - return list; - } - - /** - * Get partial details of beneficiaries (first name middle name and last name) - * list on benId's list - * - * @param benRegIds - * @return {@link List} Beneficiaries - */ - public List getBeneficiariesDeatilsByBenRegIdList(List benRegIds) { - - logger.info("IdentityService.getBeneficiariesDeatilsByBenRegIdList - end"); - List list = new ArrayList<>(); - - // new logic, 19-12-2018 - List benMapObjArr = null; - if (benRegIds != null && !benRegIds.isEmpty()) { - benMapObjArr = mappingRepo.getBenMappingByRegIDList(benRegIds); - if (benMapObjArr != null && !benMapObjArr.isEmpty()) { - for (Object[] objArr : benMapObjArr) { - MBeneficiarymapping benMap = this.getBeneficiariesDTONew(objArr); - list.add(this.getBeneficiariesDTO(benMap)); - } - } - logger.info("benMap size" + (list.isEmpty() ? "No Beneficiary Found" : list.size())); - } - // end - logger.info("IdetityService.getBeneficiariesPartialDeatilsByBenRegId - end"); - - return list; - } - - /** - * - * @param benMap - * @return - */ - private BeneficiariesDTO getBeneficiariesDTO(MBeneficiarymapping benMap) { - BeneficiariesDTO bdto = mapper.mBeneficiarymappingToBeneficiariesDTO(benMap); - if (null != benMap && null != benMap.getMBeneficiarydetail() - && !StringUtils.isEmpty(benMap.getMBeneficiarydetail().getFaceEmbedding())) { - String faceEmbedding = benMap.getMBeneficiarydetail().getFaceEmbedding(); - String trimmedInput = faceEmbedding.replaceAll("[\\[\\]]", ""); - List floatList = new ArrayList<>(); - if(!StringUtils.isEmpty(trimmedInput)) { - String[] stringNumbers = trimmedInput.split(",\\s*"); - for (String str : stringNumbers) { - floatList.add(Float.parseFloat(str)); - } - } - bdto.setFaceEmbedding(floatList); - } - // bdto.setOtherFields(benMap.getMBeneficiarydetail().getOtherFields()); - bdto.setBeneficiaryFamilyTags( - mapper.mapToMBeneficiaryfamilymappingWithBenFamilyDTOList(benMap.getMBeneficiaryfamilymappings())); - bdto.setBeneficiaryIdentites( - mapper.mBeneficiaryidentityListToBenIdentityDTOList(benMap.getMBeneficiaryidentities())); - - List abhaList = v_BenAdvanceSearchRepo.getBenAbhaDetailsByBenRegID(bdto.getBenRegId()); - if (abhaList != null && !abhaList.isEmpty()) { - List abhaDTOList = new ArrayList<>(); - AbhaAddressDTO abhaDTO; - for (Object[] objArr : abhaList) { - abhaDTO = new AbhaAddressDTO(); - abhaDTO.setBeneficiaryRegID(bdto.getBenRegId()); - if (objArr[1] != null) - abhaDTO.setHealthID(objArr[1].toString()); - if (objArr[2] != null) - abhaDTO.setHealthIDNumber(objArr[2].toString()); - if (objArr[3] != null) - abhaDTO.setAuthenticationMode(objArr[3].toString()); - if (objArr[4] != null) - abhaDTO.setCreatedDate((Timestamp) objArr[4]); - - abhaDTOList.add(abhaDTO); - - } - bdto.setAbhaDetails(abhaDTOList); - } - return bdto; - } - - private BeneficiariesDTO mBeneficiarymappingToBeneficiariesDTO(MBeneficiarymapping benMap) { - // TODO Auto-generated method stub - return null; - } - - /** - * finite search - * - * @param identityDTO - * @return - */ - public List getBeneficiaries(IdentityDTO identityDTO) { - List list = new ArrayList<>(); - - List benMapList = mappingRepo.finiteSearch(identityDTO); - for (MBeneficiarymapping benMap : benMapList) { - list.add(this.getBeneficiariesDTO(benMap)); - logger.info("benMapId: " + benMap.getBenMapId() + " :: BenId: " - + benMap.getMBeneficiaryregidmapping().getBeneficiaryID()); - } - - return list; - } - - /*** - * - * @return beneficiary image for beneficiary Reg ID. - */ - public String getBeneficiaryImage(String requestOBJ) { - OutputResponse response = new OutputResponse(); - try { - Map benImageMap = new HashMap<>(); - if (requestOBJ != null) { - - JsonElement jsnElmnt = JsonParser.parseString(requestOBJ); - JsonObject obj = jsnElmnt.getAsJsonObject(); - - if (obj != null && obj.has("beneficiaryRegID") && obj.get("beneficiaryRegID") != null) { - MBeneficiarymapping benMap = mappingRepo - .getBenImageIdByBenRegID(obj.get("beneficiaryRegID").getAsBigInteger()); - - if (benMap != null && benMap.getBenImageId() != null && benMap.getVanID() != null) { - MBeneficiaryImage benImageOBJ = imageRepo.getBenImageByBenImageID(benMap.getBenImageId(), - benMap.getVanID()); - benImageMap.put("benImage", benImageOBJ.getBenImage()); - benImageMap.put("createdDate", benImageOBJ.getCreatedDate()); - response.setResponse( - new GsonBuilder().setLongSerializationPolicy(LongSerializationPolicy.STRING).create() - .toJson(benImageMap)); - } else { - response.setResponse("Image not available"); - } - } else { - response.setError(5000, "Invalid request"); - } - } - } catch (Exception e) { - logger.error("Error while beneficiary image fetching" + e); - response.setError(e); - } - - return response.toString(); - } - - public void editIdentityEducationOrCommunity(IdentityEditDTO identity) throws MissingMandatoryFieldsException { - logger.info("IdentityService.editIdentityEducationorCommunity - start"); - if (identity.getBeneficiaryRegId() == null && null == identity.getBeneficaryId()) { - throw new MissingMandatoryFieldsException("Either of BeneficiaryID or Beneficiary Reg Id is mandatory."); - } - - // new logic : 13-11-2018 - MBeneficiarymapping benMapping = mappingRepo.findByBenRegIdOrderByBenMapIdAsc(identity.getBeneficiaryRegId()); - if (benMapping != null && benMapping.getBenDetailsId() != null && benMapping.getVanID() != null) { - if (identity.getCommunityId() != null) { - detailRepo.updateCommunity(benMapping.getBenDetailsId(), benMapping.getVanID(), - identity.getCommunityId()); - } - if (identity.getEducationId() != null) { - detailRepo.updateEducation(benMapping.getBenDetailsId(), benMapping.getVanID(), - identity.getEducationId()); - } - } - - } - - public int importBenIdToLocalServer(List benIdImportDTOList) { - logger.info("IdentityService.importBenIdToLocalServer - start"); - logger.info("IdentityService.importBenIdToLocalServer - benIdImportDTOList size : " - + (benIdImportDTOList == null ? "size:0" : benIdImportDTOList.size())); - if (!benIdImportDTOList.isEmpty()) { - ArrayList mBeneficiaryregidmappingList = benIdImportMapper - .benIdImportDTOToMBeneficiaryregidmappings(benIdImportDTOList); -logger.info("Inside if block of importBenIdToLocalServer"); - jdbcTemplate = getJdbcTemplate(); - List dataList = new ArrayList<>(); - Object[] objArr; - String query = " INSERT INTO m_beneficiaryregidmapping(BenRegId, BeneficiaryID, " - + " Provisioned, CreatedDate, CreatedBy, Reserved) VALUES (?,?,?,?,?,?) "; -logger.info("query : " + query); - for (MBeneficiaryregidmapping obj : mBeneficiaryregidmappingList) { - logger.info("inside for check->",obj); - - logger.info("In for loop of importBenIdToLocalServer"+obj.getVanID()); - objArr = new Object[7]; - - objArr[0] = obj.getBenRegId(); - objArr[1] = obj.getBeneficiaryID(); - objArr[2] = false; - objArr[3] = obj.getCreatedDate(); - objArr[4] = obj.getCreatedBy(); - objArr[5] = false; - objArr[6] = obj.getVanID(); - - dataList.add(objArr); - logger.info("regid :" + obj.getBenRegId() + " - benid :" + obj.getBeneficiaryID()); - } - - int[] i = jdbcTemplate.batchUpdate(query, dataList); - - return i.length; - } else - return 0; - - } - - public Long checkBenIDAvailabilityLocal() { - return regIdRepo.countByProvisioned(false); - - } } diff --git a/src/main/java/com/iemr/common/identity/service/elasticsearch/BeneficiaryDataService.java b/src/main/java/com/iemr/common/identity/service/elasticsearch/BeneficiaryDataService.java new file mode 100644 index 00000000..d1f919ea --- /dev/null +++ b/src/main/java/com/iemr/common/identity/service/elasticsearch/BeneficiaryDataService.java @@ -0,0 +1,140 @@ +package com.iemr.common.identity.service.elasticsearch; + +import java.math.BigInteger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.iemr.common.identity.domain.MBeneficiarymapping; +import com.iemr.common.identity.dto.BenDetailDTO; +import com.iemr.common.identity.dto.BeneficiariesDTO; +import com.iemr.common.identity.repo.BenMappingRepo; + +/** + * Service to fetch beneficiary data directly from database + * Used for Elasticsearch sync to avoid circular dependencies + */ +@Service +public class BeneficiaryDataService { + + private static final Logger logger = LoggerFactory.getLogger(BeneficiaryDataService.class); + + @Autowired + private BenMappingRepo mappingRepo; + + /** + * Fetch beneficiary data directly from database by benRegId + * This bypasses any Elasticsearch caching to get fresh database data + * + * @param benRegId + * @return + */ + public BeneficiariesDTO getBeneficiaryFromDatabase(BigInteger benRegId) { + int maxRetries = 3; + int retryCount = 0; + + while (retryCount < maxRetries) { + try { + logger.debug("Fetching beneficiary from database: benRegId={}, attempt={}", benRegId, retryCount + 1); + + MBeneficiarymapping mapping = mappingRepo.findByBenRegIdWithDetails(benRegId); + + if (mapping == null) { + logger.warn("Beneficiary mapping not found: benRegId={}", benRegId); + return null; + } + + BeneficiariesDTO dto = convertToDTO(mapping); + + logger.debug("Successfully fetched beneficiary: benRegId={}", benRegId); + return dto; + + } catch (org.springframework.orm.jpa.JpaSystemException e) { + retryCount++; + logger.warn("Database connection error for benRegId={}, attempt {}/{}: {}", + benRegId, retryCount, maxRetries, e.getMessage()); + + if (retryCount >= maxRetries) { + logger.error("Max retries reached for benRegId={}", benRegId); + return null; + } + + try { + Thread.sleep(1000 * retryCount); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + return null; + } + + } catch (Exception e) { + logger.error("Error fetching beneficiary from database: benRegId={}, error={}", + benRegId, e.getMessage(), e); + return null; + } + } + + return null; + } + + /** + * Convert MBeneficiarymapping entity to BeneficiariesDTO + */ + private BeneficiariesDTO convertToDTO(MBeneficiarymapping mapping) { + BeneficiariesDTO dto = new BeneficiariesDTO(); + + try { + dto.setBenRegId(mapping.getBenRegId()); + dto.setBenMapId(mapping.getBenMapId()); + + if (mapping.getBenRegId() != null) { + dto.setBenId(mapping.getBenRegId()); + } + + if (mapping.getMBeneficiarycontact() != null) { + dto.setPreferredPhoneNum(mapping.getMBeneficiarycontact().getPreferredPhoneNum()); + } + + if (mapping.getMBeneficiarydetail() != null) { + BenDetailDTO detailDTO = new BenDetailDTO(); + + detailDTO.setFirstName(mapping.getMBeneficiarydetail().getFirstName()); + detailDTO.setLastName(mapping.getMBeneficiarydetail().getLastName()); + + if (mapping.getMBeneficiarydetail().getDob() != null) { + detailDTO.setBeneficiaryAge(calculateAge(mapping.getMBeneficiarydetail().getDob())); + } + + dto.setBeneficiaryDetails(detailDTO); + } + + logger.debug("Successfully converted mapping to DTO: benRegId={}", mapping.getBenRegId()); + + } catch (Exception e) { + logger.error("Error converting mapping to DTO: {}", e.getMessage(), e); + } + + return dto; + } + + /** + * Calculate age from date of birth + */ + private Integer calculateAge(java.sql.Timestamp dob) { + try { + if (dob == null) { + return null; + } + + java.time.LocalDate birthDate = dob.toLocalDateTime().toLocalDate(); + java.time.LocalDate now = java.time.LocalDate.now(); + + return java.time.Period.between(birthDate, now).getYears(); + + } catch (Exception e) { + logger.error("Error calculating age: {}", e.getMessage()); + return null; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/service/elasticsearch/BeneficiaryDocumentDataService.java b/src/main/java/com/iemr/common/identity/service/elasticsearch/BeneficiaryDocumentDataService.java new file mode 100644 index 00000000..2ca3f8fb --- /dev/null +++ b/src/main/java/com/iemr/common/identity/service/elasticsearch/BeneficiaryDocumentDataService.java @@ -0,0 +1,195 @@ +package com.iemr.common.identity.service.elasticsearch; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.iemr.common.identity.data.elasticsearch.BeneficiaryDocument; +import com.iemr.common.identity.repo.BenMappingRepo; + +/** + * Optimized service to fetch complete beneficiary data in bulk + * Uses the new complete data query from BenMappingRepo + */ +@Service +public class BeneficiaryDocumentDataService { + + private static final Logger logger = LoggerFactory.getLogger(BeneficiaryDocumentDataService.class); + + @Autowired + private BenMappingRepo mappingRepo; + + /** + * Fetch multiple beneficiaries with COMPLETE data in ONE query + * This is the KEY method that replaces multiple individual queries + */ + @Transactional(readOnly = true, timeout = 30) + public List getBeneficiariesBatch(List benRegIds) { + if (benRegIds == null || benRegIds.isEmpty()) { + return new ArrayList<>(); + } + + try { + logger.debug("Fetching {} beneficiaries with complete data", benRegIds.size()); + + List results = mappingRepo.findCompleteDataByBenRegIds(benRegIds); + + logger.info("Fetched {} complete beneficiary records", results.size()); + + List documents = new ArrayList<>(); + + for (Object[] row : results) { + try { + BeneficiaryDocument doc = mapRowToDocument(row); + if (doc != null && doc.getBenId() != null) { + documents.add(doc); + } + } catch (Exception e) { + logger.error("Error mapping row to document: {}", e.getMessage(), e); + } + } + + logger.debug("Successfully converted {} beneficiaries to documents", documents.size()); + return documents; + + } catch (Exception e) { + logger.error("Error fetching beneficiaries batch: {}", e.getMessage(), e); + return new ArrayList<>(); + } + } + + /** + * Single beneficiary fetch (for backward compatibility) + */ + @Transactional(readOnly = true, timeout = 10) + public BeneficiaryDocument getBeneficiaryFromDatabase(BigInteger benRegId) { + List ids = new ArrayList<>(); + ids.add(benRegId); + + List results = getBeneficiariesBatch(ids); + return results.isEmpty() ? null : results.get(0); + } + + /** + * Map database row to BeneficiaryDocument for ES + * Matches the query column order from BenMappingRepo + */ + private BeneficiaryDocument mapRowToDocument(Object[] row) { + BeneficiaryDocument doc = new BeneficiaryDocument(); + + try { + int idx = 0; + + // Basic IDs (0-1) + Long benRegId = getLong(row[idx++]); + doc.setBenRegId(benRegId); + String beneficiaryRegID = getString(row[idx++]); // Column 1: d.BeneficiaryRegID + + // doc.setBenId(benRegId != null ? benRegId.toString() : null); + if (beneficiaryRegID != null && !beneficiaryRegID.isEmpty()) { + doc.setBenId(beneficiaryRegID); + } else { + doc.setBenId(benRegId != null ? benRegId.toString() : null); + } + doc.setBeneficiaryID(beneficiaryRegID); + + doc.setFirstName(getString(row[idx++])); + doc.setLastName(getString(row[idx++])); + doc.setGenderID(getInteger(row[idx++])); + doc.setGenderName(getString(row[idx++])); + doc.setGender(doc.getGenderName()); + doc.setDOB(getDate(row[idx++])); + doc.setAge(getInteger(row[idx++])); + doc.setFatherName(getString(row[idx++])); + doc.setSpouseName(getString(row[idx++])); + doc.setIsHIVPos(getString(row[idx++])); + + doc.setCreatedBy(getString(row[idx++])); + doc.setCreatedDate(getDate(row[idx++])); + doc.setLastModDate(getLong(row[idx++])); + doc.setBenAccountID(getLong(row[idx++])); + + doc.setPhoneNum(getString(row[idx++])); + + doc.setHealthID(getString(row[idx++])); + doc.setAbhaID(getString(row[idx++])); + doc.setFamilyID(getString(row[idx++])); + + doc.setStateID(getInteger(row[idx++])); + doc.setStateName(getString(row[idx++])); + doc.setDistrictID(getInteger(row[idx++])); + doc.setDistrictName(getString(row[idx++])); + doc.setBlockID(getInteger(row[idx++])); + doc.setBlockName(getString(row[idx++])); + doc.setVillageID(getInteger(row[idx++])); + doc.setVillageName(getString(row[idx++])); + doc.setPinCode(getString(row[idx++])); + doc.setServicePointID(getInteger(row[idx++])); + doc.setServicePointName(getString(row[idx++])); + doc.setParkingPlaceID(getInteger(row[idx++])); + + doc.setPermStateID(getInteger(row[idx++])); + doc.setPermStateName(getString(row[idx++])); + doc.setPermDistrictID(getInteger(row[idx++])); + doc.setPermDistrictName(getString(row[idx++])); + doc.setPermBlockID(getInteger(row[idx++])); + doc.setPermBlockName(getString(row[idx++])); + doc.setPermVillageID(getInteger(row[idx++])); + doc.setPermVillageName(getString(row[idx++])); + + // doc.setGovtIdentityNo(getString(row[idx++])); + // String aadhar = getString(row[idx]); + // doc.setAadharNo(aadhar != null ? aadhar : doc.getGovtIdentityNo()); + + } catch (Exception e) { + logger.error("Error mapping row to document: {}", e.getMessage(), e); + } + + return doc; + } + + // Helper methods + private String getString(Object value) { + return value != null ? value.toString() : null; + } + + private Long getLong(Object value) { + if (value == null) return null; + if (value instanceof Long) return (Long) value; + if (value instanceof Integer) return ((Integer) value).longValue(); + if (value instanceof BigInteger) return ((BigInteger) value).longValue(); + try { + return Long.parseLong(value.toString()); + } catch (NumberFormatException e) { + return null; + } + } + + private Integer getInteger(Object value) { + if (value == null) return null; + if (value instanceof Integer) return (Integer) value; + if (value instanceof Long) return ((Long) value).intValue(); + if (value instanceof BigInteger) return ((BigInteger) value).intValue(); + try { + return Integer.parseInt(value.toString()); + } catch (NumberFormatException e) { + return null; + } + } + + private java.util.Date getDate(Object value) { + if (value == null) return null; + if (value instanceof java.util.Date) return (java.util.Date) value; + if (value instanceof java.sql.Timestamp) + return new java.util.Date(((java.sql.Timestamp) value).getTime()); + if (value instanceof java.sql.Date) + return new java.util.Date(((java.sql.Date) value).getTime()); + return null; + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/service/elasticsearch/BeneficiaryElasticsearchIndexService.java b/src/main/java/com/iemr/common/identity/service/elasticsearch/BeneficiaryElasticsearchIndexService.java new file mode 100644 index 00000000..de229831 --- /dev/null +++ b/src/main/java/com/iemr/common/identity/service/elasticsearch/BeneficiaryElasticsearchIndexService.java @@ -0,0 +1,346 @@ +package com.iemr.common.identity.service.elasticsearch; + +import java.math.BigInteger; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.core.BulkRequest; +import co.elastic.clients.elasticsearch.core.BulkResponse; +import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; + +import com.iemr.common.identity.data.elasticsearch.BeneficiaryDocument; +import com.iemr.common.identity.data.elasticsearch.ElasticsearchSyncJob; +import com.iemr.common.identity.repo.elasticsearch.SyncJobRepo; + +@Service +public class BeneficiaryElasticsearchIndexService { + + private static final Logger logger = LoggerFactory.getLogger(BeneficiaryElasticsearchIndexService.class); + private static final int BATCH_SIZE = 100; + private static final int ES_BULK_SIZE = 50; + private static final int STATUS_UPDATE_FREQUENCY = 10; + + @Autowired + private ElasticsearchClient esClient; + + @Autowired + private BeneficiaryTransactionHelper transactionalWrapper; + + @Autowired + private BeneficiaryDocumentDataService dataService; + + @Autowired + private SyncJobRepo syncJobRepository; + + @Value("${elasticsearch.index.beneficiary}") + private String beneficiaryIndex; + + /** + * Start async full sync job with COMPLETE 38+ field data + */ + @Async("elasticsearchSyncExecutor") + public void syncAllBeneficiariesAsync(Long jobId, String triggeredBy) { + logger.info("Starting ASYNC full sync with COMPLETE data: jobId={}", jobId); + + ElasticsearchSyncJob job = syncJobRepository.findByJobId(jobId) + .orElseThrow(() -> new RuntimeException("Job not found: " + jobId)); + + try { + job.setStatus("RUNNING"); + job.setStartedAt(new Timestamp(System.currentTimeMillis())); + syncJobRepository.save(job); + + long totalCount = transactionalWrapper.countActiveBeneficiaries(); + job.setTotalRecords(totalCount); + syncJobRepository.save(job); + + logger.info("Total beneficiaries to sync: {}", totalCount); + + if (totalCount == 0) { + job.setStatus("COMPLETED"); + job.setCompletedAt(new Timestamp(System.currentTimeMillis())); + job.setErrorMessage("No beneficiaries found to sync"); + syncJobRepository.save(job); + return; + } + + int offset = job.getCurrentOffset() != null ? job.getCurrentOffset() : 0; + long processedCount = job.getProcessedRecords() != null ? job.getProcessedRecords() : 0; + long successCount = job.getSuccessCount() != null ? job.getSuccessCount() : 0; + long failureCount = job.getFailureCount() != null ? job.getFailureCount() : 0; + + List esBatch = new ArrayList<>(); + int batchCounter = 0; + long startTime = System.currentTimeMillis(); + + // Process in batches + while (offset < totalCount) { + try { + logger.info("=== BATCH {} START: offset={} ===", batchCounter + 1, offset); + + logger.debug("Calling getBeneficiaryIdsBatch(offset={}, limit={})", offset, BATCH_SIZE); + List batchIds = transactionalWrapper.getBeneficiaryIdsBatch(offset, BATCH_SIZE); + + logger.info("Retrieved {} IDs from database", batchIds != null ? batchIds.size() : 0); + + if (batchIds == null || batchIds.isEmpty()) { + logger.warn("No more batches to process at offset {}", offset); + break; + } + + if (batchIds.size() > 0) { + logger.debug("First ID type: {}, value: {}", + batchIds.get(0)[0].getClass().getName(), + batchIds.get(0)[0]); + } + + logger.debug("Converting {} IDs to BigInteger", batchIds.size()); + List benRegIds = batchIds.stream() + .map(arr -> toBigInteger(arr[0])) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + logger.info("Converted {} valid BigInteger IDs", benRegIds.size()); + + if (benRegIds.isEmpty()) { + logger.error("No valid IDs in batch at offset {} - ALL IDs FAILED CONVERSION", offset); + offset += BATCH_SIZE; + continue; + } + + if (benRegIds.size() > 0) { + logger.debug("First converted BigInteger: {}", benRegIds.get(0)); + } + + logger.info("Fetching complete data for {} beneficiaries...", benRegIds.size()); + + // *** CRITICAL: This returns COMPLETE BeneficiaryDocument with 38+ fields *** + List documents = dataService.getBeneficiariesBatch(benRegIds); + + logger.info("✓ Fetched {} complete documents for batch at offset {}", documents.size(), offset); + + if (!documents.isEmpty() && documents.get(0) != null) { + BeneficiaryDocument firstDoc = documents.get(0); + logger.info("Sample doc - benId: {}, name: {} {}, district: {}, state: {}", + firstDoc.getBenId(), + firstDoc.getFirstName(), + firstDoc.getLastName(), + firstDoc.getDistrictName(), + firstDoc.getStateName()); + } + + int docsAddedInThisBatch = 0; + for (BeneficiaryDocument doc : documents) { + try { + if (doc != null && doc.getBenId() != null) { + esBatch.add(doc); + docsAddedInThisBatch++; + + if (esBatch.size() >= ES_BULK_SIZE) { + logger.info("ES batch full ({} docs), indexing now...", esBatch.size()); + int indexed = bulkIndexDocuments(esBatch); + successCount += indexed; + failureCount += (esBatch.size() - indexed); + processedCount += esBatch.size(); + + logger.info("✓ Indexed {}/{} documents successfully", indexed, esBatch.size()); + esBatch.clear(); + } + } else { + logger.warn("Skipping document - doc null: {}, benId null: {}", + doc == null, doc != null ? (doc.getBenId() == null) : "N/A"); + failureCount++; + processedCount++; + } + } catch (Exception e) { + logger.error("Error processing single document: {}", e.getMessage(), e); + failureCount++; + processedCount++; + } + } + + logger.info("Added {} documents to ES batch in this iteration", docsAddedInThisBatch); + + int notFetched = benRegIds.size() - documents.size(); + if (notFetched > 0) { + failureCount += notFetched; + processedCount += notFetched; + logger.warn("{} beneficiaries not fetched from database", notFetched); + } + + offset += BATCH_SIZE; + batchCounter++; + + logger.info("=== BATCH {} END: Processed={}, Success={}, Failed={} ===", + batchCounter, processedCount, successCount, failureCount); + + if (batchCounter % STATUS_UPDATE_FREQUENCY == 0) { + logger.info("Updating job progress (every {} batches)...", STATUS_UPDATE_FREQUENCY); + updateJobProgress(job, processedCount, successCount, failureCount, + offset, totalCount, startTime); + } + + if (batchCounter % 10 == 0) { + logger.debug("Pausing for 500ms after {} batches", batchCounter); + Thread.sleep(500); + } + + } catch (Exception e) { + logger.error("!!! ERROR in batch at offset {}: {} !!!", offset, e.getMessage(), e); + logger.error("Exception type: {}", e.getClass().getName()); + logger.error("Stack trace:", e); + + job.setCurrentOffset(offset); + job.setProcessedRecords(processedCount); + job.setSuccessCount(successCount); + job.setFailureCount(failureCount); + syncJobRepository.save(job); + + offset += BATCH_SIZE; + Thread.sleep(2000); + } + } + + if (!esBatch.isEmpty()) { + logger.info("Indexing final batch of {} documents", esBatch.size()); + int indexed = bulkIndexDocuments(esBatch); + successCount += indexed; + failureCount += (esBatch.size() - indexed); + processedCount += esBatch.size(); + } + + job.setStatus("COMPLETED"); + job.setCompletedAt(new Timestamp(System.currentTimeMillis())); + job.setProcessedRecords(processedCount); + job.setSuccessCount(successCount); + job.setFailureCount(failureCount); + job.setCurrentOffset((int) totalCount); + + long duration = System.currentTimeMillis() - startTime; + job.setProcessingSpeed(processedCount / (duration / 1000.0)); + + syncJobRepository.save(job); + + logger.info("Async sync job COMPLETED: jobId={}", jobId); + logger.info("Total: {}, Processed: {}, Success: {}, Failed: {}", + totalCount, processedCount, successCount, failureCount); + logger.info("All 38+ beneficiary fields synced to Elasticsearch!"); + + } catch (Exception e) { + logger.error("CRITICAL ERROR in async sync: jobId={}, error={}", jobId, e.getMessage(), e); + + job.setStatus("FAILED"); + job.setCompletedAt(new Timestamp(System.currentTimeMillis())); + job.setErrorMessage(e.getMessage()); + syncJobRepository.save(job); + } + } + + /** + * Helper method to safely convert various numeric types to BigInteger + * CRITICAL: Native SQL queries return Long, not BigInteger + */ + private BigInteger toBigInteger(Object value) { + if (value == null) { + logger.warn("Attempted to convert null value to BigInteger"); + return null; + } + + try { + if (value instanceof BigInteger) { + return (BigInteger) value; + } + if (value instanceof Long) { + return BigInteger.valueOf((Long) value); + } + if (value instanceof Integer) { + return BigInteger.valueOf(((Integer) value).longValue()); + } + if (value instanceof Number) { + return BigInteger.valueOf(((Number) value).longValue()); + } + return new BigInteger(value.toString()); + } catch (NumberFormatException e) { + logger.error("Cannot convert '{}' (type: {}) to BigInteger: {}", + value, value.getClass().getName(), e.getMessage()); + return null; + } + } + + private void updateJobProgress(ElasticsearchSyncJob job, long processed, long success, + long failure, int offset, long total, long startTime) { + job.setProcessedRecords(processed); + job.setSuccessCount(success); + job.setFailureCount(failure); + job.setCurrentOffset(offset); + + long elapsedTime = System.currentTimeMillis() - startTime; + double speed = elapsedTime > 0 ? processed / (elapsedTime / 1000.0) : 0; + job.setProcessingSpeed(speed); + + if (speed > 0) { + long remaining = total - processed; + long estimatedSeconds = (long) (remaining / speed); + job.setEstimatedTimeRemaining(estimatedSeconds); + } + + syncJobRepository.save(job); + + } + + private int bulkIndexDocuments(List documents) { + if (documents == null || documents.isEmpty()) { + return 0; + } + + try { + BulkRequest.Builder br = new BulkRequest.Builder(); + + for (BeneficiaryDocument doc : documents) { + if (doc.getBenId() != null) { + br.operations(op -> op + .index(idx -> idx + .index(beneficiaryIndex) + .id(doc.getBenId()) + .document(doc) + ) + ); + } + } + + BulkResponse result = esClient.bulk(br.build()); + int successCount = 0; + + if (result.errors()) { + for (BulkResponseItem item : result.items()) { + if (item.error() == null) { + successCount++; + } else { + logger.error("ES indexing error for doc {}: {}", + item.id(), item.error().reason()); + } + } + } else { + successCount = documents.size(); + } + + logger.debug("Bulk indexed {} documents successfully", successCount); + return successCount; + + } catch (Exception e) { + logger.error("Error in bulk indexing: {}", e.getMessage(), e); + return 0; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/service/elasticsearch/BeneficiaryElasticsearchIndexUpdater.java b/src/main/java/com/iemr/common/identity/service/elasticsearch/BeneficiaryElasticsearchIndexUpdater.java new file mode 100644 index 00000000..82d68587 --- /dev/null +++ b/src/main/java/com/iemr/common/identity/service/elasticsearch/BeneficiaryElasticsearchIndexUpdater.java @@ -0,0 +1,107 @@ +package com.iemr.common.identity.service.elasticsearch; + +import java.math.BigInteger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.core.DeleteRequest; +import co.elastic.clients.elasticsearch.core.IndexRequest; + +import com.iemr.common.identity.data.elasticsearch.BeneficiaryDocument; + +/** + * Service for real-time Elasticsearch synchronization + * Triggers automatically when beneficiaries are created/updated in database + */ +@Service +public class BeneficiaryElasticsearchIndexUpdater { + + private static final Logger logger = LoggerFactory.getLogger(BeneficiaryElasticsearchIndexUpdater.class); + + @Autowired + private ElasticsearchClient esClient; + + @Autowired + private BeneficiaryDocumentDataService dataService; + + @Value("${elasticsearch.index.beneficiary}") + private String beneficiaryIndex; + + @Value("${elasticsearch.enabled}") + private boolean esEnabled; + + /** + * Async method to sync a single beneficiary to Elasticsearch + * Called after beneficiary is created/updated in database + */ + @Async("elasticsearchSyncExecutor") + public void syncBeneficiaryAsync(BigInteger benRegId) { + if (!esEnabled) { + logger.debug("Elasticsearch is disabled, skipping sync"); + return; + } + + try { + logger.info("Starting async sync for benRegId: {}", benRegId); + + BeneficiaryDocument doc = dataService.getBeneficiaryFromDatabase(benRegId); + + if (doc == null) { + logger.warn("Beneficiary not found in database: {}", benRegId); + return; + } + + if (doc.getBenId() == null) { + logger.error("BeneficiaryDocument has null benId: {}", benRegId); + return; + } + + IndexRequest request = IndexRequest.of(i -> i + .index(beneficiaryIndex) + .id(doc.getBenId()) + .document(doc) + ); + + esClient.index(request); + + logger.info("Successfully synced beneficiary to Elasticsearch: benRegId={}, benId={}", + benRegId, doc.getBenId()); + + } catch (Exception e) { + logger.error("Error syncing beneficiary {} to Elasticsearch: {}", benRegId, e.getMessage(), e); + } + } + + /** + * Delete beneficiary from Elasticsearch + */ + @Async("elasticsearchSyncExecutor") + public void deleteBeneficiaryAsync(String benId) { + if (!esEnabled) { + logger.debug("Elasticsearch is disabled, skipping delete"); + return; + } + + try { + logger.info("Starting async delete for benId: {}", benId); + + DeleteRequest request = DeleteRequest.of(d -> d + .index(beneficiaryIndex) + .id(benId) + ); + + esClient.delete(request); + + logger.info("Successfully deleted beneficiary from Elasticsearch: benId={}", benId); + + } catch (Exception e) { + logger.error("Error deleting beneficiary {} from Elasticsearch: {}", benId, e.getMessage(), e); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/service/elasticsearch/BeneficiaryTransactionHelper.java b/src/main/java/com/iemr/common/identity/service/elasticsearch/BeneficiaryTransactionHelper.java new file mode 100644 index 00000000..233338f0 --- /dev/null +++ b/src/main/java/com/iemr/common/identity/service/elasticsearch/BeneficiaryTransactionHelper.java @@ -0,0 +1,67 @@ +package com.iemr.common.identity.service.elasticsearch; + +import java.math.BigInteger; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import com.iemr.common.identity.repo.BenMappingRepo; + +/** + * Wrapper service to handle database operations with proper transaction management + * This prevents connection timeout issues during long-running sync operations + */ +@Service +public class BeneficiaryTransactionHelper { + + private static final Logger logger = LoggerFactory.getLogger(BeneficiaryTransactionHelper.class); + + @Autowired + private BenMappingRepo mappingRepo; + + /** + * Get beneficiary IDs in a new transaction + * This ensures connection is fresh for each batch + */ + @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true, timeout = 30) + public List getBeneficiaryIdsBatch(int offset, int limit) { + try { + return mappingRepo.getBeneficiaryIdsBatch(offset, limit); + } catch (Exception e) { + logger.error("Error fetching batch: offset={}, limit={}, error={}", + offset, limit, e.getMessage()); + throw e; + } + } + + /** + * Count beneficiaries in a new transaction + */ + @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true, timeout = 30) + public long countActiveBeneficiaries() { + try { + return mappingRepo.countActiveBeneficiaries(); + } catch (Exception e) { + logger.error("Error counting beneficiaries: {}", e.getMessage()); + throw e; + } + } + + /** + * Check if beneficiary exists in a new transaction + */ + @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true, timeout = 10) + public boolean existsByBenRegId(BigInteger benRegId) { + try { + return mappingRepo.existsByBenRegId(benRegId); + } catch (Exception e) { + logger.error("Error checking existence for benRegId={}: {}", benRegId, e.getMessage()); + throw e; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/service/elasticsearch/ElasticsearchIndexingService.java b/src/main/java/com/iemr/common/identity/service/elasticsearch/ElasticsearchIndexingService.java new file mode 100644 index 00000000..941a0555 --- /dev/null +++ b/src/main/java/com/iemr/common/identity/service/elasticsearch/ElasticsearchIndexingService.java @@ -0,0 +1,127 @@ +package com.iemr.common.identity.service.elasticsearch; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.mapping.*; +import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Map; + +@Service +public class ElasticsearchIndexingService { + + private static final Logger logger = LoggerFactory.getLogger(ElasticsearchIndexingService.class); + + @Autowired + private ElasticsearchClient esClient; + + @Autowired + private ElasticsearchSyncService syncService; + + @Value("${elasticsearch.index.beneficiary}") + private String beneficiaryIndex; + + /** + * Create or recreate the Elasticsearch index with proper mapping + */ + public void createIndexWithMapping() throws Exception { + logger.info("Creating index with mapping: {}", beneficiaryIndex); + + // Delete existing index if it exists + if (esClient.indices().exists(e -> e.index(beneficiaryIndex)).value()) { + logger.warn("Index {} already exists, deleting...", beneficiaryIndex); + esClient.indices().delete(d -> d.index(beneficiaryIndex)); + } + + // Create index with mapping + TypeMapping mapping = TypeMapping.of(tm -> tm + .properties("benId", Property.of(p -> p.keyword(k -> k))) + .properties("benRegId", Property.of(p -> p.long_(l -> l))) + .properties("beneficiaryID", Property.of(p -> p.keyword(k -> k))) + .properties("firstName", Property.of(p -> p.text(t -> t + .fields("keyword", Property.of(fp -> fp.keyword(k -> k)))))) + .properties("lastName", Property.of(p -> p.text(t -> t + .fields("keyword", Property.of(fp -> fp.keyword(k -> k)))))) + .properties("genderID", Property.of(p -> p.integer(i -> i))) + .properties("genderName", Property.of(p -> p.keyword(k -> k))) + .properties("dOB", Property.of(p -> p.date(d -> d))) + .properties("age", Property.of(p -> p.integer(i -> i))) + .properties("phoneNum", Property.of(p -> p.keyword(k -> k))) + .properties("fatherName", Property.of(p -> p.text(t -> t + .fields("keyword", Property.of(fp -> fp.keyword(k -> k)))))) + .properties("spouseName", Property.of(p -> p.text(t -> t + .fields("keyword", Property.of(fp -> fp.keyword(k -> k)))))) + .properties("isHIVPos", Property.of(p -> p.keyword(k -> k))) + .properties("createdBy", Property.of(p -> p.keyword(k -> k))) + .properties("createdDate", Property.of(p -> p.date(d -> d))) + .properties("lastModDate", Property.of(p -> p.long_(l -> l))) + .properties("benAccountID", Property.of(p -> p.long_(l -> l))) + + .properties("healthID", Property.of(p -> p.keyword(k -> k))) + .properties("abhaID", Property.of(p -> p.keyword(k -> k))) + .properties("familyID", Property.of(p -> p.keyword(k -> k))) + + .properties("stateID", Property.of(p -> p.integer(i -> i))) + .properties("stateName", Property.of(p -> p.keyword(k -> k))) + .properties("districtID", Property.of(p -> p.integer(i -> i))) + .properties("districtName", Property.of(p -> p.keyword(k -> k))) + .properties("blockID", Property.of(p -> p.integer(i -> i))) + .properties("blockName", Property.of(p -> p.keyword(k -> k))) + .properties("villageID", Property.of(p -> p.integer(i -> i))) + .properties("villageName", Property.of(p -> p.keyword(k -> k))) + .properties("pinCode", Property.of(p -> p.keyword(k -> k))) + .properties("servicePointID", Property.of(p -> p.integer(i -> i))) + .properties("servicePointName", Property.of(p -> p.keyword(k -> k))) + .properties("parkingPlaceID", Property.of(p -> p.integer(i -> i))) + + .properties("permStateID", Property.of(p -> p.integer(i -> i))) + .properties("permStateName", Property.of(p -> p.keyword(k -> k))) + .properties("permDistrictID", Property.of(p -> p.integer(i -> i))) + .properties("permDistrictName", Property.of(p -> p.keyword(k -> k))) + .properties("permBlockID", Property.of(p -> p.integer(i -> i))) + .properties("permBlockName", Property.of(p -> p.keyword(k -> k))) + .properties("permVillageID", Property.of(p -> p.integer(i -> i))) + .properties("permVillageName", Property.of(p -> p.keyword(k -> k))) + + .properties("aadharNo", Property.of(p -> p.keyword(k -> k))) + .properties("govtIdentityNo", Property.of(p -> p.keyword(k -> k))) + ); + + esClient.indices().create(c -> c + .index(beneficiaryIndex) + .mappings(mapping) + ); + + logger.info("Index created successfully: {}", beneficiaryIndex); + } + + /** + * Index all beneficiaries - delegates to existing sync service + * This is much safer than loading all records at once + */ + public Map indexAllBeneficiaries() { + logger.info("Starting full indexing via sync service..."); + + try { + ElasticsearchSyncService.SyncResult result = syncService.syncAllBeneficiaries(); + + Map response = new HashMap<>(); + response.put("success", result.getSuccessCount()); + response.put("failed", result.getFailureCount()); + + return response; + + } catch (Exception e) { + logger.error("Error during indexing", e); + Map response = new HashMap<>(); + response.put("success", 0); + response.put("failed", 0); + return response; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/service/elasticsearch/ElasticsearchService.java b/src/main/java/com/iemr/common/identity/service/elasticsearch/ElasticsearchService.java new file mode 100644 index 00000000..f522e9bd --- /dev/null +++ b/src/main/java/com/iemr/common/identity/service/elasticsearch/ElasticsearchService.java @@ -0,0 +1,598 @@ +package com.iemr.common.identity.service.elasticsearch; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.query_dsl.TextQueryType; +import co.elastic.clients.elasticsearch.core.SearchResponse; + +import com.iemr.common.identity.dto.BeneficiariesESDTO; +import com.iemr.common.identity.repo.BenDetailRepo; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.sql.Timestamp; +import java.util.*; +import java.util.stream.Collectors; + +import com.iemr.common.identity.repo.BenAddressRepo; + +@Service +public class ElasticsearchService { + + private static final Logger logger = LoggerFactory.getLogger(ElasticsearchService.class); + + @Autowired + private ElasticsearchClient esClient; + + @Autowired + private BenDetailRepo benDetailRepo; + + @Autowired + private BenAddressRepo benAddressRepo; + + @Value("${elasticsearch.index.beneficiary}") + private String beneficiaryIndex; + + /** + * Universal search with optional user location for ranking + */ + public List> universalSearch(String query, Integer userId) { + logger.info("Universal ES search for: {} with userId: {}", query, userId); + + try { + Map userLocation = null; + if (userId != null) { + userLocation = getUserLocation(userId); + logger.info("User location: {}", userLocation); + } + + boolean isNumeric = query.matches("\\d+"); + + SearchResponse response = esClient.search(s -> s + .index(beneficiaryIndex) + .query(q -> q + .bool(b -> { + // Fuzzy multi-match for text fields + b.should(s1 -> s1.multiMatch(mm -> mm + .query(query) + .fields("firstName^3", "lastName^2", "fatherName", "spouseName") + .type(TextQueryType.BestFields) + .fuzziness("AUTO") + )); + + // Exact match for phone number + b.should(s2 -> s2.term(t -> t + .field("phoneNum") + .value(query) + )); + + // NEW: Search in healthID, abhaID, familyID + b.should(s3 -> s3.term(t -> t + .field("healthID") + .value(query) + )); + + b.should(s4 -> s4.term(t -> t + .field("abhaID") + .value(query) + )); + + b.should(s5 -> s5.term(t -> t + .field("familyID") + .value(query) + )); + + // Numeric fields (only if query is numeric) + if (isNumeric) { + try { + Long numericValue = Long.parseLong(query); + b.should(s6 -> s6.term(t -> t.field("benRegId").value(numericValue))); + } catch (NumberFormatException e) { + logger.debug("Could not parse as long: {}", query); + } + + b.should(s7 -> s7.term(t -> t.field("benId").value(query))); + } + + b.minimumShouldMatch("1"); + return b; + }) + ) + .size(100) // Increased to allow for location-based filtering + , BeneficiariesESDTO.class); + + logger.info("ES returned {} hits", response.hits().hits().size()); + + // Convert ES results + List> allResults = response.hits().hits().stream() + .map(hit -> mapESResultToExpectedFormat(hit.source())) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + if (allResults.isEmpty()) { + logger.info("No results found in ES, falling back to database"); + return searchInDatabaseDirectly(query); + } + + // Apply location-based ranking if user location available + if (userLocation != null) { + allResults = rankByLocation(allResults, userLocation); + } + + List> results = allResults.stream() + .limit(20) + .collect(Collectors.toList()); + + logger.info("Returning {} results from ES", results.size()); + return results; + + } catch (Exception e) { + logger.error("ES universal search failed: {}", e.getMessage(), e); + logger.info("Fallback: Searching in MySQL database"); + return searchInDatabaseDirectly(query); + } + } + + /** + * Overloaded method without userId (backward compatibility) + */ + public List> universalSearch(String query) { + return universalSearch(query, null); + } + + /** + * Get user location from database + */ + private Map getUserLocation(Integer userId) { + try { + List results = benAddressRepo.getUserLocation(userId); + if (results != null && !results.isEmpty()) { + Object[] row = results.get(0); + Map location = new HashMap<>(); + location.put("psmId", getInteger(row[0])); + location.put("blockId", getInteger(row[1])); + location.put("villageId", getInteger(row[2])); + location.put("servicePointId", getInteger(row[3])); + return location; + } + } catch (Exception e) { + logger.error("Error fetching user location: {}", e.getMessage(), e); + } + return null; + } + + /** + * Rank results by location match priority + * Priority: Village > Block > District > State > No Match + */ + private List> rankByLocation(List> results, + Map userLocation) { + Integer userBlockId = userLocation.get("blockId"); + Integer userVillageId = userLocation.get("villageId"); + + logger.info("Ranking by location - User Block: {}, Village: {}", userBlockId, userVillageId); + + return results.stream() + .sorted((r1, r2) -> { + int score1 = calculateLocationScore(r1, userBlockId, userVillageId); + int score2 = calculateLocationScore(r2, userBlockId, userVillageId); + return Integer.compare(score2, score1); + }) + .collect(Collectors.toList()); + } + + /** + * Calculate location match score + * Higher score = better match + */ + private int calculateLocationScore(Map beneficiary, + Integer userBlockId, + Integer userVillageId) { + int score = 0; + + try { + Map demographics = (Map) beneficiary.get("i_bendemographics"); + if (demographics == null) { + return score; + } + + Integer currBlockId = getIntegerFromMap(demographics, "blockID"); + Integer currVillageId = getIntegerFromMap(demographics, "m_districtblock", "blockID"); + + // Village match (highest priority) - score: 100 + if (userVillageId != null && userVillageId.equals(currVillageId)) { + score += 100; + } + + // Block match - score: 50 + if (userBlockId != null && userBlockId.equals(currBlockId)) { + score += 50; + } + + Integer permBlockId = getIntegerFromMap(beneficiary, "permBlockID"); + Integer permVillageId = getIntegerFromMap(beneficiary, "permVillageID"); + + if (userVillageId != null && userVillageId.equals(permVillageId)) { + score += 75; + } + + if (userBlockId != null && userBlockId.equals(permBlockId)) { + score += 25; + } + + } catch (Exception e) { + logger.error("Error calculating location score: {}", e.getMessage()); + } + + return score; + } + + /** + * Helper to safely get Integer from nested maps + */ + private Integer getIntegerFromMap(Map map, String... keys) { + Object value = map; + for (String key : keys) { + if (value instanceof Map) { + value = ((Map) value).get(key); + } else { + return null; + } + } + return value instanceof Integer ? (Integer) value : null; + } + + /** + * Map ES DTO directly to expected API format with COMPLETE data + */ + private Map mapESResultToExpectedFormat(BeneficiariesESDTO esData) { + if (esData == null) { + return null; + } + + Map result = new HashMap<>(); + + try { + // Basic fields from ES + result.put("beneficiaryRegID", esData.getBenRegId()); + result.put("beneficiaryID", esData.getBeneficiaryID()); + result.put("firstName", esData.getFirstName()); + result.put("lastName", esData.getLastName()); + result.put("genderID", esData.getGenderID()); + result.put("genderName", esData.getGenderName()); + result.put("dob", esData.getDOB()); + result.put("age", esData.getAge()); + result.put("fatherName", esData.getFatherName() != null ? esData.getFatherName() : ""); + result.put("spouseName", esData.getSpouseName() != null ? esData.getSpouseName() : ""); + result.put("createdBy", esData.getCreatedBy()); + result.put("createdDate", esData.getCreatedDate()); + result.put("lastModDate", esData.getLastModDate()); + result.put("benAccountID", esData.getBenAccountID()); + + result.put("healthID", esData.getHealthID()); + result.put("abhaID", esData.getAbhaID()); + result.put("familyID", esData.getFamilyID()); + + Map mGender = new HashMap<>(); + mGender.put("genderID", esData.getGenderID()); + mGender.put("genderName", esData.getGenderName()); + result.put("m_gender", mGender); + + Map demographics = new HashMap<>(); + demographics.put("beneficiaryRegID", esData.getBenRegId()); + demographics.put("stateID", esData.getStateID()); + demographics.put("stateName", esData.getStateName()); + demographics.put("districtID", esData.getDistrictID()); + demographics.put("districtName", esData.getDistrictName()); + demographics.put("blockID", esData.getBlockID()); + demographics.put("blockName", esData.getBlockName()); + demographics.put("villageID", esData.getVillageID()); + demographics.put("villageName", esData.getVillageName()); + demographics.put("districtBranchID", null); + demographics.put("districtBranchName", null); + demographics.put("parkingPlaceID", esData.getParkingPlaceID()); + demographics.put("servicePointID", esData.getServicePointID()); + demographics.put("servicePointName", esData.getServicePointName()); + demographics.put("createdBy", esData.getCreatedBy()); + + Map mState = new HashMap<>(); + mState.put("stateID", esData.getStateID()); + mState.put("stateName", esData.getStateName()); + mState.put("stateCode", null); + mState.put("countryID", 1); + demographics.put("m_state", mState); + + Map mDistrict = new HashMap<>(); + mDistrict.put("districtID", esData.getDistrictID()); + mDistrict.put("districtName", esData.getDistrictName()); + mDistrict.put("stateID", esData.getStateID()); + demographics.put("m_district", mDistrict); + + Map mBlock = new HashMap<>(); + mBlock.put("blockID", esData.getBlockID()); + mBlock.put("blockName", esData.getBlockName()); + mBlock.put("districtID", esData.getDistrictID()); + mBlock.put("stateID", esData.getStateID()); + demographics.put("m_districtblock", mBlock); + + Map mBranch = new HashMap<>(); + mBranch.put("districtBranchID", null); + mBranch.put("blockID", esData.getBlockID()); + mBranch.put("villageName", esData.getVillageName()); + mBranch.put("pinCode", esData.getPinCode()); + demographics.put("m_districtbranchmapping", mBranch); + + result.put("i_bendemographics", demographics); + + List> benPhoneMaps = new ArrayList<>(); + if (esData.getPhoneNum() != null && !esData.getPhoneNum().isEmpty()) { + Map phoneMap = new HashMap<>(); + phoneMap.put("benPhMapID", 1L); + phoneMap.put("benificiaryRegID", esData.getBenRegId()); + phoneMap.put("parentBenRegID", esData.getBenRegId()); + phoneMap.put("benRelationshipID", 1); + phoneMap.put("phoneNo", esData.getPhoneNum()); + + Map relationType = new HashMap<>(); + relationType.put("benRelationshipID", 1); + relationType.put("benRelationshipType", "Self"); + phoneMap.put("benRelationshipType", relationType); + + benPhoneMaps.add(phoneMap); + } + result.put("benPhoneMaps", benPhoneMaps); + + result.put("isConsent", false); + result.put("m_title", new HashMap<>()); + result.put("maritalStatus", new HashMap<>()); + result.put("changeInSelfDetails", false); + result.put("changeInAddress", false); + result.put("changeInContacts", false); + result.put("changeInIdentities", false); + result.put("changeInOtherDetails", false); + result.put("changeInFamilyDetails", false); + result.put("changeInAssociations", false); + result.put("changeInBankDetails", false); + result.put("changeInBenImage", false); + result.put("is1097", false); + result.put("emergencyRegistration", false); + result.put("passToNurse", false); + result.put("beneficiaryIdentities", new ArrayList<>()); + + } catch (Exception e) { + logger.error("Error mapping ES result: {}", e.getMessage(), e); + return null; + } + + return result; + } + + /** + * Direct database search as fallback + */ + private List> searchInDatabaseDirectly(String query) { + try { + List results = benDetailRepo.searchBeneficiaries(query); + + return results.stream() + .map(this::mapToExpectedFormat) + .collect(Collectors.toList()); + + } catch (Exception e) { + logger.error("Database search failed: {}", e.getMessage(), e); + return Collections.emptyList(); + } + } + + /** + * Map database result to expected API format + */ + private Map mapToExpectedFormat(Object[] row) { + Map result = new HashMap<>(); + + try { + Long beneficiaryRegID = getLong(row[0]); + String beneficiaryID = getString(row[1]); + String firstName = getString(row[2]); + String lastName = getString(row[3]); + Integer genderID = getInteger(row[4]); + String genderName = getString(row[5]); + Date dob = getDate(row[6]); + Integer age = getInteger(row[7]); + String fatherName = getString(row[8]); + String spouseName = getString(row[9]); + String isHIVPos = getString(row[10]); + String createdBy = getString(row[11]); + Date createdDate = getDate(row[12]); + Long lastModDate = getLong(row[13]); + Long benAccountID = getLong(row[14]); + + Integer stateID = getInteger(row[15]); + String stateName = getString(row[16]); + Integer districtID = getInteger(row[17]); + String districtName = getString(row[18]); + Integer blockID = getInteger(row[19]); + String blockName = getString(row[20]); + String pinCode = getString(row[21]); + Integer servicePointID = getInteger(row[22]); + String servicePointName = getString(row[23]); + Integer parkingPlaceID = getInteger(row[24]); + String phoneNum = getString(row[25]); + + result.put("beneficiaryRegID", beneficiaryRegID); + result.put("beneficiaryID", beneficiaryID); + result.put("firstName", firstName); + result.put("lastName", lastName); + result.put("genderID", genderID); + result.put("genderName", genderName); + result.put("dOB", dob); + result.put("dob", dob); + result.put("age", age); + result.put("fatherName", fatherName != null ? fatherName : ""); + result.put("spouseName", spouseName != null ? spouseName : ""); + result.put("createdBy", createdBy); + result.put("createdDate", createdDate); + result.put("lastModDate", lastModDate); + result.put("benAccountID", benAccountID); + + Map mGender = new HashMap<>(); + mGender.put("genderID", genderID); + mGender.put("genderName", genderName); + result.put("m_gender", mGender); + + Map demographics = new HashMap<>(); + demographics.put("beneficiaryRegID", beneficiaryRegID); + demographics.put("stateID", stateID); + demographics.put("stateName", stateName); + demographics.put("districtID", districtID); + demographics.put("districtName", districtName); + demographics.put("blockID", blockID); + demographics.put("blockName", blockName); + demographics.put("districtBranchID", null); + demographics.put("districtBranchName", null); + demographics.put("parkingPlaceID", parkingPlaceID); + demographics.put("servicePointID", servicePointID); + demographics.put("servicePointName", servicePointName); + demographics.put("createdBy", createdBy); + + Map mState = new HashMap<>(); + mState.put("stateID", stateID); + mState.put("stateName", stateName); + mState.put("stateCode", null); + mState.put("countryID", 1); + demographics.put("m_state", mState); + + Map mDistrict = new HashMap<>(); + mDistrict.put("districtID", districtID); + mDistrict.put("districtName", districtName); + mDistrict.put("stateID", stateID); + demographics.put("m_district", mDistrict); + + Map mBlock = new HashMap<>(); + mBlock.put("blockID", blockID); + mBlock.put("blockName", blockName); + mBlock.put("districtID", districtID); + mBlock.put("stateID", stateID); + demographics.put("m_districtblock", mBlock); + + Map mBranch = new HashMap<>(); + mBranch.put("districtBranchID", null); + mBranch.put("blockID", blockID); + mBranch.put("villageName", null); + mBranch.put("pinCode", pinCode); + demographics.put("m_districtbranchmapping", mBranch); + + result.put("i_bendemographics", demographics); + + List> benPhoneMaps = fetchPhoneNumbers(beneficiaryRegID); + result.put("benPhoneMaps", benPhoneMaps); + + result.put("isConsent", false); + result.put("m_title", new HashMap<>()); + result.put("maritalStatus", new HashMap<>()); + result.put("changeInSelfDetails", false); + result.put("changeInAddress", false); + result.put("changeInContacts", false); + result.put("changeInIdentities", false); + result.put("changeInOtherDetails", false); + result.put("changeInFamilyDetails", false); + result.put("changeInAssociations", false); + result.put("changeInBankDetails", false); + result.put("changeInBenImage", false); + result.put("is1097", false); + result.put("emergencyRegistration", false); + result.put("passToNurse", false); + result.put("beneficiaryIdentities", new ArrayList<>()); + + } catch (Exception e) { + logger.error("Error mapping result: {}", e.getMessage(), e); + } + + return result; + } + + /** + * Fetch phone numbers for a beneficiary + */ + private List> fetchPhoneNumbers(Long beneficiaryRegID) { + List> phoneList = new ArrayList<>(); + + try { + List phones = benDetailRepo.findPhoneNumbersByBeneficiaryId(beneficiaryRegID); + + int mapId = 1; + for (Object[] phone : phones) { + String phoneNo = getString(phone[0]); + String phoneType = getString(phone[1]); + + if (phoneNo != null && !phoneNo.isEmpty()) { + Map phoneMap = new HashMap<>(); + phoneMap.put("benPhMapID", (long) mapId++); + phoneMap.put("benificiaryRegID", beneficiaryRegID); + phoneMap.put("parentBenRegID", beneficiaryRegID); + phoneMap.put("benRelationshipID", 1); + phoneMap.put("phoneNo", phoneNo); + + Map relationType = new HashMap<>(); + relationType.put("benRelationshipID", 1); + relationType.put("benRelationshipType", phoneType != null ? phoneType : "Self"); + phoneMap.put("benRelationshipType", relationType); + + phoneList.add(phoneMap); + } + } + } catch (Exception e) { + logger.error("Error fetching phone numbers: {}", e.getMessage(), e); + } + + return phoneList; + } + + // Helper methods + private String getString(Object value) { + if (value == null) return null; + return value.toString(); + } + + private Long getLong(Object value) { + if (value == null) return null; + if (value instanceof Long) return (Long) value; + if (value instanceof Integer) return ((Integer) value).longValue(); + if (value instanceof BigDecimal) return ((BigDecimal) value).longValue(); + if (value instanceof String) { + try { + return Long.parseLong((String) value); + } catch (NumberFormatException e) { + return null; + } + } + return null; + } + + private Integer getInteger(Object value) { + if (value == null) return null; + if (value instanceof Integer) return (Integer) value; + if (value instanceof Long) return ((Long) value).intValue(); + if (value instanceof BigDecimal) return ((BigDecimal) value).intValue(); + if (value instanceof String) { + try { + return Integer.parseInt((String) value); + } catch (NumberFormatException e) { + return null; + } + } + return null; + } + + private Date getDate(Object value) { + if (value == null) return null; + if (value instanceof Date) return (Date) value; + if (value instanceof Timestamp) return new Date(((Timestamp) value).getTime()); + if (value instanceof java.sql.Date) return new Date(((java.sql.Date) value).getTime()); + return null; + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/service/elasticsearch/ElasticsearchSyncService.java b/src/main/java/com/iemr/common/identity/service/elasticsearch/ElasticsearchSyncService.java new file mode 100644 index 00000000..24d10775 --- /dev/null +++ b/src/main/java/com/iemr/common/identity/service/elasticsearch/ElasticsearchSyncService.java @@ -0,0 +1,479 @@ +package com.iemr.common.identity.service.elasticsearch; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.core.BulkRequest; +import co.elastic.clients.elasticsearch.core.BulkResponse; +import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; + +import com.iemr.common.identity.data.elasticsearch.BeneficiaryDocument; +import com.iemr.common.identity.dto.BenDetailDTO; +import com.iemr.common.identity.dto.BeneficiariesDTO; +import com.iemr.common.identity.repo.BenMappingRepo; +import com.iemr.common.identity.service.elasticsearch.BeneficiaryDataService; + +/** + * Service to synchronize beneficiary data from database to Elasticsearch + */ +@Service +public class ElasticsearchSyncService { + + private static final Logger logger = LoggerFactory.getLogger(ElasticsearchSyncService.class); + private static final int BATCH_SIZE = 100; // Reduced to 100 for better connection management + private static final int ES_BULK_SIZE = 50; // Reduced to 50 for better performance + private static final int PAUSE_AFTER_BATCHES = 5; // Pause after every 5 batches + + @Autowired + private ElasticsearchClient esClient; + + @Autowired + private BenMappingRepo mappingRepo; + + @Autowired + private BeneficiaryDataService beneficiaryDataService; + + @Autowired + private BeneficiaryTransactionHelper transactionalWrapper; + + @Value("${elasticsearch.index.beneficiary}") + private String beneficiaryIndex; + + /** + * Sync all beneficiaries from database to Elasticsearch + * This should be run as a one-time operation or scheduled job + */ + public SyncResult syncAllBeneficiaries() { + logger.info("Starting full beneficiary sync to Elasticsearch..."); + + SyncResult result = new SyncResult(); + + try { + // Get total count using transactional wrapper + long totalCount = transactionalWrapper.countActiveBeneficiaries(); + logger.info("Total beneficiaries to sync: {}", totalCount); + + if (totalCount == 0) { + logger.warn("No beneficiaries found to sync!"); + return result; + } + + AtomicInteger processedCount = new AtomicInteger(0); + int offset = 0; + int batchCounter = 0; + List esBatch = new ArrayList<>(); + + // Process in batches + while (offset < totalCount) { + logger.info("Fetching batch: offset={}, limit={}", offset, BATCH_SIZE); + + List batchIds = null; + + try { + // Use transactional wrapper to get fresh connection for each batch + batchIds = transactionalWrapper.getBeneficiaryIdsBatch(offset, BATCH_SIZE); + } catch (Exception e) { + logger.error("Error fetching batch from database: {}", e.getMessage()); + // Wait and retry once + try { + Thread.sleep(2000); + batchIds = transactionalWrapper.getBeneficiaryIdsBatch(offset, BATCH_SIZE); + } catch (Exception e2) { + logger.error("Retry failed: {}", e2.getMessage()); + result.setError("Database connection error: " + e2.getMessage()); + break; + } + } + + if (batchIds == null || batchIds.isEmpty()) { + logger.info("No more records to process. Breaking loop."); + break; + } + + logger.info("Processing {} beneficiaries in current batch", batchIds.size()); + + for (Object[] benIdObj : batchIds) { + try { + BigInteger benRegId = (BigInteger) benIdObj[0]; + + // Fetch beneficiary details DIRECTLY from database + BeneficiariesDTO benDTO = beneficiaryDataService.getBeneficiaryFromDatabase(benRegId); + + if (benDTO != null) { + BeneficiaryDocument doc = convertToDocument(benDTO); + + if (doc != null && doc.getBenId() != null) { + esBatch.add(doc); + + // Send to ES when batch is full + if (esBatch.size() >= ES_BULK_SIZE) { + int indexed = bulkIndexDocuments(esBatch); + result.addSuccess(indexed); + result.addFailure(esBatch.size() - indexed); + + int current = processedCount.addAndGet(esBatch.size()); + logger.info("Progress: {}/{} ({} %) - Indexed: {}, Failed: {}", + current, totalCount, + String.format("%.2f", (current * 100.0) / totalCount), + indexed, esBatch.size() - indexed); + + esBatch.clear(); + } + } else { + logger.warn("Skipping beneficiary with null benId: benRegId={}", benRegId); + result.addFailure(); + } + } else { + logger.warn("No details found for benRegId: {}", benRegId); + result.addFailure(); + } + + } catch (Exception e) { + logger.error("Error processing beneficiary in batch: {}", e.getMessage(), e); + result.addFailure(); + } + } + + offset += BATCH_SIZE; + batchCounter++; + + // Pause after every N batches to let connections stabilize + if (batchCounter % PAUSE_AFTER_BATCHES == 0) { + logger.info("Completed {} batches. Pausing for 2 seconds...", batchCounter); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + logger.warn("Sleep interrupted: {}", e.getMessage()); + } + } + } + + // Index remaining documents + if (!esBatch.isEmpty()) { + logger.info("Indexing final batch of {} documents...", esBatch.size()); + int indexed = bulkIndexDocuments(esBatch); + result.addSuccess(indexed); + result.addFailure(esBatch.size() - indexed); + processedCount.addAndGet(esBatch.size()); + } + + logger.info("Sync completed successfully!"); + logger.info("Total Processed: {}", processedCount.get()); + logger.info("Successfully Indexed: {}", result.getSuccessCount()); + logger.info("Failed: {}", result.getFailureCount()); + + } catch (Exception e) { + logger.error("========================================"); + logger.error("CRITICAL ERROR during full sync: {}", e.getMessage(), e); + logger.error("========================================"); + result.setError(e.getMessage()); + } + + return result; + } + + /** + * Sync a single beneficiary by BenRegId + * Uses direct database access to avoid Elasticsearch circular dependency + */ + public boolean syncSingleBeneficiary(String benRegId) { + try { + logger.info("Syncing single beneficiary with BenRegId: {}", benRegId); + + BigInteger benRegIdBig = new BigInteger(benRegId); + + // Check if beneficiary exists in database first using transactional wrapper + boolean exists = transactionalWrapper.existsByBenRegId(benRegIdBig); + if (!exists) { + logger.error("Beneficiary does not exist in database: BenRegId={}", benRegId); + return false; + } + + logger.info("Beneficiary exists in database. Fetching details..."); + + // Get beneficiary DIRECTLY from database (not through IdentityService) + BeneficiariesDTO benDTO = beneficiaryDataService.getBeneficiaryFromDatabase(benRegIdBig); + + if (benDTO == null) { + logger.error("Failed to fetch beneficiary details from database: BenRegId={}", benRegId); + return false; + } + + logger.info("Beneficiary details fetched successfully"); + logger.info("BenRegId: {}, Name: {} {}", + benDTO.getBenRegId(), + benDTO.getBeneficiaryDetails() != null ? benDTO.getBeneficiaryDetails().getFirstName() : "N/A", + benDTO.getBeneficiaryDetails() != null ? benDTO.getBeneficiaryDetails().getLastName() : "N/A"); + + // Convert to Elasticsearch document + BeneficiaryDocument doc = convertToDocument(benDTO); + + if (doc == null || doc.getBenId() == null) { + logger.error("Failed to convert beneficiary to document: BenRegId={}", benRegId); + return false; + } + + logger.info("Document created. Indexing to Elasticsearch..."); + logger.info("Document ID: {}, Index: {}", doc.getBenId(), beneficiaryIndex); + + // Index to Elasticsearch + esClient.index(i -> i + .index(beneficiaryIndex) + .id(doc.getBenId()) + .document(doc) + ); + + logger.info("SUCCESS! Beneficiary synced to Elasticsearch"); + logger.info("BenRegId: {}, BenId: {}", benRegId, doc.getBenId()); + + return true; + + } catch (Exception e) { + logger.error("ERROR syncing beneficiary {}: {}", benRegId, e.getMessage(), e); + return false; + } + } + + /** + * Bulk index documents to Elasticsearch + */ + private int bulkIndexDocuments(List documents) { + if (documents == null || documents.isEmpty()) { + return 0; + } + + try { + BulkRequest.Builder br = new BulkRequest.Builder(); + + for (BeneficiaryDocument doc : documents) { + if (doc.getBenId() != null) { + br.operations(op -> op + .index(idx -> idx + .index(beneficiaryIndex) + .id(doc.getBenId()) + .document(doc) + ) + ); + } + } + + BulkResponse result = esClient.bulk(br.build()); + + int successCount = 0; + + if (result.errors()) { + logger.warn("Bulk indexing had some errors"); + for (BulkResponseItem item : result.items()) { + if (item.error() != null) { + logger.error("Error indexing document {}: {}", + item.id(), item.error().reason()); + } else { + successCount++; + } + } + } else { + successCount = documents.size(); + } + + return successCount; + + } catch (Exception e) { + logger.error("Critical error in bulk indexing: {}", e.getMessage(), e); + return 0; + } + } + + /** + * Convert BeneficiariesDTO to BeneficiaryDocument + */ + private BeneficiaryDocument convertToDocument(BeneficiariesDTO dto) { + if (dto == null) { + logger.warn("Cannot convert null DTO to document"); + return null; + } + + try { + BeneficiaryDocument doc = new BeneficiaryDocument(); + + // BenId (use benRegId as primary identifier) + if (dto.getBenRegId() != null) { + BigInteger benRegId = (BigInteger) dto.getBenRegId(); + doc.setBenId(benRegId.toString()); + doc.setBenRegId(benRegId.longValue()); + } else if (dto.getBenId() != null) { + doc.setBenId(dto.getBenId().toString()); + if (dto.getBenId() instanceof BigInteger) { + doc.setBenRegId(((BigInteger) dto.getBenId()).longValue()); + } + } else { + logger.warn("Beneficiary has no valid ID!"); + return null; + } + + // Phone number + doc.setPhoneNum(dto.getPreferredPhoneNum()); + + // Beneficiary Details (from nested DTO) + if (dto.getBeneficiaryDetails() != null) { + BenDetailDTO benDetails = dto.getBeneficiaryDetails(); + doc.setFirstName(benDetails.getFirstName()); + doc.setLastName(benDetails.getLastName()); + doc.setAge(benDetails.getBeneficiaryAge()); + doc.setGender(benDetails.getGender()); + } + + logger.debug("Successfully converted DTO to document: benId={}", doc.getBenId()); + return doc; + + } catch (Exception e) { + logger.error("Error converting DTO to document: {}", e.getMessage(), e); + return null; + } + } + + /** + * Verify sync by checking document count + */ + public SyncStatus checkSyncStatus() { + try { + long dbCount = transactionalWrapper.countActiveBeneficiaries(); + + long esCount = esClient.count(c -> c + .index(beneficiaryIndex) + ).count(); + + SyncStatus status = new SyncStatus(); + status.setDatabaseCount(dbCount); + status.setElasticsearchCount(esCount); + status.setSynced(dbCount == esCount); + status.setMissingCount(dbCount - esCount); + + logger.info("Sync Status - DB: {}, ES: {}, Missing: {}", dbCount, esCount, dbCount - esCount); + + return status; + + } catch (Exception e) { + logger.error("Error checking sync status: {}", e.getMessage(), e); + SyncStatus status = new SyncStatus(); + status.setError(e.getMessage()); + return status; + } + } + + /** + * Result class to track sync progress + */ + public static class SyncResult { + private int successCount = 0; + private int failureCount = 0; + private String error; + + public void addSuccess(int count) { + this.successCount += count; + } + + public void addFailure() { + this.failureCount++; + } + + public void addFailure(int count) { + this.failureCount += count; + } + + public int getSuccessCount() { + return successCount; + } + + public int getFailureCount() { + return failureCount; + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } + + @Override + public String toString() { + return "SyncResult{" + + "successCount=" + successCount + + ", failureCount=" + failureCount + + ", error='" + error + '\'' + + '}'; + } + } + + /** + * Status class to track sync verification + */ + public static class SyncStatus { + private long databaseCount; + private long elasticsearchCount; + private boolean synced; + private long missingCount; + private String error; + + public long getDatabaseCount() { + return databaseCount; + } + + public void setDatabaseCount(long databaseCount) { + this.databaseCount = databaseCount; + } + + public long getElasticsearchCount() { + return elasticsearchCount; + } + + public void setElasticsearchCount(long elasticsearchCount) { + this.elasticsearchCount = elasticsearchCount; + } + + public boolean isSynced() { + return synced; + } + + public void setSynced(boolean synced) { + this.synced = synced; + } + + public long getMissingCount() { + return missingCount; + } + + public void setMissingCount(long missingCount) { + this.missingCount = missingCount; + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } + + @Override + public String toString() { + return "SyncStatus{" + + "databaseCount=" + databaseCount + + ", elasticsearchCount=" + elasticsearchCount + + ", synced=" + synced + + ", missingCount=" + missingCount + + ", error='" + error + '\'' + + '}'; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/service/elasticsearch/SyncJobService.java b/src/main/java/com/iemr/common/identity/service/elasticsearch/SyncJobService.java new file mode 100644 index 00000000..e4dc44f8 --- /dev/null +++ b/src/main/java/com/iemr/common/identity/service/elasticsearch/SyncJobService.java @@ -0,0 +1,145 @@ +package com.iemr.common.identity.service.elasticsearch; + +import java.sql.Timestamp; +import java.util.List; +import java.util.Optional; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.iemr.common.identity.data.elasticsearch.ElasticsearchSyncJob; +import com.iemr.common.identity.repo.elasticsearch.SyncJobRepo; + +/** + * Service to manage Elasticsearch sync jobs + */ +@Service +public class SyncJobService { + + private static final Logger logger = LoggerFactory.getLogger(SyncJobService.class); + + @Autowired + private SyncJobRepo syncJobRepository; + + @Autowired + private BeneficiaryElasticsearchIndexService syncService; + + /** + * Start a new full sync job + * Returns immediately with job ID + */ + public ElasticsearchSyncJob startFullSyncJob(String triggeredBy) { + // Check if there's already an active full sync job + if (syncJobRepository.hasActiveFullSyncJob()) { + throw new RuntimeException("A full sync job is already running. Please wait for it to complete."); + } + + // Create new job + ElasticsearchSyncJob job = new ElasticsearchSyncJob(); + job.setJobType("FULL_SYNC"); + job.setStatus("PENDING"); + job.setTriggeredBy(triggeredBy); + job.setProcessedRecords(0L); + job.setSuccessCount(0L); + job.setFailureCount(0L); + job.setCurrentOffset(0); + + // Save job to database + job = syncJobRepository.save(job); + + logger.info("Created new full sync job: jobId={}, triggeredBy={}", job.getJobId(), triggeredBy); + + // Start async processing + syncService.syncAllBeneficiariesAsync(job.getJobId(), triggeredBy); + + return job; + } + + /** + * Resume a failed job from where it left off + */ + public ElasticsearchSyncJob resumeJob(Long jobId, String triggeredBy) { + ElasticsearchSyncJob job = syncJobRepository.findByJobId(jobId) + .orElseThrow(() -> new RuntimeException("Job not found: " + jobId)); + + if (!"FAILED".equals(job.getStatus())) { + throw new RuntimeException("Can only resume FAILED jobs. Current status: " + job.getStatus()); + } + + logger.info("Resuming job: jobId={}, from offset={}", jobId, job.getCurrentOffset()); + + job.setStatus("PENDING"); + job.setTriggeredBy(triggeredBy); + job = syncJobRepository.save(job); + + // Restart async processing from last offset + syncService.syncAllBeneficiariesAsync(job.getJobId(), triggeredBy); + + return job; + } + + /** + * Cancel a running job + */ + public boolean cancelJob(Long jobId) { + Optional jobOpt = syncJobRepository.findByJobId(jobId); + + if (jobOpt.isEmpty()) { + return false; + } + + ElasticsearchSyncJob job = jobOpt.get(); + + if (!job.isActive()) { + logger.warn("Cannot cancel job that is not active: jobId={}, status={}", jobId, job.getStatus()); + return false; + } + + // Mark as cancelled (the async thread will check this periodically) + job.setStatus("CANCELLED"); + job.setCompletedAt(new Timestamp(System.currentTimeMillis())); + syncJobRepository.save(job); + + logger.info("Job cancelled: jobId={}", jobId); + return true; + } + + /** + * Get job status by ID + */ + public ElasticsearchSyncJob getJobStatus(Long jobId) { + return syncJobRepository.findByJobId(jobId) + .orElseThrow(() -> new RuntimeException("Job not found: " + jobId)); + } + + /** + * Get all active jobs + */ + public List getActiveJobs() { + return syncJobRepository.findActiveJobs(); + } + + /** + * Get recent jobs (last 10) + */ + public List getRecentJobs() { + return syncJobRepository.findRecentJobs(); + } + + /** + * Check if any full sync is currently running + */ + public boolean isFullSyncRunning() { + return syncJobRepository.hasActiveFullSyncJob(); + } + + /** + * Get latest job of specific type + */ + public ElasticsearchSyncJob getLatestJobByType(String jobType) { + List jobs = syncJobRepository.findLatestJobsByType(jobType); + return jobs.isEmpty() ? null : jobs.get(0); + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/common/identity/utils/CookieUtil.java b/src/main/java/com/iemr/common/identity/utils/CookieUtil.java index 84f54526..dd4a02db 100644 --- a/src/main/java/com/iemr/common/identity/utils/CookieUtil.java +++ b/src/main/java/com/iemr/common/identity/utils/CookieUtil.java @@ -1,5 +1,6 @@ package com.iemr.common.identity.utils; +import java.util.Arrays; import java.util.Optional; import org.springframework.stereotype.Service; @@ -22,7 +23,15 @@ public Optional getCookieValue(HttpServletRequest request, String cookie return Optional.empty(); } - public String getJwtTokenFromCookie(HttpServletRequest request) { - return getCookieValue(request, "Jwttoken").orElse(null); + public static String getJwtTokenFromCookie(HttpServletRequest request) { + Cookie[] cookies = request.getCookies(); + if (cookies == null) { + return null; // No cookies present, return null safely + } + return Arrays.stream(cookies).filter(cookie -> "Jwttoken".equals(cookie.getName())).map(Cookie::getValue) + .findFirst().orElse(null); } + } + + diff --git a/src/main/java/com/iemr/common/identity/utils/JwtAuthenticationUtil.java b/src/main/java/com/iemr/common/identity/utils/JwtAuthenticationUtil.java index 49e48265..af2539ff 100644 --- a/src/main/java/com/iemr/common/identity/utils/JwtAuthenticationUtil.java +++ b/src/main/java/com/iemr/common/identity/utils/JwtAuthenticationUtil.java @@ -109,7 +109,7 @@ private User getUserFromCache(String userId) { private User fetchUserFromDB(String userId) { String redisKey = "user_" + userId; // Redis key format List users = jdbcTemplate.query( - "SELECT * FROM m_user WHERE UserID = ? AND Deleted = false", + "SELECT * FROM db_iemr.m_user WHERE UserID = ? AND Deleted = false", new BeanPropertyRowMapper<>(User.class), userId); if (users.isEmpty()) { diff --git a/src/main/java/com/iemr/common/identity/utils/JwtUserIdValidationFilter.java b/src/main/java/com/iemr/common/identity/utils/JwtUserIdValidationFilter.java index 6d5c55f9..1156daa1 100644 --- a/src/main/java/com/iemr/common/identity/utils/JwtUserIdValidationFilter.java +++ b/src/main/java/com/iemr/common/identity/utils/JwtUserIdValidationFilter.java @@ -162,6 +162,7 @@ private boolean isMobileClient(String userAgent) { return userAgent.contains("okhttp") || userAgent.contains("java/"); // iOS (custom clients) } + @SuppressWarnings("static-access") private String getJwtTokenFromCookies(HttpServletRequest request) { return cookieUtil.getJwtTokenFromCookie(request); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1780d8b6..7813571c 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -9,8 +9,61 @@ spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.Ph # The SQL dialect makes Hibernate generate better SQL for the chosen database spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect -#Below lines are added for security reasons +spring.datasource.hikari.leak-detection-threshold=60000 + +# MySQL specific settings to prevent connection timeout +spring.datasource.hikari.data-source-properties.cachePrepStmts=true +spring.datasource.hikari.data-source-properties.prepStmtCacheSize=250 +spring.datasource.hikari.data-source-properties.prepStmtCacheSqlLimit=2048 +spring.datasource.hikari.data-source-properties.useServerPrepStmts=true +spring.datasource.hikari.data-source-properties.autoReconnect=true +spring.datasource.hikari.data-source-properties.tcpKeepAlive=true +# spring.datasource.hikari.test-on-borrow=true + +# Reduce batch size for faster feedback +spring.jpa.properties.hibernate.jdbc.batch_size=50 +spring.jpa.properties.hibernate.order_inserts=true +spring.jpa.properties.hibernate.order_updates=true + +# Query timeout +spring.jpa.properties.hibernate.query.timeout=30000 + +spring.datasource.hikari.maximum-pool-size=20 +spring.datasource.hikari.minimum-idle=10 +spring.datasource.hikari.connection-timeout=30000 +spring.datasource.hikari.idle-timeout=300000 +spring.datasource.hikari.max-lifetime=600000 +spring.datasource.hikari.keepalive-tquickime=120000 +spring.datasource.hikari.validationTimeout=5000 + +# REMOVE CONNECTION TEST QUERY +# spring.datasource.hikari.connection-test-query=SELECT 1 + +# BETTER THAN autoReconnect + test-on-borrow +spring.datasource.hikari.health-check-properties.mysql5Validation=true + +spring.datasource.hikari.data-source-properties.cachePrepStmts=true +spring.datasource.hikari.data-source-properties.prepStmtCacheSize=250 +spring.datasource.hikari.data-source-properties.prepStmtCacheSqlLimit=2048 +spring.datasource.hikari.data-source-properties.useServerPrepStmts=true +spring.datasource.hikari.data-source-properties.tcpKeepAlive=true + + +# spring.datasource.hikari.connection-test-query=SELECT 1 + +# OLD Tomcat settings - REMOVE THESE (they conflict with HikariCP) +# spring.datasource.tomcat.initial-size=5 +# spring.datasource.tomcat.max-idle=15 +# spring.datasource.tomcat.max-active=30 +# spring.datasource.tomcat.min-idle=5 +# spring.datasource.tomcat.min-evictable-idle-time-millis=15000 +# spring.datasource.tomcat.remove-abandoned=true +# spring.datasource.tomcat.logAbandoned=true +# spring.datasource.continue-on-error=true +# spring.datasource.tomcat.remove-abandoned-timeout=600 + +#Below lines are added for security reasons spring.session.store-type=redis spring.redis.password= spring.redis.port=6379 @@ -26,16 +79,8 @@ logging.level.org.springframework.web=INFO logging.level.org.hibernate=INFO logging.level.com.iemr=DEBUG logging.level.org.springframework=INFO +logging.level.com.zaxxer.hikari=DEBUG -spring.datasource.tomcat.initial-size=5 -spring.datasource.tomcat.max-idle=15 -spring.datasource.tomcat.max-active=30 -spring.datasource.tomcat.min-idle=5 -spring.datasource.tomcat.min-evictable-idle-time-millis=15000 -spring.datasource.tomcat.remove-abandoned=true -spring.datasource.tomcat.logAbandoned=true -spring.datasource.continue-on-error=true -spring.datasource.tomcat.remove-abandoned-timeout=600 door-to-door-page-size=2 #Get-HRP-Status @@ -44,12 +89,26 @@ get-HRP-Status=ANC/getHRPStatus #Get Beneficiary ABHA getHealthID=healthID/getBenhealthID - -## commit miss error in ci - - spring.main.allow-bean-definition-overriding=true spring.main.allow-circular-references=true -#springfox.documentation.swagger-ui.enabled=true jwt.access.expiration=86400000 jwt.refresh.expiration=604800000 + +# Elasticsearch Configuration +elasticsearch.host=localhost +elasticsearch.port=9200 +elasticsearch.username=elastic +elasticsearch.password=piramalES +elasticsearch.index.beneficiary=beneficiary_index_v5 + +# Enable/Disable ES (for gradual rollout) +elasticsearch.enabled=true + +# Connection pool settings +elasticsearch.connection.timeout=5000 +elasticsearch.socket.timeout=60000 + +# Logging +logging.level.com.iemr.common.identity.service.elasticsearch=INFO +logging.level.org.elasticsearch=WARN +