Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
BFD-3665 getting security tags for claim
adding to the response claim, claimResponse, EOB V1
  • Loading branch information
MahiFentaye committed Dec 19, 2024
1 parent c08f084 commit e027fc1
Show file tree
Hide file tree
Showing 20 changed files with 581 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
package gov.cms.bfd.server.war.commons;

import gov.cms.bfd.model.rda.samhsa.FissTag;
import gov.cms.bfd.model.rda.samhsa.McsTag;
import gov.cms.bfd.model.rif.samhsa.CarrierTag;
import gov.cms.bfd.model.rif.samhsa.DmeTag;
import gov.cms.bfd.model.rif.samhsa.HhaTag;
import gov.cms.bfd.model.rif.samhsa.HospiceTag;
import gov.cms.bfd.model.rif.samhsa.InpatientTag;
import gov.cms.bfd.model.rif.samhsa.OutpatientTag;
import gov.cms.bfd.model.rif.samhsa.SnfTag;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hl7.fhir.r4.model.CodeableConcept;
import org.springframework.stereotype.Service;

/** Find security level. */
@Service
public final class LookUpSamhsaSecurityTags {

/** The Entity manager. */
private EntityManager entityManager;

/**
* Sets the {@link #entityManager}.
*
* @param entityManager a JPA {@link EntityManager} connected to the application's database
*/
@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}

/**
* Method to find the security level of a given claim ID.
*
* @param type holds Claim
* @param claimId holds Claim
* @return SecurityLevel
*/
public String getClaimSecurityLevel(CodeableConcept type, String claimId) {
// Identify the claim type (e.g., Inpatient, Outpatient, Carrier, etc.)

// claimId = claim.getIdElement().getIdPart()
// CodeableConcept type, claimId

// CodeableConcept type = claim.getType();
String claimType = getClaimType(type);

Set<String> securityTags = new HashSet<>();

// Query tags based on the claim type
switch (claimType) {
case "Inpatient":
securityTags.addAll(queryTagsForClaim(claimId, InpatientTag.class));
break;
case "Outpatient":
securityTags.addAll(queryTagsForClaim(claimId, OutpatientTag.class));
break;
case "Carrier":
securityTags.addAll(queryTagsForClaim(claimId, CarrierTag.class));
break;
case "DME":
securityTags.addAll(queryTagsForClaim(claimId, DmeTag.class));
break;
case "HHA":
securityTags.addAll(queryTagsForClaim(claimId, HhaTag.class));
break;
case "Hospice":
securityTags.addAll(queryTagsForClaim(claimId, HospiceTag.class));
break;
case "SNF":
securityTags.addAll(queryTagsForClaim(claimId, SnfTag.class));
break;
case "FISS":
securityTags.addAll(queryTagsForClaim(claimId, FissTag.class));
break;
case "MCS":
securityTags.addAll(queryTagsForClaim(claimId, McsTag.class));
break;
default:
// No tags for unrecognized claim type
break;
}

// Determine the security level based on the collected tags
return determineSecurityLevel(securityTags);
}

/**
* Helper method to get the claim type from the FHIR Claim resource.
*
* @param type the FHIR Claim resource
* @return the claim type (e.g., "Inpatient", "Outpatient", etc.)
*/
private String getClaimType(CodeableConcept type) {
// Retrieve the claim type from the Claim resource
// CodeableConcept type = claim.getType();
if (type != null && type.hasCoding()) {

String code = type.getCodingFirstRep().getCode();
switch (code) {
case "INP":
return "Inpatient";
case "OUT":
return "Outpatient";
case "CAR":
return "Carrier";
case "DME":
return "DME";
case "HHA":
return "HHA";
case "HOS":
return "Hospice";
case "SNF":
return "SNF";
case "FISS":
return "FISS";
case "MCS":
return "MCS";
default:
return "Unknown";
}
}
return "Unknown"; // Return "Unknown" if type is not set
}

/**
* Helper method to query tags for a specific claim from a specific table.
*
* @param claimId the name of the variable
* @param tagClass the name of the tag class
* @return queryTagsForClaim
*/
private Set<String> queryTagsForClaim(String claimId, Class<?> tagClass) {
Set<String> tagCodes = new HashSet<>();

String sql;
if (FissTag.class.equals(tagClass) || McsTag.class.equals(tagClass)) {
// For FissTag and McsTag, claimId is a String
sql = "SELECT t.code FROM " + tagClass.getSimpleName() + " t WHERE t.claim = :claim";
} else {
// For other tags (CarrierTag, DmeTag, etc.), claimId is a Long
sql = "SELECT t.code FROM " + tagClass.getSimpleName() + " t WHERE t.claim = :claim";
}

Query query = entityManager.createQuery(sql);
query.setParameter("claim", claimId);

@SuppressWarnings("unchecked")
List<String> resultList = query.getResultList();

// Use a parameterized constructor to initialize the Set with the List
tagCodes = new HashSet<>(resultList);
return tagCodes;
}

/**
* Helper method to determine the security level based on the collected tags.
*
* @param securityTags value of securityTags
* @return SecurityLevel
*/
private String determineSecurityLevel(Set<String> securityTags) {
// Define the rules for security levels based on tag codes
for (String tag : securityTags) {
if ("R".equals(tag) || "42CFRPart2".equals(tag)) {
return "Restricted"; // Sensitive data
}
}

// Default to 'Normal' if no sensitive tags are found
return "Normal";
}

/**
* Helper method to determine the security level based on the collected tags.
*
* @param claimId value of claimId
* @param tagClass value of tagClass
* @return SecurityLevel
*/
public String getClaimSecurityLevel(String claimId, Class<?> tagClass) {

return determineSecurityLevel(queryTagsForClaim(claimId, tagClass));
// return queryTagsForClaim(claimId, tagClass);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
import gov.cms.bfd.model.codebook.data.CcwCodebookVariable;
import gov.cms.bfd.model.rif.entities.CarrierClaim;
import gov.cms.bfd.model.rif.entities.CarrierClaimLine;
import gov.cms.bfd.model.rif.samhsa.CarrierTag;
import gov.cms.bfd.server.war.commons.ClaimType;
import gov.cms.bfd.server.war.commons.Diagnosis;
import gov.cms.bfd.server.war.commons.Diagnosis.DiagnosisLabel;
import gov.cms.bfd.server.war.commons.LookUpSamhsaSecurityTags;
import gov.cms.bfd.server.war.commons.MedicareSegment;
import gov.cms.bfd.server.war.commons.Profile;
import gov.cms.bfd.server.war.commons.carin.C4BBAdjudication;
Expand All @@ -27,6 +29,7 @@
import org.hl7.fhir.r4.model.ExplanationOfBenefit.CareTeamComponent;
import org.hl7.fhir.r4.model.ExplanationOfBenefit.ItemComponent;
import org.hl7.fhir.r4.model.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
Expand All @@ -48,6 +51,9 @@ final class CarrierClaimTransformerV2 implements ClaimTransformerInterfaceV2 {
private static final String METRIC_NAME =
MetricRegistry.name(CarrierClaimTransformerV2.class.getSimpleName(), "transform");

/** Injecting lookUpSamhsaSecurityTags. */
@Autowired private LookUpSamhsaSecurityTags lookUpSamhsaSecurityTags;

/**
* Instantiates a new transformer.
*
Expand Down Expand Up @@ -102,6 +108,15 @@ private ExplanationOfBenefit transformClaim(CarrierClaim claimGroup, boolean inc
// Required values not directly mapped
eob.getMeta().addProfile(Profile.C4BB.getVersionedEobNonclinicianUrl());

String securityTag =
lookUpSamhsaSecurityTags.getClaimSecurityLevel(
String.valueOf(claimGroup.getClaimId()), CarrierTag.class);
eob.getMeta()
.addSecurity()
.setSystem("https://terminology.hl7.org/6.1.0/CodeSystem-v3-Confidentiality.html")
.setCode(securityTag)
.setDisplay(securityTag);

// TODO: ExplanationOfBenefit.outcome is a required field. Needs to be mapped.
// eob.setOutcome(?)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
import gov.cms.bfd.model.codebook.data.CcwCodebookVariable;
import gov.cms.bfd.model.rif.entities.DMEClaim;
import gov.cms.bfd.model.rif.entities.DMEClaimLine;
import gov.cms.bfd.model.rif.samhsa.DmeTag;
import gov.cms.bfd.server.war.commons.ClaimType;
import gov.cms.bfd.server.war.commons.Diagnosis;
import gov.cms.bfd.server.war.commons.Diagnosis.DiagnosisLabel;
import gov.cms.bfd.server.war.commons.LookUpSamhsaSecurityTags;
import gov.cms.bfd.server.war.commons.MedicareSegment;
import gov.cms.bfd.server.war.commons.Profile;
import gov.cms.bfd.server.war.commons.carin.C4BBAdjudication;
Expand All @@ -27,6 +29,7 @@
import org.hl7.fhir.r4.model.ExplanationOfBenefit.ItemComponent;
import org.hl7.fhir.r4.model.Extension;
import org.hl7.fhir.r4.model.Quantity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/** Transforms CCW {@link DMEClaim} instances into FHIR {@link ExplanationOfBenefit} resources. */
Expand All @@ -46,6 +49,9 @@ final class DMEClaimTransformerV2 implements ClaimTransformerInterfaceV2 {
private static final String METRIC_NAME =
MetricRegistry.name(DMEClaimTransformerV2.class.getSimpleName(), "transform");

/** Injecting lookUpSamhsaSecurityTags. */
@Autowired private LookUpSamhsaSecurityTags lookUpSamhsaSecurityTags;

/**
* Instantiates a new transformer.
*
Expand Down Expand Up @@ -101,6 +107,15 @@ private ExplanationOfBenefit transformClaim(DMEClaim claimGroup, boolean include
// Required values not directly mapped
eob.getMeta().addProfile(Profile.C4BB.getVersionedEobInpatientUrl());

String securityTag =
lookUpSamhsaSecurityTags.getClaimSecurityLevel(
String.valueOf(claimGroup.getClaimId()), DmeTag.class);
eob.getMeta()
.addSecurity()
.setSystem("https://terminology.hl7.org/6.1.0/CodeSystem-v3-Confidentiality.html")
.setCode(securityTag)
.setDisplay(securityTag);

// Common group level fields between all claim types
// Claim Type + Claim ID => ExplanationOfBenefit.id
// CLM_ID => ExplanationOfBenefit.identifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
import gov.cms.bfd.model.codebook.data.CcwCodebookVariable;
import gov.cms.bfd.model.rif.entities.HHAClaim;
import gov.cms.bfd.model.rif.entities.HHAClaimLine;
import gov.cms.bfd.model.rif.samhsa.HhaTag;
import gov.cms.bfd.server.war.commons.C4BBInstutionalClaimSubtypes;
import gov.cms.bfd.server.war.commons.ClaimType;
import gov.cms.bfd.server.war.commons.LookUpSamhsaSecurityTags;
import gov.cms.bfd.server.war.commons.MedicareSegment;
import gov.cms.bfd.server.war.commons.Profile;
import gov.cms.bfd.server.war.commons.carin.C4BBClaimProfessionalAndNonClinicianCareTeamRole;
Expand All @@ -23,6 +25,7 @@
import org.hl7.fhir.r4.model.ExplanationOfBenefit;
import org.hl7.fhir.r4.model.ExplanationOfBenefit.ItemComponent;
import org.hl7.fhir.r4.model.Quantity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/** Transforms CCW {@link HHAClaim} instances into FHIR {@link ExplanationOfBenefit} resources. */
Expand All @@ -39,6 +42,9 @@ final class HHAClaimTransformerV2 implements ClaimTransformerInterfaceV2 {
private static final String METRIC_NAME =
MetricRegistry.name(HHAClaimTransformerV2.class.getSimpleName(), "transform");

/** Injecting lookUpSamhsaSecurityTags. */
@Autowired private LookUpSamhsaSecurityTags lookUpSamhsaSecurityTags;

/**
* Instantiates a new transformer.
*
Expand Down Expand Up @@ -87,6 +93,14 @@ private ExplanationOfBenefit transformClaim(HHAClaim claimGroup) {
// Required values not directly mapped
eob.getMeta().addProfile(Profile.C4BB.getVersionedEobNonclinicianUrl());

String securityTag =
lookUpSamhsaSecurityTags.getClaimSecurityLevel(
String.valueOf(claimGroup.getClaimId()), HhaTag.class);
eob.getMeta()
.addSecurity()
.setSystem("https://terminology.hl7.org/6.1.0/CodeSystem-v3-Confidentiality.html")
.setCode(securityTag)
.setDisplay(securityTag);
// Common group level fields between all claim types
// Claim Type + Claim ID => ExplanationOfBenefit.id
// CLM_ID => ExplanationOfBenefit.identifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
import gov.cms.bfd.model.codebook.data.CcwCodebookVariable;
import gov.cms.bfd.model.rif.entities.HospiceClaim;
import gov.cms.bfd.model.rif.entities.HospiceClaimLine;
import gov.cms.bfd.model.rif.samhsa.HospiceTag;
import gov.cms.bfd.server.war.commons.C4BBInstutionalClaimSubtypes;
import gov.cms.bfd.server.war.commons.ClaimType;
import gov.cms.bfd.server.war.commons.LookUpSamhsaSecurityTags;
import gov.cms.bfd.server.war.commons.MedicareSegment;
import gov.cms.bfd.server.war.commons.Profile;
import gov.cms.bfd.server.war.commons.carin.C4BBAdjudication;
Expand All @@ -23,6 +25,7 @@
import java.util.Optional;
import org.hl7.fhir.r4.model.ExplanationOfBenefit;
import org.hl7.fhir.r4.model.ExplanationOfBenefit.ItemComponent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
Expand All @@ -41,6 +44,9 @@ final class HospiceClaimTransformerV2 implements ClaimTransformerInterfaceV2 {
private static final String METRIC_NAME =
MetricRegistry.name(HospiceClaimTransformerV2.class.getSimpleName(), "transform");

/** Injecting lookUpSamhsaSecurityTags. */
@Autowired private LookUpSamhsaSecurityTags lookUpSamhsaSecurityTags;

/**
* Instantiates a new transformer.
*
Expand Down Expand Up @@ -89,6 +95,14 @@ private ExplanationOfBenefit transformClaim(HospiceClaim claimGroup) {
// Required values not directly mapped
eob.getMeta().addProfile(Profile.C4BB.getVersionedEobInpatientUrl());

String securityTag =
lookUpSamhsaSecurityTags.getClaimSecurityLevel(
String.valueOf(claimGroup.getClaimId()), HospiceTag.class);
eob.getMeta()
.addSecurity()
.setSystem("https://terminology.hl7.org/6.1.0/CodeSystem-v3-Confidentiality.html")
.setCode(securityTag)
.setDisplay(securityTag);
// Common group level fields between all claim types
// Claim Type + Claim ID => ExplanationOfBenefit.id
// CLM_ID => ExplanationOfBenefit.identifier
Expand Down
Loading

0 comments on commit e027fc1

Please sign in to comment.