Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.iemr.tm</groupId>
<artifactId>tm-api</artifactId>
<version>3.8.3</version>
<version>3.12.0</version>
<packaging>war</packaging>

<name>TM-API</name>
Expand Down
2 changes: 2 additions & 0 deletions src/main/environment/common_ci.properties
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ spring.redis.host=@env.REDIS_HOST@

# Stop TB: when true, beneficiary registration fails 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@
jwt.secret=@env.JWT_SECRET_KEY@


Expand Down
2 changes: 2 additions & 0 deletions src/main/environment/common_docker.properties
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ spring.redis.host=${REDIS_HOST}

# Stop TB: when true, beneficiary registration fails with an error if camp (vanID) is not configured
stoptb.enforce.vanid=${STOPTB_ENFORCE_VANID}
# Stop TB: this deployment's van/camp ID, replacing the old Redis camp:vanID lookup
stoptb.van.id=${STOPTB_VAN_ID}
jwt.secret=${JWT_SECRET_KEY}

#ELK logging file name
Expand Down
2 changes: 2 additions & 0 deletions src/main/environment/common_example.properties
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ spring.redis.host=localhost
# Stop TB: when true, beneficiary registration fails with an error if camp (vanID)
# is not configured instead of silently registering without it
stoptb.enforce.vanid=false
# Stop TB: this deployment's van/camp ID, replacing the old Redis camp:vanID lookup
stoptb.van.id=0

jwt.secret=my-32-character-ultra-secure-and-ultra-long-secret
logging.path=logs/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ public String createBeneficiary(
// beneficiary registration with common and identity new
@Operation(summary = "Register a new beneficiary new API")
@PostMapping(value = { "/registrarBeneficaryRegistrationNew" })
@PreAuthorize("hasRole('NURSE') || hasRole('REGISTRAR') || hasRole('ASHA') || hasRole('VOLUNTEER') || hasRole('REGISTRATION_OFFICER')")
@PreAuthorize("hasRole('NURSE') || hasRole('REGISTRAR') || hasRole('ASHA') || hasRole('VOLUNTEER') || hasRole('REGISTRATION_OFFICER') || hasRole('COUNSELLOR')")
public String registrarBeneficaryRegistrationNew(@RequestBody String comingReq,
@RequestHeader(value = "Authorization") String Authorization) {
String s;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,32 @@

public interface BeneficiaryFlowStatusRepo extends CrudRepository<BeneficiaryFlowStatus, Long> {

// Targeted update β€” touches ONLY vanSerialNo. A full-entity save() here would also
// rewrite every other updatable column (e.g. `deleted`, which is insertable=false but
// NOT updatable=false) with whatever stale value the in-memory Java object happens to
// hold, silently clobbering the DB's own DEFAULT for columns never explicitly set.
@Transactional
@Modifying
@Query("UPDATE BeneficiaryFlowStatus t SET t.vanSerialNo = :vanSerialNo WHERE t.benFlowID = :id")
void updateVanSerialNo(@Param("id") Long id, @Param("vanSerialNo") Long vanSerialNo);

// Stop TB's district/village IDs are Nikshay-scoped, not AMRIT's general m_district/
// m_village numbering - the two ID spaces overlap (e.g. ID 1 means "Nicobars" in
// m_district but "Alluri Sitharama Raju" in m_nikshay_district), so client-sent text
// for these IDs can silently land on the wrong scheme's name. Gate any Nikshay-table
// resolution on this check first - a PSM with no Nikshay TU mapping is a non-Stop-TB
// program (ANC/NCD/cancer-screening/etc.) and must NOT go through the Nikshay tables.
@Query(value = "SELECT COUNT(*) FROM m_userservicerolemapping "
+ "WHERE ProviderServiceMapID = :psmId AND NikshayTUID IS NOT NULL AND Deleted = false LIMIT 1",
nativeQuery = true)
int countNikshayMappedUsersForPSM(@Param("psmId") Integer psmId);

@Query(value = "SELECT DistrictName FROM m_nikshay_district WHERE NikshayDistrictID = :id", nativeQuery = true)
String getNikshayDistrictName(@Param("id") Integer id);

@Query(value = "SELECT VillageName FROM m_nikshay_village WHERE NikshayVillageID = :id", nativeQuery = true)
String getNikshayVillageName(@Param("id") Integer id);

// nurse worklist
// @Query("SELECT t from BeneficiaryFlowStatus t WHERE (t.nurseFlag = 1 OR t.nurseFlag = 100) AND (t.specialist_flag <> 100 OR t.specialist_flag is null) AND t.deleted = false "
// + " AND Date(t.visitDate) = curdate() AND t.providerServiceMapId = :providerServiceMapId "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,24 @@
int returnOBJ = 0;
try {
BeneficiaryFlowStatus obj = getBenFlowRecordObj(requestOBJ, beneficiaryRegID, beneficiaryID);
System.out.println("TRACE createBenFlowRecord: benRegID=" + obj.getBeneficiaryRegID()

Check warning on line 67 in src/main/java/com/iemr/tm/service/benFlowStatus/CommonBenStatusFlowServiceImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this use of System.out by a logger.

See more on https://sonarcloud.io/project/issues?id=PSMRI_TM-API&issues=AaFcmKDeiI-eCIal8vFr&open=AaFcmKDeiI-eCIal8vFr&pullRequest=167
+ " providerServiceMapID=" + obj.getProviderServiceMapID()
+ " villageID=" + obj.getVillageID()
+ " vanID=" + obj.getVanID());

if (beneficiaryRegID != null && beneficiaryID != null && beneficiaryRegID > 0 && beneficiaryID > 0) {
objRS = beneficiaryFlowStatusRepo.save(obj);
if (objRS != null)
if (objRS != null) {
// VanSerialNo was never populated for i_ben_flow_outreach β€” following the
// same convention used elsewhere (VanSerialNo = record's own local PK, e.g.
// IdentityService.regMap.setVanSerialNo(regMap.getBenRegId())).
// A full-entity save() here (as this used to do) would also rewrite `deleted`
// (insertable=false but NOT updatable=false) with the in-memory object's never-set
// null, clobbering the DB's own DEFAULT b'0' and making the row invisible to every
// worklist query filtering `deleted = false` β€” use a targeted UPDATE instead.
beneficiaryFlowStatusRepo.updateVanSerialNo(objRS.getBenFlowID(), objRS.getBenFlowID());
returnOBJ = 1;
else
} else
returnOBJ = 0;
} else {
Calendar cal = Calendar.getInstance();
Expand All @@ -85,9 +97,11 @@
returnOBJ = 3;
} else {
objRS = beneficiaryFlowStatusRepo.save(obj);
if (objRS != null)
if (objRS != null) {
objRS.setVanSerialNo(objRS.getBenFlowID());
objRS = beneficiaryFlowStatusRepo.save(objRS);
returnOBJ = 1;
else
} else
returnOBJ = 0;
}

Expand Down Expand Up @@ -154,6 +168,34 @@
if (obj.getI_bendemographics().getDistrictBranchName() != null)
obj.setVillageName(obj.getI_bendemographics().getDistrictBranchName());

// Stop TB's district/village IDs are Nikshay-scoped, not AMRIT's general m_district/
// m_village numbering - the same numeric ID can mean two different real places
// depending on the scheme, so the client-sent name text can silently be wrong.
// Only override for PSMs actually mapped to a Nikshay TU (i.e. genuinely Stop TB) -
// every other program (ANC/NCD/cancer-screening/etc.) keeps using client-sent text
// as before, since their IDs are correctly AMRIT-scoped already.
try {
if (obj.getProviderServiceMapID() != null
&& beneficiaryFlowStatusRepo.countNikshayMappedUsersForPSM(obj.getProviderServiceMapID()) > 0) {
if (obj.getDistrictID() != null) {
String correctDistrictName = beneficiaryFlowStatusRepo.getNikshayDistrictName(obj.getDistrictID());
if (correctDistrictName != null) {
obj.setDistrictName(correctDistrictName);
}
}
if (obj.getVillageID() != null) {
String correctVillageName = beneficiaryFlowStatusRepo.getNikshayVillageName(obj.getVillageID());
if (correctVillageName != null) {
obj.setVillageName(correctVillageName);
}
}
}
} catch (Exception e) {
// Never let a Nikshay-name lookup failure block registration - worst case the
// display text stays whatever the client sent, same as before this fix existed.
logger.warn("Nikshay district/village name resolution failed, keeping client-sent text: " + e.getMessage());

Check warning on line 196 in src/main/java/com/iemr/tm/service/benFlowStatus/CommonBenStatusFlowServiceImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Format specifiers should be used instead of string concatenation.

See more on https://sonarcloud.io/project/issues?id=PSMRI_TM-API&issues=AaFcmKDeiI-eCIal8vFs&open=AaFcmKDeiI-eCIal8vFs&pullRequest=167
}

if (obj.getI_bendemographics().getServicePointID() != null)
obj.setServicePointID(obj.getI_bendemographics().getServicePointID());
if (obj.getI_bendemographics().getServicePointName() != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
Expand Down Expand Up @@ -163,6 +164,10 @@ public class ANCMasterDataServiceImpl {
private RouteOfAdminRepo routeOfAdminRepo;
private V_DrugPrescriptionRepo v_DrugPrescriptionRepo;

// This deployment's camp van; same property RegistrarServiceImpl uses. 0 = not a camp server.
@Value("${stoptb.van.id}")
private int campVanID;

@Autowired
private CovidSymptomsMasterRepo covidSymptomsMasterRepo;
@Autowired
Expand Down Expand Up @@ -560,6 +565,12 @@ public String getCommonDoctorMasterDataForGenopdAncNcdcarePnc(Integer visitCateg
NonedlList.get(i).setUnitOfMeasurement(NonedlList.get(i).getUom().getuOMName());
}
ArrayList<V_DrugPrescription> itemList = new ArrayList<>();
// Stop TB camp: the deployment's van (stoptb.van.id) decides the store, whatever van/facility the
// app sends. Servers without a camp van (stoptb.van.id=0) keep using the request values.
if (campVanID > 0) {
vanID = campVanID;
facilityID = null;
}
if (facilityID == null || facilityID <= 0) {
Integer fID = masterVanRepo.getFacilityID(vanID);
if (fID != null && fID > 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -114,12 +112,21 @@
@Autowired
private CookieUtil cookieUtil;

@Autowired
private LettuceConnectionFactory redisConnectionFactory;
// This deployment's van/camp ID. Previously looked up from Redis ("camp:vanID"),
// written at MMU login and deleted (globally, unscoped) on ANY user's logout β€” a Redis
// outage or an unrelated user's logout would silently break registration on this camp.
// Each camp/van already runs its own dedicated backend instance, so which van this is
// never actually changes at runtime; reading it from properties removes the Redis
// dependency entirely. No inline default β€” every properties file must set this
// explicitly. Scope: vanID only, parkingPlaceID is not part of this change.
@Value("${stoptb.van.id}")
private int vanID;

// When true, beneficiary registration fails loudly if camp is not configured
// instead of silently registering with vanID unset
@Value("${stoptb.enforce.vanid:false}")
// instead of silently registering with vanID unset. No inline default β€” every
// properties file must set this explicitly, so a forgotten config fails loudly
// at startup instead of running fail-open.
@Value("${stoptb.enforce.vanid}")
private boolean enforceVanID;

@Autowired
Expand Down Expand Up @@ -662,33 +669,23 @@
}

// New beneficiary registration with common and identity
public String registerBeneficiary(String comingRequest, String Authorization) throws Exception {

Check failure on line 672 in src/main/java/com/iemr/tm/service/registrar/RegistrarServiceImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 21 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=PSMRI_TM-API&issues=AaFcmJ8FiI-eCIal8vFn&open=AaFcmJ8FiI-eCIal8vFn&pullRequest=167

OutputResponse response1 = new OutputResponse();
Long beneficiaryRegID = null;
Long beneficiaryID = null;
Map<String, Object> responseMap = new HashMap<>();

// Inject correct vanID from Redis (mobile sends vanID=0 as placeholder)
byte[] vanIDBytes = null;
byte[] ppIDBytes = null;
try {
RedisConnection conn = redisConnectionFactory.getConnection();
vanIDBytes = conn.get("camp:vanID".getBytes());
ppIDBytes = conn.get("camp:parkingPlaceID".getBytes());
conn.close();
} catch (Exception e) {
logger.warn("Camp vanID lookup failed: " + e.getMessage());
}
if (vanIDBytes != null) {
// Inject configured vanID (mobile sends vanID=0 as placeholder). Previously looked
// up from Redis at request time; now a fixed property of this deployment (see
// vanID field javadoc above).
if (vanID > 0) {
JSONObject reqJson = new JSONObject(comingRequest);
reqJson.put("vanID", Integer.parseInt(new String(vanIDBytes)));
if (ppIDBytes != null)
reqJson.put("parkingPlaceID", Integer.parseInt(new String(ppIDBytes)));
reqJson.put("vanID", vanID);
comingRequest = reqJson.toString();
} else if (enforceVanID) {
throw new Exception(
"Camp not configured: vanID missing. Please select van/service point in MMU before registering beneficiary.");
"Camp not configured: stoptb.van.id is 0. Set stoptb.van.id in this deployment's properties file.");
}

RestTemplate restTemplate = new RestTemplate();
Expand All @@ -710,13 +707,19 @@
responseMap.put("benRegId", beneficiaryRegID);

BeneficiaryFlowStatus obj = InputMapper.gson().fromJson(comingRequest, BeneficiaryFlowStatus.class);
System.out.println("TRACE registerBeneficiary: benRegID=" + beneficiaryRegID + " isMobile="

Check warning on line 710 in src/main/java/com/iemr/tm/service/registrar/RegistrarServiceImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this use of System.out by a logger.

See more on https://sonarcloud.io/project/issues?id=PSMRI_TM-API&issues=AaFcmJ8FiI-eCIal8vFo&open=AaFcmJ8FiI-eCIal8vFo&pullRequest=167
+ (obj != null ? obj.getIsMobile() : "obj=null") + " providerServiceMapID="
+ (obj != null ? obj.getProviderServiceMapID() : null) + " villageID="
+ (obj != null ? obj.getVillageID() : null));
if (obj != null && obj.getIsMobile() != null && obj.getIsMobile()) {
System.out.println("TRACE registerBeneficiary: isMobile=true branch β€” createBenFlowRecord SKIPPED, benRegID=" + beneficiaryRegID);

Check warning on line 715 in src/main/java/com/iemr/tm/service/registrar/RegistrarServiceImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this use of System.out by a logger.

See more on https://sonarcloud.io/project/issues?id=PSMRI_TM-API&issues=AaFcmJ8FiI-eCIal8vFp&open=AaFcmJ8FiI-eCIal8vFp&pullRequest=167
responseMap.put("response", "Beneficiary successfully registered. Beneficiary ID is : "+ beneficiaryID+" , BenRegID is : "+beneficiaryRegID);
response1.setResponse(new Gson().toJson(responseMap));

} else {
int i = commonBenStatusFlowServiceImpl.createBenFlowRecord(comingRequest, beneficiaryRegID,
beneficiaryID);
System.out.println("TRACE registerBeneficiary: createBenFlowRecord returned=" + i + " benRegID=" + beneficiaryRegID);

Check warning on line 722 in src/main/java/com/iemr/tm/service/registrar/RegistrarServiceImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this use of System.out by a logger.

See more on https://sonarcloud.io/project/issues?id=PSMRI_TM-API&issues=AaFcmJ8FiI-eCIal8vFq&open=AaFcmJ8FiI-eCIal8vFq&pullRequest=167

if (i > 0) {
responseMap.put("response", "Beneficiary successfully registered. Beneficiary ID is : "+ beneficiaryID+" , BenRegID is : "+beneficiaryRegID);
Expand Down
Loading