Skip to content
Merged
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
77 changes: 74 additions & 3 deletions src/main/java/com/iemr/flw/service/StopTBPrescriptionService.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
Expand Down Expand Up @@ -48,6 +49,11 @@ public class StopTBPrescriptionService {
@Autowired
private BeneficiaryRepo beneficiaryRepo;

// Off by default: save the prescription only (no store/stock check, no patient issue, stock unchanged).
// true = check stock and dispense from the camp store.
@Value("${stoptb.dispense.enabled:false}")
private boolean dispenseEnabled;

private final Logger logger = LoggerFactory.getLogger(StopTBPrescriptionService.class);

public static class InsufficientStockException extends RuntimeException {
Expand Down Expand Up @@ -150,6 +156,10 @@ public void saveChiefComplaints(List<Map<String, Object>> complaints, Long benef
public Map<String, Object> prescribeAndDispense(Map<String, Object> prescription, Long beneficiaryRegID,
BenVisitDetail visit, String submissionId, String createdBy, Integer vanID, Integer parkingPlaceID) {
List<Map<String, Object>> drugs = toList(prescription.get("drugs"));
if (!dispenseEnabled) {
return prescribeWithoutDispensing(prescription, drugs, beneficiaryRegID, visit, createdBy, vanID,
parkingPlaceID);
}
Map<String, Object> result = new LinkedHashMap<>();
if (drugs.isEmpty()) {
// Remarks without medicine are still kept, as MMU saves the visit instruction without drugs.
Expand All @@ -176,7 +186,7 @@ public Map<String, Object> prescribeAndDispense(Map<String, Object> prescription
Integer qty = toInt(d.get("qtyPrescribed"));
if (qty == null || qty <= 0) {
// No quantity from the app: tablets/capsules = doses per day x days, other forms = 1.
qty = calculateQuantity(d, items.get(drugID));
qty = calculateQuantity(d, toInt(items.get(drugID)[7]));
if (qty == null) {
throw new IllegalArgumentException("qtyPrescribed is required for drugID " + drugID
+ " (tablet/capsule quantity needs frequency and duration)");
Expand Down Expand Up @@ -480,6 +490,68 @@ private Object[] getPatientDetails(Long beneficiaryRegID) {
}
}

/**
* Dispensing off (stoptb.dispense.enabled=false): the prescription is saved as the app sent it. No store or
* stock check and no patient issue, so drugs from the app's own list need not exist in this camp's store;
* DrugID, name and form are taken from the request. A new save replaces the visit's earlier prescription
* (same as chief complaints), so an edit or retry does not leave a second copy.
*/
private Map<String, Object> prescribeWithoutDispensing(Map<String, Object> prescription,
List<Map<String, Object>> drugs, Long beneficiaryRegID, BenVisitDetail visit, String createdBy,
Integer vanID, Integer parkingPlaceID) {
for (Map<String, Object> d : drugs) {
if (toInt(d.get("drugID")) == null) throw new IllegalArgumentException("drugID is required for every drug");
}
// Processed='N' so the removal is uploaded to central again (central updates rows it already has).
for (String table : new String[] { "t_prescribeddrug", "t_prescription" }) {
em.createNativeQuery("UPDATE db_iemr." + table + " SET Deleted = true, Processed = 'N', ModifiedBy = :user "
+ "WHERE BeneficiaryRegID = :ben AND VisitCode = :visitCode AND Deleted = false")
.setParameter("user", createdBy)
.setParameter("ben", beneficiaryRegID)
.setParameter("visitCode", visit.getVisitCode())
.executeUpdate();
}

Map<String, Object> result = new LinkedHashMap<>();
String instruction = toStr(prescription.get("instruction"));
if (!drugs.isEmpty() || (instruction != null && !instruction.isBlank())) {
long prescriptionID = insertPrescription(beneficiaryRegID, visit, instruction, createdBy, vanID,
parkingPlaceID);
for (Map<String, Object> d : drugs) {
Integer qty = toInt(d.get("qtyPrescribed"));
if (qty == null || qty <= 0) qty = calculateQuantity(d, toInt(d.get("itemFormID"))); // null if unknown
em.createNativeQuery("INSERT INTO db_iemr.t_prescribeddrug (BeneficiaryRegID, BenVisitID, "
+ "ProviderServiceMapID, VisitCode, PrescriptionID, DrugForm, DrugID, GenericDrugName, Dose, "
+ "Frequency, Duration, DuartionUnit, SpecialInstruction, QtyPrescribed, Deleted, Processed, "
+ "CreatedBy, VanID, ParkingPlaceID) VALUES (:ben, :visitID, :psm, :visitCode, "
+ ":prescriptionID, :form, :drugID, :name, :dose, :frequency, :duration, :durationUnit, "
+ ":instruction, :qty, false, 'N', :user, :van, :pp)")
.setParameter("ben", beneficiaryRegID)
.setParameter("visitID", visit.getBenVisitId())
.setParameter("psm", visit.getProviderServiceMapID())
.setParameter("visitCode", visit.getVisitCode())
.setParameter("prescriptionID", prescriptionID)
.setParameter("form", toStr(d.get("drugForm")))
.setParameter("drugID", toInt(d.get("drugID")))
.setParameter("name", toStr(d.get("drugName")))
.setParameter("dose", toStr(d.get("dose")))
.setParameter("frequency", toStr(d.get("frequency")))
.setParameter("duration", toStr(d.get("duration")))
.setParameter("durationUnit", toStr(d.get("durationUnit")))
.setParameter("instruction", toStr(d.get("instructions")))
.setParameter("qty", qty)
.setParameter("user", createdBy)
.setParameter("van", vanID)
.setParameter("pp", parkingPlaceID)
.executeUpdate();
stampVanSerialNo("t_prescribeddrug", "PrescribedDrugID", lastInsertId());
}
result.put("prescriptionID", prescriptionID);
}
result.put("dispensed", new ArrayList<Map<String, Object>>());
return result;
}

// t_prescription row for the visit (Stop TB service line, same as the visit).
private long insertPrescription(Long beneficiaryRegID, BenVisitDetail visit, String instruction, String createdBy,
Integer vanID, Integer parkingPlaceID) {
Expand Down Expand Up @@ -508,8 +580,7 @@ private long insertPrescription(Long beneficiaryRegID, BenVisitDetail visit, Str
* one intake per 7 days. Other forms (syrup, cream, injection, drops...): 1 bottle/tube/vial. Null when a
* tablet/capsule quantity cannot be worked out (unknown frequency or missing duration).
*/
private Integer calculateQuantity(Map<String, Object> drug, Object[] item) {
Integer formID = item[7] != null ? ((Number) item[7]).intValue() : null;
private Integer calculateQuantity(Map<String, Object> drug, Integer formID) {
if (formID == null || (formID != 1 && formID != 2)) return 1; // 1 = Tablet, 2 = Capsule
double perIntake = formID == 2 ? 1 : tabletsPerIntake(toStr(drug.get("dose")));
String frequency = Optional.ofNullable(toStr(drug.get("frequency"))).orElse("").toUpperCase();
Expand Down
Loading