diff --git a/.gitignore b/.gitignore index 5a1e6d24a..a4786a90b 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,3 @@ mvnw.cmd .mvn /logs/ src/main/environment/common_local.properties -node_modules diff --git a/src/main/environment/common_ci.properties b/src/main/environment/common_ci.properties index 0bd9638b1..f2f3e0202 100644 --- a/src/main/environment/common_ci.properties +++ b/src/main/environment/common_ci.properties @@ -1,6 +1,7 @@ fhir-url = @env.FHIR_API@ tm-url = @env.TM_API@ +common-api-base-url=@env.COMMON_API@ ##--------------------------------------------## Primary db------------------------------------------------------------------- @@ -27,11 +28,6 @@ jwt.secret=@env.JWT_SECRET_KEY@ # Redis Config spring.redis.host=@env.REDIS_HOST@ -# Stop TB: when true, saves fail with an error if camp (vanID) is not configured -stoptb.enforce.vanid=@env.STOPTB_ENFORCE_VANID@ -# Stop TB: this deployment's van/camp ID, replacing the old Redis camp:vanID lookup -stoptb.van.id=@env.STOPTB_VAN_ID@ - cors.allowed-origins=@env.CORS_ALLOWED_ORIGINS@ #### SMS Configuration @@ -84,9 +80,3 @@ diagnostic.emrlite.truenat.password=@env.DIAGNOSTIC_EMRLITE_TRUENAT_PASSWORD@ diagnostic.emrlite.token-ttl-seconds=@env.DIAGNOSTIC_EMRLITE_TOKEN_TTL_SECONDS@ diagnostic.emrlite.refresh-ttl-seconds=@env.DIAGNOSTIC_EMRLITE_REFRESH_TTL_SECONDS@ -diagnostic.poll.xray.tick-ms=@env.DIAGNOSTIC_POLL_XRAY_TICK_MS@ -diagnostic.poll.truenat.tick-ms=@env.DIAGNOSTIC_POLL_TRUENAT_TICK_MS@ -# Daily cutoff (cron expression) after which all outstanding PENDING/IN_PROGRESS orders are marked EXPIRED -diagnostic.poll.expiry-cron=@env.DIAGNOSTIC_POLL_EXPIRY_CRON@ - -diagnostic.documents.storage-root=@env.DIAGNOSTIC_DOCUMENTS_STORAGE_ROOT@ diff --git a/src/main/environment/common_docker.properties b/src/main/environment/common_docker.properties index 2b19223c7..6c1f908c6 100644 --- a/src/main/environment/common_docker.properties +++ b/src/main/environment/common_docker.properties @@ -1,5 +1,8 @@ fhir-url = ${FHIR_API} tm-url = ${TM_API} +common-api-base-url=${COMMON_API} + + ##--------------------------------------------## Primary db------------------------------------------------------------------- diff --git a/src/main/environment/common_example.properties b/src/main/environment/common_example.properties index 9238d8be3..3c679d09c 100644 --- a/src/main/environment/common_example.properties +++ b/src/main/environment/common_example.properties @@ -2,6 +2,7 @@ server.port=8081 # FHIR Config fhir-url=http://localhost:8093/ + # TM Config tm-url=http://localhost:8089/ ##--------------------------------------------## Primary db------------------------------------------------------------------- @@ -23,17 +24,11 @@ springdoc.swagger-ui.enabled=true logging.path=logs/ logging.file.name=logs/flw-api.log -jwt.secret=eefa40497bb9b2a8491b85069aff62e7596521c6816e471c464181b52eac7670ff91394a +jwt.secret=my-32-character-ultra-secure-and-ultra-long-secret # Redis Config spring.redis.host=localhost -# Stop TB: when true, saves fail with an error if camp (vanID) is not configured -# instead of silently storing vanID=NULL (which then never gets synced to central) -stoptb.enforce.vanid=false -# Stop TB: this deployment's van/camp ID, replacing the old Redis camp:vanID lookup -stoptb.van.id=0 - cors.allowed-origins=http://localhost:* source-address= @@ -50,39 +45,6 @@ abha.token.url= abha.xcmid= -# ── Diagnostic Device Integration ──────────────────────────────────────────── -# diagnostic.provider.xray / diagnostic.provider.truenat select the vendor per orderType family -# (XRAY_CHEST vs MTB/MTB_PLUS/MDR_RIF), each must be one of com.iemr.flw.masterEnum.DiagnosticProviderCode -diagnostic.provider.xray=${DIAGNOSTIC_PROVIDER_XRAY} -diagnostic.provider.truenat=${DIAGNOSTIC_PROVIDER_TRUENAT} - -# EMR Lite - xray group (same base-url as truenat for now; split so a distinct vendor/tenant can be -# swapped in for either group later without a code change) -diagnostic.emrlite.xray.base-url=${DIAGNOSTIC_EMRLITE_XRAY_BASE_URL} -diagnostic.emrlite.xray.login-url=${diagnostic.emrlite.xray.base-url}/api/v1/integrations/login/ -diagnostic.emrlite.xray.refresh-url=${diagnostic.emrlite.xray.base-url}/api/v1/integrations/getAccessToken/ -diagnostic.emrlite.xray.order-url=${diagnostic.emrlite.xray.base-url}/api/v1/integrations/orders/ -diagnostic.emrlite.xray.result-url=${diagnostic.emrlite.xray.base-url}/api/v1/integrations/orders/result/ -diagnostic.emrlite.xray.ping-url=${diagnostic.emrlite.xray.base-url}/api/v1/integrations/ping/ -diagnostic.emrlite.xray.username=${DIAGNOSTIC_EMRLITE_XRAY_USERNAME} -diagnostic.emrlite.xray.password=${DIAGNOSTIC_EMRLITE_XRAY_PASSWORD} - -# EMR Lite - truenat group (MTB/MTB_PLUS/MDR_RIF); same value as xray for now -diagnostic.emrlite.truenat.base-url=${DIAGNOSTIC_EMRLITE_TRUENAT_BASE_URL} -diagnostic.emrlite.truenat.login-url=${diagnostic.emrlite.truenat.base-url}/api/v1/integrations/login/ -diagnostic.emrlite.truenat.refresh-url=${diagnostic.emrlite.truenat.base-url}/api/v1/integrations/getAccessToken/ -diagnostic.emrlite.truenat.order-url=${diagnostic.emrlite.truenat.base-url}/api/v1/integrations/orders/ -diagnostic.emrlite.truenat.result-url=${diagnostic.emrlite.truenat.base-url}/api/v1/integrations/orders/result/ -diagnostic.emrlite.truenat.ping-url=${diagnostic.emrlite.truenat.base-url}/api/v1/integrations/ping/ -diagnostic.emrlite.truenat.username=${DIAGNOSTIC_EMRLITE_TRUENAT_USERNAME} -diagnostic.emrlite.truenat.password=${DIAGNOSTIC_EMRLITE_TRUENAT_PASSWORD} - -diagnostic.emrlite.token-ttl-seconds=${DIAGNOSTIC_EMRLITE_TOKEN_TTL_SECONDS} -diagnostic.emrlite.refresh-ttl-seconds=${DIAGNOSTIC_EMRLITE_REFRESH_TTL_SECONDS} - -diagnostic.poll.xray.tick-ms=${DIAGNOSTIC_POLL_XRAY_TICK_MS} -diagnostic.poll.truenat.tick-ms=${DIAGNOSTIC_POLL_TRUENAT_TICK_MS} -# Daily cutoff (cron expression) after which all outstanding PENDING/IN_PROGRESS orders are marked EXPIRED -diagnostic.poll.expiry-cron=${DIAGNOSTIC_POLL_EXPIRY_CRON} - -diagnostic.documents.storage-root=${DIAGNOSTIC_DOCUMENTS_STORAGE_ROOT} + + + diff --git a/src/main/java/com/iemr/flw/controller/AshaProfileController.java b/src/main/java/com/iemr/flw/controller/AshaProfileController.java index e0a6510a4..2d02ce231 100644 --- a/src/main/java/com/iemr/flw/controller/AshaProfileController.java +++ b/src/main/java/com/iemr/flw/controller/AshaProfileController.java @@ -3,7 +3,9 @@ import com.iemr.flw.domain.iemr.AshaWorker; import com.iemr.flw.service.AshaProfileService; import com.iemr.flw.service.EmployeeMasterInter; +import io.lettuce.core.dynamic.annotation.Param; import com.iemr.flw.utils.JwtUtil; +import jakarta.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -54,15 +56,33 @@ public ResponseEntity> editEmployee(@RequestBody AshaWorker } @RequestMapping(value = "getProfile", method = RequestMethod.GET) - public ResponseEntity> getProfile( - @RequestHeader(value = "JwtToken") String jwtToken) { + public ResponseEntity> getProfile(HttpServletRequest request, @Param("employeeId") Integer employeeId) { Map response = new HashMap<>(); try { - Integer employeeId = jwtUtil.extractUserId(jwtToken); + String jwtFromHeader = request.getHeader("JwtToken"); + +// Validate JWT header presence + if (jwtFromHeader == null || jwtFromHeader.trim().isEmpty()) { + response.put("statusCode", 401); + response.put("status", "Unauthorized"); + response.put("errorMessage", "JWT token is missing"); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response); + } + + // Extract and validate user ID from JWT + int userId = jwtUtil.extractUserId(jwtFromHeader); // Make sure this returns 0 or throws for invalid token + + if (userId == 0) { + response.put("statusCode", 401); + response.put("status", "Unauthorized"); + response.put("errorMessage", "Invalid JWT token"); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response); + } - AshaWorker ashaWorker = ashaProfileService.getProfileData(employeeId); - logger.info("Asha Profile" + ashaWorker); + // Business logic + AshaWorker ashaWorker = ashaProfileService.getProfileData(userId); + logger.info("Asha Profile"+ashaWorker); response.put("statusCode", 200); response.put("status", "Success"); diff --git a/src/main/java/com/iemr/flw/controller/AshaSupervisorIncentiveApproval.java b/src/main/java/com/iemr/flw/controller/AshaSupervisorIncentiveApproval.java index 3f840f614..3905d2e6f 100644 --- a/src/main/java/com/iemr/flw/controller/AshaSupervisorIncentiveApproval.java +++ b/src/main/java/com/iemr/flw/controller/AshaSupervisorIncentiveApproval.java @@ -37,6 +37,7 @@ public ResponseEntity getAshaListByFacility( @RequestHeader(value = "JwtToken") String token) { try { + logger.info("getAshaListByFacility request{}",request.getFacilityId()); if (token == null) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("UNAUTHORIZED"); @@ -65,16 +66,34 @@ public ResponseEntity getAshaListByFacility( } + @Operation(summary = "Get comprehensive ASHA Supervisor dashboard with facilities, ASHAs, villages and incentive data") + @PostMapping("/getSubCenter") + public String getSupervisorSubCenter(@RequestBody AshaByFacilityRequestDTO request,@RequestHeader(value = "JwtToken") String token ) { + OutputResponse response = new OutputResponse(); + logger.info("dashboard request{}",request.getFacilityId()); + + try { + if(token!=null){ + String result = supervisorDashboardService.getSupervisorSubCenter(jwtUtil.extractUserId(token),request.getMonth(),request.getYear()); + response.setResponse(result); + } + } catch (Exception e) { + logger.error("getSupervisorDashboard failed: " + e.getMessage(), e); + response.setError(e); + } + return response.toString(); + } @Operation(summary = "Get comprehensive ASHA Supervisor dashboard with facilities, ASHAs, villages and incentive data") @PostMapping("/dashboard") public String getSupervisorDashboard(@RequestBody AshaByFacilityRequestDTO request,@RequestHeader(value = "JwtToken") String token ) { OutputResponse response = new OutputResponse(); + logger.info("dashboard request{}",request.getFacilityId()); try { if(token!=null){ - String result = supervisorDashboardService.getSupervisorDashboard(jwtUtil.extractUserId(token),request.getMonth(),request.getYear()); + String result = supervisorDashboardService.getSupervisorDashboard(jwtUtil.extractUserId(token),request.getMonth(),request.getYear(),request.getFacilityId()); response.setResponse(result); } diff --git a/src/main/java/com/iemr/flw/controller/IncentiveController.java b/src/main/java/com/iemr/flw/controller/IncentiveController.java index fe1d93ac2..32a5c16fa 100644 --- a/src/main/java/com/iemr/flw/controller/IncentiveController.java +++ b/src/main/java/com/iemr/flw/controller/IncentiveController.java @@ -112,14 +112,15 @@ public String getAllIncentivesByUserId(@RequestBody GetBenRequestHandler request @Operation(summary = "get high risk assessment data of all beneficiaries registered with given user id") @RequestMapping(value = {"/claimedIncentiveByUser"}, method = {RequestMethod.POST}) public String getAllIncentivesByUserIdGroupByCount(@RequestBody GetBenRequestHandler requestDTO, - @RequestHeader(value = "Authorization") String Authorization) { + @RequestHeader(value = "jwtToken") String jwtToken) { OutputResponse response = new OutputResponse(); try { if (requestDTO != null) { + Integer userId= jwtUtil.extractUserId(jwtToken); logger.info("request object with timestamp : " + new Timestamp(System.currentTimeMillis()) + " " + requestDTO); - String s = incentiveService.getAllIncentivesGroupedSummary(requestDTO); + String s = incentiveService.getAllIncentivesGroupedSummary(requestDTO,userId); logger.info("User Incentive:" + s); if (s != null) response.setResponse(s); @@ -199,7 +200,7 @@ public ResponseEntity updateApprovalStatus( request.getMonth(), request.getYear(), request.isClaimed(), - token + token,request.getIncentiveId() ); Map response = new HashMap<>(); diff --git a/src/main/java/com/iemr/flw/controller/MaternalHealthController.java b/src/main/java/com/iemr/flw/controller/MaternalHealthController.java index 9c8459daa..2e58d76ae 100644 --- a/src/main/java/com/iemr/flw/controller/MaternalHealthController.java +++ b/src/main/java/com/iemr/flw/controller/MaternalHealthController.java @@ -182,6 +182,7 @@ public ResponseEntity>> get logger.info("Request: " + requestDTO); List result = maternalHealthService.getANCCounselling(requestDTO); + logger.info("ANC Counselling result: {}", new Gson().toJson(result)); response.setStatusCode(200); response.setStatus("Success"); diff --git a/src/main/java/com/iemr/flw/controller/NotificationController.java b/src/main/java/com/iemr/flw/controller/NotificationController.java new file mode 100644 index 000000000..54d0443e4 --- /dev/null +++ b/src/main/java/com/iemr/flw/controller/NotificationController.java @@ -0,0 +1,160 @@ +package com.iemr.flw.controller; + +import com.iemr.flw.dto.iemr.NotificationListDTO; +import com.iemr.flw.dto.iemr.SendNotificationRequestDTO; +import com.iemr.flw.service.NotificationService; +import com.iemr.flw.utils.JwtUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/notification") +public class NotificationController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); + @Autowired + private JwtUtil jwtUtil; + + @Autowired + private NotificationService notificationService; + + /** GET /notifications/{receiverUserId}?page=0&size=20 */ + @PostMapping("/list") + public Map listNotifications(@RequestHeader(value = "JwtToken") String token) { + Map response = new HashMap<>(); + try { + Integer receiverUserId = jwtUtil.extractUserId(token); + if (receiverUserId != null) { + NotificationListDTO notificationListDTO = + notificationService.getNotifications(receiverUserId); + + if (notificationListDTO != null) { + response.put("statusCode", 200); + response.put("data", notificationListDTO); + } else { + response.put("statusCode", 5000); + response.put("error", "Invalid/NULL request obj"); + } + } else { + response.put("statusCode", 5000); + response.put("error", "Invalid/NULL request obj"); + } + } catch (Exception e) { + logger.error("Error in get data : " + e); + response.put("statusCode", 5000); + response.put("error", "Error in get data : " + e); + } + return response; + } + + /** GET /notifications/{receiverUserId}/unread-count */ + @GetMapping("/{receiverUserId}/unread-count") + public Map unreadCount(@PathVariable Integer receiverUserId) { + Map response = new HashMap<>(); + try { + + if (receiverUserId != null) { + Long unreadCount = notificationService.getUnreadCount(receiverUserId); + + if (unreadCount != null) { + response.put("statusCode", 200); + response.put("data", unreadCount); + } else { + response.put("statusCode", 5000); + response.put("error", "Invalid/NULL request obj"); + } + } else { + response.put("statusCode", 5000); + response.put("error", "Invalid/NULL request obj"); + } + } catch (Exception e) { + logger.error("Error in get data : " + e); + response.put("statusCode", 5000); + response.put("error", "Error in get data : " + e); + } + return response; + } + + /** PUT /notifications/{notificationId}/read */ + @PutMapping("/{notificationId}/read") + public Map markAsRead(@PathVariable Long notificationId) { + Map response = new HashMap<>(); + try { + if (notificationId != null) { + boolean success = notificationService.markAsRead(notificationId); + + response.put("statusCode", 200); + response.put("data", success); + } else { + response.put("statusCode", 5000); + response.put("error", "Invalid/NULL request obj"); + } + } catch (Exception e) { + logger.error("Error in update data : " + e); + response.put("statusCode", 5000); + response.put("error", "Error in update data : " + e); + } + return response; + } + + /** POST /notifications/send */ + @PostMapping("/send") + public Map sendNotification(@RequestBody SendNotificationRequestDTO request) { + Map response = new HashMap<>(); + try { + if (request != null) { + String result = notificationService.sendNotification( + request.getAppType(), + request.getTopic(), + request.getTitle(), + request.getBody(), + request.getRedirect(), + request.getNotificationType(), + request.getReceiverId()); + + if (result != null) { + response.put("statusCode", 200); + response.put("data", result); + } else { + response.put("statusCode", 5000); + response.put("error", "Invalid/NULL request obj"); + } + } else { + response.put("statusCode", 5000); + response.put("error", "Invalid/NULL request obj"); + } + } catch (Exception e) { + logger.error("Error in send notification : " + e); + response.put("statusCode", 5000); + response.put("error", "Error in send notification : " + e); + } + return response; + } + + /** PUT /notifications/{receiverUserId}/read-all */ + @PutMapping("/{receiverUserId}/read-all") + public Map markAllAsRead(@PathVariable Integer receiverUserId) { + Map response = new HashMap<>(); + try { + if (receiverUserId != null) { + int updatedCount = notificationService.markAllAsRead(receiverUserId); + + response.put("statusCode", 200); + response.put("data", updatedCount); + } else { + response.put("statusCode", 5000); + response.put("error", "Invalid/NULL request obj"); + } + } catch (Exception e) { + logger.error("Error in update data : " + e); + response.put("statusCode", 5000); + response.put("error", "Error in update data : " + e); + } + return response; + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/flw/domain/iemr/AncCounsellingCare.java b/src/main/java/com/iemr/flw/domain/iemr/AncCounsellingCare.java index 46737f12a..18a3f7ad4 100644 --- a/src/main/java/com/iemr/flw/domain/iemr/AncCounsellingCare.java +++ b/src/main/java/com/iemr/flw/domain/iemr/AncCounsellingCare.java @@ -13,6 +13,7 @@ public class AncCounsellingCare { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") private Long id; @Column(name = "beneficiary_id", nullable = false) @@ -25,7 +26,7 @@ public class AncCounsellingCare { private LocalDate homeVisitDate; @Column(name = "anc_visit_id", nullable = false) - private Long ancVisitId; + private Long ancVisitId=0L; @Column(name = "user_id") private Integer userId; @@ -107,6 +108,7 @@ public class AncCounsellingCare { @Column(name = "prolonged_labor") private Boolean prolongedLabor = false; + @Column(name = "malpresentation") private Boolean malpresentation = false; diff --git a/src/main/java/com/iemr/flw/domain/iemr/HbncVisit.java b/src/main/java/com/iemr/flw/domain/iemr/HbncVisit.java index 1513c0888..fa35c41e3 100644 --- a/src/main/java/com/iemr/flw/domain/iemr/HbncVisit.java +++ b/src/main/java/com/iemr/flw/domain/iemr/HbncVisit.java @@ -107,4 +107,7 @@ public class HbncVisit { @Column(name = "baby_eyes_swollen") private Boolean babyEyesSwollen; + @Column(name = "is_admitted_in_sncu") + private Boolean is_admitted_in_sncu; + }; diff --git a/src/main/java/com/iemr/flw/domain/iemr/IncentiveActivity.java b/src/main/java/com/iemr/flw/domain/iemr/IncentiveActivity.java index 016f6271d..6402d9208 100644 --- a/src/main/java/com/iemr/flw/domain/iemr/IncentiveActivity.java +++ b/src/main/java/com/iemr/flw/domain/iemr/IncentiveActivity.java @@ -57,9 +57,15 @@ public class IncentiveActivity { @Column(name = "is_deleted") private Boolean isDeleted; - @Column(name = "state_activity_code") private Integer stateActivityCode; + @Column(name = "is_default_activity") + private Boolean isDefaultActivity; + + @Column(name = "group_category_name") + private String groupCategoryName; + + } diff --git a/src/main/java/com/iemr/flw/domain/iemr/IncentiveActivityRecord.java b/src/main/java/com/iemr/flw/domain/iemr/IncentiveActivityRecord.java index b6d193e63..4a84055f0 100644 --- a/src/main/java/com/iemr/flw/domain/iemr/IncentiveActivityRecord.java +++ b/src/main/java/com/iemr/flw/domain/iemr/IncentiveActivityRecord.java @@ -87,4 +87,17 @@ public class IncentiveActivityRecord { @Transient private String groupName; + + @Transient String groupCategoryName; + + @Column(name = "is_approved") + private Boolean isApproved = false; + + @PrePersist + @PreUpdate + private void applyDefaults() { + if (isApproved == null) { + isApproved = false; + } + } } diff --git a/src/main/java/com/iemr/flw/domain/iemr/InfantRegister.java b/src/main/java/com/iemr/flw/domain/iemr/InfantRegister.java index 7a22516fa..aee846efc 100644 --- a/src/main/java/com/iemr/flw/domain/iemr/InfantRegister.java +++ b/src/main/java/com/iemr/flw/domain/iemr/InfantRegister.java @@ -100,4 +100,7 @@ public class InfantRegister { @Column(name = "is_sncu") private String isSNCU; + + @Column(name = "is_Referred_higher_facility") + private Boolean isReferredHigherFacility; } diff --git a/src/main/java/com/iemr/flw/domain/iemr/Notification.java b/src/main/java/com/iemr/flw/domain/iemr/Notification.java new file mode 100644 index 000000000..b2f4ba718 --- /dev/null +++ b/src/main/java/com/iemr/flw/domain/iemr/Notification.java @@ -0,0 +1,67 @@ +package com.iemr.flw.domain.iemr; + +import jakarta.persistence.*; +import lombok.Data; + +import java.util.Date; + +/** + * Persisted record of a notification that was sent (or attempted) to a user. + * Backs the "notification list with unread count" feature. + */ +@Data +@Entity +@Table(name = "notification") +public class Notification { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + @Column(name = "app_type") + private String appType; + + @Column(name = "sender_user_id") + private Integer senderUserId; + + @Column(name = "receiver_user_id", nullable = false) + private Integer receiverUserId; + + @Column(name = "title") + private String title; + + @Column(name = "body") + private String body; + + @Column(name = "notification_type") + private String notificationType; + + @Column(name = "nav_id") + private String navId; + + @Column(name = "redirect") + private String redirect; + + @Column(name = "priority") + private String priority; + + @Column(name = "is_read", nullable = false) + private boolean isRead = false; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "created_date", nullable = false, updatable = false) + private Date createdDate; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "read_date") + private Date readDate; + + @PrePersist + protected void onCreate() { + this.createdDate = new Date(); + if (!isRead) { + this.readDate = null; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/flw/domain/iemr/UserFcmTokenData.java b/src/main/java/com/iemr/flw/domain/iemr/UserFcmTokenData.java new file mode 100644 index 000000000..dd56c5b28 --- /dev/null +++ b/src/main/java/com/iemr/flw/domain/iemr/UserFcmTokenData.java @@ -0,0 +1,23 @@ +package com.iemr.flw.domain.iemr; + +import jakarta.persistence.*; +import lombok.Data; + +import java.sql.Timestamp; + +import static jakarta.persistence.GenerationType.IDENTITY; + +@Entity +@Table(name = "user_fcm_tokens", schema = "db_iemr") +@Data +public class UserFcmTokenData { + @Id + @GeneratedValue(strategy = IDENTITY) + private int id; + @Column(name = "user_id") + private Integer userId; + @Column(name = "token") + private String token; + @Column(name = "updated_at") + private Timestamp updatedAt; +} diff --git a/src/main/java/com/iemr/flw/dto/PaymentResponse.java b/src/main/java/com/iemr/flw/dto/PaymentResponse.java new file mode 100644 index 000000000..c9fcd2b0e --- /dev/null +++ b/src/main/java/com/iemr/flw/dto/PaymentResponse.java @@ -0,0 +1,15 @@ +package com.iemr.flw.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class PaymentResponse { + + @JsonProperty("submission_id") + private String submissionId; + + private String status; + + private String receipt; +} \ No newline at end of file diff --git a/src/main/java/com/iemr/flw/dto/identity/GetBenRequestHandler.java b/src/main/java/com/iemr/flw/dto/identity/GetBenRequestHandler.java index 94bfed1c1..957d8a86d 100644 --- a/src/main/java/com/iemr/flw/dto/identity/GetBenRequestHandler.java +++ b/src/main/java/com/iemr/flw/dto/identity/GetBenRequestHandler.java @@ -4,6 +4,7 @@ public class GetBenRequestHandler { private Integer villageID; + private Integer approvalStatus; private Timestamp fromDate; private Timestamp toDate; private Integer pageNo; @@ -112,4 +113,11 @@ public void setToDate(Timestamp toDate) { this.toDate = toDate; } + public Integer getApprovalStatus() { + return approvalStatus; + } + + public void setApprovalStatus(Integer approvalStatus) { + this.approvalStatus = approvalStatus; + } } diff --git a/src/main/java/com/iemr/flw/dto/iemr/AncCounsellingCareDTO.java b/src/main/java/com/iemr/flw/dto/iemr/AncCounsellingCareDTO.java index 76aff81da..b71086e0a 100644 --- a/src/main/java/com/iemr/flw/dto/iemr/AncCounsellingCareDTO.java +++ b/src/main/java/com/iemr/flw/dto/iemr/AncCounsellingCareDTO.java @@ -5,6 +5,7 @@ @Data public class AncCounsellingCareDTO { private String formId; + private Long id ; private Long beneficiaryId; private String visitDate; private AncCounsellingCareListDTO fields; diff --git a/src/main/java/com/iemr/flw/dto/iemr/AncCounsellingCareListDTO.java b/src/main/java/com/iemr/flw/dto/iemr/AncCounsellingCareListDTO.java index 981e34e2b..984425149 100644 --- a/src/main/java/com/iemr/flw/dto/iemr/AncCounsellingCareListDTO.java +++ b/src/main/java/com/iemr/flw/dto/iemr/AncCounsellingCareListDTO.java @@ -76,4 +76,5 @@ public class AncCounsellingCareListDTO { private String malpresentation; + } diff --git a/src/main/java/com/iemr/flw/dto/iemr/AncCounsellingCareResponseDTO.java b/src/main/java/com/iemr/flw/dto/iemr/AncCounsellingCareResponseDTO.java index 2e0195582..8c8f0fb86 100644 --- a/src/main/java/com/iemr/flw/dto/iemr/AncCounsellingCareResponseDTO.java +++ b/src/main/java/com/iemr/flw/dto/iemr/AncCounsellingCareResponseDTO.java @@ -8,6 +8,7 @@ public class AncCounsellingCareResponseDTO { private String formId; private Long beneficiaryId; + private Long id; private String visitDate; private Map fields; // for dynamic form fields diff --git a/src/main/java/com/iemr/flw/dto/iemr/HbncVisitDTO.java b/src/main/java/com/iemr/flw/dto/iemr/HbncVisitDTO.java index 239e21c8f..d5cc8acf0 100644 --- a/src/main/java/com/iemr/flw/dto/iemr/HbncVisitDTO.java +++ b/src/main/java/com/iemr/flw/dto/iemr/HbncVisitDTO.java @@ -93,6 +93,9 @@ public class HbncVisitDTO { @Column(name = "baby_eyes_swollen") private Boolean babyEyesSwollen; + @Column(name = "is_admitted_in_sncu") + private Boolean is_admitted_in_sncu; + } diff --git a/src/main/java/com/iemr/flw/dto/iemr/HbycDTO.java b/src/main/java/com/iemr/flw/dto/iemr/HbycDTO.java index 172132e07..9a983b508 100644 --- a/src/main/java/com/iemr/flw/dto/iemr/HbycDTO.java +++ b/src/main/java/com/iemr/flw/dto/iemr/HbycDTO.java @@ -119,4 +119,6 @@ public class HbycDTO { + + } diff --git a/src/main/java/com/iemr/flw/dto/iemr/IncentiveActivityDTO.java b/src/main/java/com/iemr/flw/dto/iemr/IncentiveActivityDTO.java index 0ebf4aac6..7aa856463 100644 --- a/src/main/java/com/iemr/flw/dto/iemr/IncentiveActivityDTO.java +++ b/src/main/java/com/iemr/flw/dto/iemr/IncentiveActivityDTO.java @@ -25,6 +25,7 @@ public class IncentiveActivityDTO implements Serializable { private String group; private String groupName; + private String groupCategoryName; private String fmrCode; diff --git a/src/main/java/com/iemr/flw/dto/iemr/IncentiveRecordDTO.java b/src/main/java/com/iemr/flw/dto/iemr/IncentiveRecordDTO.java index 354e762d5..e2a6787c1 100644 --- a/src/main/java/com/iemr/flw/dto/iemr/IncentiveRecordDTO.java +++ b/src/main/java/com/iemr/flw/dto/iemr/IncentiveRecordDTO.java @@ -47,6 +47,8 @@ public class IncentiveRecordDTO { private String groupName; + private String groupCategoryName; + private String reason; private String otherReason; @@ -59,6 +61,7 @@ public class IncentiveRecordDTO { private String supervisorRole; + private Boolean isApproved; diff --git a/src/main/java/com/iemr/flw/dto/iemr/InfantRegisterDTO.java b/src/main/java/com/iemr/flw/dto/iemr/InfantRegisterDTO.java index 0be067ff8..d3cc280bf 100644 --- a/src/main/java/com/iemr/flw/dto/iemr/InfantRegisterDTO.java +++ b/src/main/java/com/iemr/flw/dto/iemr/InfantRegisterDTO.java @@ -37,4 +37,6 @@ public class InfantRegisterDTO { private String deliveryDischargeSummary3; private String deliveryDischargeSummary4; private String isSNCU; + private Boolean isReferredHigherFacility; + } diff --git a/src/main/java/com/iemr/flw/dto/iemr/NotificationDTO.java b/src/main/java/com/iemr/flw/dto/iemr/NotificationDTO.java new file mode 100644 index 000000000..b20dd7155 --- /dev/null +++ b/src/main/java/com/iemr/flw/dto/iemr/NotificationDTO.java @@ -0,0 +1,13 @@ +package com.iemr.flw.dto.iemr; + +import lombok.Data; + +import java.util.Map; + +@Data +public class NotificationDTO { + private String title; + private String body; + private String token; + private Map data; +} diff --git a/src/main/java/com/iemr/flw/dto/iemr/NotificationListDTO.java b/src/main/java/com/iemr/flw/dto/iemr/NotificationListDTO.java new file mode 100644 index 000000000..2e94be29f --- /dev/null +++ b/src/main/java/com/iemr/flw/dto/iemr/NotificationListDTO.java @@ -0,0 +1,24 @@ +package com.iemr.flw.dto.iemr; + +import com.iemr.flw.domain.iemr.Notification; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * Response payload for the "list notifications" endpoint. + * Bundles the page of notifications together with the receiver's + * total unread count so the client can update a badge in one call. + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class NotificationListDTO { + private List notifications; + private long unreadCount; + private long totalCount; + private int page; + private int size; +} \ No newline at end of file diff --git a/src/main/java/com/iemr/flw/dto/iemr/SendNotificationRequestDTO.java b/src/main/java/com/iemr/flw/dto/iemr/SendNotificationRequestDTO.java new file mode 100644 index 000000000..b1551ab3c --- /dev/null +++ b/src/main/java/com/iemr/flw/dto/iemr/SendNotificationRequestDTO.java @@ -0,0 +1,18 @@ +package com.iemr.flw.dto.iemr; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SendNotificationRequestDTO { + private String appType; + private String topic; + private String title; + private String body; + private String redirect; + private String notificationType; + private Integer receiverId; +} diff --git a/src/main/java/com/iemr/flw/dto/iemr/UpdateClaimedStatusRequestDTO.java b/src/main/java/com/iemr/flw/dto/iemr/UpdateClaimedStatusRequestDTO.java index 052b7d12f..556031b64 100644 --- a/src/main/java/com/iemr/flw/dto/iemr/UpdateClaimedStatusRequestDTO.java +++ b/src/main/java/com/iemr/flw/dto/iemr/UpdateClaimedStatusRequestDTO.java @@ -8,4 +8,5 @@ public class UpdateClaimedStatusRequestDTO { private Integer month; private Integer year; private boolean isClaimed; + private String incentiveId; } diff --git a/src/main/java/com/iemr/flw/dto/iemr/UserServiceRoleDTO.java b/src/main/java/com/iemr/flw/dto/iemr/UserServiceRoleDTO.java index c336e1c98..ead3ddc06 100644 --- a/src/main/java/com/iemr/flw/dto/iemr/UserServiceRoleDTO.java +++ b/src/main/java/com/iemr/flw/dto/iemr/UserServiceRoleDTO.java @@ -27,14 +27,6 @@ public class UserServiceRoleDTO { private String villageName; private Map facilityData; - // Stop TB / Nikshay location scope — populated only when serviceName = "Stop TB". - // Set via setters after construction (additive, not part of the base constructor - // so every other service line's DTO construction stays exactly as it is today). - private String tuId; - private String tuName; - private String healthFacilityId; - private String healthFacilityName; - public UserServiceRoleDTO(Integer userId, String name, String userName, Integer stateId, String stateName, Integer workingDistrictId, String workingDistrictName, Short serviceProviderId, Integer roleId, String roleName, Integer providerServiceMapId, Integer blockId, String blockName, String villageId, String villageName) { this.userId = userId; this.name = name; diff --git a/src/main/java/com/iemr/flw/masterEnum/IncentiveApprovalStatus.java b/src/main/java/com/iemr/flw/masterEnum/IncentiveApprovalStatus.java index e40ecc980..4149cab0f 100644 --- a/src/main/java/com/iemr/flw/masterEnum/IncentiveApprovalStatus.java +++ b/src/main/java/com/iemr/flw/masterEnum/IncentiveApprovalStatus.java @@ -5,7 +5,8 @@ public enum IncentiveApprovalStatus { VERIFIED(101, "Verified"), PENDING(102, "Pending"), REJECTED(103, "Rejected"), - OVERDUE(104, "Overdue"); + OVERDUE(104, "Overdue"), + APPROVED(105, "Approved"); private final int code; private final String label; diff --git a/src/main/java/com/iemr/flw/repo/identity/BeneficiaryRepo.java b/src/main/java/com/iemr/flw/repo/identity/BeneficiaryRepo.java index a6ee9700c..d37789d11 100644 --- a/src/main/java/com/iemr/flw/repo/identity/BeneficiaryRepo.java +++ b/src/main/java/com/iemr/flw/repo/identity/BeneficiaryRepo.java @@ -161,4 +161,9 @@ SELECT COUNT(*) @Query("SELECT t FROM RMNCHMBeneficiaryaddress t WHERE t.benAddressID IN :ids") List findAddressesByIds(@Param("ids") List ids); + + @Query("SELECT b.BenRegId, b.benficieryid " + + "FROM RMNCHBeneficiaryDetailsRmnch b " + + "WHERE b.BenRegId IN :regIds AND b.benficieryid IS NOT NULL") + List getBenIdsFromRegIds(@Param("regIds") List regIds); } diff --git a/src/main/java/com/iemr/flw/repo/iemr/AshaSupervisorLoginRepo.java b/src/main/java/com/iemr/flw/repo/iemr/AshaSupervisorLoginRepo.java index 78bb368bf..13b773717 100644 --- a/src/main/java/com/iemr/flw/repo/iemr/AshaSupervisorLoginRepo.java +++ b/src/main/java/com/iemr/flw/repo/iemr/AshaSupervisorLoginRepo.java @@ -55,6 +55,150 @@ List getAshasAtFacility( @Param("endDate") Timestamp endDate); +// @Query(value = "SELECT DISTINCT asm.ashaUserID, u.FirstName, u.LastName, " +// + "COALESCE(u.AgentID,'') AS agentID, " +// + "COALESCE(u.EmergencyContactNo,'') AS mobile, " +// + "COALESCE(g.GenderName,'') AS gender " +// + "FROM asha_supervisor_mapping asm " +// + "JOIN m_User u ON u.UserID = asm.ashaUserID " +// + "AND u.Deleted = false " +// + "LEFT JOIN m_gender g ON g.GenderID = u.GenderID " +// + "JOIN incentive_activity_record iar " +// + "ON iar.asha_id = asm.ashaUserID " +// + "WHERE asm.supervisorUserID = :supervisorUserID " +// + "AND asm.facilityID = :facilityID " +// + "AND asm.deleted = false " +// + "AND iar.is_claimed = true " +// + "AND iar.start_date >= :startDate " +// + "AND iar.end_date < :endDate " +// + "AND (" +// + " :approvalStatus = 0 " +// + " OR (:approvalStatus = 105 AND iar.approval_status IN (101,105)) " +// + " OR (:approvalStatus = 106 AND iar.approval_status = 102) " +// + " OR (:approvalStatus NOT IN (105,106) AND iar.approval_status = :approvalStatus)" +// + ")", +// nativeQuery = true) +// List getAshasAtFacilityCg( +// @Param("supervisorUserID") Integer supervisorUserID, +// @Param("facilityID") Integer facilityID, +// @Param("approvalStatus") Integer approvalStatus, +// @Param("startDate") Timestamp startDate, +// @Param("endDate") Timestamp endDate); + + + @Query(value = + "SELECT DISTINCT " + + "asm.ashaUserID, " + + "u.FirstName, " + + "u.LastName, " + + "COALESCE(u.AgentID, '') AS agentID, " + + "COALESCE(u.EmergencyContactNo, '') AS mobile, " + + "COALESCE(g.GenderName, '') AS gender " + + + "FROM asha_supervisor_mapping asm " + + + "JOIN m_User u " + + "ON u.UserID = asm.ashaUserID " + + "AND u.Deleted = false " + + + "LEFT JOIN m_gender g " + + "ON g.GenderID = u.GenderID " + + + "JOIN incentive_activity_record iar " + + "ON iar.asha_id = asm.ashaUserID " + + + "WHERE asm.supervisorUserID = :supervisorUserID " + + "AND asm.facilityID = :facilityID " + + "AND asm.deleted = false " + + "AND iar.is_default_activity = true " + + "AND iar.start_date >= :startDate " + + "AND iar.end_date < :endDate " + + + "AND (" + + " (:approvalStatus = 0) " + + + " OR (:approvalStatus = 104 " + + " AND iar.is_claimed = true " + + " AND iar.approval_status IN (102, 105)) " + + + " OR (:approvalStatus = 105 " + + " AND iar.is_claimed = true " + + " AND iar.approval_status IN (101, 105)) " + + + " OR (:approvalStatus = 106 " + + " AND iar.is_claimed = false " + + " AND iar.approval_status = 102) " + + + " OR (:approvalStatus NOT IN (104, 105, 106) " + + " AND iar.is_claimed = true " + + " AND iar.approval_status = :approvalStatus) " + + ")", + nativeQuery = true) + List getAshasAtFacilityCg( + @Param("supervisorUserID") Integer supervisorUserID, + @Param("facilityID") Integer facilityID, + @Param("approvalStatus") Integer approvalStatus, + @Param("startDate") Timestamp startDate, + @Param("endDate") Timestamp endDate + ); + + @Query(value = + "SELECT DISTINCT " + + "asm.ashaUserID, " + + "u.FirstName, " + + "u.LastName, " + + "COALESCE(u.AgentID, '') AS agentID, " + + "COALESCE(u.EmergencyContactNo, '') AS mobile, " + + "COALESCE(g.GenderName, '') AS gender " + + + "FROM asha_supervisor_mapping asm " + + + "JOIN m_User u " + + "ON u.UserID = asm.ashaUserID " + + "AND u.Deleted = false " + + + "LEFT JOIN m_gender g " + + "ON g.GenderID = u.GenderID " + + + "JOIN incentive_activity_record iar " + + "ON iar.asha_id = asm.ashaUserID " + + + "WHERE asm.supervisorUserID = :supervisorUserID " + + "AND asm.deleted = false " + + "AND iar.is_default_activity = true " + + "AND iar.start_date >= :startDate " + + "AND iar.end_date < :endDate " + + + "AND (" + + " (:approvalStatus = 0) " + + + // Overdue: database status 102 or 105 + " OR (:approvalStatus = 104 " + + " AND iar.is_claimed = true " + + " AND iar.approval_status IN (102, 105)) " + + + " OR (:approvalStatus = 105 " + + " AND iar.is_claimed = true " + + " AND iar.approval_status IN (101, 105)) " + + + " OR (:approvalStatus = 106 " + + " AND iar.is_claimed = false " + + " AND iar.approval_status = 102) " + + + " OR (:approvalStatus NOT IN (104, 105, 106) " + + " AND iar.is_claimed = true " + + " AND iar.approval_status = :approvalStatus) " + + ")", + nativeQuery = true) + List getAshasAtFacilityCg( + @Param("supervisorUserID") Integer supervisorUserID, + @Param("approvalStatus") Integer approvalStatus, + @Param("startDate") Timestamp startDate, + @Param("endDate") Timestamp endDate + ); + + + @Query(value = "SELECT DISTINCT asm.ashaUserID, " + "u.FirstName, " + "u.LastName, " diff --git a/src/main/java/com/iemr/flw/repo/iemr/IncentiveRecordRepo.java b/src/main/java/com/iemr/flw/repo/iemr/IncentiveRecordRepo.java index 8c21f0e9f..bc6587dea 100644 --- a/src/main/java/com/iemr/flw/repo/iemr/IncentiveRecordRepo.java +++ b/src/main/java/com/iemr/flw/repo/iemr/IncentiveRecordRepo.java @@ -71,7 +71,8 @@ IncentiveActivityRecord findRecordByActivityIdCreatedDateBenId( @Query("SELECT " + "SUM(CASE WHEN record.approvalStatus = 101 THEN 1 ELSE 0 END), " + "SUM(CASE WHEN record.approvalStatus = 102 THEN 1 ELSE 0 END), " + - "SUM(CASE WHEN record.approvalStatus = 103 THEN 1 ELSE 0 END) " + + "SUM(CASE WHEN record.approvalStatus = 103 THEN 1 ELSE 0 END), " + + "SUM(CASE WHEN record.approvalStatus = 105 THEN 1 ELSE 0 END) " + "FROM IncentiveActivityRecord record " + "WHERE record.ashaId = :ashaId " + "AND record.isClaimed = true " + @@ -83,6 +84,59 @@ List getStatusCountByAshaId( @Param("endDate") Timestamp endDate); + @Query("SELECT " + + "SUM(CASE WHEN record.approvalStatus = 101 THEN 1 ELSE 0 END), " + + "SUM(CASE WHEN record.approvalStatus = 102 THEN 1 ELSE 0 END), " + + "SUM(CASE WHEN record.approvalStatus = 103 THEN 1 ELSE 0 END), " + + "SUM(CASE WHEN record.approvalStatus IN (102,105) THEN 1 ELSE 0 END) " + + "FROM IncentiveActivityRecord record " + + "WHERE record.ashaId = :ashaId " + + "AND record.isClaimed = true " + + "AND record.createdDate >= :startDate " + + "AND record.createdDate < :endDate") + List getStatusCountByAshaIdANM( + @Param("ashaId") Integer ashaId, + @Param("startDate") Timestamp startDate, + @Param("endDate") Timestamp endDate); + + @Query(""" +SELECT + SUM(CASE WHEN record.approvalStatus = 101 THEN 1 ELSE 0 END), + SUM(CASE WHEN record.approvalStatus = 102 THEN 1 ELSE 0 END), + SUM(CASE WHEN record.approvalStatus = 103 THEN 1 ELSE 0 END), + SUM(CASE WHEN record.approvalStatus IN (101,105) THEN 1 ELSE 0 END) +FROM IncentiveActivityRecord record +WHERE record.ashaId = :ashaId +AND record.isClaimed = true +AND record.isDefaultActivity = true +AND record.createdDate >= :startDate +AND record.createdDate < :endDate +""") + List getStatusCountByAshaIdOfDefaultActivity( + @Param("ashaId") Integer ashaId, + @Param("startDate") Timestamp startDate, + @Param("endDate") Timestamp endDate); + + + @Query(""" +SELECT + SUM(CASE WHEN record.approvalStatus = 101 THEN 1 ELSE 0 END), + SUM(CASE WHEN record.approvalStatus = 102 THEN 1 ELSE 0 END), + SUM(CASE WHEN record.approvalStatus = 103 THEN 1 ELSE 0 END), + SUM(CASE WHEN record.approvalStatus IN (101,105) THEN 1 ELSE 0 END) +FROM IncentiveActivityRecord record +WHERE record.ashaId = :ashaId +AND record.isClaimed = false +AND record.createdDate >= :startDate +AND record.createdDate < :endDate +""") + List getStatusUnclaimedCountByAshaId( + @Param("ashaId") Integer ashaId, + @Param("startDate") Timestamp startDate, + @Param("endDate") Timestamp endDate); + + + @Query("SELECT COALESCE(SUM(record.amount), 0) " + "FROM IncentiveActivityRecord record " + "JOIN IncentiveActivity master ON record.activityId = master.id " + @@ -100,6 +154,99 @@ Long getTotalAmountByAsha( @Param("stateCode") Integer stateCode); + @Query(""" + SELECT COALESCE(SUM(record.amount), 0) + FROM IncentiveActivityRecord record + JOIN IncentiveActivity master ON record.activityId = master.id + WHERE record.ashaId = :ashaId + AND master.state = :stateCode + AND record.isClaimed = true + AND record.startDate >= :fromDate + AND record.endDate <= :toDate + AND ( + :approvalStatus = 0 + OR ( + :approvalStatus = 102 + AND record.approvalStatus IN (102, 105) + ) + OR ( + :approvalStatus <> 102 + AND record.approvalStatus = :approvalStatus + ) + ) +""") + Long getTotalAmountByAshaANM( + @Param("ashaId") Integer ashaId, + @Param("fromDate") Timestamp fromDate, + @Param("toDate") Timestamp toDate, + @Param("approvalStatus") Integer approvalStatus, + @Param("stateCode") Integer stateCode + ); + + @Query(""" + SELECT COALESCE(SUM(record.amount), 0) + FROM IncentiveActivityRecord record + JOIN IncentiveActivity master ON record.activityId = master.id + WHERE record.ashaId = :ashaId + AND master.state = :stateCode + AND record.isClaimed = true + AND record.isDefaultActivity = false + AND record.startDate >= :fromDate + AND record.endDate <= :toDate + AND ( + :approvalStatus = 0 + OR ( + :approvalStatus = 102 + AND record.approvalStatus IN (102, 105) + ) + OR ( + :approvalStatus <> 102 + AND record.approvalStatus = :approvalStatus + ) + ) +""") + Long getTotalAmountByAshaANMbeforeClaimedHour( + @Param("ashaId") Integer ashaId, + @Param("fromDate") Timestamp fromDate, + @Param("toDate") Timestamp toDate, + @Param("approvalStatus") Integer approvalStatus, + @Param("stateCode") Integer stateCode + ); + + @Query("SELECT COALESCE(SUM(record.amount), 0) " + + "FROM IncentiveActivityRecord record " + + "JOIN IncentiveActivity master ON record.activityId = master.id " + + "WHERE record.ashaId = :ashaId " + + "AND master.state = :stateCode " + + "AND record.isClaimed = true " + + "AND record.isDefaultActivity = true " + + "AND record.startDate >= :fromDate " + + "AND record.endDate <= :toDate " + + "AND (" + + " :approvalStatus = 0 " + + " OR (:approvalStatus = 101 AND record.approvalStatus IN (101,105)) " + + " OR (:approvalStatus <> 101 AND record.approvalStatus = :approvalStatus)" + + ")") + Long getDefaultActivityTotalAmountByAsha( + @Param("ashaId") Integer ashaId, + @Param("fromDate") Timestamp fromDate, + @Param("toDate") Timestamp toDate, + @Param("approvalStatus") Integer approvalStatus, + @Param("stateCode") Integer stateCode); + + + @Query("SELECT record " + + "FROM IncentiveActivityRecord record " + + "WHERE record.ashaId = :ashaId " + + "AND record.isClaimed = true " + + "AND record.startDate <= :toDate " + + "AND record.isDefaultActivity = true " + + "AND record.endDate >= :fromDate") + List getDefalutRecordsByAsha( + @Param("ashaId") Integer ashaId, + @Param("fromDate") Timestamp fromDate, + @Param("toDate") Timestamp toDate); + @Query("SELECT record " + "FROM IncentiveActivityRecord record " + "WHERE record.ashaId = :ashaId " + @@ -133,7 +280,148 @@ int updateApprovalStatusByAshaAndDateRange( @Param("ashaSupervisorUserId") Integer ashaSupervisorUserId, @Param("ashaSupervisorUserName") String ashaSupervisorUserName); + @Modifying + @Transactional + @Query("UPDATE IncentiveActivityRecord iar " + + "SET iar.approvalStatus = :approvalStatus, " + + "iar.verifiedByUserId = :ashaSupervisorUserId, " + + "iar.reason = NULL, " + + "iar.otherReason = NULL, " + + "iar.approvalDate = :approvalDate, " + + "iar.verifiedByUserName = :ashaSupervisorUserName " + + "WHERE iar.id = :incentiveId " + + "AND iar.ashaId = :ashaId " + + "AND iar.isClaimed = true") + int updateApprovalStatusByIncentiveId( + @Param("incentiveId") Long incentiveId, + @Param("ashaId") Integer ashaId, + @Param("approvalStatus") Integer approvalStatus, + @Param("approvalDate") Timestamp approvalDate, + @Param("ashaSupervisorUserId") Integer ashaSupervisorUserId, + @Param("ashaSupervisorUserName") String ashaSupervisorUserName); + + @Modifying + @Transactional + @Query(""" + UPDATE IncentiveActivityRecord iar + SET iar.approvalStatus = :approvalStatus, + iar.verifiedByUserId = :ashaSupervisorUserId, + iar.reason = NULL, + iar.otherReason = NULL, + iar.approvalDate = :approvalDate, + iar.verifiedByUserName = :ashaSupervisorUserName + WHERE iar.id IN :incentiveIds + AND iar.ashaId = :ashaId + AND iar.isClaimed = true + """) + int updateApprovalStatusByIncentiveIds( + @Param("incentiveIds") List incentiveIds, + @Param("ashaId") Integer ashaId, + @Param("approvalStatus") Integer approvalStatus, + @Param("approvalDate") Timestamp approvalDate, + @Param("ashaSupervisorUserId") Integer ashaSupervisorUserId, + @Param("ashaSupervisorUserName") String ashaSupervisorUserName + ); + + + @Modifying + @Transactional + @Query(""" +UPDATE IncentiveActivityRecord iar +SET + iar.approvalStatus = :approvalStatus, + iar.verifiedByUserId = :ashaSupervisorUserId, + iar.verifiedByUserName = :ashaSupervisorUserName, + iar.approvalDate = :approvalDate, + iar.reason = NULL, + iar.otherReason = NULL +WHERE iar.ashaId = :ashaId +AND iar.isClaimed = true +AND iar.createdDate >= :startDate +AND iar.createdDate < :endDate +""") + int updateApprovalStatusByAshaAndDateRangeForDefaultActivity( + @Param("ashaId") Integer ashaId, + @Param("approvalStatus") Integer approvalStatus, + @Param("startDate") Timestamp startDate, + @Param("endDate") Timestamp endDate, + @Param("approvalDate") Timestamp approvalDate, + @Param("ashaSupervisorUserId") Integer ashaSupervisorUserId, + @Param("ashaSupervisorUserName") String ashaSupervisorUserName + ); + + @Modifying + @Transactional + @Query(""" +UPDATE IncentiveActivityRecord iar +SET + iar.approvalStatus = :approvalStatus, + iar.verifiedByUserId = :ashaSupervisorUserId, + iar.verifiedByUserName = :ashaSupervisorUserName, + iar.approvalDate = :approvalDate, + iar.reason = NULL, + iar.otherReason = NULL +WHERE iar.id = :incentiveId +AND iar.ashaId = :ashaId +AND iar.isClaimed = true +""") + int updateApprovalStatusByIncentiveIdForDefaultActivity( + @Param("incentiveId") Long incentiveId, + @Param("ashaId") Integer ashaId, + @Param("approvalStatus") Integer approvalStatus, + @Param("approvalDate") Timestamp approvalDate, + @Param("ashaSupervisorUserId") Integer ashaSupervisorUserId, + @Param("ashaSupervisorUserName") String ashaSupervisorUserName + ); + + @Modifying + @Transactional + @Query(""" + UPDATE IncentiveActivityRecord iar + SET iar.approvalStatus = :approvalStatus, + iar.verifiedByUserId = :ashaSupervisorUserId, + iar.verifiedByUserName = :ashaSupervisorUserName, + iar.approvalDate = :approvalDate, + iar.reason = NULL, + iar.otherReason = NULL + WHERE iar.id IN :incentiveIds + AND iar.ashaId = :ashaId + AND iar.isClaimed = true + AND iar.isDefaultActivity = true + """) + int updateApprovalStatusByIncentiveIdsForDefaultActivity( + @Param("incentiveIds") List incentiveIds, + @Param("ashaId") Integer ashaId, + @Param("approvalStatus") Integer approvalStatus, + @Param("approvalDate") Timestamp approvalDate, + @Param("ashaSupervisorUserId") Integer ashaSupervisorUserId, + @Param("ashaSupervisorUserName") String ashaSupervisorUserName + ); + + + @Modifying + @Transactional + @Query(""" + UPDATE IncentiveActivityRecord iar + SET iar.approvalStatus = :approvalStatus, + iar.verifiedByUserId = :ashaSupervisorUserId, + iar.verifiedByUserName = :ashaSupervisorUserName, + iar.approvalDate = :approvalDate, + iar.reason = NULL, + iar.otherReason = NULL + WHERE iar.id IN :incentiveIds + AND iar.ashaId = :ashaId + AND iar.isClaimed = true + """) + int updateApprovalStatusByIncentiveIdsForDefaultActivityForAnm( + @Param("incentiveIds") List incentiveIds, + @Param("ashaId") Integer ashaId, + @Param("approvalStatus") Integer approvalStatus, + @Param("approvalDate") Timestamp approvalDate, + @Param("ashaSupervisorUserId") Integer ashaSupervisorUserId, + @Param("ashaSupervisorUserName") String ashaSupervisorUserName + ); @Modifying @Transactional @Query("UPDATE IncentiveActivityRecord iar " @@ -143,9 +431,11 @@ int updateApprovalStatusByAshaAndDateRange( + "iar.otherReason = :otherReason, " + "iar.approvalDate = :approvalDate, " + "iar.verifiedByUserName = :ashaSupervisorUserName " - + "WHERE iar.isClaimed = true") + + "WHERE iar.isClaimed = true " + + "AND iar.ashaId = :ashaId") int updateApprovalStatusById( @Param("status") Integer status, + @Param("ashaId") Integer ashaId, @Param("ashaSupervisorUserId") Integer ashaSupervisorUserId, @Param("ashaSupervisorUserName") String ashaSupervisorUserName, @Param("reason") String reason, @@ -153,6 +443,55 @@ int updateApprovalStatusById( @Param("otherReason") String otherReason ); + @Modifying + @Transactional + @Query("UPDATE IncentiveActivityRecord iar " + + "SET iar.approvalStatus = :status, " + + "iar.verifiedByUserId = :ashaSupervisorUserId, " + + "iar.reason = :reason, " + + "iar.otherReason = :otherReason, " + + "iar.approvalDate = :approvalDate, " + + "iar.verifiedByUserName = :ashaSupervisorUserName " + + "WHERE iar.isClaimed = true " + + "AND iar.id = :incentiveId " + + "AND iar.ashaId = :ashaId") + int updateApprovalStatusByIdAndIncentiveId( + @Param("status") Integer status, + @Param("ashaId") Integer ashaId, + @Param("ashaSupervisorUserId") Integer ashaSupervisorUserId, + @Param("ashaSupervisorUserName") String ashaSupervisorUserName, + @Param("reason") String reason, + @Param("approvalDate") Timestamp approvalDate, + @Param("otherReason") String otherReason, + @Param("incentiveId") Long incentiveId + ); + + + @Modifying + @Transactional + @Query(""" + UPDATE IncentiveActivityRecord iar + SET iar.approvalStatus = :status, + iar.verifiedByUserId = :ashaSupervisorUserId, + iar.verifiedByUserName = :ashaSupervisorUserName, + iar.reason = :reason, + iar.otherReason = :otherReason, + iar.approvalDate = :approvalDate + WHERE iar.id IN :incentiveIds + AND iar.ashaId = :ashaId + AND iar.isClaimed = true + """) + int updateApprovalStatusByIdsAndIncentiveIds( + @Param("status") Integer status, + @Param("ashaId") Integer ashaId, + @Param("ashaSupervisorUserId") Integer ashaSupervisorUserId, + @Param("ashaSupervisorUserName") String ashaSupervisorUserName, + @Param("reason") String reason, + @Param("approvalDate") Timestamp approvalDate, + @Param("otherReason") String otherReason, + @Param("incentiveIds") List incentiveIds + ); + @Modifying @Transactional @Query("UPDATE IncentiveActivityRecord iar " @@ -211,4 +550,42 @@ List getRecordsBySuperVisor( @Param("startDate") Timestamp startDate, @Param("endDate") Timestamp endDate, @Param("approvalStatus") Integer approvalStatus); + @Modifying + @Transactional + @Query("UPDATE IncentiveActivityRecord iar " + + "SET iar.isClaimed = :isClaimed, " + + "iar.calimedDate = :calimedDate, " + + "iar.approvalStatus = 102 " + + "WHERE iar.ashaId = :ashaId " + + "AND iar.id = :incentiveId ") + int updateClaimStatusByAshaAndIncentiveIds( + @Param("ashaId") Integer ashaId, + @Param("isClaimed") Boolean isClaimed, + @Param("calimedDate") Timestamp calimedDate, + @Param("incentiveId") Long incentiveId + ); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Transactional + @Query(""" + UPDATE IncentiveActivityRecord iar + SET iar.approvalStatus = 102, + iar.isClaimed = false, + iar.calimedDate = NULL, + iar.approvalDate = NULL, + iar.reason = NULL, + iar.otherReason = NULL, + iar.verifiedByUserId = NULL, + iar.verifiedByUserName = NULL, + iar.updatedDate = :updatedDate, + iar.updatedBy = :updatedBy + WHERE iar.approvalStatus = 103 + AND iar.isClaimed = true + AND iar.endDate < :currentMonthStart +""") + int resetRejectedIncentivesForNewMonth( + @Param("currentMonthStart") Timestamp currentMonthStart, + @Param("updatedDate") Timestamp updatedDate, + @Param("updatedBy") String updatedBy + ); } diff --git a/src/main/java/com/iemr/flw/repo/iemr/NotificationRepository.java b/src/main/java/com/iemr/flw/repo/iemr/NotificationRepository.java new file mode 100644 index 000000000..c269c97c7 --- /dev/null +++ b/src/main/java/com/iemr/flw/repo/iemr/NotificationRepository.java @@ -0,0 +1,35 @@ +package com.iemr.flw.repo.iemr; + +import com.iemr.flw.domain.iemr.Notification; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; + +public interface NotificationRepository extends JpaRepository { + + /** Paged list for a receiver, newest first. */ + Page findByReceiverUserIdOrderByCreatedDateDesc(Integer receiverUserId, Pageable pageable); + + /** Cheap count for badge display. */ + long countByReceiverUserIdAndIsReadFalse(Integer receiverUserId); + + /** Mark a single notification as read. */ + @Modifying + @Transactional + @Query("UPDATE Notification n SET n.isRead = true, n.readDate = :readDate " + + "WHERE n.id = :id") + int markAsRead(@Param("id") Long id, @Param("readDate") Date readDate); + + /** Mark every unread notification for a user as read. */ + @Modifying + @Transactional + @Query("UPDATE Notification n SET n.isRead = true, n.readDate = :readDate " + + "WHERE n.receiverUserId = :receiverUserId AND n.isRead = false") + int markAllAsRead(@Param("receiverUserId") Integer receiverUserId, @Param("readDate") Date readDate); +} \ No newline at end of file diff --git a/src/main/java/com/iemr/flw/repo/iemr/SupervisorDashboardRepo.java b/src/main/java/com/iemr/flw/repo/iemr/SupervisorDashboardRepo.java index a56587776..c947d1449 100644 --- a/src/main/java/com/iemr/flw/repo/iemr/SupervisorDashboardRepo.java +++ b/src/main/java/com/iemr/flw/repo/iemr/SupervisorDashboardRepo.java @@ -20,35 +20,96 @@ public interface SupervisorDashboardRepo extends JpaRepository getAshaIdsBySupervisor(@Param("supervisorUserID") Integer supervisorUserID); + @Query(value = "SELECT DISTINCT usrm.FacilityID " + + "FROM m_UserServiceRoleMapping usrm " + + "WHERE usrm.UserID = :userID AND usrm.Deleted = false " + + "AND usrm.FacilityID IS NOT NULL", nativeQuery = true) + List getUserFacilityIDs(@Param("userID") Integer userID); + // Get ASHAs with facility info for a supervisor - @Query(value = "SELECT DISTINCT asm.ashaUserID, u.FirstName, u.LastName, " + @Query(value = "SELECT DISTINCT u.UserID, u.FirstName, u.LastName, " + + "COALESCE(u.EmployeeID,'') AS employeeID, " + "f.FacilityID, f.FacilityName, " + "COALESCE(ft.FacilityTypeName,'') AS facilityTypeName, " - + "COALESCE(u.AgentID,'') AS agentID, " - + "COALESCE(u.EmergencyContactNo,'') AS mobile, " - + "COALESCE(g.GenderName,'') AS gender " + + "COALESCE(u.ContactNo,'') AS mobile " + "FROM asha_supervisor_mapping asm " - + "JOIN m_User u ON u.UserID = asm.ashaUserID AND u.Deleted = false " - + "JOIN m_facility f ON f.FacilityID = asm.facilityID AND f.Deleted = false " + + "JOIN m_User u ON u.UserID = asm.ashaUserID " + + "JOIN m_facility f ON f.FacilityID = asm.facilityID " + "LEFT JOIN m_facilitytype ft ON ft.FacilityTypeID = f.FacilityTypeID " - + "LEFT JOIN m_gender g ON g.GenderID = u.GenderID " + "WHERE asm.supervisorUserID = :supervisorUserID " - + "AND asm.deleted = false", nativeQuery = true) + + "AND asm.deleted = false AND u.Deleted = false AND f.Deleted = false", nativeQuery = true) List getAshasWithFacilityInfo(@Param("supervisorUserID") Integer supervisorUserID); + + @Query(value = "SELECT DISTINCT u.UserID, u.FirstName, u.LastName, " + + "COALESCE(u.EmployeeID,'') AS employeeID, " + + "f.FacilityID, f.FacilityName, " + + "COALESCE(ft.FacilityTypeName,'') AS facilityTypeName, " + + "COALESCE(u.ContactNo,'') AS mobile " + + "FROM m_UserServiceRoleMapping usrm " + + "JOIN m_User u ON u.UserID = usrm.UserID " + + "JOIN m_Role r ON r.RoleID = usrm.RoleID " + + "JOIN m_facility f ON f.FacilityID = usrm.FacilityID " + + "LEFT JOIN m_facilitytype ft ON ft.FacilityTypeID = f.FacilityTypeID " + + "WHERE usrm.FacilityID IN :facilityIDs " + + "AND r.RoleName = 'ASHA' " + + "AND usrm.Deleted = false AND u.Deleted = false AND f.Deleted = false", nativeQuery = true) + List getAshaListByFacilities(@Param("facilityIDs") List facilityIDs); + + @Query(value = """ + SELECT asm.supervisorUserID + FROM asha_supervisor_mapping asm + WHERE asm.ashaUserID = :ashaUserID + AND asm.deleted = false + LIMIT 1 + """, nativeQuery = true) + Integer getSupervisorUserIdByAshaId(@Param("ashaUserID") Integer ashaUserID); + // Unclaimed incentive count per ASHA + @Query(value = "SELECT iar.asha_id, " + "COUNT(*) AS unclaimedCount " + "FROM incentive_activity_record iar " + "WHERE iar.asha_id IN (:ashaIds) " + "AND iar.created_date >= :startDate " + "AND iar.created_date < :endDate " + + "AND iar.approval_status = 102 " + + "AND iar.is_default_activity = true " + + "AND (iar.is_claimed = false OR iar.is_claimed IS NULL) " + + "GROUP BY iar.asha_id", + nativeQuery = true) + List getDefaultUnclaimedCountByAshaIds( + @Param("ashaIds") List ashaIds, + @Param("startDate") Timestamp startDate, + @Param("endDate") Timestamp endDate + ); + @Query(value = "SELECT iar.asha_id, " + + "COUNT(*) AS unclaimedCount " + + "FROM incentive_activity_record iar " + + "WHERE iar.asha_id IN (:ashaIds) " + + "AND iar.created_date >= :startDate " + + "AND iar.created_date < :endDate " + + "AND iar.approval_status = 102 " + "AND (iar.is_claimed = false OR iar.is_claimed IS NULL) " + "GROUP BY iar.asha_id", nativeQuery = true) List getUnclaimedCountByAshaIds( @Param("ashaIds") List ashaIds, @Param("startDate") Timestamp startDate, + @Param("endDate") Timestamp endDate + ); + + + @Query(value = "SELECT COUNT(*) " + + "FROM incentive_activity_record iar " + + "WHERE iar.asha_id = :ashaId " + + "AND iar.created_date >= :startDate " + + "AND iar.created_date < :endDate " + + "AND (iar.is_claimed = false OR iar.is_claimed IS NULL)", + nativeQuery = true) + Long getUnclaimedCountByAshaId( + @Param("ashaId") Integer ashaId, + @Param("startDate") Timestamp startDate, @Param("endDate") Timestamp endDate); // Get facility details with geo names @@ -78,7 +139,8 @@ List getUnclaimedCountByAshaIds( + "COUNT(*) AS totalRecords, " + "SUM(CASE WHEN iar.approval_status = 101 THEN 1 ELSE 0 END) AS verified, " + "SUM(CASE WHEN iar.approval_status = 103 THEN 1 ELSE 0 END) AS rejected, " - + "SUM(CASE WHEN iar.approval_status = 102 THEN 1 ELSE 0 END) AS pending " + + "SUM(CASE WHEN iar.approval_status = 102 THEN 1 ELSE 0 END) AS pending, " + + "SUM(CASE WHEN iar.approval_status IN (101, 105) THEN 1 ELSE 0 END) AS approved " + "FROM incentive_activity_record iar " + "WHERE iar.asha_id IN (:ashaIds) " + "AND iar.created_date >= :startDate " @@ -91,6 +153,102 @@ List getIncentiveStatusByAshaIds( @Param("startDate") Timestamp startDate, @Param("endDate") Timestamp endDate); + + + @Query(value = "SELECT iar.asha_id, " + + "COUNT(*) AS totalRecords, " + + "SUM(CASE WHEN iar.approval_status = 101 THEN 1 ELSE 0 END) AS verified, " + + "SUM(CASE WHEN iar.approval_status = 103 THEN 1 ELSE 0 END) AS rejected, " + + "SUM(CASE WHEN iar.approval_status = 102 THEN 1 ELSE 0 END) AS pending, " + + "SUM(CASE WHEN iar.approval_status IN (102,105) THEN 1 ELSE 0 END) AS approved " + + "FROM incentive_activity_record iar " + + "WHERE iar.asha_id IN (:ashaIds) " + + "AND iar.created_date >= :startDate " + + "AND iar.is_claimed = true " + + "AND iar.created_date < :endDate " + + "GROUP BY iar.asha_id", + nativeQuery = true) + List getIncentiveStatusByAshaIdsForAnm( + @Param("ashaIds") List ashaIds, + @Param("startDate") Timestamp startDate, + @Param("endDate") Timestamp endDate); + + @Query(value = "SELECT iar.asha_id, " + + "COUNT(*) AS totalRecords, " + + "SUM(CASE WHEN iar.approval_status = 101 THEN 1 ELSE 0 END) AS verified, " + + "SUM(CASE WHEN iar.approval_status = 103 THEN 1 ELSE 0 END) AS rejected, " + + "SUM(CASE WHEN iar.approval_status = 102 THEN 1 ELSE 0 END) AS pending, " + + "SUM(CASE WHEN iar.approval_status IN (101, 105) THEN 1 ELSE 0 END) AS approved " + + "FROM incentive_activity_record iar " + + "WHERE iar.asha_id IN (:ashaIds) " + + "AND iar.created_date >= :startDate " + + "AND iar.is_claimed = true " + + "AND iar.is_default_activity = true " + + "AND iar.is_default_activity = true " + + "AND iar.is_approved = false " + + "AND iar.created_date < :endDate " + + "GROUP BY iar.asha_id", + nativeQuery = true) + List getDefaultIncentiveStatusByAshaIds( + @Param("ashaIds") List ashaIds, + @Param("startDate") Timestamp startDate, + @Param("endDate") Timestamp endDate); + + +// @Query(value = """ +// SELECT +// iar.asha_id, +// COUNT(*) AS totalRecords, +// +// SUM( +// CASE +// WHEN iar.approval_status = 101 +// OR ( +// iar.approval_status = 105 +// AND iar.is_approved = true +// ) +// THEN 1 ELSE 0 +// END +// ) AS verified, +// +// SUM( +// CASE +// WHEN iar.approval_status = 103 +// THEN 1 ELSE 0 +// END +// ) AS rejected, +// +// SUM( +// CASE +// WHEN iar.approval_status = 102 +// THEN 1 ELSE 0 +// END +// ) AS pending, +// +// SUM( +// CASE +// WHEN iar.approval_status IN (101, 105) +// THEN 1 ELSE 0 +// END +// ) AS approved +// +// FROM incentive_activity_record iar +// +// WHERE iar.asha_id IN (:ashaIds) +// AND iar.created_date >= :startDate +// AND iar.created_date < :endDate +// AND iar.is_claimed = true +// AND iar.is_default_activity = true +// +// GROUP BY iar.asha_id +// """, +// nativeQuery = true) +// List getDefaultIncentiveStatusByAshaIds( +// @Param("ashaIds") List ashaIds, +// @Param("startDate") Timestamp startDate, +// @Param("endDate") Timestamp endDate + //); + // Incentive activity history per ASHA (recent records) @Query(value = "SELECT iar.asha_id, iar.name AS activityName, " + "iar.amount, iar.is_eligible, iar.created_date " diff --git a/src/main/java/com/iemr/flw/repo/iemr/UserFcmTokenRepo.java b/src/main/java/com/iemr/flw/repo/iemr/UserFcmTokenRepo.java new file mode 100644 index 000000000..3426f5a25 --- /dev/null +++ b/src/main/java/com/iemr/flw/repo/iemr/UserFcmTokenRepo.java @@ -0,0 +1,34 @@ +/* +* AMRIT – Accessible Medical Records via Integrated Technology +* Integrated EHR (Electronic Health Records) Solution +* +* Copyright (C) "Piramal Swasthya Management and Research Institute" +* +* This file is part of AMRIT. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +* +/* +* AMRIT – Accessible Medical Records via Integrated Technology +*/ +package com.iemr.flw.repo.iemr; + +import com.iemr.flw.domain.iemr.UserFcmTokenData; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserFcmTokenRepo extends JpaRepository { + UserFcmTokenData findByUserId(Integer userId); +} diff --git a/src/main/java/com/iemr/flw/repo/iemr/UserServiceRoleRepo.java b/src/main/java/com/iemr/flw/repo/iemr/UserServiceRoleRepo.java index b94550a28..354088892 100644 --- a/src/main/java/com/iemr/flw/repo/iemr/UserServiceRoleRepo.java +++ b/src/main/java/com/iemr/flw/repo/iemr/UserServiceRoleRepo.java @@ -36,42 +36,10 @@ public interface UserServiceRoleRepo extends JpaRepository getDistrictByBlockId(@Param("blockId") Integer blockId); - - // Stop TB / Nikshay — additive only. Reads m_userservicerolemapping directly - // (NOT the shared v_userservicerolemapping view) so the view stays untouched - // and no other service line's query is affected. Returns nothing for any - // user whose rows don't have NikshayTUID set (i.e. every non-Stop-TB user). - // NikshayTUID/NikshayFacilityID are TEXT columns holding a comma-joined list - // of IDs (e.g. "12,45,78"), not a single ID. Name resolution against - // m_nikshay_tu/m_nikshay_facility is done in Java (see UserServiceImpl) via - // an indexed IN(...) lookup on their primary keys, instead of joining here - // with FIND_IN_SET — FIND_IN_SET can't use an index on either side, so it - // forces a full scan of the master table per call (measured: ~60s against - // m_nikshay_facility's 300k+ rows for a user with ~100 mapped facilities). - @Query(value = "SELECT usrm.NikshayTUID, usrm.NikshayFacilityID, usrm.DistrictID " + - "FROM m_userservicerolemapping usrm " + - "WHERE usrm.UserID = :userId AND usrm.ProviderServiceMapID = :providerServiceMapId " + - "AND usrm.Deleted = false AND usrm.NikshayTUID IS NOT NULL", - nativeQuery = true) - List getNikshayMappingRows(@Param("userId") Integer userId, - @Param("providerServiceMapId") Integer providerServiceMapId); - - @Query(value = "SELECT NikshayTUID, TUName FROM m_nikshay_tu WHERE NikshayTUID IN (:ids)", nativeQuery = true) - List findNikshayTuNames(@Param("ids") java.util.Collection ids); - - @Query(value = "SELECT NikshayFacilityID, FacilityName FROM m_nikshay_facility WHERE NikshayFacilityID IN (:ids)", nativeQuery = true) - List findNikshayFacilityNames(@Param("ids") java.util.Collection ids); - - // DistrictID on m_userservicerolemapping is a Nikshay district ID, not an - // AMRIT one (see setWorkLocationObject in Admin-UI) - resolving its name - // against m_nikshay_district (the same ID space) is safe, unlike joining it - // against AMRIT's own m_district, which would silently match whatever AMRIT - // district happens to share that same numeric ID by coincidence. - @Query(value = "SELECT DistrictName FROM m_nikshay_district WHERE NikshayDistrictID = :id", nativeQuery = true) - String findNikshayDistrictName(@Param("id") Integer id); + @Query("SELECT new com.iemr.flw.dto.iemr.UserServiceRoleDTO(u.userId, u.name, u.userName, u.stateId, u.stateName, u.workingDistrictId," + + "u.workingDistrictName, u.serviceProviderId, u.roleId, u.roleName, u.providerServiceMapId, u.blockid, u.blockname, u.villageid, " + + "u.villagename) FROM UserServiceRole u WHERE u.userId IN :userIds " + + "AND u.userServciceRoleDeleted = false AND u.userDeleted = false") + List getUserRolesByIds(@Param("userIds") List userIds); } diff --git a/src/main/java/com/iemr/flw/service/ChildCareService.java b/src/main/java/com/iemr/flw/service/ChildCareService.java index c78de3fdc..a7e526e69 100644 --- a/src/main/java/com/iemr/flw/service/ChildCareService.java +++ b/src/main/java/com/iemr/flw/service/ChildCareService.java @@ -16,6 +16,7 @@ public interface ChildCareService { List getHBNCDetails(GetBenRequestHandler dto); String saveHBNCDetails(List hbncRequestDTOs,Integer userId); + String saveHBNCDetails(List hbncRequestDTOs); List getChildVaccinationDetails(GetBenRequestHandler dto); diff --git a/src/main/java/com/iemr/flw/service/IncentiveLogicService.java b/src/main/java/com/iemr/flw/service/IncentiveLogicService.java index 8becce199..0c86ab7be 100644 --- a/src/main/java/com/iemr/flw/service/IncentiveLogicService.java +++ b/src/main/java/com/iemr/flw/service/IncentiveLogicService.java @@ -32,4 +32,6 @@ public interface IncentiveLogicService { IncentiveActivityRecord incentiveForGiveingIFA(Long benId, Timestamp treatmentStartDate, Timestamp treatmentEndDate, Integer userId); IncentiveActivityRecord incentiveForTbSuspected(Long benId, Timestamp treatmentStartDate, Timestamp treatmentEndDate, Integer userId); + + IncentiveActivityRecord incentiveForTbPreventiveFollowUp(Long benId, Timestamp completionDate, Timestamp completionDate1, Integer userId); } diff --git a/src/main/java/com/iemr/flw/service/IncentiveService.java b/src/main/java/com/iemr/flw/service/IncentiveService.java index 8b2e46001..ad7c122c9 100644 --- a/src/main/java/com/iemr/flw/service/IncentiveService.java +++ b/src/main/java/com/iemr/flw/service/IncentiveService.java @@ -14,7 +14,7 @@ public interface IncentiveService { String getIncentiveMaster(IncentiveRequestDTO incentiveRequestDTO); String getAllIncentivesByUserId(GetBenRequestHandler requestDTO); - String getAllIncentivesGroupedSummary(GetBenRequestHandler requestDTO); + String getAllIncentivesGroupedSummary(GetBenRequestHandler requestDTO,Integer userId); String getAllIncentivesGroupedActivity(GetBenRequestHandler requestDTO); String updateIncentive(PendingActivityDTO pendingActivityDTO); @@ -22,4 +22,4 @@ public String updateClaimStatus(Integer ashaId, Integer month, Integer year, Boolean isClaimed, - String token);} + String token,String incentiveId);} diff --git a/src/main/java/com/iemr/flw/service/NotificationService.java b/src/main/java/com/iemr/flw/service/NotificationService.java new file mode 100644 index 000000000..4d561b517 --- /dev/null +++ b/src/main/java/com/iemr/flw/service/NotificationService.java @@ -0,0 +1,14 @@ +package com.iemr.flw.service; + +import com.iemr.flw.dto.iemr.NotificationListDTO; + +public interface NotificationService { + public String sendNotification(String appType, String topic, String title, String body, String redirect,String notificationType,Integer reciverID); + NotificationListDTO getNotifications(Integer receiverUserId); + + Long getUnreadCount(Integer receiverUserId); + + boolean markAsRead(Long notificationId); + + int markAllAsRead(Integer receiverUserId); +} diff --git a/src/main/java/com/iemr/flw/service/SupervisorDashboardService.java b/src/main/java/com/iemr/flw/service/SupervisorDashboardService.java index bc580a26d..d406bf628 100644 --- a/src/main/java/com/iemr/flw/service/SupervisorDashboardService.java +++ b/src/main/java/com/iemr/flw/service/SupervisorDashboardService.java @@ -5,7 +5,8 @@ public interface SupervisorDashboardService { - String getSupervisorDashboard(Integer supervisorUserID, Integer month, Integer year); + String getSupervisorDashboard(Integer supervisorUserID, Integer month, Integer year,Integer facilityId); + String getSupervisorSubCenter(Integer supervisorUserID, Integer month, Integer year); Map getAshasAtFacility(Integer supervisorId, Integer facilityId, Integer month, Integer year, Integer approvalStatusID); diff --git a/src/main/java/com/iemr/flw/service/impl/ChildCareServiceImpl.java b/src/main/java/com/iemr/flw/service/impl/ChildCareServiceImpl.java index e65e0f53e..60cfa29f2 100644 --- a/src/main/java/com/iemr/flw/service/impl/ChildCareServiceImpl.java +++ b/src/main/java/com/iemr/flw/service/impl/ChildCareServiceImpl.java @@ -198,7 +198,7 @@ public List getHbycRecords(GetBenRequestHandler dto) { addIfValid(fields, "is_child_sick", convert(hbycChildVisit.getIs_child_sick())); addIfValid(fields, "exclusive_breastfeeding", convert(hbycChildVisit.getExclusive_breastfeeding())); addIfValid(fields, "mother_counseled_ebf", convert(hbycChildVisit.getMother_counseled_ebf())); -// addIfValid(fields, "complementary_feeding", convert(hbycChildVisit.getComplementary_feeding())); + addIfValid(fields, "complementary_feeding", convert(hbycChildVisit.getComplementary_feeding())); addIfValid(fields, "mother_counseled_cf", convert(hbycChildVisit.getMother_counseled_cf())); addIfValid(fields, "weight_recorded", convert(hbycChildVisit.getWeight_recorded())); addIfValid(fields, "developmental_delay", convert(hbycChildVisit.getDevelopmental_delay())); @@ -212,7 +212,7 @@ public List getHbycRecords(GetBenRequestHandler dto) { addIfValid(fields, "parenting_counseling", convert(hbycChildVisit.getParenting_counseling())); addIfValid(fields, "family_planning_counseling", convert(hbycChildVisit.getFamily_planning_counseling())); addIfValid(fields, "diarrhoea_episode", convert(hbycChildVisit.getDiarrhoea_episode())); -// addIfValid(fields, "breathing_difficulty", convert(hbycChildVisit.getBreathing_difficulty())); + addIfValid(fields, "breathing_difficulty", convert(hbycChildVisit.getBreathing_difficulty())); addIfValid(fields, "temperature_check", hbycChildVisit.getTemperature()); addIfValid(fields, "mcp_card_images", hbycChildVisit.getMcp_card_images()); @@ -279,6 +279,7 @@ public List getHBNCDetails(GetBenRequestHandler dto) { addIfValid(fields, "umbilical_stump", visit.getUmbilical_stump()); addIfValid(fields, "discharged_from_sncu", convert(visit.getDischarged_from_sncu())); addIfValid(fields, "discharge_summary_upload", visit.getDischarge_summary_upload()); + addIfValid(fields, "is_admitted_in_sncu", convert(visit.getIs_admitted_in_sncu())); // Add more fields as required @@ -371,28 +372,92 @@ public String saveHBNCDetails(List hbncRequestDTOs, Integer user return null; } + @Override + public String saveHBNCDetails(List hbncRequestDTOs) { + try { + List hbncList = new ArrayList<>(); + + hbncRequestDTOs.forEach(it -> { + if (it.getVisitDate() != null) { + + HbncVisitDTO hbncVisitDTO = it.getFields(); + hbncVisitDTO.setVisit_date(it.getVisitDate()); + HbncVisit hbncVisit = hbncVisitRepo.findByBeneficiaryIdAndVisit_day(it.getBeneficiaryId(), hbncVisitDTO.getVisit_day()); + + if (hbncVisit != null) { + Long id = hbncVisit.getId(); + modelMapper.map(hbncVisitDTO, hbncVisit); + hbncVisit.setId(id); + } else { + hbncVisit = new HbncVisit(); + modelMapper.map(hbncVisitDTO, hbncVisit); + hbncVisit.setBeneficiaryId(it.getBeneficiaryId()); + hbncVisit.setAshaId(userRepo.getUserIdByName(it.getUserName())); + hbncVisit.setCreatedBy(it.getUserName()); + hbncVisit.setHouseHoldId(it.getHouseHoldId()); + hbncVisit.setId(null); + } + hbncList.add(hbncVisit); + } + }); + + + hbncVisitRepo.saveAll(hbncList); + + + logger.info("HBNC details saved"); + return "no of hbnc details saved: " + (hbncList.size()); + } catch (Exception e) { + logger.info("Saving HBNC details failed with error : " + e.getMessage()); + } + return null; + } + @Override public List getChildVaccinationDetails(GetBenRequestHandler dto) { try { String user = beneficiaryRepo.getUserName(dto.getAshaId()); - List vaccinationDetails = childVaccinationRepo.getChildVaccinationDetails(user, dto.getFromDate(), dto.getToDate()); + List vaccinationDetails = + childVaccinationRepo.getChildVaccinationDetails(user, dto.getFromDate(), dto.getToDate()); - List result = new ArrayList<>(); - vaccinationDetails.forEach(childVaccination -> { - ChildVaccinationDTO vaccinationDTO = mapper.convertValue(childVaccination, ChildVaccinationDTO.class); - if(childVaccination.getBeneficiaryRegId()!=null){ - BigInteger benId = beneficiaryRepo.getBenIdFromRegID(childVaccination.getBeneficiaryRegId()); - vaccinationDTO.setBeneficiaryId(benId.longValue()); + if (vaccinationDetails.isEmpty()) { + return new ArrayList<>(); + } - } - if(!vaccinationDetails.isEmpty()){ - checkAndAddIncentives(vaccinationDetails); + // Bulk fetch all beneficiary IDs in ONE query instead of one-per-record + List regIds = vaccinationDetails.stream() + .map(ChildVaccination::getBeneficiaryRegId) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + Map regIdToBenIdMap = new HashMap<>(); + if (!regIds.isEmpty()) { + List benIdRows = beneficiaryRepo.getBenIdsFromRegIds(regIds); + for (Object[] row : benIdRows) { + Long regId = ((Number) row[0]).longValue(); + BigInteger benId = (BigInteger) row[1]; + regIdToBenIdMap.put(regId, benId); } + } + + // Call ONCE for the whole batch — not per record + checkAndAddIncentives(vaccinationDetails); + List result = new ArrayList<>(); + for (ChildVaccination childVaccination : vaccinationDetails) { + ChildVaccinationDTO vaccinationDTO = mapper.convertValue(childVaccination, ChildVaccinationDTO.class); + + if (childVaccination.getBeneficiaryRegId() != null) { + BigInteger benId = regIdToBenIdMap.get(childVaccination.getBeneficiaryRegId()); + if (benId != null) { + vaccinationDTO.setBeneficiaryId(benId.longValue()); + } + } result.add(vaccinationDTO); - }); + } + return result; } catch (Exception e) { logger.error(e.getMessage()); @@ -709,7 +774,8 @@ public List saveAllIfa(List dtoList, Intege savedList.forEach(data -> { Timestamp visitTimestamp = Timestamp.valueOf(data.getIfaProvisionDate().atStartOfDay()); - if(data.getIfaBottleCount().equals("10.0")){ + + if(data!=null){ incentiveLogicService.incentiveForGiveingIFA( data.getBeneficiaryId(), visitTimestamp, @@ -774,8 +840,10 @@ private IfaDistributionDTO mapToDTO(IfaDistribution entity) { fields.setIfa_provision_date(entity.getIfaProvisionDate().format(FORMATTER)); } fields.setMcp_card_upload(entity.getMcpCardUpload()); - fields.setIfa_bottle_count(Double.valueOf(entity.getIfaBottleCount())); + if(entity.getIfaBottleCount()!=null){ + fields.setIfa_bottle_count(Double.valueOf(entity.getIfaBottleCount())); + } dto.setFields(fields); return dto; } @@ -803,7 +871,10 @@ private IfaDistribution mapToEntity(IfaDistributionDTO dto, Integer userId) { entity.setIfaProvisionDate(null); } } - entity.setIfaBottleCount(dto.getFields().getIfa_bottle_count().toString()); + if(dto.getFields().getIfa_bottle_count()!=null){ + entity.setIfaBottleCount(dto.getFields().getIfa_bottle_count().toString()); + + } entity.setMcpCardUpload(dto.getFields().getMcp_card_upload()); } diff --git a/src/main/java/com/iemr/flw/service/impl/CoupleServiceImpl.java b/src/main/java/com/iemr/flw/service/impl/CoupleServiceImpl.java index 44926729a..b650dd430 100644 --- a/src/main/java/com/iemr/flw/service/impl/CoupleServiceImpl.java +++ b/src/main/java/com/iemr/flw/service/impl/CoupleServiceImpl.java @@ -16,6 +16,7 @@ import com.iemr.flw.repo.iemr.*; import com.iemr.flw.service.CoupleService; import com.iemr.flw.service.UserService; +import org.joda.time.DateTime; import org.modelmapper.ModelMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,6 +27,8 @@ import java.io.IOException; import java.math.BigInteger; +import java.sql.Timestamp; +import java.time.LocalDate; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; @@ -75,8 +78,8 @@ public String registerEligibleCouple(List eligibleCoupleDTOs, List ecrList = new ArrayList<>(); if(!eligibleCoupleDTOs.isEmpty()){ for (EligibleCoupleDTO it : eligibleCoupleDTOs) { - Integer userId = userRepo.getUserIdByName(it.getCreatedBy()); - Integer stateId = userService.getUserDetail(userId).getStateId(); + Integer userId = userRepo.getUserIdByName(it.getCreatedBy()); + Integer stateId = userService.getUserDetail(userId).getStateId(); EligibleCoupleRegister existingECR = eligibleCoupleRegisterRepo.findEligibleCoupleRegisterByBenId(it.getBenId()); @@ -157,16 +160,16 @@ public String registerEligibleCouple(List eligibleCoupleDTOs, if (Boolean.TRUE.equals(existingECR.getIsKitHandedOver()) && ((existingECR.getKitPhoto1() != null && !existingECR.getKitPhoto1().isEmpty()) || (existingECR.getKitPhoto2() != null && !existingECR.getKitPhoto2().isEmpty()))) { - if(stateId.equals(StateCode.AM.getStateCode())){ - IncentiveActivity activity = - incentivesRepo.findIncentiveMasterByNameAndGroup( - "FP_NP_KIT", - GroupName.FAMILY_PLANNING.getDisplayName()); - - if (activity != null) { - createIncentiveRecord(existingECR, activity); - } - } + if(stateId.equals(StateCode.AM.getStateCode())){ + IncentiveActivity activity = + incentivesRepo.findIncentiveMasterByNameAndGroup( + "FP_NP_KIT", + GroupName.FAMILY_PLANNING.getDisplayName()); + + if (activity != null) { + createIncentiveRecordForKitHandOver(existingECR, activity); + } + } if(stateId.equals(StateCode.CG.getStateCode())){ IncentiveActivity activity = incentivesRepo.findIncentiveMasterByNameAndGroup( @@ -174,7 +177,7 @@ public String registerEligibleCouple(List eligibleCoupleDTOs, GroupName.ACTIVITY.getDisplayName()); if (activity != null) { - createIncentiveRecord(existingECR, activity); + createIncentiveRecordForKitHandOver(existingECR, activity); } } @@ -335,7 +338,7 @@ private void checkIncentiveForChildGap(Integer stateId, String userName,List new Object()); + if (activity == null + || eligibleCoupleDTO == null + || eligibleCoupleDTO.getKitHandedOverDate() == null + || eligibleCoupleDTO.getKitHandedOverDate().trim().isEmpty()) { + return; + } + + LocalDate kitHandOverDate = + LocalDate.parse(eligibleCoupleDTO.getKitHandedOverDate()); + + Timestamp kitHandOverTimestamp = + Timestamp.valueOf(kitHandOverDate.atStartOfDay()); + synchronized (lock){ + if (activity != null) { + if(eligibleCoupleDTO.getKitHandedOverDate()!=null && !eligibleCoupleDTO.getKitHandedOverDate().isEmpty()){ + + } + Integer userId = userRepo.getUserIdByName(eligibleCoupleDTO.getCreatedBy()); + + IncentiveActivityRecord record = recordRepo + .findRecordByActivityIdCreatedDateBenId(activity.getId(), kitHandOverTimestamp, eligibleCoupleDTO.getBenId(),userId); + + if (record == null) { + record = new IncentiveActivityRecord(); + record.setActivityId(activity.getId()); + record.setCreatedDate(kitHandOverTimestamp); + record.setCreatedBy(eligibleCoupleDTO.getCreatedBy()); + record.setStartDate(kitHandOverTimestamp); + record.setEndDate(kitHandOverTimestamp); + record.setUpdatedDate(eligibleCoupleDTO.getCreatedDate()); + record.setUpdatedBy(eligibleCoupleDTO.getCreatedBy()); + record.setBenId(eligibleCoupleDTO.getBenId()); + record.setAshaId(userId); + record.setAmount(Long.valueOf(activity.getRate())); + recordRepo.save(record); + } + } + } + lockMap.remove(lockKey, lock); + + + } @Override @@ -475,7 +526,7 @@ private void checkAndAddAntaraIncentive(EligibleCoupleTracking ect) { }else if (ect.getAntraDose().contains("Dose-5")) { IncentiveActivity antaraActivity4 = incentivesRepo.findIncentiveMasterByNameAndGroup("FP_ANC_MPA5", GroupName.FAMILY_PLANNING.getDisplayName()); - + if (antaraActivity4 != null) { addIncenticeRecord(ect, userId, antaraActivity4); @@ -489,29 +540,29 @@ private void checkAndAddAntaraIncentive(EligibleCoupleTracking ect) { addIncenticeRecord(ect, userId, antaraActivity4CH); } } - - + + } else if (ect.getMethodOfContraception() != null && ect.getMethodOfContraception().equals("MALE STERILIZATION")) { if(stateId.equals(StateCode.AM.getStateCode())){ IncentiveActivity maleSterilizationActivityAM = incentivesRepo.findIncentiveMasterByNameAndGroup("FP_MALE_STER", "FAMILY PLANNING"); - + if (maleSterilizationActivityAM != null) { addIncenticeRecord(ect, userId, maleSterilizationActivityAM); } - + } if(stateId.equals(StateCode.CG.getStateCode())){ - + IncentiveActivity maleSterilizationActivityCH = incentivesRepo.findIncentiveMasterByNameAndGroup("FP_MALE_STER", GroupName.ACTIVITY.getDisplayName()); - + if (maleSterilizationActivityCH != null) { addIncenticeRecord(ect, userId, maleSterilizationActivityCH); } } - + } else if (ect.getMethodOfContraception() != null && ect.getMethodOfContraception().equals("FEMALE STERILIZATION")) { if(stateId.equals(StateCode.CG.getStateCode())){ IncentiveActivity femaleSterilizationActivityCH = @@ -531,8 +582,8 @@ private void checkAndAddAntaraIncentive(EligibleCoupleTracking ect) { } - - + + } else if (ect.getMethodOfContraception() != null && ect.getMethodOfContraception().equals("MiniLap")) { if(stateId.equals(StateCode.AM.getStateCode())){ IncentiveActivity miniLapActivity = @@ -541,7 +592,7 @@ private void checkAndAddAntaraIncentive(EligibleCoupleTracking ect) { addIncenticeRecord(ect, userId, miniLapActivity); } } - + } else if (ect.getMethodOfContraception() != null && ect.getMethodOfContraception().equals("Condom")) { if(stateId.equals(StateCode.AM.getStateCode())){ IncentiveActivity comdomActivity = @@ -550,7 +601,7 @@ private void checkAndAddAntaraIncentive(EligibleCoupleTracking ect) { addIncenticeRecord(ect, userId, comdomActivity); } } - + } else if (ect.getMethodOfContraception() != null && ect.getMethodOfContraception().equals("Copper T (IUCD)")) { if(stateId.equals(StateCode.AM.getStateCode())){ IncentiveActivity copperTActivity = @@ -559,7 +610,7 @@ private void checkAndAddAntaraIncentive(EligibleCoupleTracking ect) { addIncenticeRecord(ect, userId, copperTActivity); } } - + } if (ect.getMethodOfContraception() != null && (ect.getMethodOfContraception().contains("POST PARTUM STERILIZATION (PPS WITHIN 7 DAYS OF DELIVERY)") || ect.getMethodOfContraception().contains("MiniLap") || ect.getMethodOfContraception().contains("MALE STERILIZATION") || ect.getMethodOfContraception().contains("FEMALE STERILIZATION"))) { if(stateId.equals(StateCode.AM.getStateCode())){ @@ -578,8 +629,8 @@ private void checkAndAddAntaraIncentive(EligibleCoupleTracking ect) { addIncenticeRecord(ect, userId, limitiing2ChildActivityCH); } } - - + + } } diff --git a/src/main/java/com/iemr/flw/service/impl/DeathReportsServiceImpl.java b/src/main/java/com/iemr/flw/service/impl/DeathReportsServiceImpl.java index b7eee7dd0..cfc772142 100644 --- a/src/main/java/com/iemr/flw/service/impl/DeathReportsServiceImpl.java +++ b/src/main/java/com/iemr/flw/service/impl/DeathReportsServiceImpl.java @@ -81,37 +81,6 @@ public String registerCDR(List cdrDTOs) { } } - public String updateCDRUploadFiles(CdrDTO cdrDTOs, Long incentiveActivityId) { - try { - Optional cdrOptional = cdrRepo.findById(cdrDTOs.getId()); - CDR cdr = new CDR(); - if (cdrOptional.isPresent()) { - cdr = cdrOptional.get(); - if (cdrDTOs.getCdrImage() != null && !cdrDTOs.getCdrImage().isEmpty()) { - cdr.setCdrImage(cdrDTOs.getCdrImage()); - } - - if (cdrDTOs.getCdrImage2() != null && !cdrDTOs.getCdrImage2().isEmpty()) { - cdr.setCdrImage2(cdrDTOs.getCdrImage2()); - } - - if (cdrDTOs.getDeathCertImage1() != null && !cdrDTOs.getDeathCertImage1().isEmpty()) { - cdr.setDeathCertImage1(cdrDTOs.getDeathCertImage1()); - } - - if (cdrDTOs.getDeathCertImage2() != null && !cdrDTOs.getDeathCertImage2().isEmpty()) { - cdr.setDeathCertImage2(cdrDTOs.getDeathCertImage2()); - } - } - cdrRepo.save(cdr); - - pendindDocService.updateIncentive(incentiveActivityId); - - return "no of cdr details update: "; - } catch (Exception e) { - return "error while saving cdr details: " + e.getMessage(); - } - } @Override public String registerMDSR(List mdsrDTOs) { @@ -141,43 +110,6 @@ public String registerMDSR(List mdsrDTOs) { } } - public String updateMDSR(MdsrDTO mdsrDTO, Long incentiveActivityId) { - try { - - Optional mdsrOptional = mdsrRepo.findById(mdsrDTO.getId()); - MDSR mdsr = new MDSR(); - - if (mdsrOptional.isPresent()) { - - mdsr = mdsrOptional.get(); - - if (mdsrDTO.getMdsr1File() != null && !mdsrDTO.getMdsr1File().isEmpty()) { - mdsr.setMdsr1File(mdsrDTO.getMdsr1File()); - } - - if (mdsrDTO.getMdsr2File() != null && !mdsrDTO.getMdsr2File().isEmpty()) { - mdsr.setMdsr2File(mdsrDTO.getMdsr2File()); - } - - if (mdsrDTO.getMdsrDeathCertFile() != null && !mdsrDTO.getMdsrDeathCertFile().isEmpty()) { - mdsr.setMdsrDeathCertFile(mdsrDTO.getMdsrDeathCertFile()); - } - - } else { - return "MDSR record not found with id: " + mdsrDTO.getId(); - } - - mdsrRepo.save(mdsr); - - // incentive update - pendindDocService.updateIncentive(incentiveActivityId); - - return "MDSR updated successfully for id: " + mdsrDTO.getId(); - - } catch (Exception e) { - return "error while updating mdsr details: " + e.getMessage(); - } - } @Override public List getCdrRecords(GetBenRequestHandler dto) { diff --git a/src/main/java/com/iemr/flw/service/impl/DiseaseControlServiceImpl.java b/src/main/java/com/iemr/flw/service/impl/DiseaseControlServiceImpl.java index 35746b2f8..08caccd03 100644 --- a/src/main/java/com/iemr/flw/service/impl/DiseaseControlServiceImpl.java +++ b/src/main/java/com/iemr/flw/service/impl/DiseaseControlServiceImpl.java @@ -1249,6 +1249,36 @@ private void checkAndAddIncentives(ScreeningMalaria diseaseScreening) { } + if (diseaseScreening.getCaseStatus().equals("Suspected")) { + if (!diseaseScreening.getMalariaTestType().isEmpty()) { + if (stateId.equals(StateCode.AM.getStateCode())) { + if (incentiveActivityForCollectSlideAM != null) { + addIncentive(incentiveActivityForCollectSlideAM, diseaseScreening); + + } + } + + if (stateId.equals(StateCode.CG.getStateCode())) { + if (incentiveActivityForCollectSlideCG != null) { + addIncentive(incentiveActivityForCollectSlideCG, diseaseScreening); + + } + } + + + } + + }else { + if(!diseaseScreening.getMalariaTestType().isEmpty()){ + if (stateId.equals(StateCode.CG.getStateCode())) { + if (incentiveActivityForCollectSlideCG != null) { + addIncentive(incentiveActivityForCollectSlideCG, diseaseScreening); + + } + } + + } + } if (diseaseScreening.getCaseStatus().equals("Suspected")) { if (!diseaseScreening.getMalariaTestType().isEmpty()) { if (stateId.equals(StateCode.AM.getStateCode())) { diff --git a/src/main/java/com/iemr/flw/service/impl/IncentiveLogicImpl.java b/src/main/java/com/iemr/flw/service/impl/IncentiveLogicImpl.java index b6e4b7c7a..7200d4e04 100644 --- a/src/main/java/com/iemr/flw/service/impl/IncentiveLogicImpl.java +++ b/src/main/java/com/iemr/flw/service/impl/IncentiveLogicImpl.java @@ -85,6 +85,48 @@ public IncentiveActivityRecord incentiveForLeprosyPaucibacillaryConfirmed( } } + @Override + public IncentiveActivityRecord incentiveForTbPreventiveFollowUp(Long benId, Timestamp treatmentStartDate, Timestamp treatmentEndDate, Integer userId) { + try { + Integer stateCode = userService.getUserDetail(userId).getStateId(); + + if (stateCode == null) { + logger.warn("State code is null for user: {}", userId); + return null; + } + + String activityName = "TPT_PROVIDING"; + + if (stateCode.equals(StateCode.CG.getStateCode())) { + return processIncentive( + activityName, + GroupName.ACTIVITY.getDisplayName(), + benId, + treatmentStartDate, + treatmentStartDate, + userId); + } + + if (stateCode.equals(StateCode.AM.getStateCode())) { + return processIncentive( + activityName, + GroupName.UMBRELLA_PROGRAMMES.getDisplayName(), + benId, + treatmentStartDate, + treatmentEndDate, + userId); + } + + // state not supported + logger.info("No incentive mapping for stateCode: {}", stateCode); + return null; + + } catch (Exception e) { + logger.error("Check TB Incentive Exception: ", e); + return null; + } + } + @Override public IncentiveActivityRecord incentiveForTbSuspected(Long benId, Timestamp treatmentStartDate, Timestamp treatmentEndDate, Integer userId) { try { diff --git a/src/main/java/com/iemr/flw/service/impl/IncentiveMonthlyScheduler.java b/src/main/java/com/iemr/flw/service/impl/IncentiveMonthlyScheduler.java new file mode 100644 index 000000000..2624f5644 --- /dev/null +++ b/src/main/java/com/iemr/flw/service/impl/IncentiveMonthlyScheduler.java @@ -0,0 +1,49 @@ +package com.iemr.flw.service.impl; + +import com.iemr.flw.repo.iemr.IncentiveRecordRepo; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.sql.Timestamp; +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +@Component +@RequiredArgsConstructor +@Slf4j +public class IncentiveMonthlyScheduler { + + private static final ZoneId INDIA_ZONE = + ZoneId.of("Asia/Kolkata"); + @Autowired + private IncentiveRecordRepo recordRepo; + + @Scheduled(cron = "0 5 0 1 * *", zone = "Asia/Kolkata") + public void resetRejectedIncentivesForNewMonth() { + + LocalDate firstDayOfCurrentMonth = + LocalDate.now(INDIA_ZONE).withDayOfMonth(1); + + Timestamp currentMonthStart = + Timestamp.valueOf(firstDayOfCurrentMonth.atStartOfDay()); + + Timestamp updatedDate = + Timestamp.from(ZonedDateTime.now(INDIA_ZONE).toInstant()); + + int updatedCount = + recordRepo.resetRejectedIncentivesForNewMonth( + currentMonthStart, + updatedDate, + "SYSTEM" + ); + + log.info( + "Rejected incentives reset successfully. Updated records: {}", + updatedCount + ); + } +} \ No newline at end of file diff --git a/src/main/java/com/iemr/flw/service/impl/IncentiveServiceImpl.java b/src/main/java/com/iemr/flw/service/impl/IncentiveServiceImpl.java index f109c88a8..4da29ff43 100644 --- a/src/main/java/com/iemr/flw/service/impl/IncentiveServiceImpl.java +++ b/src/main/java/com/iemr/flw/service/impl/IncentiveServiceImpl.java @@ -3,18 +3,17 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.iemr.flw.domain.identity.RMNCHMBeneficiarydetail; import com.iemr.flw.domain.iemr.*; import com.iemr.flw.dto.identity.GetBenRequestHandler; import com.iemr.flw.dto.iemr.*; import com.iemr.flw.masterEnum.GroupName; import com.iemr.flw.masterEnum.IncentiveApprovalStatus; -import com.iemr.flw.masterEnum.IncentiveName; import com.iemr.flw.masterEnum.StateCode; import com.iemr.flw.repo.identity.BeneficiaryRepo; import com.iemr.flw.repo.iemr.*; import com.iemr.flw.service.IncentiveService; import com.iemr.flw.service.MaaMeetingService; +import com.iemr.flw.service.NotificationService; import com.iemr.flw.service.UserService; import com.iemr.flw.utils.JwtUtil; import jakarta.persistence.criteria.CriteriaBuilder; @@ -30,11 +29,8 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; -import java.math.BigInteger; import java.sql.Timestamp; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; +import java.time.*; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; @@ -85,6 +81,12 @@ public class IncentiveServiceImpl implements IncentiveService { private final ConcurrentHashMap lockMap = new ConcurrentHashMap<>(); + @Autowired + private NotificationService notificationService; + + @Autowired + private SupervisorDashboardRepo dashboardRepo; + // ================= MASTER SAVE ================= @@ -150,7 +152,12 @@ public String getIncentiveMaster(IncentiveRequestDTO incentiveRequestDTO) { dto.setName(mapping.getName()); if (isCG) { - dto.setGroupName(""); + if (inc.getGroupCategoryName() != null + && !inc.getGroupCategoryName().isEmpty()) { + dto.setGroupName(inc.getGroupCategoryName()); + } else { + dto.setGroupName(inc.getGroup()); + } } else if (isAM) { dto.setGroupName(mapping.getGroup()); } @@ -173,11 +180,14 @@ public String getIncentiveMaster(IncentiveRequestDTO incentiveRequestDTO) { } else { if (isCG) { - dto.setGroupName(""); - + if (inc.getGroupCategoryName() != null + && !inc.getGroupCategoryName().isEmpty()) { + dto.setGroupName(inc.getGroupCategoryName()); + } else { + dto.setGroupName(inc.getGroup()); + } } else { dto.setGroupName(inc.getGroup()); - } } @@ -192,26 +202,25 @@ public String getIncentiveMaster(IncentiveRequestDTO incentiveRequestDTO) { } return null; } - @Override public String getAllIncentivesByUserId(GetBenRequestHandler request) { int page = 0; - int size = 20; + int size = 200; // bumped from 20 — fewer round trips for large histories Page pageResult; List finalDtos = new ArrayList<>(); - Integer stateCode = userService.getUserDetail(request.getAshaId()).getStateId(); - String userName = userService.getUserDetail(request.getAshaId()).getUserName(); - try { + // Fetch user detail ONCE instead of twice + UserServiceRoleDTO userDetail = userService.getUserDetail(request.getAshaId()); + Integer stateCode = userDetail.getStateId(); + String userName = userDetail.getUserName(); + try { if (stateCode.equals(StateCode.AM.getStateCode())) { checkMonthlyAshaIncentive(request.getAshaId()); } if (stateCode.equals(StateCode.CG.getStateCode())) { checkMonthlyAshaIncentiveForCg(request.getAshaId()); - } - } catch (Exception e) { logger.error("Error in checkMonthlyAshaIncentive: ", e); } @@ -219,7 +228,6 @@ public String getAllIncentivesByUserId(GetBenRequestHandler request) { try { addIncentiveForIronTablets(request.getAshaId()); incentiveOfNcdReferal(request.getAshaId(), request.getVillageID()); - } catch (Exception e) { logger.error("Error in incentiveOfNcdReferal: ", e); } @@ -227,17 +235,9 @@ public String getAllIncentivesByUserId(GetBenRequestHandler request) { boolean isCG = stateCode != null && stateCode.equals(StateCode.CG.getStateCode()); do { + Pageable pageable = PageRequest.of(page, size, Sort.by("id").descending()); - Pageable pageable = PageRequest.of( - page, - size, - Sort.by("id").descending() // latest first - ); - - pageResult = recordRepo.findRecordsByAsha( - request.getAshaId(), - pageable - ); + pageResult = recordRepo.findRecordsByAsha(request.getAshaId(), pageable); List entities = pageResult.getContent(); @@ -245,30 +245,27 @@ public String getAllIncentivesByUserId(GetBenRequestHandler request) { return new Gson().toJson(Collections.emptyList()); } - // Step 2: Collect all activityIds — fetch valid ones in ONE query + // Bulk fetch valid activity ids List activityIds = entities.stream() .map(IncentiveActivityRecord::getActivityId) .distinct() .collect(Collectors.toList()); - // Single bulk query instead of N individual findIncentiveMasterById() calls Set validActivityIds = isCG ? incentivesRepo.findValidActivityIds(activityIds, true) : incentivesRepo.findValidActivityIds(activityIds, false); - // Filter entities based on valid activity IDs entities = entities.stream() .filter(e -> validActivityIds.contains(e.getActivityId())) .collect(Collectors.toList()); - // Step 3: Collect all benIds that need name lookup (name == null and benId > 0) + // Bulk fetch beneficiary names List benIdsToFetch = entities.stream() .filter(e -> e.getName() == null && e.getBenId() != null && e.getBenId() > 0) .map(IncentiveActivityRecord::getBenId) .distinct() .collect(Collectors.toList()); - // Step 4: Bulk fetch all beneficiary names in ONE query instead of 3 queries per record Map benIdToNameMap = new HashMap<>(); if (!benIdsToFetch.isEmpty()) { List benDetails = beneficiaryRepo.findBenNamesByBenIds(benIdsToFetch); @@ -280,7 +277,23 @@ public String getAllIncentivesByUserId(GetBenRequestHandler request) { } } - // Step 5: Map entities to DTOs + // NEW: Bulk fetch verifier (supervisor) roles — replaces N+1 userRepo.getUserRole() calls + // Bulk fetch verifier (supervisor) roles — replaces N+1 userRepo.getUserRole() calls + List verifierIds = entities.stream() + .filter(e -> e.getName() == null && e.getVerifiedByUserId() != null) + .map(e -> e.getVerifiedByUserId().intValue()) // adjust if getVerifiedByUserId() already returns Integer + .distinct() + .collect(Collectors.toList()); + + Map verifierRoleMap = new HashMap<>(); + if (!verifierIds.isEmpty()) { + List roles = userRepo.getUserRolesByIds(verifierIds); + for (UserServiceRoleDTO r : roles) { + verifierRoleMap.put(r.getUserId(), r); + } + } + + // Map entities to DTOs List dtos = entities.stream().map(entry -> { if (entry.getName() == null) { if (entry.getBenId() != null && entry.getBenId() > 0) { @@ -292,63 +305,165 @@ public String getAllIncentivesByUserId(GetBenRequestHandler request) { } else { entry.setName(""); } - if (entry.getVerifiedByUserId() != null) { - entry.setSupervisorRole(userRepo.getUserRole(entry.getVerifiedByUserId()).get(0).getRoleName()); - entry.setVerifiedByUserName(userRepo.getUserRole(entry.getVerifiedByUserId()).get(0).getName()); + if (entry.getVerifiedByUserId() != null) { + UserServiceRoleDTO role = verifierRoleMap.get(entry.getVerifiedByUserId()); + if (role != null) { + entry.setSupervisorRole(role.getRoleName()); + entry.setVerifiedByUserName(role.getName()); + } } + if (entry.getAshaId() != null) { if (entry.getCreatedBy() == null) { entry.setCreatedBy(userName); } - if (entry.getUpdatedBy() == null) { entry.setUpdatedBy(userName); } - if (entry.getIsEligible() == null) { entry.setIsEligible(true); } } - - } return modelMapper.map(entry, IncentiveRecordDTO.class); }).collect(Collectors.toList()); - finalDtos.addAll(dtos); + finalDtos.addAll(dtos); page++; } while (pageResult.hasNext()); - - Gson gson = new GsonBuilder().setDateFormat("MMM dd, yyyy h:mm:ss a").create(); return gson.toJson(finalDtos); } + + @Transactional + public void resetRejectedIncentivesForPreviousMonths() { + + ZoneId zoneId = ZoneId.of("Asia/Kolkata"); + + LocalDate firstDayOfCurrentMonth = + LocalDate.now(zoneId).withDayOfMonth(1); + + Timestamp currentMonthStart = + Timestamp.valueOf(firstDayOfCurrentMonth.atStartOfDay()); + + Timestamp now = + Timestamp.from(ZonedDateTime.now(zoneId).toInstant()); + + recordRepo.resetRejectedIncentivesForNewMonth( + currentMonthStart, + now, + "SYSTEM" + ); + } // ================= GROUPED SUMMARY ================= @Override - public String getAllIncentivesGroupedSummary(GetBenRequestHandler request) { - + public String getAllIncentivesGroupedSummary(GetBenRequestHandler request,Integer userId) { + String roleName = userService.getUserDetail(userId).getRoleName(); LocalDate start = LocalDate.of(request.getYear(), request.getMonth(), 1); LocalDate end = start.withDayOfMonth(start.lengthOfMonth()); - Timestamp startTs = Timestamp.valueOf(start.atStartOfDay()); - Timestamp endTs = Timestamp.valueOf(end.atTime(23, 59, 59)); + + LocalDate monthStart = LocalDate.of( + request.getYear(), + request.getMonth(), + 1 + ); + + Timestamp startTs = + Timestamp.valueOf(monthStart.atStartOfDay()); + + Timestamp nextMonthTs = + Timestamp.valueOf(monthStart.plusMonths(1).atStartOfDay()); Integer villageID = userRepo.getUserRole(request.getUserId()).get(0).getStateId(); boolean isCG = villageID != null && villageID.intValue() == StateCode.CG.getStateCode(); - + logger.info("Request getAllIncentivesGroupedSummary: "+request.getApprovalStatus()); List records = recordRepo.findRecordsByAsha(request.getUserId()) .stream() - .filter(r -> r.getCreatedDate() != null - && r.getEndDate() != null - && r.getEndDate().toLocalDateTime().getMonthValue() == request.getMonth() - && r.getEndDate().toLocalDateTime().getYear() == request.getYear() - && r.getIsClaimed()) - .toList(); + .filter(r -> + r.getCreatedDate() != null + + // Month filter using createdDate + && r.getCreatedDate() + .toLocalDateTime() + .getMonthValue() + == request.getMonth() + + && r.getCreatedDate() + .toLocalDateTime() + .getYear() + == request.getYear() + + && Boolean.TRUE.equals(r.getIsClaimed()) + + && ( + // Overdue: 102, 104 or 105 + ( + Objects.equals( + request.getApprovalStatus(), + 104 + ) + && ( + Objects.equals( + r.getApprovalStatus(), + 102 + ) + || Objects.equals( + r.getApprovalStatus(), + 104 + ) + || Objects.equals( + r.getApprovalStatus(), + 105 + ) + ) + ) + + || + + // Verified: 101 or 105 + ( + Objects.equals( + request.getApprovalStatus(), + 105 + ) + && ( + Objects.equals( + r.getApprovalStatus(), + 101 + ) + || Objects.equals( + r.getApprovalStatus(), + 105 + ) + ) + ) + + || + + // Other statuses + ( + !Objects.equals( + request.getApprovalStatus(), + 104 + ) + && !Objects.equals( + request.getApprovalStatus(), + 105 + ) + && Objects.equals( + r.getApprovalStatus(), + request.getApprovalStatus() + ) + ) + ) + ) + .collect(Collectors.toList()); // Bulk fetch valid activity IDs — state wise @@ -361,9 +476,91 @@ public String getAllIncentivesGroupedSummary(GetBenRequestHandler request) { : incentivesRepo.findValidActivityIds(activityIds, false); // Filter records based on valid activity IDs - records = records.stream() - .filter(r -> validActivityIds.contains(r.getActivityId())) - .collect(Collectors.toList()); + if(isCG){ + if("ASHA Supervisor".equalsIgnoreCase(roleName)){ + if(request.getApprovalStatus().equals(104)){ + records = records.stream() + .filter(r -> validActivityIds.contains(r.getActivityId()) && r.getIsDefaultActivity() && r.getApprovalStatus().equals(102)) + .collect(Collectors.toList()); + }else { + records = records.stream() + .filter(r -> validActivityIds.contains(r.getActivityId()) && r.getIsDefaultActivity()) + .collect(Collectors.toList()); + } + + }else if ("ANM".equalsIgnoreCase(roleName) || "CHO".equalsIgnoreCase(roleName)) { + if(request.getApprovalStatus().equals(102) || request.getApprovalStatus().equals(105)){ + records = records.stream() + .filter(record -> + validActivityIds.contains(record.getActivityId()) + ) + .filter(record -> + !Boolean.TRUE.equals( + record.getIsDefaultActivity() + ) + + || Boolean.TRUE.equals( + record.getIsApproved() + ) + ) + .collect(Collectors.toList()); + }else if(request.getApprovalStatus().equals(104)){ + records = records.stream() + .filter(r -> validActivityIds.contains(r.getActivityId())) + .filter(r -> { + if (Objects.equals(request.getApprovalStatus(), 104)) { + + boolean isDefault = + Boolean.TRUE.equals(r.getIsDefaultActivity()); + + boolean isApproved = + Boolean.TRUE.equals(r.getIsApproved()); + + // All non-default 102 records, + // and approved default 102 records + boolean status102 = + Objects.equals(r.getApprovalStatus(), 102) + && (!isDefault || isApproved); + + // Default 105 records, regardless of isApproved + boolean status105 = + Objects.equals(r.getApprovalStatus(), 105) + && isDefault; + + // Existing overdue records + boolean status104 = + Objects.equals(r.getApprovalStatus(), 104); + + return status102 || status105 || status104; + } + + return Objects.equals( + r.getApprovalStatus(), + request.getApprovalStatus() + ); + }) + .collect(Collectors.toList()); + }else { + records = records.stream() + .filter(r -> validActivityIds.contains(r.getActivityId())) + .collect(Collectors.toList()); + } + + + + + logger.info( + "ANM/CHO records after default activity filter: {}", + records.size() + ); + } + + }else { + records = records.stream() + .filter(r -> validActivityIds.contains(r.getActivityId())) + .collect(Collectors.toList()); + } + Map> grouped = records.stream().collect(Collectors.groupingBy(IncentiveActivityRecord::getActivityId)); @@ -378,6 +575,20 @@ public String getAllIncentivesGroupedSummary(GetBenRequestHandler request) { IncentiveActivity activity = incentivesRepo.findById(activityId).orElse(null); + Integer approvalStatus = list.stream() + .max(Comparator.comparing(IncentiveActivityRecord::getCreatedDate)) + .map(IncentiveActivityRecord::getApprovalStatus) + .orElse(0); + + boolean isApproved = list.stream() + .max(Comparator.comparing(IncentiveActivityRecord::getCreatedDate)) + .map(IncentiveActivityRecord::getIsApproved) + .orElse(false); + Long incentiveId = list.stream() + .max(Comparator.comparing(IncentiveActivityRecord::getCreatedDate)) + .map(IncentiveActivityRecord::getId) + .orElse(null); + if (activity == null) continue; long total = list.stream() @@ -385,19 +596,59 @@ public String getAllIncentivesGroupedSummary(GetBenRequestHandler request) { .sum(); Map map = new HashMap<>(); - map.put("activityId", activityId); - map.put("activityDec", activity.getDescription()); - map.put("groupName", activity.getGroup()); - map.put("claimCount", list.size()); - map.put("totalAmount", total); - map.put("amount", activity.getRate()); + if(isCG){ + map.put("activityId", activityId); + map.put("incentiveId",incentiveId); + map.put("activityDec", activity.getDescription()); + if(activity.getGroupCategoryName()!=null && !activity.getGroupCategoryName().isEmpty()){ + map.put("groupName", activity.getGroupCategoryName()); + + }else { + map.put("groupName", activity.getGroup()); + + } + map.put("isDefault", activity.getIsDefaultActivity()); + map.put("approvalStatus", approvalStatus); + map.put("isApproved", isApproved); + map.put("claimCount", list.size()); + map.put("totalAmount", total); + map.put("amount", activity.getRate()); + + }else { + map.put("activityId", activityId); + map.put("incentiveId",incentiveId); + map.put("activityDec", activity.getDescription()); + map.put("groupName", activity.getGroup()); + map.put("claimCount", list.size()); + map.put("totalAmount", total); + map.put("amount", activity.getRate()); + + } result.add(map); + + + } return new Gson().toJson(result); } + private boolean isAfter24Hours(Timestamp claimedDate) { + if (claimedDate == null) { + return false; + } + + long now = System.currentTimeMillis(); + long diff = now - claimedDate.getTime(); + + logger.info("Now: {}", new Timestamp(now)); + logger.info("ClaimedDate: {}", claimedDate); + logger.info("Diff(ms): {}", diff); + logger.info("Diff(hours): {}", diff / (1000 * 60 * 60.0)); + + return diff >= 24L * 60 * 60 * 1000; + } @Override public String getAllIncentivesGroupedActivity(GetBenRequestHandler request) { try { @@ -411,17 +662,75 @@ public String getAllIncentivesGroupedActivity(GetBenRequestHandler request) { List records = recordRepo.findRecordsByAsha(request.getUserId()) .stream() - .filter(r -> r.getActivityId() != null - && r.getActivityId().equals(request.getActivityId()) - && r.getCreatedDate() != null - && !r.getCreatedDate().before(startTs) - && r.getCreatedDate().before(endTs)) + .filter(r -> + r.getActivityId() != null + && Objects.equals( + r.getActivityId(), + request.getActivityId() + ) + && r.getCreatedDate() != null + && !r.getCreatedDate().before(startTs) + && r.getCreatedDate().before(endTs) + ) + .filter(r -> { + + Integer requestedStatus = + request.getApprovalStatus(); + + Integer recordStatus = + r.getApprovalStatus(); + + boolean isDefault = + Boolean.TRUE.equals( + r.getIsDefaultActivity() + ); + + boolean isApproved = + Boolean.TRUE.equals( + r.getIsApproved() + ); + + // Overdue + if (Objects.equals(requestedStatus, 104)) { + + // 102 non-default records OR approved default records + boolean status102 = + Objects.equals(recordStatus, 102) + && (!isDefault || isApproved); + + // 105 only for default activities + boolean status105 = + Objects.equals(recordStatus, 105) + && isDefault; + + // Existing overdue records + boolean status104 = + Objects.equals(recordStatus, 104); + + return status102 + || status105 + || status104; + } + + // Verified: 101 or 105 + if (Objects.equals(requestedStatus, 105)) { + return Objects.equals(recordStatus, 101) + || Objects.equals(recordStatus, 105); + } + + // Pending, rejected or other status + return Objects.equals( + recordStatus, + requestedStatus + ); + }) .collect(Collectors.toList()); if (records.isEmpty()) { return new Gson().toJson(new ArrayList<>()); } + // 🔹 Get beneficiary names Set benIds = records.stream() .map(IncentiveActivityRecord::getBenId) @@ -445,6 +754,7 @@ public String getAllIncentivesGroupedActivity(GetBenRequestHandler request) { incentivesRepo.findById(request.getActivityId()).orElse(null); String groupName = activity != null ? activity.getGroup() : ""; + String groupCategoryName = activity != null ? activity.getGroupCategoryName() :activity.getGroup(); String description = activity != null ? activity.getDescription() : ""; // 🔹 Map result @@ -458,7 +768,7 @@ public String getAllIncentivesGroupedActivity(GetBenRequestHandler request) { } } - r.setGroupName(groupName); + r.setGroupName(groupCategoryName); r.setActivityDec(description); return modelMapper.map(r, IncentiveRecordDTO.class); @@ -553,18 +863,87 @@ public String updateIncentive(PendingActivityDTO pendingActivityDTO) { // ================= UPDATE CLAIM ================= @Transactional - public String updateClaimStatus(Integer ashaId, Integer month, Integer year, Boolean isClaimed, String token) { + public String updateClaimStatus(Integer ashaId, Integer month, Integer year, Boolean isClaimed, String token,String incentive) { + String title = null; try { LocalDate start = LocalDate.of(year, month, 1); LocalDate end = start.plusMonths(1); - int updated = recordRepo.updateClaimStatusByAshaAndDateRange( - ashaId, - isClaimed, - Timestamp.valueOf(LocalDateTime.now()), - Timestamp.valueOf(start.atStartOfDay()), - Timestamp.valueOf(end.atStartOfDay()) - ); + int updated=0; + + Timestamp claimedDate = Timestamp.valueOf(LocalDateTime.now()); + + if (incentive == null || incentive.isEmpty()) { + + // No incentive IDs → all incentives for selected month/date range + updated = recordRepo.updateClaimStatusByAshaAndDateRange( + ashaId, + isClaimed, + claimedDate, + Timestamp.valueOf(start.atStartOfDay()), + Timestamp.valueOf(end.atStartOfDay()) + ); + + } else { + + for (String incentiveId : incentive.split(",")) { + + Long id = Long.parseLong(incentiveId.trim()); + updated = recordRepo.updateClaimStatusByAshaAndIncentiveIds( + ashaId, + isClaimed, + claimedDate,id + ); + } + } + + if (updated > 0) { + + Map data = new HashMap<>(); + data.put("notification_type", "INCENTIVE_APPROVAL"); + data.put("nav_id", "INCENTIVE_HISTORY"); + data.put("sender_user_id", String.valueOf(ashaId)); + data.put("receiver_user_id", String.valueOf(dashboardRepo.getSupervisorUserIdByAshaId(ashaId))); + data.put("month", String.valueOf(month)); + data.put("year", String.valueOf(year)); + data.put("approval_status", String.valueOf(102)); + data.put("priority", "HIGH"); + + title = "Incentive Claimed"; + + if (isClaimed) { + + String body = "Your incentive successfully claimed for month of " + + Month.of(month).name() + " " + year; + + notificationService.sendNotification( + "FLW", + "NA", + title, + body, + "INCENTIVE_CLAIMED", + "INCENTIVE", + dashboardRepo.getSupervisorUserIdByAshaId(ashaId) + ); + + String supervisorBody = + userService.getUserDetail(ashaId).getName() + + " successfully claimed incentive for month of " + + Month.of(month).name() + + " " + + year; + + notificationService.sendNotification( + "FLW", + "NA", + title, + supervisorBody, + "INCENTIVE_CLAIMED", + "INCENTIVE", + dashboardRepo.getSupervisorUserIdByAshaId(ashaId) + ); + } + } return updated > 0 ? "Success" : "No records"; @@ -691,15 +1070,15 @@ private void checkMonthlyAshaIncentive(Integer ashaId) { IncentiveActivity ADDITIONAL_ASHA_INCENTIVE = incentivesRepo.findIncentiveMasterByNameAndGroup("ADDITIONAL_ASHA_INCENTIVE", GroupName.ADDITIONAL_INCENTIVE.getDisplayName()); IncentiveActivity ASHA_MONTHLY_ROUTINE = incentivesRepo.findIncentiveMasterByNameAndGroup("ASHA_MONTHLY_ROUTINE", GroupName.ASHA_MONTHLY_ROUTINE.getDisplayName()); if (MOBILEBILLREIMB_ACTIVITY != null) { - addMonthlyAshaIncentiveRecord(MOBILEBILLREIMB_ACTIVITY, ashaId, userName); + addMonthlyAshaIncentiveRecord(MOBILEBILLREIMB_ACTIVITY, ashaId, userName,false); } if (ADDITIONAL_ASHA_INCENTIVE != null) { - addMonthlyAshaIncentiveRecord(ADDITIONAL_ASHA_INCENTIVE, ashaId, userName); + addMonthlyAshaIncentiveRecord(ADDITIONAL_ASHA_INCENTIVE, ashaId, userName,false); } if (ASHA_MONTHLY_ROUTINE != null) { - addMonthlyAshaIncentiveRecord(ASHA_MONTHLY_ROUTINE, ashaId, userName); + addMonthlyAshaIncentiveRecord(ASHA_MONTHLY_ROUTINE, ashaId, userName,false); } } catch (Exception e) { @@ -717,15 +1096,15 @@ private void checkMonthlyAshaIncentiveForCg(Integer ashaId) { IncentiveActivity MITANIN_REGISTER_5_INFO_FILL = incentivesRepo.findIncentiveMasterByNameAndGroup("MITANIN_REGISTER_5_INFO_FILL", GroupName.ACTIVITY.getDisplayName()); IncentiveActivity MITANIN_REGISTER = incentivesRepo.findIncentiveMasterByNameAndGroup("MITANIN_REGISTER", GroupName.ACTIVITY.getDisplayName()); if (MONTHLY_HONORARIUM != null) { - addMonthlyAshaIncentiveRecord(MONTHLY_HONORARIUM, ashaId, userName); + addMonthlyAshaIncentiveRecord(MONTHLY_HONORARIUM, ashaId, userName,true); } if (MITANIN_REGISTER_5_INFO_FILL != null) { - addMonthlyAshaIncentiveRecord(MITANIN_REGISTER_5_INFO_FILL, ashaId, userName); + addMonthlyAshaIncentiveRecord(MITANIN_REGISTER_5_INFO_FILL, ashaId, userName,false); } if (MITANIN_REGISTER != null) { - addMonthlyAshaIncentiveRecord(MITANIN_REGISTER, ashaId, userName); + addMonthlyAshaIncentiveRecord(MITANIN_REGISTER, ashaId, userName,false); } } catch (Exception e) { @@ -735,7 +1114,7 @@ private void checkMonthlyAshaIncentiveForCg(Integer ashaId) { } - private void addMonthlyAshaIncentiveRecord(IncentiveActivity incentiveActivity, Integer ashaId, String userName) { + private void addMonthlyAshaIncentiveRecord(IncentiveActivity incentiveActivity, Integer ashaId, String userName,Boolean isApproved) { try { Timestamp timestamp = Timestamp.valueOf(LocalDateTime.now()); @@ -764,6 +1143,7 @@ record = new IncentiveActivityRecord(); record.setAshaId(ashaId); record.setIsEligible(true); record.setIsDefaultActivity(true); + record.setIsApproved(isApproved); record.setAmount(Long.valueOf(incentiveActivity.getRate())); recordRepo.save(record); } diff --git a/src/main/java/com/iemr/flw/service/impl/MaternalHealthServiceImpl.java b/src/main/java/com/iemr/flw/service/impl/MaternalHealthServiceImpl.java index 23973862a..81eeb4ec8 100644 --- a/src/main/java/com/iemr/flw/service/impl/MaternalHealthServiceImpl.java +++ b/src/main/java/com/iemr/flw/service/impl/MaternalHealthServiceImpl.java @@ -216,8 +216,6 @@ public String saveANCVisit(List ancVisitDTOs, Integer userId) { benVisitDetail.setModifiedBy(it.getUpdatedBy()); benVisitDetail.setLastModDate(it.getUpdatedDate()); benVisitDetail.setProviderServiceMapID(it.getProviderServiceMapID()); - if (benVisitDetail.getCreatedDate() == null) - benVisitDetail.setCreatedDate(new java.sql.Timestamp(System.currentTimeMillis())); logger.info("Saving BenVisitDetail"); @@ -420,8 +418,6 @@ public String savePNCVisit(List pncVisitDTOs) { benVisitDetail.setProcessed("N"); benVisitDetail.setModifiedBy(it.getUpdatedBy()); benVisitDetail.setLastModDate(it.getUpdatedDate()); - if (benVisitDetail.getCreatedDate() == null) - benVisitDetail.setCreatedDate(new java.sql.Timestamp(System.currentTimeMillis())); benVisitDetail = benVisitDetailsRepo.save(benVisitDetail); // Saving Data in AncCare table @@ -443,22 +439,37 @@ public String savePNCVisit(List pncVisitDTOs) { logger.info("PNC visit details saved"); return "no of pnc details saved: " + pncList.size(); } catch (Exception e) { - logger.info("Saving PNC visit details failed with error : " + e.getMessage()); + logger.error("Saving PNC visit details failed", e); + } return null; } @Override @Transactional - public String saveANCVisitQuestions(List dtos, String authorization) throws IEMRException { + public String saveANCVisitQuestions( + List dtos, + String authorization) throws IEMRException { + Integer userId = jwtUtil.extractUserId(authorization); String userName = userRepo.getUserNamedByUserId(userId); - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); + if (dtos == null || dtos.isEmpty()) { + throw new IllegalArgumentException("ANC visit data is mandatory"); + } + + DateTimeFormatter formatter = DateTimeFormatter + .ofPattern("dd-MM-uuuu") + .withResolverStyle(java.time.format.ResolverStyle.STRICT); + List entities = new ArrayList<>(); for (AncCounsellingCareDTO dto : dtos) { + if (dto == null) { + throw new IllegalArgumentException("ANC visit record cannot be null"); + } + if (!StringUtils.hasText(dto.getVisitDate())) { throw new IllegalArgumentException("visitDate is mandatory"); } @@ -472,21 +483,35 @@ public String saveANCVisitQuestions(List dtos, String aut try { visitDate = LocalDate.parse(dto.getVisitDate(), formatter); } catch (DateTimeParseException e) { - throw new IllegalArgumentException("Invalid visitDate format, expected dd-MM-yyyy"); + throw new IllegalArgumentException( + "Invalid visitDate, expected dd-MM-yyyy"); } LocalDate homeVisitDate; try { homeVisitDate = StringUtils.hasText(fields.getHomeVisitDate()) ? LocalDate.parse(fields.getHomeVisitDate(), formatter) - : visitDate; // ✅ fallback + : visitDate; } catch (DateTimeParseException e) { - throw new IllegalArgumentException("Invalid home_visit_date format, expected dd-MM-yyyy"); + throw new IllegalArgumentException( + "Invalid home_visit_date, expected dd-MM-yyyy"); + } + + AncCounsellingCare entity; + + if (dto.getId() != null && dto.getId() > 0) { + // Update existing record + entity = ancCounsellingCareRepo.findById(dto.getId()) + .orElseThrow(() -> new IllegalArgumentException( + "ANC visit not found for id: " + dto.getId())); + } else { + // Create new record + entity = new AncCounsellingCare(); + entity.setBeneficiaryId(dto.getBeneficiaryId()); + entity.setUserId(userId); + entity.setCreatedBy(userName); } - AncCounsellingCare entity = new AncCounsellingCare(); - entity.setBeneficiaryId(dto.getBeneficiaryId()); - entity.setAncVisitId(0L); entity.setVisitDate(visitDate); entity.setHomeVisitDate(homeVisitDate); @@ -495,28 +520,28 @@ public String saveANCVisitQuestions(List dtos, String aut entity.setHighBp(yesNoToBoolean(fields.getHighBp())); entity.setConvulsions(yesNoToBoolean(fields.getConvulsions())); entity.setAnemia(yesNoToBoolean(fields.getAnemia())); - entity.setReducedFetalMovement(yesNoToBoolean(fields.getReducedFetalMovement())); + entity.setReducedFetalMovement( + yesNoToBoolean(fields.getReducedFetalMovement())); entity.setAgeRisk(yesNoToBoolean(fields.getAgeRisk())); entity.setChildGap(yesNoToBoolean(fields.getChildGap())); entity.setShortHeight(yesNoToBoolean(fields.getShortHeight())); entity.setPrePregWeight(yesNoToBoolean(fields.getPrePregWeight())); entity.setBleeding(yesNoToBoolean(fields.getBleeding())); - entity.setMiscarriageHistory(yesNoToBoolean(fields.getMiscarriageHistory())); + entity.setMiscarriageHistory( + yesNoToBoolean(fields.getMiscarriageHistory())); entity.setFourPlusDelivery(yesNoToBoolean(fields.getFourPlusDelivery())); entity.setFirstDelivery(yesNoToBoolean(fields.getFirstDelivery())); entity.setTwinPregnancy(yesNoToBoolean(fields.getTwinPregnancy())); entity.setCSectionHistory(yesNoToBoolean(fields.getCSectionHistory())); - entity.setPreExistingDisease(yesNoToBoolean(fields.getPreExistingDisease())); + entity.setPreExistingDisease( + yesNoToBoolean(fields.getPreExistingDisease())); entity.setFeverMalaria(yesNoToBoolean(fields.getFeverMalaria())); entity.setJaundice(yesNoToBoolean(fields.getJaundice())); entity.setSickleCell(yesNoToBoolean(fields.getSickleCell())); entity.setProlongedLabor(yesNoToBoolean(fields.getProlongedLabor())); entity.setMalpresentation(yesNoToBoolean(fields.getMalpresentation())); - entity.setUserId(userId); - entity.setCreatedBy(userName); entity.setUpdatedBy(userName); - entities.add(entity); } @@ -539,6 +564,7 @@ public List getANCCounselling(GetBenRequestHandle AncCounsellingCareResponseDTO responseDTO = new AncCounsellingCareResponseDTO(); responseDTO.setFormId("anc_form_001"); + responseDTO.setId(entity.getId()); responseDTO.setBeneficiaryId(entity.getBeneficiaryId()); // Update with actual value responseDTO.setVisitDate(entity.getVisitDate().format(formatter)); // Format visit.getVisitDate() @@ -572,7 +598,7 @@ public List getANCCounselling(GetBenRequestHandle fields.put("sickle_cell", booleanToYesNo(entity.getSickleCell())); fields.put("prolonged_labor", booleanToYesNo(entity.getProlongedLabor())); fields.put("malpresentation", booleanToYesNo(entity.getMalpresentation())); - + fields.put("id", entity.getId()); responseDTO.setFields(fields); responseDTOList.add(responseDTO); @@ -595,7 +621,6 @@ private Boolean yesNoToBoolean(String value) { private void checkAndAddAntaraIncentive(PNCVisit ect) { Integer userId = userRepo.getUserIdByName(ect.getCreatedBy()); Integer stateId = userRepo.getUserRole(userId).get(0).getStateId(); - logger.info("ContraceptionMethod:" + ect.getContraceptionMethod()); // logic for assam if (stateId.equals(StateCode.AM.getStateCode())) { @@ -664,18 +689,24 @@ private void checkAndAddAntaraIncentive(PNCVisit ect) { if (PPIUCDActivityCH != null) { - if (ect.getContraceptionMethod().equals("POST PARTUM IUCD (PPIUCD)")) { - addIncenticeRecord(ect, userId, PPIUCDActivityCH); + if(ect.getContraceptionMethod()!=null){ + if (ect.getContraceptionMethod().equals("POST PARTUM IUCD (PPIUCD)")) { + addIncenticeRecord(ect, userId, PPIUCDActivityCH); + } } + } if (femaleSterilizationActivityCH != null) { - if (ect.getContraceptionMethod().equals("FEMALE STERILIZATION")) { - addIncenticeRecord(ect, userId, femaleSterilizationActivityCH); + if(ect.getAnyContraceptionMethod()!=null){ + if (ect.getContraceptionMethod().equals("FEMALE STERILIZATION")) { + addIncenticeRecord(ect, userId, femaleSterilizationActivityCH); + } } + } @@ -712,18 +743,20 @@ private void checkAndAddAntaraIncentive(PNCVisit ect) { } if (ect.getPncPeriod() == 1 || ect.getPncPeriod() == 3 || ect.getPncPeriod() == 7) { + if(ect.getContraceptionMethod()!=null){ + if ((ect.getContraceptionMethod().equals("POST PARTUM STERILIZATION (PPS)") + || ect.getContraceptionMethod().equals("MiniLap")) + && ect.getSterilisationDate() != null) { + IncentiveActivity ppsActivityCH = + incentivesRepo.findIncentiveMasterByNameAndGroup("FP_PPS", GroupName.ACTIVITY.getDisplayName()); + if (ppsActivityCH != null) { - if ((ect.getContraceptionMethod().equals("POST PARTUM STERILIZATION (PPS)") - || ect.getContraceptionMethod().equals("MiniLap")) - && ect.getSterilisationDate() != null) { - IncentiveActivity ppsActivityCH = - incentivesRepo.findIncentiveMasterByNameAndGroup("FP_PPS", GroupName.ACTIVITY.getDisplayName()); - if (ppsActivityCH != null) { + addIncenticeRecord(ect, userId, ppsActivityCH); - addIncenticeRecord(ect, userId, ppsActivityCH); + } + } + } - } - } } } @@ -854,7 +887,7 @@ private void checkAndAddIncentives(List ancList, Integer userId) { if (ancFullActivityCH != null && ancVisit.getAncVisit() != null && ancVisit.getAncVisit() == 4) { - recordAncRelatedIncentive(ancFullActivityCH, ancVisit); + recordFullAncIncentive(ancFullActivityCH, ancVisit); } @@ -876,12 +909,12 @@ private void recordAncRelatedIncentive(IncentiveActivity incentiveActivity, ANCV if (record == null) { record = new IncentiveActivityRecord(); record.setActivityId(incentiveActivity.getId()); - record.setCreatedDate(ancVisit.getCreatedDate()); + record.setCreatedDate(ancVisit.getAncDate()); record.setCreatedBy(ancVisit.getCreatedBy()); - record.setUpdatedDate(ancVisit.getCreatedDate()); + record.setUpdatedDate(ancVisit.getAncDate()); record.setUpdatedBy(ancVisit.getCreatedBy()); - record.setStartDate(ancVisit.getCreatedDate()); - record.setEndDate(ancVisit.getCreatedDate()); + record.setStartDate(ancVisit.getAncDate()); + record.setEndDate(ancVisit.getAncDate()); record.setBenId(ancVisit.getBenId()); record.setAshaId(userId); record.setAmount(Long.valueOf(incentiveActivity.getRate())); diff --git a/src/main/java/com/iemr/flw/service/impl/NotificationSchedulerService.java b/src/main/java/com/iemr/flw/service/impl/NotificationSchedulerService.java index 21d0da458..39314c8ff 100644 --- a/src/main/java/com/iemr/flw/service/impl/NotificationSchedulerService.java +++ b/src/main/java/com/iemr/flw/service/impl/NotificationSchedulerService.java @@ -14,8 +14,6 @@ public class NotificationSchedulerService { final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); - @Autowired - private NotificationService notificationService; @Autowired EmployeeMasterInter employeeMasterInter; @@ -43,13 +41,6 @@ public void triggerAncRemindersForAllAsha() { String topic = "All"; // or some user/topic identifier String title = "ANC Reminder"; - notificationService.sendNotification( - appType, - topic, - title, - body, - redirectPath - ); } diff --git a/src/main/java/com/iemr/flw/service/impl/NotificationService.java b/src/main/java/com/iemr/flw/service/impl/NotificationService.java deleted file mode 100644 index 838ff3ac8..000000000 --- a/src/main/java/com/iemr/flw/service/impl/NotificationService.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.iemr.flw.service.impl; - -import com.google.gson.Gson; -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -import java.util.HashMap; -import java.util.Map; - -@Service -public class NotificationService { - final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); - - - private String NOTIFICATION_URL = "https://uatamrit.piramalswasthya.org/common-api/firebaseNotification/sendNotification"; - - public String sendNotification(String appType, String topic, String title, String body, String redirect) { - String authHeader = null; - String jwtToken = null; - - // Check if we have HTTP request context - ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); - if (attributes != null) { - HttpServletRequest httpServletRequest = attributes.getRequest(); - - authHeader = httpServletRequest.getHeader("Authorization"); - - if (httpServletRequest.getCookies() != null) { - for (Cookie cookie : httpServletRequest.getCookies()) { - if ("Jwttoken".equals(cookie.getName())) { - jwtToken = cookie.getValue(); - } - } - } - } - - // If no request context, set default (for scheduler/startup use) - if (authHeader == null) { - authHeader = "Bearer DEFAULT_TOKEN_IF_REQUIRED"; // or leave null if API allows - } - if (jwtToken == null) { - jwtToken = "DEFAULT_JWT_IF_REQUIRED"; - } - - RestTemplate restTemplate = new RestTemplate(); - MultiValueMap headers = new LinkedMultiValueMap<>(); - headers.add("Content-Type", "application/json"); -// headers.add("AUTHORIZATION", authHeader); -// headers.add("Cookie", "Jwttoken=" + jwtToken); - - Map requestBody = new HashMap<>(); - requestBody.put("appType", appType); - requestBody.put("token", topic); - requestBody.put("title", title); - requestBody.put("body", body); - - Map dataMap = new HashMap<>(); - dataMap.put("NotificationTypeId", redirect); - requestBody.put("data", dataMap); - - String jsonRequest = new Gson().toJson(requestBody); - - HttpEntity request = new HttpEntity<>(jsonRequest, headers); - - ResponseEntity response = restTemplate.exchange(NOTIFICATION_URL, HttpMethod.POST, request, String.class); - - return response.getBody(); - } -} diff --git a/src/main/java/com/iemr/flw/service/impl/NotificationServiceImpl.java b/src/main/java/com/iemr/flw/service/impl/NotificationServiceImpl.java new file mode 100644 index 000000000..8a157cb2f --- /dev/null +++ b/src/main/java/com/iemr/flw/service/impl/NotificationServiceImpl.java @@ -0,0 +1,222 @@ +package com.iemr.flw.service.impl; + +import com.google.gson.Gson; +import com.iemr.flw.domain.iemr.Notification; +import com.iemr.flw.domain.iemr.UserFcmTokenData; +import com.iemr.flw.dto.iemr.NotificationListDTO; +import com.iemr.flw.repo.iemr.NotificationRepository; +import com.iemr.flw.repo.iemr.UserFcmTokenRepo; +import com.iemr.flw.service.NotificationService; +import com.iemr.flw.utils.JwtUtil; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +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.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@Service +public class NotificationServiceImpl implements NotificationService { + final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); + + @Value("${common-api-base-url}") + private String commonApiBaseUrl; + @Autowired + private JwtUtil jwtUtil; + + @Autowired + private NotificationRepository notificationRepository; + + @Autowired + private UserFcmTokenRepo userFcmTokenRepo; + + + private String NOTIFICATION_URL = "/firebaseNotification/sendNotification"; + + public String sendNotification(String appType, String topic, String title, + String body, String redirect, + String notificationType, Integer receiverId) { + + logger.info("Initiating notification. appType={}, receiverId={}, type={} , commonApiBaseUrl={}", + appType, receiverId, notificationType,commonApiBaseUrl); + + try { + String authHeader = null; + ServletRequestAttributes attributes = + (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + + if (attributes != null) { + HttpServletRequest request = attributes.getRequest(); + authHeader = request.getHeader("jwtToken"); + } + + Integer senderId = jwtUtil.extractUserId(authHeader); + + logger.debug("Sender Id: {}", senderId); + + + UserFcmTokenData tokenData = userFcmTokenRepo.findByUserId(receiverId); + + if (tokenData == null) { + logger.warn("FCM token not found for receiverId={}", receiverId); + return "FCM token not found."; + } + + String token = tokenData.getToken(); + + + + RestTemplate restTemplate = new RestTemplate(); + + MultiValueMap headers = new LinkedMultiValueMap<>(); + headers.add("Content-Type", "application/json"); + headers.add("jwtToken", authHeader); + + Map requestBody = new HashMap<>(); + requestBody.put("appType", appType); + requestBody.put("token", token); + requestBody.put("title", title); + requestBody.put("body", body); + + Map dataMap = new HashMap<>(); + dataMap.put("notification_id", notificationType); + dataMap.put("notification_type", notificationType); + dataMap.put("nav_id", redirect); + dataMap.put("sender_user_id", senderId); + dataMap.put("receiver_user_id", receiverId); + dataMap.put("priority", "HIGH"); + dataMap.put("redirect", redirect); + + requestBody.put("data", dataMap); + + String jsonRequest = new Gson().toJson(requestBody); + + logger.debug("Notification request payload: {}", NOTIFICATION_URL); + HttpEntity request = new HttpEntity<>(jsonRequest, headers); + + ResponseEntity response = restTemplate.exchange( + commonApiBaseUrl+NOTIFICATION_URL, + HttpMethod.POST, + request, + String.class); + + logger.info("Notification API response. Status={}, Body={}", + response.getStatusCode(), + response.getBody()); + + saveNotificationRecord(appType, senderId, receiverId, title, body, + notificationType, "INCENTIVE_APPROVAL", redirect, "HIGH"); + + logger.info("Notification record saved successfully. receiverId={}", receiverId); + + return response.getBody(); + + } catch (HttpClientErrorException | HttpServerErrorException ex) { + + logger.error("Notification API failed. Status={}, Response={}", + ex.getStatusCode(), + ex.getResponseBodyAsString(), + ex); + + throw ex; + + } catch (Exception ex) { + + logger.error("Unexpected error while sending notification. receiverId={}, type={}", + receiverId, + notificationType, + ex); + + throw new RuntimeException("Failed to send notification.", ex); + } + } + + + private void saveNotificationRecord(String appType, Integer senderUserId, Integer receiverUserId, + String title, String body, String notificationType, + String navId, String redirect, String priority) { + try { + Notification notification = new Notification(); + notification.setAppType(appType); + notification.setSenderUserId(senderUserId); + notification.setReceiverUserId(receiverUserId); + notification.setTitle(title); + notification.setBody(body); + notification.setNotificationType(notificationType); + notification.setNavId(navId); + notification.setRedirect(redirect); + notification.setPriority(priority); + notification.setRead(false); + notificationRepository.save(notification); + } catch (Exception e) { + logger.error("Failed to persist notification record for receiver {}", receiverUserId, e); + } + } + + /** Paged list of a user's notifications, newest first, with unread count attached. */ + public NotificationListDTO getNotifications(Integer receiverUserId) { + + int page = 0; // First page + int size = 20; // Records per page + + Pageable pageable = PageRequest.of( + page, + size, + Sort.by(Sort.Direction.DESC, "createdDate") + ); + + Page result = + notificationRepository.findByReceiverUserIdOrderByCreatedDateDesc( + receiverUserId, + pageable + ); + + long unreadCount = + notificationRepository.countByReceiverUserIdAndIsReadFalse(receiverUserId); + + return new NotificationListDTO( + result.getContent(), + unreadCount, + result.getTotalElements(), + result.getNumber(), + result.getSize() + ); + } + + /** + * Lightweight call for a badge — no list, just the count. + */ + public Long getUnreadCount(Integer receiverUserId) { + return notificationRepository.countByReceiverUserIdAndIsReadFalse(receiverUserId); + } + + /** Marks a single notification read. Returns true if a row was updated. */ + public boolean markAsRead(Long notificationId) { + int updated = notificationRepository.markAsRead(notificationId, new Date()); + return updated > 0; + } + + /** Marks all of a user's notifications read. Returns the number updated. */ + public int markAllAsRead(Integer receiverUserId) { + return notificationRepository.markAllAsRead(receiverUserId, new Date()); + } +} diff --git a/src/main/java/com/iemr/flw/service/impl/SupervisorDashboardServiceImpl.java b/src/main/java/com/iemr/flw/service/impl/SupervisorDashboardServiceImpl.java index 771810e20..cc287117d 100644 --- a/src/main/java/com/iemr/flw/service/impl/SupervisorDashboardServiceImpl.java +++ b/src/main/java/com/iemr/flw/service/impl/SupervisorDashboardServiceImpl.java @@ -1,20 +1,21 @@ package com.iemr.flw.service.impl; +import java.math.BigDecimal; import java.sql.Timestamp; import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.time.Month; +import java.time.ZoneId; +import java.util.*; import java.util.stream.Collectors; +import com.google.gson.Gson; import com.iemr.flw.domain.iemr.IncentiveActivityRecord; import com.iemr.flw.dto.iemr.UserServiceRoleDTO; import com.iemr.flw.masterEnum.IncentiveApprovalStatus; +import com.iemr.flw.masterEnum.StateCode; import com.iemr.flw.repo.iemr.*; +import com.iemr.flw.service.NotificationService; import com.iemr.flw.service.UserService; import com.iemr.flw.utils.JwtUtil; import org.json.JSONArray; @@ -50,9 +51,17 @@ public class SupervisorDashboardServiceImpl implements SupervisorDashboardServic @Autowired private UserService userService; + @Autowired + private NotificationService notificationService; + @Override - public String getSupervisorDashboard(Integer supervisorUserID, Integer month, Integer year) { + public String getSupervisorDashboard(Integer supervisorUserID, Integer month, Integer year,Integer facilityId) { JSONObject result = new JSONObject(); + Integer stateId = userService.getUserDetail(supervisorUserID).getStateId(); + String rollName = userService.getUserDetail(supervisorUserID).getRoleName(); + + LocalDate today = LocalDate.now(); + // 1. Supervisor user details List supervisorRows = dashboardRepo.getSupervisorUserDetails(supervisorUserID); @@ -66,28 +75,99 @@ public String getSupervisorDashboard(Integer supervisorUserID, Integer month, In supervisor.put("gender", str(sRow[5]).isEmpty() ? JSONObject.NULL : str(sRow[5])); result.put("supervisor", supervisor); } + logger.info("Supervisor id"+supervisorUserID); // 2. Get all ASHAs with facility info - List ashaRows = dashboardRepo.getAshasWithFacilityInfo(supervisorUserID); + logger.info("Fetching ASHA details for supervisorUserID: {}", supervisorUserID); + + + LocalDate dueDate = LocalDate.of(year, month, 1) + .plusMonths(1) + .withDayOfMonth(5); + + boolean isOverDue = + (rollName.equalsIgnoreCase("ANM") || rollName.equalsIgnoreCase("ASHA Supervisor")) + && today.isAfter(dueDate); + + + List ashaRows; + + if ("ANM".equalsIgnoreCase(rollName) || "CHO".equalsIgnoreCase(rollName)) { + if(facilityId.equals(0)){ + List facilityIDs = + facilityLoginRepo.getUserFacilityIDs(supervisorUserID); + + ashaRows = + facilityLoginRepo.getAshaListByFacilities(facilityIDs); + }else { + + + ashaRows = facilityLoginRepo.getAshaListByFacilities( + Collections.singletonList(facilityId)); + } + + + } else { + if(facilityId.equals(0)){ + List facilityIDs = + facilityLoginRepo.getUserFacilityIDs(supervisorUserID); + + ashaRows = + facilityLoginRepo.getAshaListByFacilities(facilityIDs); + }else { + ashaRows = facilityLoginRepo.getAshaListByFacilities( + Collections.singletonList(facilityId)); + } + + + } + if (ashaRows == null || ashaRows.isEmpty()) { + logger.warn("No ASHA records found for supervisorUserID: {}", supervisorUserID); + result.put("totalAshaCount", 0); result.put("incentiveSummary", buildEmptyIncentiveSummary()); result.put("facilities", new JSONArray()); + + logger.info("Returning empty dashboard response for supervisorUserID: {}", supervisorUserID); + return result.toString(); } + + // Collect distinct facility IDs and ASHA IDs + + logger.info("Processing {} ASHA records", ashaRows.size()); + Set facilityIDSet = new HashSet<>(); Set ashaIDSet = new HashSet<>(); + for (Object[] row : ashaRows) { - if (row[3] != null) - facilityIDSet.add((Integer) row[3]); + + logger.info("Complete Row: {}", Arrays.toString(row)); + + for (int i = 0; i < row.length; i++) { + logger.info("row[{}] = {} ({})", + i, + row[i], + row[i] != null ? row[i].getClass().getName() : "null"); + } + + + if (row[4] != null) + facilityIDSet.add((Integer) row[4]); + if (row[0] != null) ashaIDSet.add((Integer) row[0]); + } + List facilityIDs = new ArrayList<>(facilityIDSet); List ashaIDs = new ArrayList<>(ashaIDSet); + logger.info("Facility IDs: {}", facilityIDs); + logger.info("ASHA IDs: {}", ashaIDs); result.put("totalAshaCount", ashaIDs.size()); // 3. Location from first facility @@ -116,7 +196,7 @@ public String getSupervisorDashboard(Integer supervisorUserID, Integer month, In } // 5. Get incentive status per ASHA (verified, rejected, pending, totalAmount) - long overallVerified = 0, overallRejected = 0, overallPending = 0; + long overallVerified = 0, overallRejected = 0, overallPending = 0, overallOverDue =0; long overallUnclaimed = 0; try { @@ -133,27 +213,181 @@ public String getSupervisorDashboard(Integer supervisorUserID, Integer month, In Timestamp endDate = Timestamp.valueOf(endLocalDate.atStartOfDay()); logger.info("Asha ID" + ashaIDs); - List statusRows = dashboardRepo.getIncentiveStatusByAshaIds(ashaIDs, startDate, endDate); - if (statusRows != null) { - for (Object[] sRow : statusRows) { - long verified = ((Number) sRow[2]).longValue(); - long rejected = ((Number) sRow[3]).longValue(); - long pending = ((Number) sRow[4]).longValue(); + if(stateId.equals(StateCode.AM.getStateCode())){ + List statusRows = dashboardRepo.getIncentiveStatusByAshaIds(ashaIDs, startDate, endDate); + if (statusRows != null) { + for (Object[] sRow : statusRows) { + long verified = ((Number) sRow[2]).longValue(); + long rejected = ((Number) sRow[3]).longValue(); + long pending = ((Number) sRow[4]).longValue(); + + if (verified > 0) overallVerified += 1; + if (rejected > 0) overallRejected += 1; + if (pending > 0) overallPending += 1; + } + } + List unclaimedRows = dashboardRepo.getUnclaimedCountByAshaIds(ashaIDs, startDate, endDate); + if (unclaimedRows != null) { + for (Object[] uRow : unclaimedRows) { + long count = ((Number) uRow[1]).longValue(); + if (count > 0) overallUnclaimed += 1; + } + } + }else if (stateId.equals(StateCode.CG.getStateCode())) { + + if ("ASHA Supervisor".equalsIgnoreCase(rollName)) { + + List statusRows = + dashboardRepo.getDefaultIncentiveStatusByAshaIds( + ashaIDs, + startDate, + endDate + ); + + if (statusRows != null) { + for (Object[] statusRow : statusRows) { + + long verified = statusRow[5] != null + ? ((Number) statusRow[5]).longValue() + : 0L; + + long rejected = statusRow[3] != null + ? ((Number) statusRow[3]).longValue() + : 0L; + + long pending = statusRow[4] != null + ? ((Number) statusRow[4]).longValue() + : 0L; + + if (verified > 0) { + overallVerified++; + } + + if (rejected > 0) { + overallRejected++; + } + + if (pending > 0) { + if (isOverDue) { + overallOverDue++; + } else { + overallPending++; + } + } + } + } - if (verified > 0) overallVerified += 1; - if (rejected > 0) overallRejected += 1; - if (pending > 0) overallPending += 1; + // ASHA Supervisor: only default unclaimed activities + List unclaimedRows = + dashboardRepo.getDefaultUnclaimedCountByAshaIds( + ashaIDs, + startDate, + endDate + ); + + if (unclaimedRows != null) { + for (Object[] unclaimedRow : unclaimedRows) { + + Integer ashaId = unclaimedRow[0] != null + ? ((Number) unclaimedRow[0]).intValue() + : null; + + long unclaimedCount = unclaimedRow[1] != null + ? ((Number) unclaimedRow[1]).longValue() + : 0L; + + logger.info( + "Supervisor unclaimed count: ashaId={}, count={}", + ashaId, + unclaimedCount + ); + + if (unclaimedCount > 0) { + overallUnclaimed++; + } + } } - } - List unclaimedRows = dashboardRepo.getUnclaimedCountByAshaIds(ashaIDs, startDate, endDate); - if (unclaimedRows != null) { - for (Object[] uRow : unclaimedRows) { - long count = ((Number) uRow[1]).longValue(); - if (count > 0) overallUnclaimed += 1; + + } else if ("ANM".equalsIgnoreCase(rollName) + || "CHO".equalsIgnoreCase(rollName)) { + + List statusRows = + dashboardRepo.getIncentiveStatusByAshaIdsForAnm( + ashaIDs, + startDate, + endDate + ); + + if (statusRows != null) { + for (Object[] statusRow : statusRows) { + + long verified = statusRow[2] != null + ? ((Number) statusRow[2]).longValue() + : 0L; + + long rejected = statusRow[3] != null + ? ((Number) statusRow[3]).longValue() + : 0L; + + long pending = statusRow[5] != null + ? ((Number) statusRow[5]).longValue() + : 0L; + + if (verified > 0) { + overallVerified++; + } + + if (rejected > 0) { + overallRejected++; + } + + if (pending > 0) { + if (isOverDue) { + overallOverDue++; + } else { + overallPending++; + } + } + } + } + + // ANM/CHO: all unclaimed activities + List unclaimedRows = + dashboardRepo.getUnclaimedCountByAshaIds( + ashaIDs, + startDate, + endDate + ); + + if (unclaimedRows != null) { + for (Object[] unclaimedRow : unclaimedRows) { + + Integer ashaId = unclaimedRow[0] != null + ? ((Number) unclaimedRow[0]).intValue() + : null; + + long unclaimedCount = unclaimedRow[1] != null + ? ((Number) unclaimedRow[1]).longValue() + : 0L; + + logger.info( + "ANM/CHO unclaimed count: ashaId={}, count={}", + ashaId, + unclaimedCount + ); + + if (unclaimedCount > 0) { + overallUnclaimed++; + } + } } } + } + + } catch (Exception e) { logger.error("Error fetching incentive status: " + e.getMessage(), e); + } @@ -163,14 +397,14 @@ public String getSupervisorDashboard(Integer supervisorUserID, Integer month, In overallSummary.put("verified", overallVerified); overallSummary.put("rejected", overallRejected); overallSummary.put("pending", overallPending); - overallSummary.put("overDue", 0); + overallSummary.put("overDue", overallOverDue); overallSummary.put("unclaimed", overallUnclaimed); result.put("incentiveSummary", overallSummary); // 7. Build facilities array with nested ASHAs Map> ashasByFacility = new HashMap<>(); for (Object[] row : ashaRows) { - Integer facID = (Integer) row[3]; + Integer facID = (Integer) row[4]; ashasByFacility.computeIfAbsent(facID, k -> new ArrayList<>()).add(row); } @@ -204,7 +438,6 @@ public String getSupervisorDashboard(Integer supervisorUserID, Integer month, In asha.put("fullName", fullName(row[1], row[2])); asha.put("employeeId", str(row[6]).isEmpty() ? JSONObject.NULL : str(row[6])); asha.put("mobile", str(row[7]).isEmpty() ? JSONObject.NULL : str(row[7])); - asha.put("gender", str(row[8]).isEmpty() ? JSONObject.NULL : str(row[8])); ashasArray.put(asha); } @@ -218,10 +451,360 @@ public String getSupervisorDashboard(Integer supervisorUserID, Integer month, In return result.toString(); } + + @Override - public Map getAshasAtFacility(Integer supervisorId, Integer facilityId, - Integer month, Integer year, Integer approvalStatusID) { - List rows; + public String getSupervisorSubCenter(Integer supervisorUserID, Integer month, Integer year) { + JSONObject result = new JSONObject(); + Integer stateId = userService.getUserDetail(supervisorUserID).getStateId(); + String rollName = userService.getUserDetail(supervisorUserID).getRoleName(); + + + // 1. Supervisor user details + List supervisorRows = dashboardRepo.getSupervisorUserDetails(supervisorUserID); + if (supervisorRows != null && !supervisorRows.isEmpty()) { + Object[] sRow = supervisorRows.get(0); + JSONObject supervisor = new JSONObject(); + supervisor.put("userId", sRow[0]); + supervisor.put("fullName", fullName(sRow[1], sRow[2])); + supervisor.put("employeeId", str(sRow[3]).isEmpty() ? JSONObject.NULL : str(sRow[3])); + supervisor.put("mobile", str(sRow[4]).isEmpty() ? JSONObject.NULL : str(sRow[4])); + supervisor.put("gender", str(sRow[5]).isEmpty() ? JSONObject.NULL : str(sRow[5])); + result.put("supervisor", supervisor); + } + logger.info("Supervisor id"+supervisorUserID); + + // 2. Get all ASHAs with facility info + logger.info("Fetching ASHA details for supervisorUserID: {}", supervisorUserID); + + + LocalDate today = LocalDate.now(ZoneId.of("Asia/Kolkata")); + + LocalDate dueDate = LocalDate.of(year, month, 1) + .plusMonths(1) + .withDayOfMonth(5); + + boolean isOverDue = + "ASHA Supervisor".equalsIgnoreCase(rollName) + && today.isAfter(dueDate); + + + List ashaRows; + + if ("ANM".equalsIgnoreCase(rollName) || "CHO".equalsIgnoreCase(rollName)) { + List facilityIDs = + facilityLoginRepo.getUserFacilityIDs(supervisorUserID); + + ashaRows = + facilityLoginRepo.getAshaListByFacilities(facilityIDs); + + + } else { + ashaRows = + dashboardRepo.getAshasWithFacilityInfo(supervisorUserID); + + + } + + if (ashaRows == null || ashaRows.isEmpty()) { + logger.warn("No ASHA records found for supervisorUserID: {}", supervisorUserID); + + result.put("totalAshaCount", 0); + result.put("incentiveSummary", buildEmptyIncentiveSummary()); + result.put("facilities", new JSONArray()); + + logger.info("Returning empty dashboard response for supervisorUserID: {}", supervisorUserID); + + return result.toString(); + } + + + + // Collect distinct facility IDs and ASHA IDs + + logger.info("Processing {} ASHA records", ashaRows.size()); + + Set facilityIDSet = new HashSet<>(); + Set ashaIDSet = new HashSet<>(); + + for (Object[] row : ashaRows) { + + logger.info("Complete Row: {}", Arrays.toString(row)); + + for (int i = 0; i < row.length; i++) { + logger.info("row[{}] = {} ({})", + i, + row[i], + row[i] != null ? row[i].getClass().getName() : "null"); + } + + + if (row[4] != null) + facilityIDSet.add((Integer) row[4]); + + if (row[0] != null) + ashaIDSet.add((Integer) row[0]); + + } + + List facilityIDs = new ArrayList<>(facilityIDSet); + List ashaIDs = new ArrayList<>(ashaIDSet); + + logger.info("Facility IDs: {}", facilityIDs); + logger.info("ASHA IDs: {}", ashaIDs); + result.put("totalAshaCount", ashaIDs.size()); + + // 3. Location from first facility + List facilityRows = dashboardRepo.getFacilityDetails(facilityIDs); + if (facilityRows != null && !facilityRows.isEmpty()) { + Object[] fRow = facilityRows.get(0); + JSONObject location = new JSONObject(); + location.put("state", str(fRow[2])); + location.put("district", str(fRow[3])); + location.put("blockOrUlb", str(fRow[4])); + location.put("locationType", str(fRow[5])); + result.put("location", location); + } + + // 4. Build village map (facilityID -> villages) + Map> villageMap = new HashMap<>(); + List villageRows = dashboardRepo.getVillagesForFacilities(facilityIDs); + if (villageRows != null) { + for (Object[] vRow : villageRows) { + Integer facID = (Integer) vRow[0]; + JSONObject village = new JSONObject(); + village.put("villageId", vRow[1]); + village.put("villageName", str(vRow[2])); + villageMap.computeIfAbsent(facID, k -> new ArrayList<>()).add(village); + } + } + + // 5. Get incentive status per ASHA (verified, rejected, pending, totalAmount) + long overallVerified = 0, overallRejected = 0, overallPending = 0, overallOverDue =0; + long overallUnclaimed = 0; + + try { + logger.info("Month: {}", month); + logger.info("Year: {}", year); + + LocalDate startLocalDate = LocalDate.of(year, month, 1); + LocalDate endLocalDate = startLocalDate.plusMonths(1); + + logger.info("startLocalDate {}", startLocalDate); + logger.info("endLocalDate {}", endLocalDate); + + Timestamp startDate = Timestamp.valueOf(startLocalDate.atStartOfDay()); + Timestamp endDate = Timestamp.valueOf(endLocalDate.atStartOfDay()); + logger.info("Asha ID" + ashaIDs); + + if(stateId.equals(StateCode.AM.getStateCode())){ + List statusRows = dashboardRepo.getIncentiveStatusByAshaIds(ashaIDs, startDate, endDate); + if (statusRows != null) { + for (Object[] sRow : statusRows) { + long verified = ((Number) sRow[2]).longValue(); + long rejected = ((Number) sRow[3]).longValue(); + long pending = ((Number) sRow[4]).longValue(); + + if (verified > 0) overallVerified += 1; + if (rejected > 0) overallRejected += 1; + if (pending > 0) overallPending += 1; + } + } + List unclaimedRows = dashboardRepo.getUnclaimedCountByAshaIds(ashaIDs, startDate, endDate); + if (unclaimedRows != null) { + for (Object[] uRow : unclaimedRows) { + long count = ((Number) uRow[1]).longValue(); + if (count > 0) overallUnclaimed += 1; + } + } + }else if(stateId.equals(StateCode.CG.getStateCode())){ + if("ASHA Supervisor".equalsIgnoreCase(rollName)){ + List statusRows = dashboardRepo.getDefaultIncentiveStatusByAshaIds(ashaIDs, startDate, endDate); + logger.info( + "Supervisor dashboard: role={}, today={}, dueDate={}, " + + "isOverDue={}, month={}, year={}, ashaIDs={}", + rollName, + today, + dueDate, + isOverDue, + month, + year, + ashaIDs + ); + + if (statusRows != null) { + for (Object[] statusRow : statusRows) { + + Integer ashaId = statusRow[0] != null + ? ((Number) statusRow[0]).intValue() + : null; + + long verified = statusRow[2] != null + ? ((Number) statusRow[2]).longValue() + : 0L; + + long rejected = statusRow[3] != null + ? ((Number) statusRow[3]).longValue() + : 0L; + + long pending = statusRow[4] != null + ? ((Number) statusRow[4]).longValue() + : 0L; + + logger.info( + "Supervisor status: ashaId={}, verified={}, rejected={}, " + + "pending={}, isOverDue={}", + ashaId, + verified, + rejected, + pending, + isOverDue + ); + + if (verified > 0) { + overallVerified++; + } + + if (rejected > 0) { + overallRejected++; + } + + if (pending > 0) { + if (isOverDue) { + overallOverDue++; + } else { + overallPending++; + } + } + } + } + }else if("ANM".equalsIgnoreCase(rollName)){ + List statusRows = dashboardRepo.getIncentiveStatusByAshaIdsForAnm(ashaIDs, startDate, endDate); + if (statusRows != null) { + for (Object[] sRow : statusRows) { + long verified = ((Number) sRow[2]).longValue(); + long rejected = ((Number) sRow[3]).longValue(); + long pending = ((Number) sRow[5]).longValue(); + + if (verified > 0) overallVerified += 1; + if (rejected > 0) overallRejected += 1; + if (pending > 0) { + if (isOverDue) { + overallOverDue++; + } else { + overallPending++; + } + } + } + } + } + + List unclaimedRows = dashboardRepo.getUnclaimedCountByAshaIds(ashaIDs, startDate, endDate); + if (unclaimedRows != null) { + for (Object[] uRow : unclaimedRows) { + long count = ((Number) uRow[1]).longValue(); + if (count > 0) overallUnclaimed += 1; + } + } + } + + + } catch (Exception e) { + logger.error("Error fetching incentive status: " + e.getMessage(), e); + + } + + + + // Overall incentive summary across all ASHAs + JSONObject overallSummary = new JSONObject(); + overallSummary.put("verified", overallVerified); + overallSummary.put("rejected", overallRejected); + overallSummary.put("pending", overallPending); + overallSummary.put("overDue", overallOverDue); + overallSummary.put("unclaimed", overallUnclaimed); + result.put("incentiveSummary", overallSummary); + + // 7. Build facilities array with nested ASHAs + Map> ashasByFacility = new HashMap<>(); + for (Object[] row : ashaRows) { + Integer facID = (Integer) row[4]; + ashasByFacility.computeIfAbsent(facID, k -> new ArrayList<>()).add(row); + } + + Map facilityDetailsMap = new HashMap<>(); + if (facilityRows != null) { + for (Object[] fRow : facilityRows) { + facilityDetailsMap.put((Integer) fRow[0], fRow); + } + } + + JSONArray facilitiesArray = new JSONArray(); + for (Integer facID : facilityIDs) { + JSONObject facility = new JSONObject(); + facility.put("facilityId", facID); + + Object[] fDetails = facilityDetailsMap.get(facID); + if (fDetails != null) { + facility.put("facilityName", str(fDetails[1])); + facility.put("facilityType", str(fDetails[6])); + } + + + // ASHAs at this facility + JSONArray ashasArray = new JSONArray(); + List facAshaRows = ashasByFacility.get(facID); + if (facAshaRows != null) { + for (Object[] row : facAshaRows) { + Integer ashaId = (Integer) row[0]; + JSONObject asha = new JSONObject(); + asha.put("userId", ashaId); + asha.put("fullName", fullName(row[1], row[2])); + asha.put("employeeId", str(row[6]).isEmpty() ? JSONObject.NULL : str(row[6])); + asha.put("mobile", str(row[7]).isEmpty() ? JSONObject.NULL : str(row[7])); + + ashasArray.put(asha); + } + } + + facility.put("ashaCount", ashasArray.length()); + facilitiesArray.put(facility); + } + + result.put("facilities", facilitiesArray); + return result.toString(); + } + + + + @Override + public Map getAshasAtFacility(Integer supervisorId, Integer facilityId, + Integer month, Integer year, Integer approvalStatusID) { + Integer supervisorstateCode = userService.getUserDetail(supervisorId).getStateId(); + List rows = null; + LocalDate today = LocalDate.now(); + + + String roleName = userService.getUserDetail(supervisorId).getRoleName(); + + LocalDate currentMonthStartDate = LocalDate.of(year, month, 1); + LocalDate currentMonthendLocalDate = currentMonthStartDate.plusMonths(1); + + LocalDate dueDate = LocalDate.of(year, month, 1) + .plusMonths(1) + .withDayOfMonth(5); + + boolean isOverDue = + ("ANM".equalsIgnoreCase(roleName) + || "ASHA Supervisor".equalsIgnoreCase(roleName)) + && today.isAfter(dueDate); + + + logger.info("Login user role:"+ roleName); + + boolean isCurrentMonth = + today.getYear() == year && + today.getMonthValue() == month; logger.info("approvalStatusID:" + approvalStatusID); List superVisorRow = ashaSupervisorLoginRepo.getAllMappedAshas(supervisorId); @@ -234,15 +817,57 @@ public Map getAshasAtFacility(Integer supervisorId, Integer faci Timestamp startDate = Timestamp.valueOf(startLocalDate.atStartOfDay()); Timestamp endDate = Timestamp.valueOf(endLocalDate.atStartOfDay()); - if (facilityId.equals(0)) { - rows = ashaSupervisorLoginRepo.getAshasAtFacility( - supervisorId, approvalStatusID, startDate, endDate); + + + + if ("ANM".equalsIgnoreCase(roleName) || "CHO".equalsIgnoreCase(roleName)) { + logger.info("ANM:" + roleName); + + if (facilityId.equals(0)) { + + List facilityIDs = facilityLoginRepo.getUserFacilityIDs(supervisorId); + rows = facilityLoginRepo.getAshaListByFacilities(facilityIDs); + + } else { + + rows = facilityLoginRepo.getAshaListByFacilities( + Collections.singletonList(facilityId)); + + } + } else { - rows = ashaSupervisorLoginRepo.getAshasAtFacility( - supervisorId, facilityId, approvalStatusID, startDate, endDate); + logger.info("Other:" + roleName); + + if (facilityId.equals(0)) { + if(supervisorstateCode.equals(StateCode.CG.getStateCode())){ + if("ASHA Supervisor".equalsIgnoreCase(roleName)){ + rows = ashaSupervisorLoginRepo.getAshasAtFacilityCg( + supervisorId, approvalStatusID, startDate, endDate); + } + }else if(supervisorstateCode.equals(StateCode.AM.getStateCode())){ + rows = ashaSupervisorLoginRepo.getAshasAtFacility( + supervisorId, approvalStatusID, startDate, endDate); + } + } else { + if(supervisorstateCode.equals(StateCode.CG.getStateCode())){ + if("ASHA Supervisor".equalsIgnoreCase(roleName)){ + rows = ashaSupervisorLoginRepo.getAshasAtFacilityCg( + supervisorId, facilityId, approvalStatusID, startDate, endDate); + } + }else if(supervisorstateCode.equals(StateCode.AM.getStateCode())){ + rows = ashaSupervisorLoginRepo.getAshasAtFacility( + supervisorId, facilityId, approvalStatusID, startDate, endDate); + } + + + } + } + logger.info("Other:" + rows); + long pending = 0, verified = 0, rejected = 0 , unclaimedCount = 0 , overDue = 0 ; + - long overallVerified = 0, overallRejected = 0, overallPending = 0; + long overallVerified = 0, overallRejected = 0, overallPending = 0 , overallUnclaimed=0 ,overallOverDue =0; String facilityName = ""; String facilityType = ""; @@ -259,23 +884,496 @@ public Map getAshasAtFacility(Integer supervisorId, Integer faci Map asha = new HashMap<>(); Integer ashaId = ((Number) row[0]).intValue(); + logger.info("ASHA_ID"+ashaId); + List countList =null; + + if(supervisorstateCode.equals(StateCode.CG.getStateCode())){ + + if("ASHA Supervisor".equalsIgnoreCase(roleName)){ + if(approvalStatusID.equals(106)){ + countList = incentiveRecordRepo.getStatusUnclaimedCountByAshaId(ashaId, startDate, endDate); + + }else { + countList = incentiveRecordRepo.getStatusCountByAshaIdOfDefaultActivity(ashaId, startDate, endDate); + + } + + logger.info("countList = {}", Arrays.deepToString(countList.toArray())); + + + + }else if(("ANM".equalsIgnoreCase(roleName) || "CHO".equalsIgnoreCase(roleName) )){ + logger.info("ASHA_ID = {}", ashaId); + logger.info("Role = {}", roleName); + + if(approvalStatusID.equals(106)){ + countList = incentiveRecordRepo.getStatusUnclaimedCountByAshaId(ashaId, startDate, endDate); + + }else { + countList = incentiveRecordRepo.getStatusCountByAshaIdANM(ashaId, startDate, endDate); + + } + + + logger.info("Count List = {}", countList); + + } + + }else if(supervisorstateCode.equals(StateCode.AM.getStateCode())){ + countList = incentiveRecordRepo.getStatusCountByAshaId(ashaId, startDate, endDate); + + } - List countList = incentiveRecordRepo.getStatusCountByAshaId(ashaId, startDate, endDate); Long totalAmount = null; if (userService.getUserDetail(ashaId) != null) { Integer stateCode = userService.getUserDetail(ashaId).getStateId(); - totalAmount = incentiveRecordRepo.getTotalAmountByAsha( - ashaId, startDate, endDate, approvalStatusID, stateCode); + if(stateCode.equals(StateCode.AM.getStateCode())){ + totalAmount = incentiveRecordRepo.getTotalAmountByAsha( + ashaId, startDate, endDate, approvalStatusID, stateCode); + }else if(stateCode.equals(StateCode.CG.getStateCode())){ - } + if("ASHA Supervisor".equalsIgnoreCase(roleName)){ + totalAmount = incentiveRecordRepo.getDefaultActivityTotalAmountByAsha( + ashaId, startDate, endDate, approvalStatusID, stateCode); + + }else if("ANM".equalsIgnoreCase(roleName) || "CHO".equalsIgnoreCase(roleName) ){ + totalAmount = incentiveRecordRepo.getTotalAmountByAsha( + ashaId, startDate, endDate, approvalStatusID, stateCode); + } + } + + + } + Integer stateCode = userService.getUserDetail(ashaId).getStateId(); + + + List incentiveActivityRecord = null; + if(stateCode.equals(StateCode.AM.getStateCode())){ + List dbRecords = + incentiveRecordRepo.getRecordsByAsha(ashaId, startDate, endDate); + incentiveActivityRecord= dbRecords + .stream() + .filter(r -> approvalStatusID == 0 || + approvalStatusID.equals(r.getApprovalStatus())) + .collect(Collectors.toList()); + }else if(stateCode.equals(StateCode.CG.getStateCode())){ + List dbRecords = + incentiveRecordRepo.getRecordsByAsha(ashaId, startDate, endDate); + + if (Objects.equals(approvalStatusID, 104) && isOverDue) { + if("ASHA Supervisor".equalsIgnoreCase(roleName)){ + incentiveActivityRecord = dbRecords.stream() + + // Overdue applicable statuses + + .filter(record -> + (Objects.equals(record.getApprovalStatus(), 102) + || Objects.equals(record.getApprovalStatus(), 104)) && record.getIsDefaultActivity() + ) + + + .peek(record -> { + logger.info( + "Overdue record matched: role={}, ashaId={}, " + + "recordId={}, oldStatus={}, default={}, " + + "approved={}, claimedDate={}", + roleName, + ashaId, + record.getId(), + record.getApprovalStatus(), + record.getIsDefaultActivity(), + record.getIsApproved(), + record.getCalimedDate() + ); + + record.setApprovalStatus(104); + }) + .collect(Collectors.toList()); + + overDue = incentiveActivityRecord.size(); + + totalAmount = incentiveActivityRecord.stream() + .map(IncentiveActivityRecord::getAmount) + .filter(Objects::nonNull) + .mapToLong(Long::longValue) + .sum(); + }else if("ANM".equalsIgnoreCase(roleName) || "CHO".equalsIgnoreCase(roleName)){ + incentiveActivityRecord = dbRecords.stream() + .filter(record -> { + + boolean isDefault = + Boolean.TRUE.equals(record.getIsDefaultActivity()); + + boolean isApproved = + Boolean.TRUE.equals(record.getIsApproved()); + + Integer status = record.getApprovalStatus(); + + // 102: + // Non-default OR approved default activity + boolean status102 = + Objects.equals(status, 102) + && (!isDefault || isApproved); + + // 105: + // Only default activity + boolean status105 = + Objects.equals(status, 105) + && isDefault; + + // Already overdue + boolean status104 = + Objects.equals(status, 104); + + return status102 || status105 || status104; + }) + .peek(record -> { + logger.info( + "Overdue record matched: role={}, ashaId={}, " + + "recordId={}, oldStatus={}, default={}, " + + "approved={}, claimedDate={}", + roleName, + ashaId, + record.getId(), + record.getApprovalStatus(), + record.getIsDefaultActivity(), + record.getIsApproved(), + record.getCalimedDate() + ); + + record.setApprovalStatus(104); + }) + .collect(Collectors.toList()); + + overDue = incentiveActivityRecord.size(); + + totalAmount = incentiveActivityRecord.stream() + .map(IncentiveActivityRecord::getAmount) + .filter(Objects::nonNull) + .mapToLong(Long::longValue) + .sum(); + + } + + + logger.info( + "Overdue final: role={}, ashaId={}, count={}, totalAmount={}", + roleName, + ashaId, + overDue, + totalAmount + ); + } else if("ASHA Supervisor".equalsIgnoreCase(roleName)){ + if (approvalStatusID.equals(102)) { + + incentiveActivityRecord = dbRecords.stream() + .filter(record -> + Objects.equals(record.getApprovalStatus(), 102) + ) + .filter(record -> + Boolean.TRUE.equals( + record.getIsDefaultActivity() + ) + ) + .peek(record -> { + logger.info( + "Supervisor record matched: ashaId={}, " + + "recordId={}, oldStatus={}, isOverDue={}, " + + "defaultActivity={}", + ashaId, + record.getId(), + record.getApprovalStatus(), + isOverDue, + record.getIsDefaultActivity() + ); + + if (isOverDue) { + record.setApprovalStatus(104); + } + }) + .collect(Collectors.toList()); + + if (isOverDue) { + overDue = incentiveActivityRecord.size(); + } + + totalAmount = incentiveActivityRecord.stream() + .map(IncentiveActivityRecord::getAmount) + .filter(Objects::nonNull) + .mapToLong(Long::longValue) + .sum(); + + }else if (approvalStatusID.equals(103)) { + + if (Objects.equals(approvalStatusID, 103)) { + + // ASHA Supervisor can view only rejected default activities + // that are unclaimed + incentiveActivityRecord = dbRecords.stream() + .filter(record -> + Objects.equals(record.getApprovalStatus(), 103) + && Boolean.TRUE.equals( + record.getIsDefaultActivity() + ) + ) + .collect(Collectors.toList()); + } + + + totalAmount = incentiveActivityRecord.stream() + .map(IncentiveActivityRecord::getAmount) + .filter(Objects::nonNull) + .mapToLong(Long::longValue) + .sum(); + + } else if (approvalStatusID.equals(104) && isOverDue) { + + /* + */ + incentiveActivityRecord = dbRecords.stream() + .filter(record -> + Objects.equals(record.getApprovalStatus(), 102) + || Objects.equals( + record.getApprovalStatus(), 104 + ) + || Objects.equals( + record.getApprovalStatus(), 105 + ) + ) + .filter(record -> + Boolean.TRUE.equals( + record.getIsDefaultActivity() + ) + ) + .peek(record -> + record.setApprovalStatus(104) + ) + .collect(Collectors.toList()); + + overDue = incentiveActivityRecord.size(); + + totalAmount = incentiveActivityRecord.stream() + .map(IncentiveActivityRecord::getAmount) + .filter(Objects::nonNull) + .mapToLong(Long::longValue) + .sum(); + + } else if (approvalStatusID.equals(105)) { + + incentiveActivityRecord = dbRecords.stream() + .filter(record -> + ( + Objects.equals( + record.getApprovalStatus(), 101 + ) + || Objects.equals( + record.getApprovalStatus(), 105 + ) + ) + && Boolean.TRUE.equals( + record.getIsDefaultActivity() + ) + ) + .collect(Collectors.toList()); + + } else if (approvalStatusID.equals(106)) { + + incentiveActivityRecord = dbRecords.stream() + .filter(record -> + Objects.equals(record.getApprovalStatus(), 102) + && Boolean.TRUE.equals( + record.getIsDefaultActivity() + ) + && !Boolean.TRUE.equals( + record.getIsClaimed() + ) + ) + .collect(Collectors.toList()); + + totalAmount = incentiveActivityRecord.stream() + .map(IncentiveActivityRecord::getAmount) + .filter(Objects::nonNull) + .mapToLong(Long::longValue) + .sum(); + + }else if (approvalStatusID.equals(0)) { + + incentiveActivityRecord = dbRecords.stream() + .filter(record -> + ( + Objects.equals( + record.getApprovalStatus(), 101 + ) + || Objects.equals( + record.getApprovalStatus(), 102 + ) + || Objects.equals( + record.getApprovalStatus(), 103 + ) + || Objects.equals( + record.getApprovalStatus(), 104 + ) + || Objects.equals( + record.getApprovalStatus(), 105 + ) + ) + && Boolean.TRUE.equals( + record.getIsDefaultActivity() + ) + ) + .collect(Collectors.toList()); + + } else { + + incentiveActivityRecord = Collections.emptyList(); + } + + }else if ("ANM".equalsIgnoreCase(roleName) || "CHO".equalsIgnoreCase(roleName)) { + if (approvalStatusID.equals(102)) { + if (Objects.equals(approvalStatusID, 102)) { + + incentiveActivityRecord = dbRecords.stream() + + .filter(record -> + Objects.equals(record.getApprovalStatus(), 102) + || Objects.equals( + record.getApprovalStatus(), 105 + ) + ) + + .peek(record -> { + if (Objects.equals(record.getApprovalStatus(), 102) + && Boolean.TRUE.equals( + record.getIsDefaultActivity() + ) + && Boolean.TRUE.equals( + record.getIsApproved() + )) { + + logger.info( + "Changing record status 102 to 105: " + + "id={}, activityId={}", + record.getId(), + record.getActivityId() + ); + + record.setApprovalStatus(105); + } + }) + + + .filter(record -> + !Boolean.TRUE.equals( + record.getIsDefaultActivity() + ) + || Boolean.TRUE.equals( + record.getIsApproved() + ) + ) + .collect(Collectors.toList()); + + totalAmount = incentiveActivityRecord.stream() + .map(IncentiveActivityRecord::getAmount) + .filter(Objects::nonNull) + .mapToLong(Long::longValue) + .sum(); + + logger.info( + "ANM final filtered records: count={}, totalAmount={}", + incentiveActivityRecord.size(), + totalAmount + ); + + incentiveActivityRecord.forEach(record -> + logger.info( + "Final record: id={}, activityId={}, status={}, " + + "default={}, approved={}", + record.getId(), + record.getActivityId(), + record.getApprovalStatus(), + record.getIsDefaultActivity(), + record.getIsApproved() + ) + ); + } + totalAmount = incentiveActivityRecord.stream() + .map(IncentiveActivityRecord::getAmount) + .filter(Objects::nonNull) + .mapToLong(Long::longValue) + .sum(); + + dbRecords.forEach(r -> + logger.info( + "DB Record -> id: {}, approvalStatus: {}, ashaId: {}, benId: {}, activityId: {}", + r.getId(), + r.getApprovalStatus(), + r.getAshaId(), + r.getBenId(), + r.getActivityId() + ) + ); + }else if (Objects.equals(approvalStatusID, 103)) { + + // ANM/CHO can view all rejected activities + // that are unclaimed + incentiveActivityRecord = dbRecords.stream() + .filter(record -> + Objects.equals(record.getApprovalStatus(), 103) + + ) + .collect(Collectors.toList()); + totalAmount = incentiveActivityRecord.stream() + .map(IncentiveActivityRecord::getAmount) + .filter(Objects::nonNull) + .mapToLong(Long::longValue) + .sum(); + }else if(approvalStatusID.equals(106)){ + incentiveActivityRecord = dbRecords.stream() + .filter(r->!r.getIsClaimed() && r.getApprovalStatus().equals(102)).peek(r->{r.setApprovalStatus(106);}).collect(Collectors.toList()); + totalAmount = incentiveActivityRecord.stream() + .map(IncentiveActivityRecord::getAmount) + .filter(Objects::nonNull) + .mapToLong(Long::longValue) + .sum(); + }else if(approvalStatusID.equals(0)){ + incentiveActivityRecord = dbRecords.stream() + .filter(r->((r.getApprovalStatus().equals(102) && r.getIsClaimed()) ||(r.getApprovalStatus().equals(102) && !r.getIsClaimed()) || r.getApprovalStatus().equals(103) || r.getApprovalStatus().equals(105) || r.getApprovalStatus().equals(101) || r.getApprovalStatus().equals(104))).collect(Collectors.toList()); + } else{ + incentiveActivityRecord = dbRecords.stream() + .filter(r -> { + + if (approvalStatusID != 0 + && !approvalStatusID.equals(r.getApprovalStatus())) { + return false; + } + + // 102 should be visible only after 24 hours + if (r.getApprovalStatus().equals(102)) { + return true; + } + + // 105 should always be visible + return true; + }) + .peek(r -> { + if (r.getApprovalStatus().equals(102)) { + r.setApprovalStatus(105); + } + }) + .collect(Collectors.toList()); + } + + } + + + logger.info("CG - Records after approvalStatus filter: {}", incentiveActivityRecord.size()); + + } + logger.info("Final incentiveActivityRecord count: {}", incentiveActivityRecord.size()); + logger.info("Final incentiveActivityRecord: {}", + new Gson().toJson(incentiveActivityRecord)); - List incentiveActivityRecord = - incentiveRecordRepo.getRecordsByAsha(ashaId, startDate, endDate) - .stream() - .filter(r -> approvalStatusID == 0 || - approvalStatusID.equals(r.getApprovalStatus())) - .collect(Collectors.toList()); List> activityList = new ArrayList<>(); for (IncentiveActivityRecord record : incentiveActivityRecord) { Map activity = new HashMap<>(); @@ -285,14 +1383,16 @@ public Map getAshasAtFacility(Integer supervisorId, Integer faci activity.put("approvalStatus", record.getApprovalStatus()); if(record.getVerifiedByUserId()!=null){ activity.put("verifiedByUserName", userService.getUserDetail(record.getVerifiedByUserId()).getName()); + activity.put("verifiedByUserId", record.getVerifiedByUserId()); + UserServiceRoleDTO roles = userService.getUserDetail(record.getVerifiedByUserId()); + activity.put("role", (roles != null ) ? roles.getRoleName() : null); + } - activity.put("verifiedByUserId", record.getVerifiedByUserId()); activity.put("isClaimed", record.getIsClaimed()); activity.put("claimedDate", record.getCalimedDate()); - UserServiceRoleDTO roles = userService.getUserDetail(record.getVerifiedByUserId()); - activity.put("role", (roles != null ) ? roles.getRoleName() : null); + activityList.add(activity); } @@ -302,34 +1402,114 @@ public Map getAshasAtFacility(Integer supervisorId, Integer faci asha.put("facilityType", facilityType); asha.put("userId", row[0]); asha.put("fullName", fullName(row[1], row[2])); - asha.put("employeeId", str(row[3]).isEmpty() ? null : str(row[3])); + asha.put("employeeId", row[0]); asha.put("mobile", str(row[4]).isEmpty() ? null : str(row[4])); asha.put("gender", str(row[5]).isEmpty() ? null : str(row[5])); asha.put("totalAmount", totalAmount); asha.put("activities", activityList); - long pending = 0, verified = 0, rejected = 0; + + + + if (countList != null && !countList.isEmpty()) { Object[] counts = countList.get(0); - verified = counts[0] != null ? ((Number) counts[0]).longValue() : 0; - pending = counts[1] != null ? ((Number) counts[1]).longValue() : 0; - rejected = counts[2] != null ? ((Number) counts[2]).longValue() : 0; + logger.info("Count List = {}", Arrays.deepToString(countList.toArray())); + logger.info("101={}, 102={}, 103={}, 101+105={}", + counts[0], counts[1], counts[2], counts[3]); + + if(stateCode.equals(StateCode.CG.getStateCode())){ + if(roleName.equalsIgnoreCase("ANM")){ + verified = counts[0] != null ? ((Number) counts[0]).longValue() : 0; + rejected = counts[2] != null ? ((Number) counts[2]).longValue() : 0; + if(approvalStatusID.equals(106)){ + unclaimedCount = counts[1] != null ? ((Number) counts[1]).longValue() : 0; + + }else if(approvalStatusID.equals(0)){ + unclaimedCount = counts[1] != null ? ((Number) counts[1]).longValue() : 0; + pending = counts[3] != null ? ((Number) counts[3]).longValue() : 0; + + }else{ + + pending = counts[3] != null ? ((Number) counts[3]).longValue() : 0; + + } + + + }else if(roleName.equalsIgnoreCase("ASHA Supervisor")) { + verified = counts[0] != null ? ((Number) counts[0]).longValue() : 0; + + if(approvalStatusID.equals(106)){ + unclaimedCount = counts[1] != null ? ((Number) counts[1]).longValue() : 0; + + }else if(approvalStatusID.equals(0)){ + unclaimedCount = counts[1] != null ? ((Number) counts[1]).longValue() : 0; + pending = counts[1] != null ? ((Number) counts[1]).longValue() : 0; + + }else{ + pending = counts[1] != null ? ((Number) counts[1]).longValue() : 0; + + } + rejected = counts[2] != null ? ((Number) counts[2]).longValue() : 0; + + + } + }else { + verified = counts[0] != null ? ((Number) counts[0]).longValue() : 0; + pending = counts[1] != null ? ((Number) counts[1]).longValue() : 0; + rejected = counts[2] != null ? ((Number) counts[2]).longValue() : 0; + } + } + + if (verified > 0) overallVerified += 1; if (rejected > 0) overallRejected += 1; - if (pending > 0) overallPending += 1; + if (pending > 0) { + if (isOverDue) { + overallOverDue++; + } else { + overallPending++; + } + } + + if (unclaimedCount > 0) overallUnclaimed += 1; asha.put("pending", pending); asha.put("verified", verified); asha.put("rejected", rejected); + asha.put("unClaimed", unclaimedCount); int approvalStatus = 0; if (!activityList.isEmpty()) { approvalStatus = (int) activityList.get(0).get("approvalStatus"); } - if (pending == 0 && verified == 0 && rejected == 0) continue; + if ((!approvalStatusID.equals(106) || !facilityId.equals(0))) { + + if (totalAmount == null || totalAmount <= 0) { + logger.info( + "Skipping ASHA {} because totalAmount={}", + ashaId, + totalAmount + ); + continue; + } + } + + logger.info( + "Incentive counts for ASHA ID {} - pending: {}, verified: {}, rejected: {}, unclaimedCount: {}, overallOverDue: {} , approvalStatus: {}", + ashaId, + pending, + verified, + rejected, + unclaimedCount, + overallOverDue,approvalStatus + ); + + if (pending == 0 && verified == 0 && rejected == 0 && unclaimedCount == 0 && overDue==0) continue; + if (approvalStatusID.equals(0)) { asha.put("approvalStatus", approvalStatus); @@ -347,6 +1527,7 @@ public Map getAshasAtFacility(Integer supervisorId, Integer faci approvalStatus.put("verified", overallVerified); approvalStatus.put("pending", overallPending); approvalStatus.put("rejected", overallRejected); + approvalStatus.put("unClaimed", overallUnclaimed); response.put("approvalStatus", approvalStatus); response.put("data", ashaList); @@ -355,6 +1536,31 @@ public Map getAshasAtFacility(Integer supervisorId, Integer faci return response; } + private boolean isAfter24Hours(Timestamp claimedDate) { + if (claimedDate == null) { + return false; + } + + long now = System.currentTimeMillis(); + long diff = now - claimedDate.getTime(); + + logger.info("Now: {}", new Timestamp(now)); + logger.info("ClaimedDate: {}", claimedDate); + logger.info("Diff(ms): {}", diff); + logger.info("Diff(hours): {}", diff / (1000 * 60 * 60.0)); + + return diff >= 24L * 60 * 60 * 1000; + } + private boolean isWithin24Hours(Timestamp claimedDate) { + if (claimedDate == null) { + return false; + } + + long diff = System.currentTimeMillis() - claimedDate.getTime(); + return diff <= 24 * 60 * 60 * 1000L; + } + + private String getGroupNameByState(Integer stateCode) { switch (stateCode) { case 5: @@ -374,6 +1580,8 @@ public int updateApprovalStatus(Integer ashaId, String otherReason, String token) { try { + String title = null; + String body = null; Timestamp approvalDate = Timestamp.valueOf(LocalDateTime.now()); LocalDate startLocalDate = LocalDate.of(year, month, 1); @@ -384,32 +1592,136 @@ public int updateApprovalStatus(Integer ashaId, Integer ashaSupervisorUserId = jwtUtil.extractUserId(token); logger.info("Asha Supervisor User Id : {}", ashaSupervisorUserId); - String ashaSupervisorUsername = userService.getUserDetail(ashaSupervisorUserId).getUserName(); + logger.info("Asha Incentive Id : {}", incentiveIds); + UserServiceRoleDTO ashaSupervisorDetails = userService.getUserDetail(ashaSupervisorUserId); + + int updatedCount = 0; + if(incentiveIds.isEmpty()){ + if (approvalStatus.equals(IncentiveApprovalStatus.REJECTED.getCode())) { + updatedCount = incentiveRecordRepo.updateApprovalStatusById( + approvalStatus, + ashaId, + ashaSupervisorUserId, + ashaSupervisorDetails.getUserName(), + reason, + approvalDate, + otherReason + ); + } else { + + if (ashaSupervisorDetails.getStateId().equals(StateCode.AM.getStateCode())) { + + updatedCount = incentiveRecordRepo.updateApprovalStatusByAshaAndDateRange( + ashaId, approvalStatus, startDate, endDate, + approvalDate, ashaSupervisorUserId, + ashaSupervisorDetails.getUserName()); - if (approvalStatus.equals(IncentiveApprovalStatus.REJECTED.getCode())) { - int totalUpdated = 0; + } else if(ashaSupervisorDetails.getStateId().equals(StateCode.CG.getStateCode())){ - totalUpdated += incentiveRecordRepo.updateApprovalStatusById( + if ("ASHA Supervisor".equalsIgnoreCase(ashaSupervisorDetails.getRoleName())) { + + updatedCount = incentiveRecordRepo.updateApprovalStatusByAshaAndDateRange( + ashaId, 105, startDate, endDate, + approvalDate, ashaSupervisorUserId, + ashaSupervisorDetails.getUserName()); + + } else if("ANM".equalsIgnoreCase(ashaSupervisorDetails.getRoleName())){ + + updatedCount = incentiveRecordRepo.updateApprovalStatusByAshaAndDateRangeForDefaultActivity( + ashaId, approvalStatus, startDate, endDate, + approvalDate, ashaSupervisorUserId, + ashaSupervisorDetails.getUserName()); + + } + } + } + }else { + if (approvalStatus.equals(IncentiveApprovalStatus.REJECTED.getCode())) { + if (incentiveIds != null && !incentiveIds.trim().isEmpty()) { + List ids = Arrays.stream(incentiveIds.split(",")) + .map(String::trim) + .filter(value -> !value.isEmpty()) + .map(Long::valueOf) + .collect(Collectors.toList()); + + updatedCount += incentiveRecordRepo.updateApprovalStatusByIdsAndIncentiveIds( + approvalStatus, + ashaId, + ashaSupervisorUserId, + ashaSupervisorDetails.getUserName(), + reason, + approvalDate, + otherReason, + ids + ); + } + } else { + + if (ashaSupervisorDetails.getStateId().equals(StateCode.AM.getStateCode())) { + if (incentiveIds != null && !incentiveIds.trim().isEmpty()) { + + for (String incentiveId : incentiveIds.split(",")) { + + Long id = Long.parseLong(incentiveId.trim()); + + updatedCount = incentiveRecordRepo.updateApprovalStatusByIncentiveId(id, ashaId, approvalStatus, approvalDate, ashaSupervisorUserId, ashaSupervisorDetails.getUserName()); + + } + } + + + } else if(ashaSupervisorDetails.getStateId().equals(StateCode.CG.getStateCode())){ + + if ("ASHA Supervisor".equalsIgnoreCase(ashaSupervisorDetails.getRoleName())) { + + if (incentiveIds != null && !incentiveIds.trim().isEmpty()) { + + List ids = Arrays.stream(incentiveIds.split(",")) + .map(String::trim) + .filter(value -> !value.isEmpty()) + .map(Long::valueOf) + .collect(Collectors.toList()); + + updatedCount = incentiveRecordRepo.updateApprovalStatusByIncentiveIds(ids, ashaId, 105, approvalDate, ashaSupervisorUserId, ashaSupervisorDetails.getUserName()); + + } + + + } else if("ANM".equalsIgnoreCase(ashaSupervisorDetails.getRoleName())){ + + if (incentiveIds != null && !incentiveIds.trim().isEmpty()) { + List ids = Arrays.stream(incentiveIds.split(",")) + .map(String::trim) + .filter(value -> !value.isEmpty()) + .map(Long::valueOf) + .collect(Collectors.toList()); + + updatedCount = incentiveRecordRepo.updateApprovalStatusByIncentiveIds(ids, + ashaId, approvalStatus, + approvalDate, ashaSupervisorUserId, + ashaSupervisorDetails.getUserName()); + } + + } + } + } + } + + + if (updatedCount > 0) { + sendApprovalNotification( approvalStatus, - ashaSupervisorUserId, - ashaSupervisorUsername, + ashaId, + month, + year, reason, - approvalDate, - otherReason + otherReason, + ashaSupervisorUserId, + ashaSupervisorDetails ); - - return totalUpdated; } - return incentiveRecordRepo.updateApprovalStatusByAshaAndDateRange( - ashaId, - approvalStatus, - startDate, - endDate, - approvalDate, - ashaSupervisorUserId, - ashaSupervisorUsername - ); + return updatedCount; } catch (Exception e) { logger.error("Update claim :" + e.getMessage()); @@ -418,6 +1730,72 @@ public int updateApprovalStatus(Integer ashaId, } } + + private void sendApprovalNotification( + Integer approvalStatus, + Integer ashaId, + Integer month, + Integer year, + String reason, + String otherReason, + Integer supervisorId, + UserServiceRoleDTO supervisor) { + + String title; + String body; + + if (approvalStatus.equals(IncentiveApprovalStatus.REJECTED.getCode())) { + + title = "Incentive Rejected"; + + body = "Incentive claim for " + Month.of(month).name() + " " + year + " has been rejected."; + + notificationService.sendNotification( + "FLW", "NA", + title, + body, + "INCENTIVE_REJECTED", + "INCENTIVE", + supervisorId); + + body = supervisor.getName() + " has rejected your incentive claim for " + + Month.of(month).name() + " " + year + "due to "+reason+" "+otherReason; + + notificationService.sendNotification( + "FLW", "NA", + title, + body, + "INCENTIVE_REJECTED", + "INCENTIVE", + ashaId); + + } else { + + title = "Incentive Approved"; + + body = "Incentive claim for " + Month.of(month).name() + " " + year + " has been approved."; + + notificationService.sendNotification( + "FLW", "NA", + title, + body, + "INCENTIVE_CLAIMED", + "INCENTIVE", + supervisorId); + + body = supervisor.getName() + " has approved your incentive claim for " + + Month.of(month).name() + " " + year; + + notificationService.sendNotification( + "FLW", "NA", + title, + body, + "INCENTIVE_CLAIMED", + "INCENTIVE", + ashaId); + } + } + private JSONObject buildEmptyIncentiveSummary() { JSONObject summary = new JSONObject(); summary.put("verified", 0); diff --git a/src/main/java/com/iemr/flw/service/impl/UTPReronaPaymentJob.java b/src/main/java/com/iemr/flw/service/impl/UTPReronaPaymentJob.java index c45f18e1c..30a791020 100644 --- a/src/main/java/com/iemr/flw/service/impl/UTPReronaPaymentJob.java +++ b/src/main/java/com/iemr/flw/service/impl/UTPReronaPaymentJob.java @@ -11,6 +11,8 @@ import com.iemr.flw.repo.iemr.IncentivesRepo; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -23,7 +25,7 @@ @Slf4j @Component -public class UTPReronaPaymentJob { +public class UTPReronaPaymentJob implements CommandLineRunner { @Autowired private IncentiveRecordRepo recordRepo; @@ -34,18 +36,76 @@ public class UTPReronaPaymentJob { @Autowired private UtpreronaPaymentIntegrationImpl paymentService; - // Runs automatically on 1st of every month at midnight - @Scheduled(cron = "0 0 0 1 * *") - public void sendMonthlyPayments() { - triggerPayment(); - } +// // Runs automatically on 1st of every month at midnight +// @Scheduled(cron = "0 0 0 1 * *") +// public void sendMonthlyPayments() { +// triggerPayment(); +// } + + @Override + public void run(String... args) { + log.info("========================================"); + + log.info("FLW application started successfully and is now running."); + + log.info("========================================"); + triggerStaticPayment(); + } // ✅ Separate method — call this for immediate testing + + public void triggerStaticPayment() { + try { + Period period = new Period(); + period.setStart("2026-01-01"); + period.setEnd("2026-01-31"); + + VerifiedBy verifiedBy = new VerifiedBy(); + verifiedBy.setEmployeeId("34455"); + verifiedBy.setName("ASHA Supervisor/CHO name"); + + List items = new ArrayList<>(); + + PaymentItem item1 = new PaymentItem(); + item1.setActivityCode("1"); + item1.setCount("3"); + item1.setIncentiveAmount("300"); + items.add(item1); + + PaymentItem item2 = new PaymentItem(); + item2.setActivityCode("2"); + item2.setCount("4"); + item2.setIncentiveAmount("400"); + items.add(item2); + + PaymentRequest paymentRequest = new PaymentRequest( + "4d0d8f3a-0bh9b-fff4e7edd-8bdd7a-rfgggdjhCCrrj", + "AMRIT", + period, + "1857708", + "2026-02-01T02:00:00+05:30", + verifiedBy, + items + ); + + log.info("========================================"); + log.info("STATIC PAYMENT REQUEST"); + log.info("Payload: {}", new Gson().toJson(paymentRequest)); + log.info("========================================"); + + paymentService.sendPaymentRequest(paymentRequest); + + log.info("Static payment request sent successfully."); + + } catch (Exception e) { + log.error("Static payment request failed: {}", e.getMessage(), e); + } + } public void triggerPayment() { LocalDate today = LocalDate.now(); -// ✅ Current month ka data — testing ke liye +// ✅ Current month ka data LocalDate firstDay = today.withDayOfMonth(1); // Mar 1, 2026 LocalDate lastDay = today; // Mar 11, 2026 (aaj) @@ -192,4 +252,6 @@ public void triggerPayment() { log.info("Job Complete | Success: {} | Failed: {} | Skipped: {}", success, failed, skipped); log.info("========================================"); } + + } \ No newline at end of file diff --git a/src/main/java/com/iemr/flw/service/impl/UserServiceImpl.java b/src/main/java/com/iemr/flw/service/impl/UserServiceImpl.java index 52d3eefb1..60ae973e7 100644 --- a/src/main/java/com/iemr/flw/service/impl/UserServiceImpl.java +++ b/src/main/java/com/iemr/flw/service/impl/UserServiceImpl.java @@ -8,13 +8,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TreeSet; -import java.util.stream.Collectors; - @Service public class UserServiceImpl implements UserService { @@ -30,92 +23,6 @@ public UserServiceRoleDTO getUserDetail(Integer userId) { logger.info("calling getUserRole for userId: " + userId); UserServiceRoleDTO userRole = userServiceRoleRepo.getUserRole(userId).get(0); userRole.setFacilityData(facilityDataService.buildFacilityData(userId, userRole.getRoleName())); - - // Stop TB / Nikshay — additive only. This naturally returns nothing for - // any user whose rows don't have NikshayTUID set, i.e. every non-Stop-TB - // user. Fetched first so the district-by-block patch below can tell - // Stop TB users apart and skip them. - List nikshayRows = userServiceRoleRepo.getNikshayMappingRows(userId, userRole.getProviderServiceMapId()); - boolean isStopTBUser = nikshayRows != null && !nikshayRows.isEmpty(); - - // Stop TB's BlockId holds a Nikshay TU ID, not an AMRIT BlockID - - // joining it against m_districtblock/m_district (what - // getDistrictByBlockId does) would resolve to whatever AMRIT - // district happens to share that same numeric ID by coincidence, - // not real data. Skip this patch for Stop TB users. - if (!isStopTBUser && userRole.getWorkingDistrictId() == null && userRole.getBlockId() != null) { - List districtResults = userServiceRoleRepo.getDistrictByBlockId(userRole.getBlockId()); - if (districtResults != null && !districtResults.isEmpty()) { - Object[] district = districtResults.get(0); - if (district != null && district.length == 2) { - userRole.setWorkingDistrictId(((Number) district[0]).intValue()); - userRole.setWorkingDistrictName((String) district[1]); - } - } - } - - if (isStopTBUser) { - TreeSet tuIds = new TreeSet<>(); - TreeSet facilityIds = new TreeSet<>(); - Integer districtId = null; - for (Object[] row : nikshayRows) { - addCsvIds((String) row[0], tuIds); - addCsvIds((String) row[1], facilityIds); - if (districtId == null && row[2] != null) { - districtId = ((Number) row[2]).intValue(); - } - } - - Map tuNames = tuIds.isEmpty() ? Map.of() - : toIdNameMap(userServiceRoleRepo.findNikshayTuNames(tuIds)); - Map facilityNames = facilityIds.isEmpty() ? Map.of() - : toIdNameMap(userServiceRoleRepo.findNikshayFacilityNames(facilityIds)); - - userRole.setTuId(joinIds(tuIds)); - userRole.setTuName(joinNames(tuIds, tuNames)); - userRole.setHealthFacilityId(joinIds(facilityIds)); - userRole.setHealthFacilityName(joinNames(facilityIds, facilityNames)); - - // Stop TB never sets WorkingLocationID, so workingDistrictId/Name - // (derived from it) are always null. DistrictID sits directly on - // the mapping row instead - Stop TB has no "work location" - // indirection layer the way other servicelines do, so read it - // straight from there rather than trying to derive it. - if (districtId != null) { - userRole.setWorkingDistrictId(districtId); - userRole.setWorkingDistrictName(userServiceRoleRepo.findNikshayDistrictName(districtId)); - } - } - return userRole; } - - private void addCsvIds(String csv, Collection target) { - if (csv == null || csv.isBlank()) { - return; - } - for (String id : csv.split(",")) { - try { - target.add(Integer.valueOf(id.trim())); - } catch (NumberFormatException ignored) { - // skip malformed entries rather than fail the whole login - } - } - } - - private Map toIdNameMap(List rows) { - Map map = new HashMap<>(); - for (Object[] row : rows) { - map.put(((Number) row[0]).intValue(), (String) row[1]); - } - return map; - } - - private String joinIds(Collection ids) { - return ids.stream().map(String::valueOf).collect(Collectors.joining(",")); - } - - private String joinNames(Collection ids, Map names) { - return ids.stream().map(id -> names.getOrDefault(id, "")).collect(Collectors.joining(",")); - } } diff --git a/src/main/java/com/iemr/flw/service/impl/UtpreronaPaymentIntegrationImpl.java b/src/main/java/com/iemr/flw/service/impl/UtpreronaPaymentIntegrationImpl.java index f0e5a5544..ad4e7d381 100644 --- a/src/main/java/com/iemr/flw/service/impl/UtpreronaPaymentIntegrationImpl.java +++ b/src/main/java/com/iemr/flw/service/impl/UtpreronaPaymentIntegrationImpl.java @@ -1,9 +1,8 @@ package com.iemr.flw.service.impl; import com.fasterxml.jackson.databind.ObjectMapper; +import com.iemr.flw.dto.PaymentResponse; import com.iemr.flw.dto.iemr.PaymentRequest; -import io.swagger.v3.oas.models.responses.ApiResponse; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.io.IOException; @@ -15,9 +14,13 @@ @Service public class UtpreronaPaymentIntegrationImpl { -// @Value("${ssdPortalUrl}") - private String API_URL = "https://nhmssd.assam.gov.in/APPMS_2024_25/api/utpreronaPayment.php"; - private String API_KEY = "41202fa384eab2725a17bbac58cf708bf04cd1dd5175010941606156dc36d6b5"; + + private String API_URL = + "https://nhmssd.assam.gov.in/APPMS_2024_25/api/api_receipt_entry.php"; + + private String API_KEY = + "41202fa384eab2725a17bbac58cf708bf04cd1dd5175010941606156dc36d6b5"; + private static final int TIMEOUT_SECONDS = 30; private final HttpClient httpClient; @@ -27,16 +30,21 @@ public UtpreronaPaymentIntegrationImpl() { this.httpClient = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(TIMEOUT_SECONDS)) .build(); + this.objectMapper = new ObjectMapper(); } - public ApiResponse sendPaymentRequest(PaymentRequest paymentRequest) + public PaymentResponse sendPaymentRequest(PaymentRequest paymentRequest) throws IOException, InterruptedException { - String jsonBody = objectMapper.writeValueAsString(paymentRequest); + String jsonBody = + objectMapper.writeValueAsString(paymentRequest); + System.out.println("Sending Request:"); - System.out.println(objectMapper.writerWithDefaultPrettyPrinter() - .writeValueAsString(paymentRequest)); + System.out.println( + objectMapper.writerWithDefaultPrettyPrinter() + .writeValueAsString(paymentRequest) + ); HttpRequest httpRequest = HttpRequest.newBuilder() .uri(URI.create(API_URL)) @@ -47,20 +55,51 @@ public ApiResponse sendPaymentRequest(PaymentRequest paymentRequest) .POST(HttpRequest.BodyPublishers.ofString(jsonBody)) .build(); - HttpResponse httpResponse = httpClient.send( - httpRequest, - HttpResponse.BodyHandlers.ofString() + HttpResponse httpResponse = + httpClient.send( + httpRequest, + HttpResponse.BodyHandlers.ofString() + ); + + System.out.println( + "Response Status: " + httpResponse.statusCode() + ); + + System.out.println( + "Response Body: " + httpResponse.body() ); - System.out.println("Response Status: " + httpResponse.statusCode()); - System.out.println("Response Body: " + httpResponse.body()); + if (httpResponse.statusCode() >= 200 + && httpResponse.statusCode() < 300) { + + PaymentResponse response = + objectMapper.readValue( + httpResponse.body(), + PaymentResponse.class + ); + + System.out.println( + "Submission ID: " + response.getSubmissionId() + ); + + System.out.println( + "Status: " + response.getStatus() + ); + + System.out.println( + "Receipt: " + response.getReceipt() + ); + + return response; - if (httpResponse.statusCode() == 200) { - return objectMapper.readValue(httpResponse.body(), ApiResponse.class); } else { - throw new IOException("API Error - Status: " + httpResponse.statusCode() - + " | Body: " + httpResponse.body()); + + throw new IOException( + "API Error - Status: " + + httpResponse.statusCode() + + " | Body: " + + httpResponse.body() + ); } } - -} +} \ No newline at end of file diff --git a/src/main/java/com/iemr/flw/service/impl/VillageLevelFormServiceImpl.java b/src/main/java/com/iemr/flw/service/impl/VillageLevelFormServiceImpl.java index 7f1104d1d..c21cc9a5e 100644 --- a/src/main/java/com/iemr/flw/service/impl/VillageLevelFormServiceImpl.java +++ b/src/main/java/com/iemr/flw/service/impl/VillageLevelFormServiceImpl.java @@ -339,6 +339,7 @@ record = new IncentiveActivityRecord(); record.setUpdatedBy(userRepo.getUserNamedByUserId(userId)); record.setAshaId(userId); record.setBenId(0L); + record.setIsDefaultActivity(true); record.setAmount(Long.valueOf(activity.getRate())); record.setIsEligible(true); recordRepo.save(record); @@ -375,6 +376,7 @@ record = new IncentiveActivityRecord(); record.setUpdatedBy(userRepo.getUserNamedByUserId(userId)); record.setAshaId(userId); record.setBenId(0L); + record.setIsDefaultActivity(true); record.setAmount(Long.valueOf(activity.getRate())); record.setIsEligible(true); recordRepo.save(record); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 84cca4815..2ffd6d6b8 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -62,7 +62,7 @@ spring.jpa.defer-datasource-initialization=true fhir-url= # TM Config -tm-url=https://amritdemo.piramalswasthya.org/tm-api +tm-url= springdoc.api-docs.enabled=true springdoc.swagger-ui.enabled=true @@ -71,4 +71,64 @@ spring.main.allow-bean-definition-overriding=true spring.redis.password= spring.redis.port=6379 -notificationurl=https://uatamrit.piramalswasthya.org/common-api/firebaseNotification/sendNotification +notificationurl=firebaseNotification/sendNotification + + + +server.port=8081 +# FHIR Config + +# TM Config +##--------------------------------------------## Primary db------------------------------------------------------------------- + +spring.datasource.url=jdbc:mysql://localhost:3306/db_iemr +spring.datasource.username=root +spring.datasource.password=1234 +spring.datasource.driver-class-name=com.mysql.jdbc.Driver + +##--------------------------------------------## Secondary db------------------------------------------------------------------- + +secondary.datasource.url=jdbc:mysql://localhost:3306/db_identity +secondary.datasource.username=root +secondary.datasource.password=1234 +secondary.datasource.driver-class-name=com.mysql.jdbc.Driver + + + +logging.path=logs/ +logging.file.name=logs/flw-api.log + +jwt.secret=my-32-character-ultra-secure-and-ultra-long-secret + +# Redis Config + +cors.allowed-origins=http://localhost:* + +source-address= +sms-username= +sms-password= +send-message-url= + +crash.logs.base.path= + +# ABHA Token Config +abha.client.id= +abha.client.secret= +abha.token.url= +abha.xcmid= + + +#crash.logs.base.path=@env.CRASH_LOGS_PATH@ + +# ABHA Token Config + + +# GovThealth API Config +govthealth.user.details.url=@env.GOVTHEALTH_USER_DETAILS_URL@ +govthealth.user.id=@env.GOVTHEALTH_USER_ID@ +govthealth.password=@env.GOVTHEALTH_PASSWORD@ +common-api-base-url= + + + +