diff --git a/pom.xml b/pom.xml index 3250086b..b4e8c0d9 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.iemr.common-API common-api - 3.8.0 + 3.8.1 war Common-API diff --git a/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java b/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java index 554500f3..701add24 100644 --- a/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java +++ b/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java @@ -56,6 +56,7 @@ import com.iemr.common.model.user.ForceLogoutRequestModel; import com.iemr.common.model.user.LoginRequestModel; import com.iemr.common.service.recaptcha.CaptchaValidationService; +import com.iemr.common.service.users.AshaSupervisorLoginService; import com.iemr.common.service.users.IEMRAdminUserService; import com.iemr.common.utils.CookieUtil; import com.iemr.common.utils.JwtUtil; @@ -117,6 +118,9 @@ public void setSessionObject(SessionObject sessionObject) { @Autowired SecurePassword securePassword; + @Autowired + private AshaSupervisorLoginService ashaSupervisorLoginService; + @Operation(summary = "New user authentication") @RequestMapping(value = "/userAuthenticateNew", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON) public String userAuthenticateNew( @@ -232,6 +236,46 @@ public String userAuthenticate( responseObj = iemrAdminUserServiceImpl.generateKeyAndValidateIP(responseObj, remoteAddress, request.getRemoteHost()); + // Facility data for ALL users - common pattern, empty if not applicable + try { + if (mUser.size() == 1) { + User loggedInUser = mUser.get(0); + String userRoleName = ""; + if (loggedInUser.getM_UserServiceRoleMapping() != null) { + for (UserServiceRoleMapping usrm : loggedInUser.getM_UserServiceRoleMapping()) { + if (usrm.getM_Role() != null && usrm.getM_Role().getRoleName() != null) { + userRoleName = usrm.getM_Role().getRoleName(); + break; + } + } + } + JSONObject facilityData = ashaSupervisorLoginService + .buildFacilityLoginData(loggedInUser.getUserID(), userRoleName); + + // User details + JSONObject userObj = new JSONObject(); + userObj.put("userId", loggedInUser.getUserID()); + userObj.put("employeeId", loggedInUser.getEmployeeID() != null ? loggedInUser.getEmployeeID() : JSONObject.NULL); + userObj.put("role", userRoleName); + String first = loggedInUser.getFirstName() != null ? loggedInUser.getFirstName() : ""; + String last = loggedInUser.getLastName() != null ? loggedInUser.getLastName() : ""; + userObj.put("fullName", (first + " " + last).trim()); + + JSONObject demographics = new JSONObject(); + String genderName = ashaSupervisorLoginService.getGenderName(loggedInUser.getGenderID()); + demographics.put("gender", genderName != null ? genderName : JSONObject.NULL); + demographics.put("dob", loggedInUser.getdOB() != null ? loggedInUser.getdOB().toString() : JSONObject.NULL); + demographics.put("mobile", loggedInUser.getEmergencyContactNo() != null ? loggedInUser.getEmergencyContactNo() : JSONObject.NULL); + demographics.put("email", loggedInUser.getEmailID() != null ? loggedInUser.getEmailID() : JSONObject.NULL); + userObj.put("demographics", demographics); + + facilityData.put("user", userObj); + responseObj.put("facilityData", facilityData); + } + } catch (Exception e) { + logger.error("Error fetching facility login data: " + e.getMessage(), e); + } + // Add tokens to response for mobile if (isMobile && !mUser.isEmpty()) { responseObj.put("jwtToken", jwtToken); diff --git a/src/main/java/com/iemr/common/data/users/AshaSupervisorMapping.java b/src/main/java/com/iemr/common/data/users/AshaSupervisorMapping.java new file mode 100644 index 00000000..9aa38db6 --- /dev/null +++ b/src/main/java/com/iemr/common/data/users/AshaSupervisorMapping.java @@ -0,0 +1,34 @@ +package com.iemr.common.data.users; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Entity +@Table(name = "asha_supervisor_mapping") +@Data +@NoArgsConstructor +public class AshaSupervisorMapping { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + @Column(name = "supervisorUserID") + private Integer supervisorUserID; + + @Column(name = "ashaUserID") + private Integer ashaUserID; + + @Column(name = "facilityID") + private Integer facilityID; + + @Column(name = "deleted", insertable = false, updatable = true) + private Boolean deleted; +} diff --git a/src/main/java/com/iemr/common/data/users/User.java b/src/main/java/com/iemr/common/data/users/User.java index 275b0ec6..4a9c6158 100644 --- a/src/main/java/com/iemr/common/data/users/User.java +++ b/src/main/java/com/iemr/common/data/users/User.java @@ -132,6 +132,9 @@ public class User implements Serializable { @Expose private Status m_status; + @Expose + @Column(name = "EmployeeID") + private String employeeID; @Expose @Column(name = "AadhaarNo") private String aadhaarNo; @@ -515,6 +518,10 @@ public String getAgentID() { return agentID; } + public String getEmployeeID() { + return employeeID; + } + public String getAgentPassword() { return agentPassword; } diff --git a/src/main/java/com/iemr/common/model/user/LoginResponseModel.java b/src/main/java/com/iemr/common/model/user/LoginResponseModel.java index 10d45222..17d353e4 100644 --- a/src/main/java/com/iemr/common/model/user/LoginResponseModel.java +++ b/src/main/java/com/iemr/common/model/user/LoginResponseModel.java @@ -50,6 +50,7 @@ private MaritalStatusModel maritalstatus; private Integer statusID; private StatusModel status; + private String employeeID; private String aadhaarNo; private String pAN; private Timestamp dOB; diff --git a/src/main/java/com/iemr/common/repository/users/AshaSupervisorLoginRepo.java b/src/main/java/com/iemr/common/repository/users/AshaSupervisorLoginRepo.java new file mode 100644 index 00000000..9bc07a17 --- /dev/null +++ b/src/main/java/com/iemr/common/repository/users/AshaSupervisorLoginRepo.java @@ -0,0 +1,14 @@ +package com.iemr.common.repository.users; + +import java.util.ArrayList; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import com.iemr.common.data.users.AshaSupervisorMapping; + +@Repository +public interface AshaSupervisorLoginRepo extends CrudRepository { + + ArrayList findBySupervisorUserIDAndDeletedFalse(Integer supervisorUserID); +} diff --git a/src/main/java/com/iemr/common/repository/users/FacilityLoginRepo.java b/src/main/java/com/iemr/common/repository/users/FacilityLoginRepo.java new file mode 100644 index 00000000..92af0fd2 --- /dev/null +++ b/src/main/java/com/iemr/common/repository/users/FacilityLoginRepo.java @@ -0,0 +1,67 @@ +package com.iemr.common.repository.users; + +import java.util.List; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.iemr.common.data.users.AshaSupervisorMapping; + +@Repository +public interface FacilityLoginRepo extends CrudRepository { + + // Get user's facility IDs from m_UserServiceRoleMapping (for ANY user) + @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 facility details with geo names and facilityType + @Query(value = "SELECT DISTINCT f.FacilityID, f.FacilityName, " + + "f.StateID, COALESCE(s.StateName,'') AS stateName, " + + "f.DistrictID, COALESCE(d.DistrictName,'') AS districtName, " + + "f.BlockID, COALESCE(b.BlockName,'') AS blockName, " + + "COALESCE(f.RuralUrban,'') AS ruralUrban, " + + "COALESCE(ft.FacilityTypeName,'') AS facilityTypeName " + + "FROM m_facility f " + + "LEFT JOIN m_state s ON s.StateID = f.StateID " + + "LEFT JOIN m_district d ON d.DistrictID = f.DistrictID " + + "LEFT JOIN m_districtblock b ON b.BlockID = f.BlockID " + + "LEFT JOIN m_facilitytype ft ON ft.FacilityTypeID = f.FacilityTypeID " + + "WHERE f.FacilityID IN :facilityIDs AND f.Deleted = false", nativeQuery = true) + List getFacilityDetails(@Param("facilityIDs") List facilityIDs); + + // ASHA login: get supervisor details + @Query(value = "SELECT asm.supervisorUserID, u.FirstName, u.LastName, u.ContactNo, " + + "COALESCE(u.EmployeeID,'') AS employeeID " + + "FROM asha_supervisor_mapping asm " + + "JOIN m_User u ON u.UserID = asm.supervisorUserID " + + "WHERE asm.ashaUserID = :ashaUserID AND asm.deleted = false " + + "AND u.Deleted = false LIMIT 1", nativeQuery = true) + List getSupervisorForAsha(@Param("ashaUserID") Integer ashaUserID); + + @Query(value = "SELECT GenderName FROM m_gender WHERE GenderID = :genderID", nativeQuery = true) + String getGenderName(@Param("genderID") Integer genderID); + + // Villages mapped to facilities + @Query(value = "SELECT fvm.FacilityID, fvm.DistrictBranchID, dbm.VillageName " + + "FROM facility_village_mapping fvm " + + "JOIN m_DistrictBranchMapping dbm ON dbm.DistrictBranchID = fvm.DistrictBranchID " + + "WHERE fvm.FacilityID IN :facilityIDs AND fvm.Deleted = false", nativeQuery = true) + List getVillagesForFacilities(@Param("facilityIDs") List facilityIDs); + + // ASHA login: get peers at same facility (ANM, CHO, etc.) + @Query(value = "SELECT DISTINCT usrm.UserID, u.FirstName, u.LastName, r.RoleName, " + + "COALESCE(u.EmployeeID,'') AS employeeID " + + "FROM m_UserServiceRoleMapping usrm " + + "JOIN m_User u ON u.UserID = usrm.UserID " + + "JOIN m_Role r ON r.RoleID = usrm.RoleID " + + "WHERE usrm.FacilityID IN :facilityIDs " + + "AND usrm.UserID != :currentUserID " + + "AND usrm.Deleted = false AND u.Deleted = false", nativeQuery = true) + List getPeersAtFacility(@Param("facilityIDs") List facilityIDs, + @Param("currentUserID") Integer currentUserID); +} diff --git a/src/main/java/com/iemr/common/service/users/AshaSupervisorLoginService.java b/src/main/java/com/iemr/common/service/users/AshaSupervisorLoginService.java new file mode 100644 index 00000000..2ea0b5f4 --- /dev/null +++ b/src/main/java/com/iemr/common/service/users/AshaSupervisorLoginService.java @@ -0,0 +1,202 @@ +package com.iemr.common.service.users; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.json.JSONArray; +import org.json.JSONObject; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.iemr.common.data.users.AshaSupervisorMapping; +import com.iemr.common.repository.users.AshaSupervisorLoginRepo; +import com.iemr.common.repository.users.FacilityLoginRepo; + +@Service +public class AshaSupervisorLoginService { + + private final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); + + @Autowired + private AshaSupervisorLoginRepo ashaSupervisorLoginRepo; + + @Autowired + private FacilityLoginRepo facilityLoginRepo; + + /** + * Common facilityData block for ALL users. + * Returns empty structure if user has no facility mapping. + */ + public JSONObject buildFacilityLoginData(Long userID, String roleName) { + JSONObject result = new JSONObject(); + result.put("location", buildEmptyLocation()); + try { + if ("ASHA Supervisor".equalsIgnoreCase(roleName)) { + enrichAshaSupervisorData(result, userID.intValue()); + } else if ("ASHA".equalsIgnoreCase(roleName)) { + enrichAshaData(result, userID.intValue()); + } else { + enrichGeneralFacilityData(result, userID.intValue()); + } + } catch (Exception e) { + logger.error("Error building facility login data for userID " + userID + ": " + e.getMessage(), e); + } + return result; + } + + private JSONObject buildEmptyLocation() { + return new JSONObject() + .put("state", "") + .put("district", "") + .put("blockOrUlb", "") + .put("locationType", ""); + } + + // ==================== ASHA ==================== + + private void enrichAshaData(JSONObject result, Integer ashaUserID) { + List facilityIDs = facilityLoginRepo.getUserFacilityIDs(ashaUserID); + if (facilityIDs == null || facilityIDs.isEmpty()) + return; + + List facilityRows = facilityLoginRepo.getFacilityDetails(facilityIDs); + if (facilityRows == null || facilityRows.isEmpty()) + return; + + populateLocation(result, facilityRows.get(0)); + + // ASHA gets a single facility (first mapped) + Object[] row = facilityRows.get(0); + JSONObject facility = new JSONObject(); + facility.put("facilityId", row[0]); + facility.put("facilityName", str(row[1])); + facility.put("facilityType", str(row[9])); + result.put("facility", facility); + + // Supervisor details + List supervisorRows = facilityLoginRepo.getSupervisorForAsha(ashaUserID); + 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("mobile", str(sRow[3])); + supervisor.put("employeeId", str(sRow[4]).isEmpty() ? JSONObject.NULL : str(sRow[4])); + result.put("supervisor", supervisor); + } else { + result.put("supervisor", JSONObject.NULL); + } + + // Peers at same facility + List peerRows = facilityLoginRepo.getPeersAtFacility(facilityIDs, ashaUserID); + JSONArray peers = new JSONArray(); + if (peerRows != null) { + for (Object[] pRow : peerRows) { + JSONObject peer = new JSONObject(); + peer.put("userId", pRow[0]); + peer.put("fullName", fullName(pRow[1], pRow[2])); + peer.put("role", str(pRow[3])); + peer.put("employeeId", str(pRow[4]).isEmpty() ? JSONObject.NULL : str(pRow[4])); + peers.put(peer); + } + } + result.put("peersAtFacility", peers); + } + + // ==================== ASHA Supervisor ==================== + + private void enrichAshaSupervisorData(JSONObject result, Integer supervisorUserID) { + ArrayList mappings = ashaSupervisorLoginRepo + .findBySupervisorUserIDAndDeletedFalse(supervisorUserID); + if (mappings == null || mappings.isEmpty()) + return; + + Set facilityIDSet = new HashSet<>(); + for (AshaSupervisorMapping m : mappings) { + if (m.getFacilityID() != null) + facilityIDSet.add(m.getFacilityID()); + } + if (facilityIDSet.isEmpty()) + return; + List facilityIDs = new ArrayList<>(facilityIDSet); + + List facilityRows = facilityLoginRepo.getFacilityDetails(facilityIDs); + if (facilityRows == null || facilityRows.isEmpty()) + return; + + populateLocation(result, facilityRows.get(0)); + + JSONArray facilitiesArray = new JSONArray(); + for (Object[] row : facilityRows) { + JSONObject facility = new JSONObject(); + facility.put("facilityId", row[0]); + facility.put("facilityName", str(row[1])); + facility.put("facilityType", str(row[9])); + facilitiesArray.put(facility); + } + result.put("facilities", facilitiesArray); + + // Count distinct ASHAs mapped to this supervisor + Set ashaUserIDs = new HashSet<>(); + for (AshaSupervisorMapping m : mappings) { + if (m.getAshaUserID() != null) + ashaUserIDs.add(m.getAshaUserID()); + } + result.put("totalAshaCount", ashaUserIDs.size()); + } + + // ==================== General Facility User (CHO, ANM, etc.) + // ==================== + + private void enrichGeneralFacilityData(JSONObject result, Integer userID) { + List facilityIDs = facilityLoginRepo.getUserFacilityIDs(userID); + if (facilityIDs == null || facilityIDs.isEmpty()) + return; + + List facilityRows = facilityLoginRepo.getFacilityDetails(facilityIDs); + if (facilityRows == null || facilityRows.isEmpty()) + return; + + populateLocation(result, facilityRows.get(0)); + + JSONArray facilitiesArray = new JSONArray(); + for (Object[] row : facilityRows) { + JSONObject facility = new JSONObject(); + facility.put("facilityId", row[0]); + facility.put("facilityName", str(row[1])); + facility.put("facilityType", str(row[9])); + facilitiesArray.put(facility); + } + result.put("facilities", facilitiesArray); + } + + // ==================== Shared Helpers ==================== + + private void populateLocation(JSONObject result, Object[] facilityRow) { + JSONObject location = new JSONObject(); + location.put("state", str(facilityRow[3])); + location.put("district", str(facilityRow[5])); + location.put("blockOrUlb", str(facilityRow[7])); + location.put("locationType", str(facilityRow[8])); + result.put("location", location); + } + + private String str(Object val) { + return val != null ? val.toString() : ""; + } + + private String fullName(Object first, Object last) { + return (str(first) + " " + str(last)).trim(); + } + + public String getGenderName(Integer genderID) { + if (genderID == null) + return null; + return facilityLoginRepo.getGenderName(genderID); + } +}