Skip to content
Draft
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 src/main/java/org/oscarehr/common/model/Property.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
public class Property extends AbstractModel<Integer> implements Serializable {

public enum PROPERTY_KEY {invoice_payee_display_clinic, invoice_payee_info, default_billing_provider, default_billing_form,
bc_default_service_location, auto_populate_refer}
bc_default_service_location, auto_populate_refer, provider_linking_rules}

public enum PROPERTY_VALUE {clinicdefault}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package org.oscarehr.dashboard.admin;

import org.apache.logging.log4j.Logger;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;
import org.oscarehr.managers.ProviderManager2;
import org.oscarehr.managers.SecurityInfoManager;
import org.oscarehr.util.LoggedInInfo;
import org.oscarehr.util.MiscUtils;
import org.oscarehr.util.SpringUtils;

import net.sf.json.JSONObject;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.PrintWriter;

public class ProviderLinkingRulesAction extends DispatchAction {
private static final Logger logger = MiscUtils.getLogger();

private ProviderManager2 providerManager2 = SpringUtils.getBean(ProviderManager2.class);
private SecurityInfoManager securityInfoManager = SpringUtils.getBean(SecurityInfoManager.class);

public ActionForward updateProviderLinkingRulesProperty(ActionMapping actionmapping,ActionForm actionform, HttpServletRequest request, HttpServletResponse response) {
LoggedInInfo loggedInInfo = LoggedInInfo.getLoggedInInfoFromSession(request);
if (!securityInfoManager.hasPrivilege(loggedInInfo, "_admin", SecurityInfoManager.WRITE, null) &&
!securityInfoManager.hasPrivilege(loggedInInfo, "_lab", SecurityInfoManager.WRITE, null)) {
throw new RuntimeException("missing required security object (_admin or _lab)");
}

String value = request.getParameter("status");
boolean status = providerManager2.updateProviderLinkingRulesProperty(loggedInInfo, value);

JSONObject json = new JSONObject();
json.put("status", status);
writeJsonResponse(response, json.toString());
return null;
}

public ActionForward viewProviderLinkingRulesPropertyStatus(ActionMapping actionmapping,ActionForm actionform, HttpServletRequest request, HttpServletResponse response) {
LoggedInInfo loggedInInfo = LoggedInInfo.getLoggedInInfoFromSession(request);
if (!securityInfoManager.hasPrivilege(loggedInInfo, "_admin", SecurityInfoManager.READ, null) &&
!securityInfoManager.hasPrivilege(loggedInInfo, "_lab", SecurityInfoManager.READ, null)) {
throw new RuntimeException("missing required security object (_admin or _lab)");
}

boolean status = providerManager2.viewProviderLinkingRulesPropertyStatus(loggedInInfo);

JSONObject json = new JSONObject();
json.put("status", status);
writeJsonResponse(response, json.toString());
return null;
}

private void writeJsonResponse(HttpServletResponse response, String json) {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");

try (PrintWriter out = response.getWriter()) {
out.write(json);
} catch (Exception e) {
logger.error("An error occurred while writing JSON response to the output stream", e);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@
import org.oscarehr.hospitalReportManager.model.HRMDocumentSubClass;
import org.oscarehr.hospitalReportManager.model.HRMDocumentToDemographic;
import org.oscarehr.hospitalReportManager.model.HRMDocumentToProvider;
import org.oscarehr.managers.DemographicManager;
import org.oscarehr.managers.ProviderManager2;
import org.oscarehr.managers.SecurityInfoManager;
import org.oscarehr.common.model.Provider;
import org.oscarehr.util.LoggedInInfo;
import org.oscarehr.util.MiscUtils;
import org.oscarehr.util.SpringUtils;
Expand All @@ -44,6 +47,8 @@ public class HRMModifyDocumentAction extends DispatchAction {
HRMDocumentSubClassDao hrmDocumentSubClassDao = (HRMDocumentSubClassDao) SpringUtils.getBean(HRMDocumentSubClassDao.class);
HRMDocumentCommentDao hrmDocumentCommentDao = (HRMDocumentCommentDao) SpringUtils.getBean(HRMDocumentCommentDao.class);
private SecurityInfoManager securityInfoManager = SpringUtils.getBean(SecurityInfoManager.class);
private ProviderManager2 providerManager2 = SpringUtils.getBean(ProviderManager2.class);
private DemographicManager demographicManager = SpringUtils.getBean(DemographicManager.class);

public ActionForward undefined(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {
String method = request.getParameter("method");
Expand Down Expand Up @@ -171,8 +176,6 @@ public ActionForward signOff(ActionMapping mapping, ActionForm form, HttpServlet
}

public ActionForward assignProvider(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {
//Gets the Dao for incoming lab rules
IncomingLabRulesDao incomingLabRulesDao = SpringUtils.getBean(IncomingLabRulesDao.class);
String providerNo = request.getParameter("providerNo");

if(!securityInfoManager.hasPrivilege(LoggedInInfo.getLoggedInInfoFromSession(request), "_hrm", "w", null)) {
Expand All @@ -181,45 +184,11 @@ public ActionForward assignProvider(ActionMapping mapping, ActionForm form, Http


try {
HRMDocumentToProvider providerMapping = new HRMDocumentToProvider();
Integer hrmDocumentId = Integer.valueOf(request.getParameter("reportId"));
providerMapping.setHrmDocumentId(hrmDocumentId);
providerMapping.setProviderNo(providerNo);
providerMapping.setSignedOff(0);

hrmDocumentToProviderDao.merge(providerMapping);

//Gets the list of IncomingLabRules pertaining to the current provider
List<IncomingLabRules> incomingLabRules = incomingLabRulesDao.findCurrentByProviderNo(providerNo);
//If the list is not null
if (incomingLabRules != null) {
//For each labRule in the list
for(IncomingLabRules labRule : incomingLabRules) {
if (labRule.getForwardTypeStrings().contains("HRM")) {
//Creates a string of the provider number that the lab will be forwarded to
String forwardProviderNumber = labRule.getFrwdProviderNo();
//Checks to see if this provider is already linked to this lab
HRMDocumentToProvider hrmDocumentToProvider = hrmDocumentToProviderDao.findByHrmDocumentIdAndProviderNo(hrmDocumentId, forwardProviderNumber);
//If a record was not found
if (hrmDocumentToProvider == null) {
//Puts the information into the HRMDocumentToProvider object
hrmDocumentToProvider = new HRMDocumentToProvider();
hrmDocumentToProvider.setHrmDocumentId(hrmDocumentId);
hrmDocumentToProvider.setProviderNo(forwardProviderNumber);
hrmDocumentToProvider.setSignedOff(0);
//Stores it in the table
hrmDocumentToProviderDao.persist(hrmDocumentToProvider);
}
}
}
}


//we want to remove any unmatched entries when we do a manual match like this. -1 means unclaimed in this table.
HRMDocumentToProvider existingUnmatched = hrmDocumentToProviderDao.findByHrmDocumentIdAndProviderNo(hrmDocumentId, "-1");
if(existingUnmatched != null) {
hrmDocumentToProviderDao.remove(existingUnmatched.getId());
}
HRMUtil.assignProviderToDocument(hrmDocumentId, providerNo);
HRMUtil.processIncomingLabRules(hrmDocumentId, providerNo);
HRMUtil.removeUnclaimedProviderMappings(hrmDocumentId);

request.setAttribute("success", true);
} catch (Exception e) {
Expand Down Expand Up @@ -284,6 +253,19 @@ public ActionForward assignDemographic(ActionMapping mapping, ActionForm form, H
demographicMapping.setTimeAssigned(new Date());

hrmDocumentToDemographicDao.merge(demographicMapping);

// Check if provider linking rules are enabled
LoggedInInfo loggedInInfo = LoggedInInfo.getLoggedInInfoFromSession(request);
if (providerManager2.viewProviderLinkingRulesPropertyStatus(loggedInInfo)) {
// Get the demographic's MRP
Provider mrp = demographicManager.getMRP(loggedInInfo, Integer.parseInt(demographicNo));
if (mrp != null) {
// Link the document to the MRP as well using assignProvider logic
HRMUtil.assignProviderToDocument(Integer.valueOf(hrmDocumentId), mrp.getProviderNo());
HRMUtil.processIncomingLabRules(Integer.valueOf(hrmDocumentId), mrp.getProviderNo());
HRMUtil.removeUnclaimedProviderMappings(Integer.valueOf(hrmDocumentId));
}
}

request.setAttribute("success", true);
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@
import org.oscarehr.common.dao.DemographicCustDao;
import org.oscarehr.common.dao.DemographicDao;
import org.oscarehr.common.dao.IncomingLabRulesDao;
import org.oscarehr.common.dao.PropertyDao;
import org.oscarehr.common.model.Demographic;
import org.oscarehr.common.model.DemographicCust;
import org.oscarehr.common.model.IncomingLabRules;
import org.oscarehr.common.model.Property;
import org.oscarehr.common.model.Provider;
import org.oscarehr.hospitalReportManager.dao.HRMDocumentDao;
import org.oscarehr.hospitalReportManager.dao.HRMDocumentSubClassDao;
Expand Down Expand Up @@ -232,8 +234,17 @@ public static void addReportToInbox(LoggedInInfo loggedInInfo, HRMReport report)
logger.debug("MERGED DOCUMENTS ID"+document.getId());


HRMReportParser.routeReportToDemographic(report, document);
String demProviderNo = HRMReportParser.routeReportToDemographic(report, document);
HRMReportParser.doSimilarReportCheck(loggedInInfo, report, document);

PropertyDao propertyDao = SpringUtils.getBean(PropertyDao.class);

// Link the HRM to the MRP
boolean providerLinkingRules = propertyDao.isActiveBooleanProperty(Property.PROPERTY_KEY.provider_linking_rules);
if (providerLinkingRules && demProviderNo != null && !demProviderNo.equals("0")) {
routeReportToProvider(document.getId(), demProviderNo);
}

// Attempt a route to the provider listed in the report -- if they don't exist, note that in the record
Boolean routeSuccess = HRMReportParser.routeReportToProvider(report, document.getId());
if (!routeSuccess) {
Expand Down Expand Up @@ -261,11 +272,11 @@ public static void addReportToInbox(LoggedInInfo loggedInInfo, HRMReport report)
}
}

private static void routeReportToDemographic(HRMReport report, HRMDocument mergedDocument) {
private static String routeReportToDemographic(HRMReport report, HRMDocument mergedDocument) {

if(report == null) {
logger.info("routeReportToDemographic cannot continue, report parameter is null");
return;
return null;
}


Expand All @@ -276,13 +287,15 @@ private static void routeReportToDemographic(HRMReport report, HRMDocument merge

List<Demographic> matchingDemographicListByHin = demographicDao.searchDemographicByHIN(report.getHCN());

String demProviderNo = null;
if (matchingDemographicListByHin.size() > 0) {
if (OscarProperties.getInstance().isPropertyActive("omd_hrm_demo_matching_criteria")) {
for (Demographic d : matchingDemographicListByHin) {
if (report.getGender().equalsIgnoreCase(d.getSex())
&& report.getDateOfBirthAsString().equalsIgnoreCase(d.getBirthDayAsString())
&& report.getLegalLastName().equalsIgnoreCase(d.getLastName())) {
HRMReportParser.routeReportToDemographic(mergedDocument.getId(), d.getDemographicNo());
demProviderNo = d.getProviderNo();
break;
}
}
Expand All @@ -292,9 +305,12 @@ private static void routeReportToDemographic(HRMReport report, HRMDocument merge
// if not empty and DOB matches as well, route report to Demographic
if (report.getDateOfBirthAsString().equalsIgnoreCase(demographic.getBirthDayAsString())) {
HRMReportParser.routeReportToDemographic(mergedDocument.getId(), demographic.getDemographicNo());
demProviderNo = demographic.getProviderNo();
}
}
}

return demProviderNo;
}


Expand Down Expand Up @@ -589,8 +605,14 @@ public static void routeReportToProvider(HRMDocument originalDocument, HRMReport

public static void routeReportToProvider(Integer reportId, String providerNo) {
HRMDocumentToProviderDao hrmDocumentToProviderDao = (HRMDocumentToProviderDao) SpringUtils.getBean(HRMDocumentToProviderDao.class);

// Check if routing already exists
HRMDocumentToProvider existing = hrmDocumentToProviderDao.findByHrmDocumentIdAndProviderNo(reportId, providerNo);
if (existing != null) {
return; // Don't create duplicate
}

HRMDocumentToProvider providerRouting = new HRMDocumentToProvider();

providerRouting.setHrmDocumentId(reportId);
providerRouting.setProviderNo(providerNo);

Expand Down
50 changes: 50 additions & 0 deletions src/main/java/org/oscarehr/hospitalReportManager/HRMUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,18 @@
import java.io.IOException;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;

import org.apache.logging.log4j.Logger;
import org.oscarehr.hospitalReportManager.dao.*;
import org.oscarehr.hospitalReportManager.model.HRMCategory;
import org.oscarehr.hospitalReportManager.model.HRMDocument;
import org.oscarehr.hospitalReportManager.model.HRMDocumentSubClass;
import org.oscarehr.hospitalReportManager.model.HRMDocumentToDemographic;
import org.oscarehr.hospitalReportManager.model.HRMDocumentToProvider;
import org.oscarehr.hospitalReportManager.model.HRMSubClass;
import org.oscarehr.common.dao.IncomingLabRulesDao;
import org.oscarehr.common.model.IncomingLabRules;
import org.oscarehr.managers.NioFileManager;
import org.oscarehr.managers.SecurityInfoManager;
import org.oscarehr.util.LoggedInInfo;
Expand All @@ -40,9 +44,11 @@ public class HRMUtil {

private static HRMDocumentDao hrmDocumentDao = (HRMDocumentDao) SpringUtils.getBean(HRMDocumentDao.class);
private static HRMDocumentToDemographicDao hrmDocumentToDemographicDao = (HRMDocumentToDemographicDao) SpringUtils.getBean(HRMDocumentToDemographicDao.class);
private static HRMDocumentToProviderDao hrmDocumentToProviderDao = (HRMDocumentToProviderDao) SpringUtils.getBean(HRMDocumentToProviderDao.class);
private static HRMSubClassDao hrmSubClassDao = (HRMSubClassDao) SpringUtils.getBean(HRMSubClassDao.class);
private static HRMDocumentSubClassDao hrmDocumentSubClassDao = (HRMDocumentSubClassDao) SpringUtils.getBean(HRMDocumentSubClassDao.class);
private static HRMCategoryDao hrmCategoryDao = SpringUtils.getBean(HRMCategoryDao.class);
private static IncomingLabRulesDao incomingLabRulesDao = SpringUtils.getBean(IncomingLabRulesDao.class);
private static final NioFileManager nioFileManager = SpringUtils.getBean(NioFileManager.class);
private static final SecurityInfoManager securityInfoManager = SpringUtils.getBean(SecurityInfoManager.class);

Expand Down Expand Up @@ -356,4 +362,48 @@ private static String getHRMDocumentDisplayName(Integer hrmId) {
HRMDocument hrmDocument = hrmDocumentDao.find(hrmId);
return getHRMDocumentDisplayName(hrmDocument.getDescription(), "", hrmDocument.getReportType(), hrmDocument.getReportStatus());
}

public static void assignProviderToDocument(Integer hrmDocumentId, String providerNo) {
HRMDocumentToProvider existingMapping = hrmDocumentToProviderDao.findByHrmDocumentIdAndProviderNo(hrmDocumentId, providerNo);
if (existingMapping == null) {
HRMDocumentToProvider providerMapping = new HRMDocumentToProvider();
providerMapping.setHrmDocumentId(hrmDocumentId);
providerMapping.setProviderNo(providerNo);
providerMapping.setSignedOff(0);
hrmDocumentToProviderDao.persist(providerMapping);
}
}

public static void processIncomingLabRules(Integer hrmDocumentId, String providerNo) {
List<IncomingLabRules> incomingLabRules = incomingLabRulesDao.findCurrentByProviderNo(providerNo);
if (incomingLabRules == null || incomingLabRules.isEmpty()) {
return;
}

// Get all existing provider mappings for this document once
List<HRMDocumentToProvider> existingMappings = hrmDocumentToProviderDao.findByHrmDocumentId(hrmDocumentId);
Set<String> existingProviderNumbers = existingMappings.stream()
.map(HRMDocumentToProvider::getProviderNo)
.collect(Collectors.toSet());

// Process only HRM rules and create mappings for providers not already assigned
incomingLabRules.stream()
.filter(rule -> rule.getForwardTypeStrings().contains("HRM"))
.map(IncomingLabRules::getFrwdProviderNo)
.filter(forwardProviderNo -> !existingProviderNumbers.contains(forwardProviderNo))
.forEach(forwardProviderNo -> {
HRMDocumentToProvider mapping = new HRMDocumentToProvider();
mapping.setHrmDocumentId(hrmDocumentId);
mapping.setProviderNo(forwardProviderNo);
mapping.setSignedOff(0);
hrmDocumentToProviderDao.persist(mapping);
});
}

public static void removeUnclaimedProviderMappings(Integer hrmDocumentId) {
HRMDocumentToProvider existingUnmatched = hrmDocumentToProviderDao.findByHrmDocumentIdAndProviderNo(hrmDocumentId, "-1");
if(existingUnmatched != null) {
hrmDocumentToProviderDao.remove(existingUnmatched.getId());
}
}
}
34 changes: 34 additions & 0 deletions src/main/java/org/oscarehr/managers/ProviderManager2.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ public class ProviderManager2 {

@Autowired
private ProviderExtDao providerExtDao;

@Autowired
private SecurityInfoManager securityInfoManager;

public List<Provider> getProviders(LoggedInInfo loggedInInfo, Boolean active) {
List<Provider> results = null;
Expand Down Expand Up @@ -747,4 +750,35 @@ public void updateProvider(LoggedInInfo loggedInInfo, Provider provider) {
LogAction.addLogSynchronous(loggedInInfo, "ProviderManager.updateProvider, providerNo=" + provider.getProviderNo(), null);

}

public boolean updateProviderLinkingRulesProperty(LoggedInInfo loggedInInfo, String value) {
if (!securityInfoManager.hasPrivilege(loggedInInfo, "_admin", SecurityInfoManager.WRITE, null) &&
!securityInfoManager.hasPrivilege(loggedInInfo, "_lab", SecurityInfoManager.WRITE, null)) {
throw new RuntimeException("missing required security object (_admin or _lab)");
}

List<Property> properties = propertyDao.findGlobalByName(Property.PROPERTY_KEY.provider_linking_rules);
if (properties.size() > 0) {
for (Property property: properties) {
property.setValue(value);
propertyDao.merge(property);
}
} else {
Property property = new Property();
property.setName(Property.PROPERTY_KEY.provider_linking_rules.name());
property.setValue(value);
propertyDao.persist(property);
}

return propertyDao.isActiveBooleanProperty(Property.PROPERTY_KEY.provider_linking_rules);
}

public boolean viewProviderLinkingRulesPropertyStatus(LoggedInInfo loggedInInfo) {
if (!securityInfoManager.hasPrivilege(loggedInInfo, "_admin", SecurityInfoManager.READ, null) &&
!securityInfoManager.hasPrivilege(loggedInInfo, "_lab", SecurityInfoManager.READ, null)) {
throw new RuntimeException("missing required security object (_admin or _lab)");
}

return propertyDao.isActiveBooleanProperty(Property.PROPERTY_KEY.provider_linking_rules);
}
}
Loading