use of org.mitre.synthea.world.concepts.Claim.ClaimEntry in project synthea by synthetichealth.
the class BB2RIFExporter method exportInpatient.
/**
* Export inpatient claims details for a single person.
* @param person the person to export
* @param startTime earliest claim date to export
* @param stopTime end time of simulation
* @throws IOException if something goes wrong
*/
private void exportInpatient(Person person, long startTime, long stopTime) throws IOException {
HashMap<INPATIENT, String> fieldValues = new HashMap<>();
boolean previousEmergency = false;
for (HealthRecord.Encounter encounter : person.record.encounters) {
if (encounter.stop < startTime) {
continue;
}
boolean isInpatient = encounter.type.equals(EncounterType.INPATIENT.toString());
boolean isEmergency = encounter.type.equals(EncounterType.EMERGENCY.toString());
boolean isVA = (ProviderType.VETERAN == encounter.provider.type);
// IHS facilities have valid 6 digit id, IHS centers don't
boolean isIHSCenter = (ProviderType.IHS == encounter.provider.type) && encounter.provider.id.length() != 6;
if (isVA || isIHSCenter || !(isInpatient || isEmergency)) {
previousEmergency = false;
continue;
}
long claimId = BB2RIFExporter.claimId.getAndDecrement();
int claimGroupId = BB2RIFExporter.claimGroupId.getAndDecrement();
long fiDocId = BB2RIFExporter.fiDocCntlNum.getAndDecrement();
fieldValues.clear();
staticFieldConfig.setValues(fieldValues, INPATIENT.class, person);
// The REQUIRED fields
fieldValues.put(INPATIENT.BENE_ID, (String) person.attributes.get(BB2_BENE_ID));
fieldValues.put(INPATIENT.CLM_ID, "" + claimId);
fieldValues.put(INPATIENT.CLM_GRP_ID, "" + claimGroupId);
fieldValues.put(INPATIENT.FI_DOC_CLM_CNTL_NUM, "" + fiDocId);
fieldValues.put(INPATIENT.CLM_FROM_DT, bb2DateFromTimestamp(encounter.start));
fieldValues.put(INPATIENT.CLM_ADMSN_DT, bb2DateFromTimestamp(encounter.start));
fieldValues.put(INPATIENT.CLM_THRU_DT, bb2DateFromTimestamp(encounter.stop));
fieldValues.put(INPATIENT.NCH_BENE_DSCHRG_DT, bb2DateFromTimestamp(encounter.stop));
fieldValues.put(INPATIENT.NCH_WKLY_PROC_DT, bb2DateFromTimestamp(ExportHelper.nextFriday(encounter.stop)));
fieldValues.put(INPATIENT.PRVDR_NUM, encounter.provider.id);
fieldValues.put(INPATIENT.AT_PHYSN_NPI, encounter.clinician.npi);
fieldValues.put(INPATIENT.ORG_NPI_NUM, encounter.provider.npi);
fieldValues.put(INPATIENT.OP_PHYSN_NPI, encounter.clinician.npi);
fieldValues.put(INPATIENT.CLM_PMT_AMT, String.format("%.2f", encounter.claim.getTotalClaimCost()));
if (encounter.claim.payer == Payer.getGovernmentPayer(HealthInsuranceModule.MEDICARE)) {
fieldValues.put(INPATIENT.NCH_PRMRY_PYR_CLM_PD_AMT, "0");
} else {
fieldValues.put(INPATIENT.NCH_PRMRY_PYR_CLM_PD_AMT, String.format("%.2f", encounter.claim.getCoveredCost()));
}
fieldValues.put(INPATIENT.PRVDR_STATE_CD, locationMapper.getStateCode(encounter.provider.state));
// PTNT_DSCHRG_STUS_CD: 1=home, 2=transfer, 3=SNF, 20=died, 30=still here
String field = null;
String patientStatus = null;
if (encounter.ended) {
// TODO 2=transfer if the next encounter is also inpatient
field = "1";
// discharged
patientStatus = "A";
} else {
// the patient is still here
field = "30";
// still a patient
patientStatus = "C";
}
if (!person.alive(encounter.stop)) {
// the patient died before the encounter ended
field = "20";
// died
patientStatus = "B";
}
fieldValues.put(INPATIENT.PTNT_DSCHRG_STUS_CD, field);
fieldValues.put(INPATIENT.NCH_PTNT_STATUS_IND_CD, patientStatus);
fieldValues.put(INPATIENT.CLM_TOT_CHRG_AMT, String.format("%.2f", encounter.claim.getTotalClaimCost()));
if (isEmergency) {
// emergency
field = "1";
} else if (previousEmergency) {
// urgent
field = "2";
} else {
// elective
field = "3";
}
fieldValues.put(INPATIENT.CLM_IP_ADMSN_TYPE_CD, field);
fieldValues.put(INPATIENT.NCH_BENE_IP_DDCTBL_AMT, String.format("%.2f", encounter.claim.getDeductiblePaid()));
fieldValues.put(INPATIENT.NCH_BENE_PTA_COINSRNC_LBLTY_AM, String.format("%.2f", encounter.claim.getCoinsurancePaid()));
fieldValues.put(INPATIENT.NCH_IP_NCVRD_CHRG_AMT, String.format("%.2f", encounter.claim.getPatientCost()));
fieldValues.put(INPATIENT.NCH_IP_TOT_DDCTN_AMT, String.format("%.2f", encounter.claim.getPatientCost()));
int days = (int) ((encounter.stop - encounter.start) / (1000 * 60 * 60 * 24));
fieldValues.put(INPATIENT.CLM_UTLZTN_DAY_CNT, "" + days);
if (days > 60) {
field = "" + (days - 60);
} else {
field = "0";
}
fieldValues.put(INPATIENT.BENE_TOT_COINSRNC_DAYS_CNT, field);
if (days > 60) {
// days outlier
field = "1";
} else if (encounter.claim.getTotalClaimCost() > 100_000) {
// cost outlier
field = "2";
} else {
// no outlier
field = "0";
}
fieldValues.put(INPATIENT.CLM_DRG_OUTLIER_STAY_CD, field);
fieldValues.put(INPATIENT.REV_CNTR_TOT_CHRG_AMT, String.format("%.2f", encounter.claim.getCoveredCost()));
fieldValues.put(INPATIENT.REV_CNTR_NCVRD_CHRG_AMT, String.format("%.2f", encounter.claim.getPatientCost()));
// OPTIONAL FIELDS
fieldValues.put(INPATIENT.RNDRNG_PHYSN_NPI, encounter.clinician.npi);
String icdReasonCode = null;
if (encounter.reason != null) {
// values into the principle diagnoses code.
if (conditionCodeMapper.canMap(encounter.reason.code)) {
icdReasonCode = conditionCodeMapper.map(encounter.reason.code, person, true);
fieldValues.put(INPATIENT.PRNCPAL_DGNS_CD, icdReasonCode);
fieldValues.put(INPATIENT.ADMTG_DGNS_CD, icdReasonCode);
}
}
// Use the active condition diagnoses to enter mapped values
// into the diagnoses codes.
List<String> presentOnAdmission = getDiagnosesCodes(person, encounter.start);
List<String> mappedDiagnosisCodes = getDiagnosesCodes(person, encounter.stop);
boolean noDiagnoses = mappedDiagnosisCodes.isEmpty();
if (!noDiagnoses) {
int smallest = Math.min(mappedDiagnosisCodes.size(), BB2RIFStructure.inpatientDxFields.length);
for (int i = 0; i < smallest; i++) {
INPATIENT[] dxField = BB2RIFStructure.inpatientDxFields[i];
String dxCode = mappedDiagnosisCodes.get(i);
fieldValues.put(dxField[0], dxCode);
// 0=ICD10
fieldValues.put(dxField[1], "0");
String present = presentOnAdmission.contains(dxCode) ? "Y" : "N";
fieldValues.put(dxField[2], present);
}
if (!fieldValues.containsKey(INPATIENT.PRNCPAL_DGNS_CD)) {
fieldValues.put(INPATIENT.PRNCPAL_DGNS_CD, mappedDiagnosisCodes.get(0));
}
}
if (fieldValues.containsKey(INPATIENT.PRNCPAL_DGNS_CD)) {
String icdCode = fieldValues.get(INPATIENT.PRNCPAL_DGNS_CD);
// Add a DRG code, if applicable
if (drgCodeMapper.canMap(icdCode)) {
fieldValues.put(INPATIENT.CLM_DRG_CD, drgCodeMapper.map(icdCode, person));
}
// Check for external code...
setExternalCode(person, fieldValues, INPATIENT.PRNCPAL_DGNS_CD, INPATIENT.ICD_DGNS_E_CD1, INPATIENT.ICD_DGNS_E_VRSN_CD1, INPATIENT.CLM_E_POA_IND_SW1, presentOnAdmission);
setExternalCode(person, fieldValues, INPATIENT.PRNCPAL_DGNS_CD, INPATIENT.FST_DGNS_E_CD, INPATIENT.FST_DGNS_E_VRSN_CD);
}
// Use the procedures in this encounter to enter mapped values
boolean noProcedures = false;
if (!encounter.procedures.isEmpty()) {
List<HealthRecord.Procedure> mappableProcedures = new ArrayList<>();
List<String> mappedProcedureCodes = new ArrayList<>();
for (HealthRecord.Procedure procedure : encounter.procedures) {
for (HealthRecord.Code code : procedure.codes) {
if (conditionCodeMapper.canMap(code.code)) {
mappableProcedures.add(procedure);
mappedProcedureCodes.add(conditionCodeMapper.map(code.code, person, true));
// take the first mappable code for each procedure
break;
}
}
}
if (!mappableProcedures.isEmpty()) {
int smallest = Math.min(mappableProcedures.size(), BB2RIFStructure.inpatientPxFields.length);
for (int i = 0; i < smallest; i++) {
INPATIENT[] pxField = BB2RIFStructure.inpatientPxFields[i];
fieldValues.put(pxField[0], mappedProcedureCodes.get(i));
// 0=ICD10
fieldValues.put(pxField[1], "0");
fieldValues.put(pxField[2], bb2DateFromTimestamp(mappableProcedures.get(i).start));
}
} else {
noProcedures = true;
}
}
if (icdReasonCode == null && noDiagnoses && noProcedures) {
// skip this encounter
continue;
}
previousEmergency = isEmergency;
synchronized (rifWriters.getOrCreateWriter(INPATIENT.class)) {
int claimLine = 1;
for (ClaimEntry lineItem : encounter.claim.items) {
String hcpcsCode = null;
if (lineItem.entry instanceof HealthRecord.Procedure) {
for (HealthRecord.Code code : lineItem.entry.codes) {
if (hcpcsCodeMapper.canMap(code.code)) {
hcpcsCode = hcpcsCodeMapper.map(code.code, person, true);
// take the first mappable code for each procedure
break;
}
}
fieldValues.remove(INPATIENT.REV_CNTR_NDC_QTY);
fieldValues.remove(INPATIENT.REV_CNTR_NDC_QTY_QLFR_CD);
} else if (lineItem.entry instanceof HealthRecord.Medication) {
HealthRecord.Medication med = (HealthRecord.Medication) lineItem.entry;
if (med.administration) {
// Administration of medication
hcpcsCode = "T1502";
// 1 Unit
fieldValues.put(INPATIENT.REV_CNTR_NDC_QTY, "1");
// Unit
fieldValues.put(INPATIENT.REV_CNTR_NDC_QTY_QLFR_CD, "UN");
}
}
if (hcpcsCode == null) {
continue;
}
fieldValues.put(INPATIENT.CLM_LINE_NUM, Integer.toString(claimLine++));
fieldValues.put(INPATIENT.HCPCS_CD, hcpcsCode);
fieldValues.put(INPATIENT.REV_CNTR_UNIT_CNT, "" + Integer.max(1, days));
fieldValues.put(INPATIENT.REV_CNTR_RATE_AMT, String.format("%.2f", (lineItem.cost / Integer.max(1, days))));
fieldValues.put(INPATIENT.REV_CNTR_TOT_CHRG_AMT, String.format("%.2f", lineItem.cost));
fieldValues.put(INPATIENT.REV_CNTR_NCVRD_CHRG_AMT, String.format("%.2f", lineItem.copay + lineItem.deductible + lineItem.pocket));
if (lineItem.pocket == 0 && lineItem.deductible == 0) {
// Not subject to deductible or coinsurance
fieldValues.put(INPATIENT.REV_CNTR_DDCTBL_COINSRNC_CD, "3");
} else if (lineItem.pocket > 0 && lineItem.deductible > 0) {
// Subject to deductible and coinsurance
fieldValues.put(INPATIENT.REV_CNTR_DDCTBL_COINSRNC_CD, "0");
} else if (lineItem.pocket == 0) {
// Not subject to deductible
fieldValues.put(INPATIENT.REV_CNTR_DDCTBL_COINSRNC_CD, "1");
} else {
// Not subject to coinsurance
fieldValues.put(INPATIENT.REV_CNTR_DDCTBL_COINSRNC_CD, "2");
}
rifWriters.writeValues(INPATIENT.class, fieldValues);
}
if (claimLine == 1) {
// If claimLine still equals 1, then no line items were successfully added.
// Add a single top-level entry.
fieldValues.put(INPATIENT.CLM_LINE_NUM, Integer.toString(claimLine));
// HCPCS 99221: "Inpatient hospital visits: Initial and subsequent"
fieldValues.put(INPATIENT.HCPCS_CD, "99221");
rifWriters.writeValues(INPATIENT.class, fieldValues);
}
}
}
}
use of org.mitre.synthea.world.concepts.Claim.ClaimEntry in project synthea by synthetichealth.
the class BB2RIFExporter method exportHome.
/**
* Export Home Health Agency visits for a single person.
* @param person the person to export
* @param startTime earliest claim date to export
* @param stopTime end time of simulation
* @throws IOException if something goes wrong
*/
private void exportHome(Person person, long startTime, long stopTime) throws IOException {
HashMap<HHA, String> fieldValues = new HashMap<>();
int homeVisits = 0;
for (HealthRecord.Encounter encounter : person.record.encounters) {
if (encounter.stop < startTime) {
continue;
}
boolean isVA = (ProviderType.VETERAN == encounter.provider.type);
boolean isHome = encounter.type.equals(EncounterType.HOME.toString());
// IHS facilities have valid 6 digit id, IHS centers don't
boolean isIHSCenter = (ProviderType.IHS == encounter.provider.type) && encounter.provider.id.length() != 6;
if (isVA || isIHSCenter || !isHome) {
continue;
}
homeVisits += 1;
long claimId = BB2RIFExporter.claimId.getAndDecrement();
int claimGroupId = BB2RIFExporter.claimGroupId.getAndDecrement();
long fiDocId = BB2RIFExporter.fiDocCntlNum.getAndDecrement();
fieldValues.clear();
staticFieldConfig.setValues(fieldValues, HHA.class, person);
// The REQUIRED fields
fieldValues.put(HHA.BENE_ID, (String) person.attributes.get(BB2_BENE_ID));
fieldValues.put(HHA.CLM_ID, "" + claimId);
fieldValues.put(HHA.CLM_GRP_ID, "" + claimGroupId);
fieldValues.put(HHA.FI_DOC_CLM_CNTL_NUM, "" + fiDocId);
fieldValues.put(HHA.CLM_FROM_DT, bb2DateFromTimestamp(encounter.start));
fieldValues.put(HHA.CLM_ADMSN_DT, bb2DateFromTimestamp(encounter.start));
fieldValues.put(HHA.CLM_THRU_DT, bb2DateFromTimestamp(encounter.stop));
fieldValues.put(HHA.NCH_WKLY_PROC_DT, bb2DateFromTimestamp(ExportHelper.nextFriday(encounter.stop)));
fieldValues.put(HHA.PRVDR_NUM, encounter.provider.id);
fieldValues.put(HHA.ORG_NPI_NUM, encounter.provider.npi);
fieldValues.put(HHA.AT_PHYSN_NPI, encounter.clinician.npi);
fieldValues.put(HHA.RNDRNG_PHYSN_NPI, encounter.clinician.npi);
fieldValues.put(HHA.CLM_PMT_AMT, String.format("%.2f", encounter.claim.getCoveredCost()));
if (encounter.claim.payer == Payer.getGovernmentPayer(HealthInsuranceModule.MEDICARE)) {
fieldValues.put(HHA.NCH_PRMRY_PYR_CLM_PD_AMT, "0");
} else {
fieldValues.put(HHA.NCH_PRMRY_PYR_CLM_PD_AMT, String.format("%.2f", encounter.claim.getCoveredCost()));
}
fieldValues.put(HHA.PRVDR_STATE_CD, locationMapper.getStateCode(encounter.provider.state));
fieldValues.put(HHA.CLM_TOT_CHRG_AMT, String.format("%.2f", encounter.claim.getTotalClaimCost()));
fieldValues.put(HHA.CLM_HHA_TOT_VISIT_CNT, "" + homeVisits);
int days = (int) ((encounter.stop - encounter.start) / (1000 * 60 * 60 * 24));
if (days <= 0) {
days = 1;
}
fieldValues.put(HHA.REV_CNTR_UNIT_CNT, "" + days);
fieldValues.put(HHA.REV_CNTR_RATE_AMT, String.format("%.2f", (encounter.claim.getTotalClaimCost() / days)));
fieldValues.put(HHA.REV_CNTR_PMT_AMT_AMT, String.format("%.2f", encounter.claim.getCoveredCost()));
fieldValues.put(HHA.REV_CNTR_TOT_CHRG_AMT, String.format("%.2f", encounter.claim.getTotalClaimCost()));
fieldValues.put(HHA.REV_CNTR_NCVRD_CHRG_AMT, String.format("%.2f", encounter.claim.getPatientCost()));
if (encounter.reason != null) {
// values into the principle diagnoses code.
if (conditionCodeMapper.canMap(encounter.reason.code)) {
String icdCode = conditionCodeMapper.map(encounter.reason.code, person, true);
fieldValues.put(HHA.PRNCPAL_DGNS_CD, icdCode);
}
}
// PTNT_DSCHRG_STUS_CD: 1=home, 2=transfer, 3=SNF, 20=died, 30=still here
String dischargeStatus = null;
if (encounter.ended) {
// TODO 2=transfer if the next encounter is also inpatient
dischargeStatus = "1";
} else {
// the patient is still here
dischargeStatus = "30";
}
if (!person.alive(encounter.stop)) {
// the patient died before the encounter ended
dischargeStatus = "20";
}
fieldValues.put(HHA.PTNT_DSCHRG_STUS_CD, dischargeStatus);
// Use the active condition diagnoses to enter mapped values
// into the diagnoses codes.
List<String> mappedDiagnosisCodes = getDiagnosesCodes(person, encounter.stop);
if (mappedDiagnosisCodes.isEmpty()) {
// skip this encounter
continue;
}
int smallest = Math.min(mappedDiagnosisCodes.size(), BB2RIFStructure.homeDxFields.length);
for (int i = 0; i < smallest; i++) {
HHA[] dxField = BB2RIFStructure.homeDxFields[i];
fieldValues.put(dxField[0], mappedDiagnosisCodes.get(i));
// 0=ICD10
fieldValues.put(dxField[1], "0");
}
if (!fieldValues.containsKey(HHA.PRNCPAL_DGNS_CD)) {
fieldValues.put(HHA.PRNCPAL_DGNS_CD, mappedDiagnosisCodes.get(0));
}
// Check for external code...
setExternalCode(person, fieldValues, HHA.PRNCPAL_DGNS_CD, HHA.ICD_DGNS_E_CD1, HHA.ICD_DGNS_E_VRSN_CD1);
setExternalCode(person, fieldValues, HHA.PRNCPAL_DGNS_CD, HHA.FST_DGNS_E_CD, HHA.FST_DGNS_E_VRSN_CD);
synchronized (rifWriters.getOrCreateWriter(HHA.class)) {
int claimLine = 1;
for (ClaimEntry lineItem : encounter.claim.items) {
String hcpcsCode = null;
if (lineItem.entry instanceof HealthRecord.Procedure) {
for (HealthRecord.Code code : lineItem.entry.codes) {
if (hcpcsCodeMapper.canMap(code.code)) {
hcpcsCode = hcpcsCodeMapper.map(code.code, person, true);
// take the first mappable code for each procedure
break;
}
}
fieldValues.remove(HHA.REV_CNTR_NDC_QTY);
fieldValues.remove(HHA.REV_CNTR_NDC_QTY_QLFR_CD);
} else if (lineItem.entry instanceof HealthRecord.Medication) {
HealthRecord.Medication med = (HealthRecord.Medication) lineItem.entry;
if (med.administration) {
// Administration of medication
hcpcsCode = "T1502";
// 1 Unit
fieldValues.put(HHA.REV_CNTR_NDC_QTY, "1");
// Unit
fieldValues.put(HHA.REV_CNTR_NDC_QTY_QLFR_CD, "UN");
}
}
if (hcpcsCode == null) {
continue;
}
fieldValues.put(HHA.CLM_LINE_NUM, Integer.toString(claimLine++));
fieldValues.put(HHA.REV_CNTR_DT, bb2DateFromTimestamp(lineItem.entry.start));
fieldValues.put(HHA.HCPCS_CD, hcpcsCode);
fieldValues.put(HHA.REV_CNTR_RATE_AMT, String.format("%.2f", (lineItem.cost / Integer.max(1, days))));
fieldValues.put(HHA.REV_CNTR_PMT_AMT_AMT, String.format("%.2f", lineItem.coinsurance + lineItem.payer));
fieldValues.put(HHA.REV_CNTR_TOT_CHRG_AMT, String.format("%.2f", lineItem.cost));
fieldValues.put(HHA.REV_CNTR_NCVRD_CHRG_AMT, String.format("%.2f", lineItem.copay + lineItem.deductible + lineItem.pocket));
if (lineItem.pocket == 0 && lineItem.deductible == 0) {
// Not subject to deductible or coinsurance
fieldValues.put(HHA.REV_CNTR_DDCTBL_COINSRNC_CD, "3");
} else if (lineItem.pocket > 0 && lineItem.deductible > 0) {
// Subject to deductible and coinsurance
fieldValues.put(HHA.REV_CNTR_DDCTBL_COINSRNC_CD, "0");
} else if (lineItem.pocket == 0) {
// Not subject to deductible
fieldValues.put(HHA.REV_CNTR_DDCTBL_COINSRNC_CD, "1");
} else {
// Not subject to coinsurance
fieldValues.put(HHA.REV_CNTR_DDCTBL_COINSRNC_CD, "2");
}
rifWriters.writeValues(HHA.class, fieldValues);
}
if (claimLine == 1) {
// If claimLine still equals 1, then no line items were successfully added.
// Add a single top-level entry.
fieldValues.put(HHA.CLM_LINE_NUM, Integer.toString(claimLine));
fieldValues.put(HHA.REV_CNTR_DT, bb2DateFromTimestamp(encounter.start));
// home health visit
fieldValues.put(HHA.HCPCS_CD, "T1021");
rifWriters.writeValues(HHA.class, fieldValues);
}
}
}
}
use of org.mitre.synthea.world.concepts.Claim.ClaimEntry in project synthea by synthetichealth.
the class BB2RIFExporter method exportSNF.
/**
* Export Home Health Agency visits for a single person.
* @param person the person to export
* @param startTime earliest claim date to export
* @param stopTime end time of simulation
* @throws IOException if something goes wrong
*/
private void exportSNF(Person person, long startTime, long stopTime) throws IOException {
HashMap<SNF, String> fieldValues = new HashMap<>();
boolean previousEmergency;
boolean previousUrgent;
for (HealthRecord.Encounter encounter : person.record.encounters) {
if (encounter.stop < startTime) {
continue;
}
boolean isVA = (ProviderType.VETERAN == encounter.provider.type);
// IHS facilities have valid 6 digit id, IHS centers don't
boolean isIHSCenter = (ProviderType.IHS == encounter.provider.type) && encounter.provider.id.length() != 6;
boolean isSNF = encounter.type.equals(EncounterType.SNF.toString());
if (isVA || isIHSCenter || !isSNF) {
continue;
}
previousEmergency = encounter.type.equals(EncounterType.EMERGENCY.toString());
previousUrgent = encounter.type.equals(EncounterType.URGENTCARE.toString());
long claimId = BB2RIFExporter.claimId.getAndDecrement();
int claimGroupId = BB2RIFExporter.claimGroupId.getAndDecrement();
long fiDocId = BB2RIFExporter.fiDocCntlNum.getAndDecrement();
fieldValues.clear();
staticFieldConfig.setValues(fieldValues, SNF.class, person);
// The REQUIRED Fields
fieldValues.put(SNF.BENE_ID, (String) person.attributes.get(BB2_BENE_ID));
fieldValues.put(SNF.CLM_ID, "" + claimId);
fieldValues.put(SNF.CLM_GRP_ID, "" + claimGroupId);
fieldValues.put(SNF.FI_DOC_CLM_CNTL_NUM, "" + fiDocId);
fieldValues.put(SNF.CLM_FROM_DT, bb2DateFromTimestamp(encounter.start));
fieldValues.put(SNF.CLM_ADMSN_DT, bb2DateFromTimestamp(encounter.start));
fieldValues.put(SNF.CLM_THRU_DT, bb2DateFromTimestamp(encounter.stop));
fieldValues.put(SNF.NCH_WKLY_PROC_DT, bb2DateFromTimestamp(ExportHelper.nextFriday(encounter.stop)));
fieldValues.put(SNF.PRVDR_NUM, encounter.provider.id);
fieldValues.put(SNF.ORG_NPI_NUM, encounter.provider.npi);
fieldValues.put(SNF.AT_PHYSN_NPI, encounter.clinician.npi);
fieldValues.put(SNF.OP_PHYSN_NPI, encounter.clinician.npi);
fieldValues.put(SNF.RNDRNG_PHYSN_NPI, encounter.clinician.npi);
fieldValues.put(SNF.CLM_PMT_AMT, String.format("%.2f", encounter.claim.getCoveredCost()));
if (encounter.claim.payer == Payer.getGovernmentPayer(HealthInsuranceModule.MEDICARE)) {
fieldValues.put(SNF.NCH_PRMRY_PYR_CLM_PD_AMT, "0");
} else {
fieldValues.put(SNF.NCH_PRMRY_PYR_CLM_PD_AMT, String.format("%.2f", encounter.claim.getCoveredCost()));
}
fieldValues.put(SNF.PRVDR_STATE_CD, locationMapper.getStateCode(encounter.provider.state));
fieldValues.put(SNF.CLM_TOT_CHRG_AMT, String.format("%.2f", encounter.claim.getTotalClaimCost()));
if (previousEmergency) {
fieldValues.put(SNF.CLM_IP_ADMSN_TYPE_CD, "1");
} else if (previousUrgent) {
fieldValues.put(SNF.CLM_IP_ADMSN_TYPE_CD, "2");
} else {
fieldValues.put(SNF.CLM_IP_ADMSN_TYPE_CD, "3");
}
fieldValues.put(SNF.NCH_BENE_IP_DDCTBL_AMT, String.format("%.2f", encounter.claim.getDeductiblePaid()));
fieldValues.put(SNF.NCH_BENE_PTA_COINSRNC_LBLTY_AM, String.format("%.2f", encounter.claim.getCoinsurancePaid()));
fieldValues.put(SNF.NCH_IP_NCVRD_CHRG_AMT, String.format("%.2f", encounter.claim.getPatientCost()));
fieldValues.put(SNF.NCH_IP_TOT_DDCTN_AMT, String.format("%.2f", encounter.claim.getDeductiblePaid() + encounter.claim.getCoinsurancePaid()));
int days = (int) ((encounter.stop - encounter.start) / (1000 * 60 * 60 * 24));
if (days <= 0) {
days = 1;
}
fieldValues.put(SNF.CLM_UTLZTN_DAY_CNT, "" + days);
// first 21 days no coinsurance
int coinDays = days - 21;
if (coinDays < 0) {
coinDays = 0;
}
fieldValues.put(SNF.BENE_TOT_COINSRNC_DAYS_CNT, "" + coinDays);
fieldValues.put(SNF.REV_CNTR_UNIT_CNT, "" + days);
fieldValues.put(SNF.REV_CNTR_RATE_AMT, String.format("%.2f", (encounter.claim.getTotalClaimCost() / days)));
fieldValues.put(SNF.REV_CNTR_TOT_CHRG_AMT, String.format("%.2f", encounter.claim.getTotalClaimCost()));
fieldValues.put(SNF.REV_CNTR_NCVRD_CHRG_AMT, String.format("%.2f", encounter.claim.getPatientCost()));
// OPTIONAL CODES
if (encounter.reason != null) {
// values into the principle diagnoses code.
if (conditionCodeMapper.canMap(encounter.reason.code)) {
String icdCode = conditionCodeMapper.map(encounter.reason.code, person, true);
fieldValues.put(SNF.PRNCPAL_DGNS_CD, icdCode);
fieldValues.put(SNF.ADMTG_DGNS_CD, icdCode);
if (drgCodeMapper.canMap(icdCode)) {
fieldValues.put(SNF.CLM_DRG_CD, drgCodeMapper.map(icdCode, person));
}
}
}
// PTNT_DSCHRG_STUS_CD: 1=home, 2=transfer, 3=SNF, 20=died, 30=still here
// NCH_PTNT_STUS_IND_CD: A = Discharged, B = Died, C = Still a patient
String dischargeStatus = null;
String patientStatus = null;
String dischargeDate = null;
if (encounter.ended) {
// TODO 2=transfer if the next encounter is also inpatient
dischargeStatus = "1";
// discharged
patientStatus = "A";
dischargeDate = bb2DateFromTimestamp(ExportHelper.nextFriday(encounter.stop));
} else {
// the patient is still here
dischargeStatus = "30";
// still a patient
patientStatus = "C";
}
if (!person.alive(encounter.stop)) {
// the patient died before the encounter ended
dischargeStatus = "20";
// died
patientStatus = "B";
dischargeDate = bb2DateFromTimestamp(ExportHelper.nextFriday(encounter.stop));
}
fieldValues.put(SNF.PTNT_DSCHRG_STUS_CD, dischargeStatus);
fieldValues.put(SNF.NCH_PTNT_STATUS_IND_CD, patientStatus);
if (dischargeDate != null) {
fieldValues.put(SNF.NCH_BENE_DSCHRG_DT, dischargeDate);
}
// Use the active condition diagnoses to enter mapped values
// into the diagnoses codes.
List<String> mappedDiagnosisCodes = getDiagnosesCodes(person, encounter.stop);
boolean noDiagnoses = mappedDiagnosisCodes.isEmpty();
if (!noDiagnoses) {
int smallest = Math.min(mappedDiagnosisCodes.size(), BB2RIFStructure.snfDxFields.length);
for (int i = 0; i < smallest; i++) {
SNF[] dxField = BB2RIFStructure.snfDxFields[i];
fieldValues.put(dxField[0], mappedDiagnosisCodes.get(i));
// 0=ICD10
fieldValues.put(dxField[1], "0");
}
if (!fieldValues.containsKey(SNF.PRNCPAL_DGNS_CD)) {
fieldValues.put(SNF.PRNCPAL_DGNS_CD, mappedDiagnosisCodes.get(0));
fieldValues.put(SNF.ADMTG_DGNS_CD, mappedDiagnosisCodes.get(0));
}
}
// Check for external code...
setExternalCode(person, fieldValues, SNF.PRNCPAL_DGNS_CD, SNF.ICD_DGNS_E_CD1, SNF.ICD_DGNS_E_VRSN_CD1);
setExternalCode(person, fieldValues, SNF.PRNCPAL_DGNS_CD, SNF.FST_DGNS_E_CD, SNF.FST_DGNS_E_VRSN_CD);
// Use the procedures in this encounter to enter mapped values
boolean noProcedures = false;
if (!encounter.procedures.isEmpty()) {
List<HealthRecord.Procedure> mappableProcedures = new ArrayList<>();
List<String> mappedProcedureCodes = new ArrayList<>();
for (HealthRecord.Procedure procedure : encounter.procedures) {
for (HealthRecord.Code code : procedure.codes) {
if (conditionCodeMapper.canMap(code.code)) {
mappableProcedures.add(procedure);
mappedProcedureCodes.add(conditionCodeMapper.map(code.code, person, true));
// take the first mappable code for each procedure
break;
}
}
}
if (!mappableProcedures.isEmpty()) {
int smallest = Math.min(mappableProcedures.size(), BB2RIFStructure.snfPxFields.length);
for (int i = 0; i < smallest; i++) {
SNF[] pxField = BB2RIFStructure.snfPxFields[i];
fieldValues.put(pxField[0], mappedProcedureCodes.get(i));
// 0=ICD10
fieldValues.put(pxField[1], "0");
fieldValues.put(pxField[2], bb2DateFromTimestamp(mappableProcedures.get(i).start));
}
} else {
noProcedures = true;
}
}
if (noDiagnoses && noProcedures) {
// skip this encounter
continue;
}
synchronized (rifWriters.getOrCreateWriter(SNF.class)) {
int claimLine = 1;
for (ClaimEntry lineItem : encounter.claim.items) {
String hcpcsCode = null;
if (lineItem.entry instanceof HealthRecord.Procedure) {
for (HealthRecord.Code code : lineItem.entry.codes) {
if (hcpcsCodeMapper.canMap(code.code)) {
hcpcsCode = hcpcsCodeMapper.map(code.code, person, true);
// take the first mappable code for each procedure
break;
}
}
fieldValues.remove(SNF.REV_CNTR_NDC_QTY);
fieldValues.remove(SNF.REV_CNTR_NDC_QTY_QLFR_CD);
} else if (lineItem.entry instanceof HealthRecord.Medication) {
HealthRecord.Medication med = (HealthRecord.Medication) lineItem.entry;
if (med.administration) {
// Administration of medication
hcpcsCode = "T1502";
// 1 Unit
fieldValues.put(SNF.REV_CNTR_NDC_QTY, "1");
// Unit
fieldValues.put(SNF.REV_CNTR_NDC_QTY_QLFR_CD, "UN");
}
}
if (hcpcsCode == null) {
continue;
}
fieldValues.put(SNF.CLM_LINE_NUM, Integer.toString(claimLine++));
fieldValues.put(SNF.HCPCS_CD, hcpcsCode);
fieldValues.put(SNF.REV_CNTR_RATE_AMT, String.format("%.2f", (lineItem.cost / Integer.max(1, days))));
fieldValues.put(SNF.REV_CNTR_TOT_CHRG_AMT, String.format("%.2f", lineItem.cost));
fieldValues.put(SNF.REV_CNTR_NCVRD_CHRG_AMT, String.format("%.2f", lineItem.copay + lineItem.deductible + lineItem.pocket));
if (lineItem.pocket == 0 && lineItem.deductible == 0) {
// Not subject to deductible or coinsurance
fieldValues.put(SNF.REV_CNTR_DDCTBL_COINSRNC_CD, "3");
} else if (lineItem.pocket > 0 && lineItem.deductible > 0) {
// Subject to deductible and coinsurance
fieldValues.put(SNF.REV_CNTR_DDCTBL_COINSRNC_CD, "0");
} else if (lineItem.pocket == 0) {
// Not subject to deductible
fieldValues.put(SNF.REV_CNTR_DDCTBL_COINSRNC_CD, "1");
} else {
// Not subject to coinsurance
fieldValues.put(SNF.REV_CNTR_DDCTBL_COINSRNC_CD, "2");
}
rifWriters.writeValues(SNF.class, fieldValues);
}
if (claimLine == 1) {
// If claimLine still equals 1, then no line items were successfully added.
// Add a single top-level entry.
fieldValues.put(SNF.CLM_LINE_NUM, Integer.toString(claimLine));
// G0299: "direct skilled nursing services of a registered nurse (RN) in the home health
// or hospice setting"
fieldValues.put(SNF.HCPCS_CD, "G0299");
rifWriters.writeValues(SNF.class, fieldValues);
}
}
}
}
use of org.mitre.synthea.world.concepts.Claim.ClaimEntry in project synthea by synthetichealth.
the class BB2RIFExporter method exportDME.
/**
* Export DME details for a single person.
* @param person the person to export
* @param startTime earliest claim date to export
* @param stopTime end time of simulation
* @throws IOException if something goes wrong
*/
private void exportDME(Person person, long startTime, long stopTime) throws IOException {
HashMap<DME, String> fieldValues = new HashMap<>();
for (HealthRecord.Encounter encounter : person.record.encounters) {
if (encounter.stop < startTime) {
continue;
}
boolean isVA = (ProviderType.VETERAN == encounter.provider.type);
// IHS facilities have valid 6 digit id, IHS centers don't
boolean isIHSCenter = (ProviderType.IHS == encounter.provider.type) && encounter.provider.id.length() != 6;
if (isVA || isIHSCenter) {
continue;
}
long claimId = BB2RIFExporter.claimId.getAndDecrement();
int claimGroupId = BB2RIFExporter.claimGroupId.getAndDecrement();
long carrClmId = BB2RIFExporter.carrClmCntlNum.getAndDecrement();
double latestHemoglobin = 0;
for (HealthRecord.Observation observation : encounter.observations) {
if (observation.containsCode("718-7", "http://loinc.org")) {
latestHemoglobin = (double) observation.value;
}
}
fieldValues.clear();
staticFieldConfig.setValues(fieldValues, DME.class, person);
// complex fields that could not easily be set using cms_field_values.tsv
fieldValues.put(DME.CLM_ID, "" + claimId);
fieldValues.put(DME.CLM_GRP_ID, "" + claimGroupId);
fieldValues.put(DME.CARR_CLM_CNTL_NUM, "" + carrClmId);
fieldValues.put(DME.BENE_ID, (String) person.attributes.get(BB2_BENE_ID));
fieldValues.put(DME.LINE_HCT_HGB_RSLT_NUM, "" + latestHemoglobin);
fieldValues.put(DME.CARR_NUM, getCarrier(encounter.provider.state, CARRIER.CARR_NUM));
fieldValues.put(DME.NCH_WKLY_PROC_DT, bb2DateFromTimestamp(ExportHelper.nextFriday(encounter.stop)));
fieldValues.put(DME.PRVDR_NUM, encounter.provider.id);
fieldValues.put(DME.PRVDR_NPI, encounter.provider.npi);
fieldValues.put(DME.RFR_PHYSN_NPI, encounter.clinician.npi);
fieldValues.put(DME.PRVDR_SPCLTY, ClinicianSpecialty.getCMSProviderSpecialtyCode((String) encounter.clinician.attributes.get(Clinician.SPECIALTY)));
fieldValues.put(DME.PRVDR_STATE_CD, locationMapper.getStateCode(encounter.provider.state));
fieldValues.put(DME.TAX_NUM, bb2TaxId((String) encounter.clinician.attributes.get(Person.IDENTIFIER_SSN)));
fieldValues.put(DME.DMERC_LINE_PRCNG_STATE_CD, locationMapper.getStateCode((String) person.attributes.get(Person.STATE)));
fieldValues.put(DME.LINE_1ST_EXPNS_DT, bb2DateFromTimestamp(encounter.start));
fieldValues.put(DME.LINE_LAST_EXPNS_DT, bb2DateFromTimestamp(encounter.stop));
fieldValues.put(DME.LINE_SRVC_CNT, "" + encounter.claim.items.size());
// OPTIONAL
if (encounter.reason != null) {
// values into the principle diagnoses code.
if (conditionCodeMapper.canMap(encounter.reason.code)) {
String icdCode = conditionCodeMapper.map(encounter.reason.code, person, true);
fieldValues.put(DME.PRNCPAL_DGNS_CD, icdCode);
fieldValues.put(DME.LINE_ICD_DGNS_CD, icdCode);
}
}
// Use the active condition diagnoses to enter mapped values
// into the diagnoses codes.
List<String> mappedDiagnosisCodes = getDiagnosesCodes(person, encounter.stop);
if (mappedDiagnosisCodes.isEmpty()) {
// skip this encounter
continue;
}
int smallest = Math.min(mappedDiagnosisCodes.size(), BB2RIFStructure.dmeDxFields.length);
for (int i = 0; i < smallest; i++) {
DME[] dxField = BB2RIFStructure.dmeDxFields[i];
fieldValues.put(dxField[0], mappedDiagnosisCodes.get(i));
// 0=ICD10
fieldValues.put(dxField[1], "0");
}
if (!fieldValues.containsKey(DME.PRNCPAL_DGNS_CD)) {
fieldValues.put(DME.PRNCPAL_DGNS_CD, mappedDiagnosisCodes.get(0));
fieldValues.put(DME.LINE_ICD_DGNS_CD, mappedDiagnosisCodes.get(0));
}
// preprocess some subtotals...
ClaimEntry subTotals = (encounter.claim).new ClaimEntry(null);
for (ClaimEntry lineItem : encounter.claim.items) {
if (lineItem.entry instanceof Device || lineItem.entry instanceof Supply) {
subTotals.addCosts(lineItem);
}
}
fieldValues.put(DME.CARR_CLM_CASH_DDCTBL_APLD_AMT, String.format("%.2f", subTotals.deductible));
fieldValues.put(DME.CARR_CLM_PRMRY_PYR_PD_AMT, String.format("%.2f", subTotals.coinsurance + subTotals.payer));
fieldValues.put(DME.NCH_CARR_CLM_ALOWD_AMT, String.format("%.2f", subTotals.cost - subTotals.adjustment));
fieldValues.put(DME.NCH_CARR_CLM_SBMTD_CHRG_AMT, String.format("%.2f", subTotals.cost));
fieldValues.put(DME.NCH_CLM_PRVDR_PMT_AMT, String.format("%.2f", subTotals.coinsurance + subTotals.payer));
fieldValues.put(DME.CLM_PMT_AMT, String.format("%.2f", subTotals.coinsurance + subTotals.payer));
synchronized (rifWriters.getOrCreateWriter(DME.class)) {
int lineNum = 1;
// Now generate the line items...
for (ClaimEntry lineItem : encounter.claim.items) {
if (!(lineItem.entry instanceof Device || lineItem.entry instanceof Supply)) {
continue;
}
if (lineItem.entry instanceof Supply) {
Supply supply = (Supply) lineItem.entry;
fieldValues.put(DME.DMERC_LINE_MTUS_CNT, "" + supply.quantity);
} else {
fieldValues.put(DME.DMERC_LINE_MTUS_CNT, "");
}
if (!dmeCodeMapper.canMap(lineItem.entry.codes.get(0).code)) {
System.err.println(" *** Possibly Missing DME Code: " + lineItem.entry.codes.get(0).code + " " + lineItem.entry.codes.get(0).display);
continue;
}
fieldValues.put(DME.CLM_FROM_DT, bb2DateFromTimestamp(lineItem.entry.start));
fieldValues.put(DME.CLM_THRU_DT, bb2DateFromTimestamp(lineItem.entry.start));
String hcpcsCode = dmeCodeMapper.map(lineItem.entry.codes.get(0).code, person);
fieldValues.put(DME.HCPCS_CD, hcpcsCode);
if (betosCodeMapper.canMap(hcpcsCode)) {
fieldValues.put(DME.BETOS_CD, betosCodeMapper.map(hcpcsCode, person));
} else {
fieldValues.put(DME.BETOS_CD, "");
}
fieldValues.put(DME.LINE_CMS_TYPE_SRVC_CD, dmeCodeMapper.map(lineItem.entry.codes.get(0).code, DME.LINE_CMS_TYPE_SRVC_CD.toString().toLowerCase(), person));
fieldValues.put(DME.LINE_BENE_PTB_DDCTBL_AMT, String.format("%.2f", lineItem.deductible));
fieldValues.put(DME.LINE_COINSRNC_AMT, String.format("%.2f", lineItem.getCoinsurancePaid()));
fieldValues.put(DME.LINE_BENE_PMT_AMT, String.format("%.2f", lineItem.copay + lineItem.deductible + lineItem.pocket));
fieldValues.put(DME.LINE_PRVDR_PMT_AMT, String.format("%.2f", lineItem.coinsurance + lineItem.payer));
fieldValues.put(DME.LINE_SBMTD_CHRG_AMT, String.format("%.2f", lineItem.cost));
fieldValues.put(DME.LINE_ALOWD_CHRG_AMT, String.format("%.2f", lineItem.cost - lineItem.adjustment));
fieldValues.put(DME.LINE_PRMRY_ALOWD_CHRG_AMT, String.format("%.2f", lineItem.cost - lineItem.adjustment));
fieldValues.put(DME.LINE_NCH_PMT_AMT, String.format("%.2f", lineItem.coinsurance + lineItem.payer));
// set the line number and write out field values
fieldValues.put(DME.LINE_NUM, Integer.toString(lineNum++));
rifWriters.writeValues(DME.class, fieldValues);
}
}
}
}
use of org.mitre.synthea.world.concepts.Claim.ClaimEntry in project synthea by synthetichealth.
the class BB2RIFExporter method exportOutpatient.
/**
* Export outpatient claims details for a single person.
* @param person the person to export
* @param startTime earliest claim date to export
* @param stopTime end time of simulation
* @throws IOException if something goes wrong
*/
private void exportOutpatient(Person person, long startTime, long stopTime) throws IOException {
HashMap<OUTPATIENT, String> fieldValues = new HashMap<>();
for (HealthRecord.Encounter encounter : person.record.encounters) {
if (encounter.stop < startTime) {
continue;
}
boolean isAmbulatory = encounter.type.equals(EncounterType.AMBULATORY.toString());
boolean isOutpatient = encounter.type.equals(EncounterType.OUTPATIENT.toString());
boolean isUrgent = encounter.type.equals(EncounterType.URGENTCARE.toString());
boolean isPrimary = (ProviderType.PRIMARY == encounter.provider.type);
// IHS facilities have valid 6 digit id, IHS centers don't
boolean isIHSCenter = (ProviderType.IHS == encounter.provider.type) && encounter.provider.id.length() != 6;
boolean isVA = (ProviderType.VETERAN == encounter.provider.type);
if (isVA || isIHSCenter || isPrimary || isUrgent || !(isAmbulatory || isOutpatient)) {
continue;
}
long claimId = BB2RIFExporter.claimId.getAndDecrement();
int claimGroupId = BB2RIFExporter.claimGroupId.getAndDecrement();
long fiDocId = BB2RIFExporter.fiDocCntlNum.getAndDecrement();
staticFieldConfig.setValues(fieldValues, OUTPATIENT.class, person);
// The REQUIRED fields
fieldValues.put(OUTPATIENT.BENE_ID, (String) person.attributes.get(BB2_BENE_ID));
fieldValues.put(OUTPATIENT.CLM_ID, "" + claimId);
fieldValues.put(OUTPATIENT.CLM_GRP_ID, "" + claimGroupId);
fieldValues.put(OUTPATIENT.FI_DOC_CLM_CNTL_NUM, "" + fiDocId);
fieldValues.put(OUTPATIENT.CLM_FROM_DT, bb2DateFromTimestamp(encounter.start));
fieldValues.put(OUTPATIENT.CLM_THRU_DT, bb2DateFromTimestamp(encounter.stop));
fieldValues.put(OUTPATIENT.NCH_WKLY_PROC_DT, bb2DateFromTimestamp(ExportHelper.nextFriday(encounter.stop)));
fieldValues.put(OUTPATIENT.PRVDR_NUM, encounter.provider.id);
fieldValues.put(OUTPATIENT.AT_PHYSN_NPI, encounter.clinician.npi);
fieldValues.put(OUTPATIENT.RNDRNG_PHYSN_NPI, encounter.clinician.npi);
fieldValues.put(OUTPATIENT.ORG_NPI_NUM, encounter.provider.npi);
fieldValues.put(OUTPATIENT.OP_PHYSN_NPI, encounter.clinician.npi);
fieldValues.put(OUTPATIENT.CLM_PMT_AMT, String.format("%.2f", encounter.claim.getTotalClaimCost()));
if (encounter.claim.payer == Payer.getGovernmentPayer(HealthInsuranceModule.MEDICARE)) {
fieldValues.put(OUTPATIENT.NCH_PRMRY_PYR_CLM_PD_AMT, "0");
} else {
fieldValues.put(OUTPATIENT.NCH_PRMRY_PYR_CLM_PD_AMT, String.format("%.2f", encounter.claim.getCoveredCost()));
}
fieldValues.put(OUTPATIENT.PRVDR_STATE_CD, locationMapper.getStateCode(encounter.provider.state));
// PTNT_DSCHRG_STUS_CD: 1=home, 2=transfer, 3=SNF, 20=died, 30=still here
String field = null;
if (encounter.ended) {
field = "1";
} else {
// the patient is still here
field = "30";
}
if (!person.alive(encounter.stop)) {
// the patient died before the encounter ended
field = "20";
}
fieldValues.put(OUTPATIENT.PTNT_DSCHRG_STUS_CD, field);
fieldValues.put(OUTPATIENT.CLM_TOT_CHRG_AMT, String.format("%.2f", encounter.claim.getTotalClaimCost()));
fieldValues.put(OUTPATIENT.CLM_OP_PRVDR_PMT_AMT, String.format("%.2f", encounter.claim.getTotalClaimCost()));
fieldValues.put(OUTPATIENT.REV_CNTR_TOT_CHRG_AMT, String.format("%.2f", encounter.claim.getCoveredCost()));
fieldValues.put(OUTPATIENT.REV_CNTR_NCVRD_CHRG_AMT, String.format("%.2f", encounter.claim.getPatientCost()));
fieldValues.put(OUTPATIENT.NCH_BENE_PTB_DDCTBL_AMT, String.format("%.2f", encounter.claim.getDeductiblePaid()));
fieldValues.put(OUTPATIENT.REV_CNTR_CASH_DDCTBL_AMT, String.format("%.2f", encounter.claim.getDeductiblePaid()));
fieldValues.put(OUTPATIENT.REV_CNTR_COINSRNC_WGE_ADJSTD_C, String.format("%.2f", encounter.claim.getCoinsurancePaid()));
fieldValues.put(OUTPATIENT.REV_CNTR_PMT_AMT_AMT, String.format("%.2f", encounter.claim.getTotalClaimCost()));
fieldValues.put(OUTPATIENT.REV_CNTR_PRVDR_PMT_AMT, String.format("%.2f", encounter.claim.getTotalClaimCost()));
fieldValues.put(OUTPATIENT.REV_CNTR_PTNT_RSPNSBLTY_PMT, String.format("%.2f", encounter.claim.getDeductiblePaid() + encounter.claim.getCoinsurancePaid()));
fieldValues.put(OUTPATIENT.REV_CNTR_RDCD_COINSRNC_AMT, String.format("%.2f", encounter.claim.getCoinsurancePaid()));
String icdReasonCode = null;
if (encounter.reason != null) {
// values into the principle diagnoses code.
if (conditionCodeMapper.canMap(encounter.reason.code)) {
icdReasonCode = conditionCodeMapper.map(encounter.reason.code, person, true);
fieldValues.put(OUTPATIENT.PRNCPAL_DGNS_CD, icdReasonCode);
}
}
// Use the active condition diagnoses to enter mapped values
// into the diagnoses codes.
List<String> mappedDiagnosisCodes = getDiagnosesCodes(person, encounter.stop);
boolean noDiagnoses = mappedDiagnosisCodes.isEmpty();
if (!noDiagnoses) {
int smallest = Math.min(mappedDiagnosisCodes.size(), BB2RIFStructure.outpatientDxFields.length);
for (int i = 0; i < smallest; i++) {
OUTPATIENT[] dxField = BB2RIFStructure.outpatientDxFields[i];
fieldValues.put(dxField[0], mappedDiagnosisCodes.get(i));
// 0=ICD10
fieldValues.put(dxField[1], "0");
}
if (!fieldValues.containsKey(OUTPATIENT.PRNCPAL_DGNS_CD)) {
fieldValues.put(OUTPATIENT.PRNCPAL_DGNS_CD, mappedDiagnosisCodes.get(0));
}
}
// Check for external code...
setExternalCode(person, fieldValues, OUTPATIENT.PRNCPAL_DGNS_CD, OUTPATIENT.ICD_DGNS_E_CD1, OUTPATIENT.ICD_DGNS_E_VRSN_CD1);
setExternalCode(person, fieldValues, OUTPATIENT.PRNCPAL_DGNS_CD, OUTPATIENT.FST_DGNS_E_CD, OUTPATIENT.FST_DGNS_E_VRSN_CD);
// Use the procedures in this encounter to enter mapped values
boolean noProcedures = false;
if (!encounter.procedures.isEmpty()) {
List<HealthRecord.Procedure> mappableProcedures = new ArrayList<>();
List<String> mappedProcedureCodes = new ArrayList<>();
for (HealthRecord.Procedure procedure : encounter.procedures) {
for (HealthRecord.Code code : procedure.codes) {
if (conditionCodeMapper.canMap(code.code)) {
mappableProcedures.add(procedure);
mappedProcedureCodes.add(conditionCodeMapper.map(code.code, person, true));
// take the first mappable code for each procedure
break;
}
}
}
if (!mappableProcedures.isEmpty()) {
int smallest = Math.min(mappableProcedures.size(), BB2RIFStructure.outpatientPxFields.length);
for (int i = 0; i < smallest; i++) {
OUTPATIENT[] pxField = BB2RIFStructure.outpatientPxFields[i];
fieldValues.put(pxField[0], mappedProcedureCodes.get(i));
// 0=ICD10
fieldValues.put(pxField[1], "0");
fieldValues.put(pxField[2], bb2DateFromTimestamp(mappableProcedures.get(i).start));
}
} else {
noProcedures = true;
}
}
if (icdReasonCode == null && noDiagnoses && noProcedures) {
// skip this encounter
continue;
}
synchronized (rifWriters.getOrCreateWriter(OUTPATIENT.class)) {
int claimLine = 1;
for (ClaimEntry lineItem : encounter.claim.items) {
String hcpcsCode = null;
if (lineItem.entry instanceof HealthRecord.Procedure) {
for (HealthRecord.Code code : lineItem.entry.codes) {
if (hcpcsCodeMapper.canMap(code.code)) {
hcpcsCode = hcpcsCodeMapper.map(code.code, person, true);
// take the first mappable code for each procedure
break;
}
}
fieldValues.remove(OUTPATIENT.REV_CNTR_IDE_NDC_UPC_NUM);
fieldValues.remove(OUTPATIENT.REV_CNTR_NDC_QTY);
fieldValues.remove(OUTPATIENT.REV_CNTR_NDC_QTY_QLFR_CD);
} else if (lineItem.entry instanceof HealthRecord.Medication) {
HealthRecord.Medication med = (HealthRecord.Medication) lineItem.entry;
if (med.administration) {
// Administration of medication
hcpcsCode = "T1502";
String ndcCode = medicationCodeMapper.map(med.codes.get(0).code, person);
fieldValues.put(OUTPATIENT.REV_CNTR_IDE_NDC_UPC_NUM, ndcCode);
// 1 Unit
fieldValues.put(OUTPATIENT.REV_CNTR_NDC_QTY, "1");
// Unit
fieldValues.put(OUTPATIENT.REV_CNTR_NDC_QTY_QLFR_CD, "UN");
}
}
if (hcpcsCode == null) {
continue;
}
fieldValues.put(OUTPATIENT.CLM_LINE_NUM, Integer.toString(claimLine++));
fieldValues.put(OUTPATIENT.REV_CNTR_DT, bb2DateFromTimestamp(lineItem.entry.start));
fieldValues.put(OUTPATIENT.HCPCS_CD, hcpcsCode);
fieldValues.put(OUTPATIENT.REV_CNTR_RATE_AMT, String.format("%.2f", (lineItem.cost)));
fieldValues.put(OUTPATIENT.REV_CNTR_PMT_AMT_AMT, String.format("%.2f", lineItem.coinsurance + lineItem.payer));
fieldValues.put(OUTPATIENT.REV_CNTR_TOT_CHRG_AMT, String.format("%.2f", lineItem.cost));
fieldValues.put(OUTPATIENT.REV_CNTR_NCVRD_CHRG_AMT, String.format("%.2f", lineItem.copay + lineItem.deductible + lineItem.pocket));
rifWriters.writeValues(OUTPATIENT.class, fieldValues);
}
if (claimLine == 1) {
// If claimLine still equals 1, then no line items were successfully added.
// Add a single top-level entry.
fieldValues.put(OUTPATIENT.CLM_LINE_NUM, Integer.toString(claimLine));
fieldValues.put(OUTPATIENT.REV_CNTR_DT, bb2DateFromTimestamp(encounter.start));
// 99241: "Office consultation for a new or established patient"
fieldValues.put(OUTPATIENT.HCPCS_CD, "99241");
rifWriters.writeValues(OUTPATIENT.class, fieldValues);
}
}
}
}
Aggregations