diff --git a/src/main/java/com/iemr/common/data/location/NikshayDistrict.java b/src/main/java/com/iemr/common/data/location/NikshayDistrict.java new file mode 100644 index 00000000..6c9771aa --- /dev/null +++ b/src/main/java/com/iemr/common/data/location/NikshayDistrict.java @@ -0,0 +1,44 @@ +/* +* 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/. +*/ +package com.iemr.common.data.location; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Data; + +/** + * Nikshay's own district master (m_nikshay_district) — an isolated ID space + * from AMRIT's standard m_district, used only for Stop TB location mapping. + */ +@Entity +@Table(name = "m_nikshay_district") +@Data +public class NikshayDistrict { + @Id + @Column(name = "NikshayDistrictID") + private Integer nikshayDistrictID; + + @Column(name = "DistrictName") + private String districtName; +} diff --git a/src/main/java/com/iemr/common/data/location/NikshayTU.java b/src/main/java/com/iemr/common/data/location/NikshayTU.java new file mode 100644 index 00000000..09071ff0 --- /dev/null +++ b/src/main/java/com/iemr/common/data/location/NikshayTU.java @@ -0,0 +1,44 @@ +/* +* 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/. +*/ +package com.iemr.common.data.location; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Data; + +/** + * Nikshay's Tuberculosis Unit master (m_nikshay_tu) — Stop TB's equivalent + * of a "block", but scoped to Nikshay's own hierarchy, not m_districtblock. + */ +@Entity +@Table(name = "m_nikshay_tu") +@Data +public class NikshayTU { + @Id + @Column(name = "NikshayTUID") + private Integer nikshayTUID; + + @Column(name = "TUName") + private String tuName; +} diff --git a/src/main/java/com/iemr/common/data/location/NikshayVillage.java b/src/main/java/com/iemr/common/data/location/NikshayVillage.java new file mode 100644 index 00000000..d89825f8 --- /dev/null +++ b/src/main/java/com/iemr/common/data/location/NikshayVillage.java @@ -0,0 +1,44 @@ +/* +* 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/. +*/ +package com.iemr.common.data.location; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Data; + +/** + * Nikshay's own village master (m_nikshay_village) — an isolated ID space + * from AMRIT's standard m_DistrictBranchMapping, used only for Stop TB. + */ +@Entity +@Table(name = "m_nikshay_village") +@Data +public class NikshayVillage { + @Id + @Column(name = "NikshayVillageID") + private Integer nikshayVillageID; + + @Column(name = "VillageName") + private String villageName; +} diff --git a/src/main/java/com/iemr/common/mapper/CommonIdentityMapperDecorator.java b/src/main/java/com/iemr/common/mapper/CommonIdentityMapperDecorator.java index f18920ad..3ee5acff 100644 --- a/src/main/java/com/iemr/common/mapper/CommonIdentityMapperDecorator.java +++ b/src/main/java/com/iemr/common/mapper/CommonIdentityMapperDecorator.java @@ -29,8 +29,11 @@ import com.iemr.common.dto.identity.Identity; import com.iemr.common.model.beneficiary.BeneficiaryDemographicsModel; import com.iemr.common.model.beneficiary.BeneficiaryModel; +import com.iemr.common.service.location.NikshayAddressResolver; public abstract class CommonIdentityMapperDecorator implements CommonIdentityMapper { + @Autowired + NikshayAddressResolver nikshayAddressResolver; @Autowired StateMapper stateMapper; @Autowired @@ -69,11 +72,13 @@ public CommonIdentityDTO beneficiaryModelCommonIdentityDTO(BeneficiaryModel bene return null; } CommonIdentityDTO commonIdentityDTO = new CommonIdentityDTO(); - commonIdentityDTO - .setPermanentAddress(beneficiaryDemographicsModelToAddress(beneficiary.getI_bendemographics())); - commonIdentityDTO.setCurrentAddress(beneficiaryDemographicsModelToAddress(beneficiary.getI_bendemographics())); - commonIdentityDTO - .setEmergencyAddress(beneficiaryDemographicsModelToAddress(beneficiary.getI_bendemographics())); + boolean isStopTB = nikshayAddressResolver.isStopTB(beneficiary.getProviderServiceMapID()); + commonIdentityDTO.setPermanentAddress( + beneficiaryDemographicsModelToAddress(beneficiary.getI_bendemographics(), isStopTB)); + commonIdentityDTO.setCurrentAddress( + beneficiaryDemographicsModelToAddress(beneficiary.getI_bendemographics(), isStopTB)); + commonIdentityDTO.setEmergencyAddress( + beneficiaryDemographicsModelToAddress(beneficiary.getI_bendemographics(), isStopTB)); commonIdentityDTO.setPlaceOfWork(beneficiary.getPlaceOfWork()); commonIdentityDTO.setMarriageDate(beneficiary.getMarriageDate()); commonIdentityDTO.setIsHIVPositive(beneficiary.getIsHIVPos()); @@ -210,6 +215,11 @@ public CommonIdentityDTO beneficiaryModelCommonIdentityDTO(BeneficiaryModel bene } protected Address beneficiaryDemographicsModelToAddress(BeneficiaryDemographicsModel beneficiaryDemographicsModel) { + return beneficiaryDemographicsModelToAddress(beneficiaryDemographicsModel, false); + } + + protected Address beneficiaryDemographicsModelToAddress(BeneficiaryDemographicsModel beneficiaryDemographicsModel, + boolean isStopTB) { if (beneficiaryDemographicsModel == null) { return null; } @@ -222,8 +232,10 @@ protected Address beneficiaryDemographicsModelToAddress(BeneficiaryDemographicsM address.setStateId(beneficiaryDemographicsModel.getStateID()); address.setDistrictId(beneficiaryDemographicsModel.getDistrictID()); if (beneficiaryDemographicsModel.getDistrictID() != null) { - address.setDistrict( - districtMapper.districtToModelByID(beneficiaryDemographicsModel.getDistrictID()).getDistrictName()); + address.setDistrict(isStopTB + ? nikshayAddressResolver.resolveDistrictName(beneficiaryDemographicsModel.getDistrictID()) + : districtMapper.districtToModelByID(beneficiaryDemographicsModel.getDistrictID()) + .getDistrictName()); } address.setServicePointName(beneficiaryDemographicsModel.getServicePointName()); address.setCountry(beneficiaryDemographicsModel.getCountryName()); @@ -239,14 +251,17 @@ protected Address beneficiaryDemographicsModelToAddress(BeneficiaryDemographicsM address.setParkingPlaceID(beneficiaryDemographicsModel.getParkingPlaceID()); address.setServicePointID(beneficiaryDemographicsModel.getServicePointID()); if (beneficiaryDemographicsModel.getDistrictBranchID() != null) { - address.setVillage(branchMapper - .districtBranchToModelByID(beneficiaryDemographicsModel.getDistrictBranchID()).getVillageName()); + address.setVillage(isStopTB + ? nikshayAddressResolver.resolveVillageName(beneficiaryDemographicsModel.getDistrictBranchID()) + : branchMapper.districtBranchToModelByID(beneficiaryDemographicsModel.getDistrictBranchID()) + .getVillageName()); } address.setSubDistrictId(beneficiaryDemographicsModel.getBlockID()); address.setCountryId(beneficiaryDemographicsModel.getCountryID()); if (beneficiaryDemographicsModel.getBlockID() != null) { - address.setSubDistrict( - blockMapper.districtBlockToModelByID(beneficiaryDemographicsModel.getBlockID()).getBlockName()); + address.setSubDistrict(isStopTB + ? nikshayAddressResolver.resolveTUName(beneficiaryDemographicsModel.getBlockID()) + : blockMapper.districtBlockToModelByID(beneficiaryDemographicsModel.getBlockID()).getBlockName()); } address.setGpsLatitude(beneficiaryDemographicsModel.getLatitude()); address.setGpsLongitude(beneficiaryDemographicsModel.getLongitude()); diff --git a/src/main/java/com/iemr/common/mapper/IdentityBenEditMapperDecorator.java b/src/main/java/com/iemr/common/mapper/IdentityBenEditMapperDecorator.java index 27b4a602..999ddf67 100644 --- a/src/main/java/com/iemr/common/mapper/IdentityBenEditMapperDecorator.java +++ b/src/main/java/com/iemr/common/mapper/IdentityBenEditMapperDecorator.java @@ -33,8 +33,11 @@ import com.iemr.common.model.beneficiary.BenPhoneMapModel; import com.iemr.common.model.beneficiary.BeneficiaryDemographicsModel; import com.iemr.common.model.beneficiary.BeneficiaryModel; +import com.iemr.common.service.location.NikshayAddressResolver; public abstract class IdentityBenEditMapperDecorator implements IdentityBenEditMapper { + @Autowired + NikshayAddressResolver nikshayAddressResolver; @Autowired StateMapper stateMapper; @Autowired @@ -69,6 +72,11 @@ public abstract class IdentityBenEditMapperDecorator implements IdentityBenEditM MaritalStatusMapper maritalStatusMapper; protected Address beneficiaryDemographicsModelToAddress(BeneficiaryDemographicsModel beneficiaryDemographicsModel) { + return beneficiaryDemographicsModelToAddress(beneficiaryDemographicsModel, false); + } + + protected Address beneficiaryDemographicsModelToAddress(BeneficiaryDemographicsModel beneficiaryDemographicsModel, + boolean isStopTB) { if (beneficiaryDemographicsModel == null) { return null; } @@ -81,8 +89,10 @@ protected Address beneficiaryDemographicsModelToAddress(BeneficiaryDemographicsM address.setStateId(beneficiaryDemographicsModel.getStateID()); address.setDistrictId(beneficiaryDemographicsModel.getDistrictID()); if (beneficiaryDemographicsModel.getDistrictID() != null) { - address.setDistrict( - districtMapper.districtToModelByID(beneficiaryDemographicsModel.getDistrictID()).getDistrictName()); + address.setDistrict(isStopTB + ? nikshayAddressResolver.resolveDistrictName(beneficiaryDemographicsModel.getDistrictID()) + : districtMapper.districtToModelByID(beneficiaryDemographicsModel.getDistrictID()) + .getDistrictName()); } address.setServicePointName(beneficiaryDemographicsModel.getServicePointName()); address.setCountry(beneficiaryDemographicsModel.getCountryName()); @@ -98,14 +108,17 @@ protected Address beneficiaryDemographicsModelToAddress(BeneficiaryDemographicsM address.setParkingPlaceID(beneficiaryDemographicsModel.getParkingPlaceID()); address.setServicePointID(beneficiaryDemographicsModel.getServicePointID()); if (beneficiaryDemographicsModel.getDistrictBranchID() != null) { - address.setVillage(branchMapper - .districtBranchToModelByID(beneficiaryDemographicsModel.getDistrictBranchID()).getVillageName()); + address.setVillage(isStopTB + ? nikshayAddressResolver.resolveVillageName(beneficiaryDemographicsModel.getDistrictBranchID()) + : branchMapper.districtBranchToModelByID(beneficiaryDemographicsModel.getDistrictBranchID()) + .getVillageName()); } address.setSubDistrictId(beneficiaryDemographicsModel.getBlockID()); address.setCountryId(beneficiaryDemographicsModel.getCountryID()); if (beneficiaryDemographicsModel.getBlockID() != null) { - address.setSubDistrict( - blockMapper.districtBlockToModelByID(beneficiaryDemographicsModel.getBlockID()).getBlockName()); + address.setSubDistrict(isStopTB + ? nikshayAddressResolver.resolveTUName(beneficiaryDemographicsModel.getBlockID()) + : blockMapper.districtBlockToModelByID(beneficiaryDemographicsModel.getBlockID()).getBlockName()); } address.setGpsLatitude(beneficiaryDemographicsModel.getLatitude()); address.setGpsLongitude(beneficiaryDemographicsModel.getLongitude()); @@ -124,9 +137,13 @@ public IdentityEditDTO BenToIdentityEditMapper(BeneficiaryModel beneficiary) { } IdentityEditDTO identityEditDTO = new IdentityEditDTO(); - identityEditDTO.setPermanentAddress(beneficiaryDemographicsModelToAddress(beneficiary.getI_bendemographics())); - identityEditDTO.setCurrentAddress(beneficiaryDemographicsModelToAddress(beneficiary.getI_bendemographics())); - identityEditDTO.setEmergencyAddress(beneficiaryDemographicsModelToAddress(beneficiary.getI_bendemographics())); + boolean isStopTB = nikshayAddressResolver.isStopTB(beneficiary.getProviderServiceMapID()); + identityEditDTO.setPermanentAddress( + beneficiaryDemographicsModelToAddress(beneficiary.getI_bendemographics(), isStopTB)); + identityEditDTO.setCurrentAddress( + beneficiaryDemographicsModelToAddress(beneficiary.getI_bendemographics(), isStopTB)); + identityEditDTO.setEmergencyAddress( + beneficiaryDemographicsModelToAddress(beneficiary.getI_bendemographics(), isStopTB)); identityEditDTO.setPlaceOfWork(beneficiary.getPlaceOfWork()); identityEditDTO.setMarriageDate(beneficiary.getMarriageDate()); identityEditDTO.setIsHIVPositive(beneficiary.getIsHIVPos()); diff --git a/src/main/java/com/iemr/common/repository/location/NikshayDistrictRepository.java b/src/main/java/com/iemr/common/repository/location/NikshayDistrictRepository.java new file mode 100644 index 00000000..34e202c2 --- /dev/null +++ b/src/main/java/com/iemr/common/repository/location/NikshayDistrictRepository.java @@ -0,0 +1,31 @@ +/* +* 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/. +*/ +package com.iemr.common.repository.location; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import com.iemr.common.data.location.NikshayDistrict; + +@Repository +public interface NikshayDistrictRepository extends CrudRepository { +} diff --git a/src/main/java/com/iemr/common/repository/location/NikshayTURepository.java b/src/main/java/com/iemr/common/repository/location/NikshayTURepository.java new file mode 100644 index 00000000..c810613d --- /dev/null +++ b/src/main/java/com/iemr/common/repository/location/NikshayTURepository.java @@ -0,0 +1,31 @@ +/* +* 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/. +*/ +package com.iemr.common.repository.location; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import com.iemr.common.data.location.NikshayTU; + +@Repository +public interface NikshayTURepository extends CrudRepository { +} diff --git a/src/main/java/com/iemr/common/repository/location/NikshayVillageRepository.java b/src/main/java/com/iemr/common/repository/location/NikshayVillageRepository.java new file mode 100644 index 00000000..ee89c402 --- /dev/null +++ b/src/main/java/com/iemr/common/repository/location/NikshayVillageRepository.java @@ -0,0 +1,31 @@ +/* +* 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/. +*/ +package com.iemr.common.repository.location; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import com.iemr.common.data.location.NikshayVillage; + +@Repository +public interface NikshayVillageRepository extends CrudRepository { +} diff --git a/src/main/java/com/iemr/common/service/location/NikshayAddressResolver.java b/src/main/java/com/iemr/common/service/location/NikshayAddressResolver.java new file mode 100644 index 00000000..96f078fb --- /dev/null +++ b/src/main/java/com/iemr/common/service/location/NikshayAddressResolver.java @@ -0,0 +1,82 @@ +/* +* 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/. +*/ +package com.iemr.common.service.location; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.iemr.common.data.location.NikshayDistrict; +import com.iemr.common.data.location.NikshayTU; +import com.iemr.common.data.location.NikshayVillage; +import com.iemr.common.data.users.ProviderServiceMapping; +import com.iemr.common.repository.location.NikshayDistrictRepository; +import com.iemr.common.repository.location.NikshayTURepository; +import com.iemr.common.repository.location.NikshayVillageRepository; +import com.iemr.common.repository.users.ProviderServiceMapRepository; + +/** + * Stop TB workers are mapped against Nikshay's own, isolated location + * hierarchy (m_nikshay_district/tu/village), which uses a separate ID space + * from AMRIT's standard masters (m_district/m_districtblock/m_DistrictBranchMapping). + * The same numeric district/block/village IDs mean different places in each + * hierarchy, so a Stop TB registration must never be resolved against the + * standard masters (see StopTB district/village mismatch investigation, 2026-07-28). + * + * Every other service line (FLW/HWC/MMU) keeps using the standard masters + * untouched — this resolver only changes behavior for Stop TB beneficiaries. + */ +@Component +public class NikshayAddressResolver { + + @Autowired + private ProviderServiceMapRepository providerServiceMapRepository; + @Autowired + private NikshayDistrictRepository nikshayDistrictRepository; + @Autowired + private NikshayTURepository nikshayTURepository; + @Autowired + private NikshayVillageRepository nikshayVillageRepository; + + private static final String STOP_TB_SERVICE_NAME = "Stop TB"; + + public boolean isStopTB(Integer providerServiceMapID) { + if (providerServiceMapID == null) { + return false; + } + ProviderServiceMapping psm = providerServiceMapRepository.findByID(providerServiceMapID); + return psm != null && psm.getM_ServiceMaster() != null + && STOP_TB_SERVICE_NAME.equalsIgnoreCase(psm.getM_ServiceMaster().getServiceName()); + } + + public String resolveDistrictName(Integer nikshayDistrictID) { + return nikshayDistrictRepository.findById(nikshayDistrictID).map(NikshayDistrict::getDistrictName) + .orElse(null); + } + + public String resolveTUName(Integer nikshayTUID) { + return nikshayTURepository.findById(nikshayTUID).map(NikshayTU::getTuName).orElse(null); + } + + public String resolveVillageName(Integer nikshayVillageID) { + return nikshayVillageRepository.findById(nikshayVillageID).map(NikshayVillage::getVillageName).orElse(null); + } +}