/// <summary> /// Applies the non fee schedule. /// </summary> /// <param name="paymentResult">The payment result.</param> /// <param name="claimCharge">The claim charge.</param> /// <returns></returns> private void ApplyNonFeeSchedule(PaymentResult paymentResult, ClaimCharge claimCharge) { if (PaymentTypeFeeSchedule.NonFeeSchedule.HasValue) { if (claimCharge.Amount.HasValue) { paymentResult.AdjudicatedValue = (PaymentTypeFeeSchedule.NonFeeSchedule.Value / 100) * claimCharge.Amount.Value; paymentResult.ClaimStatus = (byte)Enums.AdjudicationOrVarianceStatuses.Adjudicated; } else { paymentResult.ClaimStatus = (byte)Enums.AdjudicationOrVarianceStatuses.ClaimDataError; } } else { paymentResult.ClaimStatus = (byte)Enums.AdjudicationOrVarianceStatuses .AdjudicationErrorInvalidPaymentData; } }
/// <summary> /// Evaluates the type of the payment. /// </summary> /// <param name="paymentResult">The payment result.</param> /// <param name="claimCharge">The claim charge.</param> /// <returns></returns> private void EvaluateLine(PaymentResult paymentResult, ClaimCharge claimCharge) { //Update PaymentResult and set matching ServiceTypeId,PaymentTypeDetailId & PaymentTypeId Utilities.UpdatePaymentResult(paymentResult, PaymentTypeFeeSchedule.ServiceTypeId, PaymentTypeFeeSchedule.PaymentTypeDetailId, PaymentTypeFeeSchedule.PaymentTypeId); if (PaymentTypeFeeSchedule.ClaimFieldDoc != null && PaymentTypeFeeSchedule.ClaimFieldDoc.ClaimFieldValues != null && PaymentTypeFeeSchedule.ClaimFieldDoc.ClaimFieldValues.Count > 0) { string hcpcsCode = claimCharge.HcpcsCodeWithModifier.ToUpper(); ClaimFieldValue claimFieldValue = PaymentTypeFeeSchedule.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault( currentClaimFieldValue => (currentClaimFieldValue.Identifier.ToUpper() == hcpcsCode)); if (claimFieldValue == null && hcpcsCode.Trim().Length != 5) { claimFieldValue = PaymentTypeFeeSchedule.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault( currentClaimFieldValue => (currentClaimFieldValue.Identifier.ToUpper() == hcpcsCode.Substring(0, 5))); } if (claimFieldValue != null) { ApplyFeeSchedule(paymentResult, claimFieldValue, claimCharge); } else { ApplyNonFeeSchedule(paymentResult, claimCharge); } } }
/// <summary> /// Applies the type of the charges on payment. /// </summary> /// <param name="claim">The claim.</param> /// <param name="paymentResults">The payment results.</param> /// <param name="isCarveOut">if set to <c>true</c> [is carve out].</param> /// <param name="claimCharge">The claim charge.</param> /// <param name="lineId">The line identifier.</param> private void ApplyChargesOnPaymentType(IEvaluateableClaim claim, List <PaymentResult> paymentResults, bool isCarveOut, ClaimCharge claimCharge, int lineId) { if (PaymentTypeStopLoss.Threshold != null && (claimCharge != null && (PaymentTypeBase.ValidLineIds.Contains( claimCharge.Line) && paymentResults.Any( currentPaymentResult => currentPaymentResult.Line == claimCharge.Line && (currentPaymentResult.AdjudicatedValue == null || isCarveOut || currentPaymentResult.ServiceTypeId == PaymentTypeStopLoss.ServiceTypeId))) && claimCharge.Amount > PaymentTypeStopLoss.Threshold.Value)) { PaymentResult paymentResult = paymentResults.Any( result => result.ServiceTypeId == PaymentTypeStopLoss.ServiceTypeId && result.Line == lineId) ? paymentResults.FirstOrDefault( result => result.ServiceTypeId == PaymentTypeStopLoss.ServiceTypeId && result.Line == lineId) : GetPaymentResult(paymentResults, isCarveOut, claimCharge.Line); GetTotalLinesValue(paymentResult, claimCharge.Amount, claim); } }
/// <summary> /// Calculates the adjudicated value. /// </summary> /// <param name="claimPaymentResult">The claim payment result.</param> /// <param name="claim">The claim.</param> /// <param name="codeDetailsList">The per day of stays.</param> /// <param name="claimCharge">The claim charge.</param> /// <param name="multiplierExpandedExpression">The multiplier expanded expression.</param> /// <param name="claimFieldDocValueDictionary">The claim field document value dictionary.</param> /// <param name="codeValue">The code value.</param> /// <param name="codeOccurence">The code occurence.</param> /// <param name="formula">The formula.</param> /// <param name="isMultiplierExist">if set to <c>true</c> [is multiplier exist].</param> private void CalculateAdjudicatedValue(PaymentResult claimPaymentResult, IEvaluateableClaim claim, List <CodeDetails> codeDetailsList, ClaimCharge claimCharge, string multiplierExpandedExpression, Dictionary <string, string> claimFieldDocValueDictionary, string codeValue, int codeOccurence, double?formula, bool isMultiplierExist) { multiplierExpandedExpression = GetExpandedExpression(claimFieldDocValueDictionary, multiplierExpandedExpression); if (PaymentTypeCustomTable.IsPerDayOfStay) { var perDayOfStay = codeDetailsList.FirstOrDefault( p => p.Code == codeValue && p.Day == claimCharge.ServiceFromDate); if (perDayOfStay != null) { GetMultipliedFormulaValue(claimPaymentResult, claim, multiplierExpandedExpression, codeOccurence, formula); UpdateLimit(claimPaymentResult, codeDetailsList, claimCharge, codeValue, isMultiplierExist ); } claimPaymentResult.ServiceLineCode = codeValue; claimPaymentResult.ClaimStatus = (byte)Enums.AdjudicationOrVarianceStatuses.Adjudicated; Utilities.UpdateCustomTableDetails(claimPaymentResult, claim.SmartBox, PaymentTypeCustomTable, codeOccurence); } else { GetMultipliedFormulaValue(claimPaymentResult, claim, multiplierExpandedExpression, codeOccurence, formula); UpdateLimit(claimPaymentResult, codeDetailsList, claimCharge, codeValue, isMultiplierExist); claimPaymentResult.ServiceLineCode = codeValue; claimPaymentResult.ClaimStatus = (byte)Enums.AdjudicationOrVarianceStatuses.Adjudicated; Utilities.UpdateCustomTableDetails(claimPaymentResult, claim.SmartBox, PaymentTypeCustomTable, codeOccurence); } }
/// <summary> /// Gets the current sellection. /// </summary> /// <param name="claim">The claim.</param> /// <param name="paymentResults">The payment results.</param> /// <param name="isRevCodeAvailable">if set to <c>true</c> [is rev code available].</param> /// <param name="chargeData">The charge data.</param> /// <param name="isCptCodeAvailable">if set to <c>true</c> [is CPT code available].</param> /// <param name="validPaymentResults">The valid payment results.</param> /// <returns></returns> private List <PaymentResult> GetCurrentSelection(IEvaluateableClaim claim, List <PaymentResult> paymentResults, bool isRevCodeAvailable, ClaimCharge chargeData, bool isCptCodeAvailable, IEnumerable <PaymentResult> validPaymentResults) { List <ClaimCharge> claimCharges = claim.ClaimCharges.Where( currentClaimCharge => (!isRevCodeAvailable || chargeData.RevCode == currentClaimCharge.RevCode) && (!isCptCodeAvailable || chargeData.HcpcsCode == currentClaimCharge.HcpcsCode) && chargeData.ServiceFromDate == currentClaimCharge.ServiceFromDate && validPaymentResults.Select(currentPaymentType => currentPaymentType.Line) .ToList() .Contains(chargeData.Line)).ToList(); //Get valid line ids based on current rev/cpt/thrudate selection List <int> lineItemWithCurrentSelection = claimCharges.Select(currentClaimCharge => currentClaimCharge.Line).ToList(); //Get Sum of Unit based on current rev/cpt/thrudate selection int?unitSum = claimCharges.Sum(currentClaimCharge => currentClaimCharge.Units); if (lineItemWithCurrentSelection.Any()) { paymentResults = EvaluateWithMaxCases(paymentResults, claim, lineItemWithCurrentSelection, unitSum); } return(paymentResults); }
/// <summary> /// Adds the limits by per day of stay. /// </summary> /// <param name="claimCharge">The claim charge.</param> /// <param name="codes">The per day of stays.</param> /// <param name="code">The code.</param> /// <param name="limit">The limit.</param> private static void AddLimitsPerdayOfStay(ClaimCharge claimCharge, List <CodeDetails> codes, string code, int limit) { if (codes.Count == 0 || codes.All(day => day.Day != claimCharge.ServiceFromDate || day.Code != code)) { codes.Add(new CodeDetails { Code = code, Day = claimCharge.ServiceFromDate, Occurence = Constants.One, Limit = limit }); } }
/// <summary> /// /// </summary> /// <param name="claim"></param> /// <param name="paymentResults"></param> /// <param name="isCarveOut"></param> /// <returns></returns> private void ApplyPerChargeLine(IEvaluateableClaim claim, List <PaymentResult> paymentResults, bool isCarveOut) { if (PaymentTypeBase.ValidLineIds != null && PaymentTypeBase.ValidLineIds.Any()) { List <int> adjudicatedLines = new List <int>(); foreach ( var lineId in PaymentTypeStopLoss.ValidLineIds.Where(lineId => !adjudicatedLines.Contains(lineId))) { //Add lineId into Adjudicated line list adjudicatedLines.Add(lineId); ClaimCharge claimCharge = claim.ClaimCharges.FirstOrDefault(currentClaimCharge => currentClaimCharge.Line == lineId); ApplyChargesOnPaymentType(claim, paymentResults, isCarveOut, claimCharge, lineId); } } }
/// <summary> /// Gets the code and occurence value. /// </summary> /// <param name="uploadedValue">The uploaded value.</param> /// <param name="codeDetailsList">The codes.</param> /// <param name="claimCharge">The claim charge.</param> /// <param name="codeDetails">The code details.</param> private void GetCodeAndOccurenceValue(ClaimFieldValue uploadedValue, IEnumerable <CodeDetails> codeDetailsList, ClaimCharge claimCharge, CodeDetails codeDetails) { if (!PaymentTypeCustomTable.IsPerDayOfStay) { CodeDetails perCode = codeDetailsList.First( pday => pday.Code == uploadedValue.Identifier); codeDetails.Occurence = perCode.Occurence; codeDetails.Code = perCode.Code; codeDetails.Limit = perCode.Limit; } else { CodeDetails perDayOfStay = codeDetailsList.First( pday => pday.Code == uploadedValue.Identifier && pday.Day == claimCharge.ServiceFromDate); codeDetails.Occurence = perDayOfStay.Occurence; codeDetails.Code = perDayOfStay.Code; codeDetails.Limit = perDayOfStay.Limit; } }
/// <summary> /// Evaluates the line. /// </summary> /// <param name="paymentResult">The payment result.</param> /// <param name="claimCharge">The claim charge.</param> /// <param name="medicareLabFeeSchedules">The medicare lab fee schedules.</param> /// <returns></returns> private void EvaluateLine(PaymentResult paymentResult, ClaimCharge claimCharge, List <MedicareLabFeeSchedule> medicareLabFeeSchedules) { //Update PaymentResult and set matching ServiceTypeId,PaymentTypeDetailId & PaymentTypeId Utilities.UpdatePaymentResult(paymentResult, PaymentTypeMedicareLabFeeSchedule.ServiceTypeId, PaymentTypeMedicareLabFeeSchedule.PaymentTypeDetailId, PaymentTypeMedicareLabFeeSchedule.PaymentTypeId); string hcpcsCode = claimCharge.HcpcsCodeWithModifier; //Get Medicare Lab Fee Schedule Amount based on HCPCS code double?medicareLabFeeScheduleAmount = GetAmount(medicareLabFeeSchedules, hcpcsCode); if (medicareLabFeeScheduleAmount.HasValue) { paymentResult.AdjudicatedValue = (PaymentTypeMedicareLabFeeSchedule.Percentage / 100) * medicareLabFeeScheduleAmount.Value; paymentResult.ClaimStatus = (byte)Enums.AdjudicationOrVarianceStatuses.Adjudicated; } else { paymentResult.ClaimStatus = (byte)Enums.AdjudicationOrVarianceStatuses.AdjudicationErrorInvalidPaymentData; } }
/// <summary> /// Evaluates the total charge at line level. /// </summary> /// <param name="claim">The claim.</param> /// <param name="paymentResults">The payment results.</param> /// <param name="isCarveOut">if set to <c>true</c> [is carve out].</param> /// <returns></returns> private void EvaluateTotalChargeAtLineLevel(IEvaluateableClaim claim, List <PaymentResult> paymentResults, bool isCarveOut) { if (PaymentTypeBase.ValidLineIds != null && PaymentTypeBase.ValidLineIds.Count > 0 && PaymentTypeStopLoss.Threshold.HasValue && PaymentTypeStopLoss.Percentage.HasValue) { List <int> adjudicatedLines = new List <int>(); foreach (var lineId in PaymentTypeStopLoss.ValidLineIds) { if (!adjudicatedLines.Contains(lineId)) { ClaimCharge claimCharge = claim.ClaimCharges.FirstOrDefault( currentClaimCharge => currentClaimCharge.Line == lineId); if (claimCharge != null && (paymentResults.Any( currentPaymentResult => currentPaymentResult.Line == claimCharge.Line && (currentPaymentResult.AdjudicatedValue == null || isCarveOut || currentPaymentResult.ServiceTypeId == PaymentTypeStopLoss.ServiceTypeId)))) { List <ClaimCharge> claimCharges = claim.ClaimCharges.Where(currentClaimCharge => (string.IsNullOrEmpty(PaymentTypeStopLoss.RevCode) || claimCharge.RevCode == currentClaimCharge.RevCode) && (string.IsNullOrEmpty(PaymentTypeStopLoss.HcpcsCode) || (claimCharge.HcpcsCode.Trim().ToUpper()) == (currentClaimCharge.HcpcsCode.Trim().ToUpper()) && PaymentTypeStopLoss.ValidLineIds.Contains(currentClaimCharge.Line))).ToList(); if (claimCharges.Any()) { //Get Sum of Unit based on current rev/cpt selection CalculateSum(claim, paymentResults, isCarveOut, claimCharges, lineId, adjudicatedLines); } } } } } }
/// <summary> /// Applies the per case with maximum cases. /// </summary> /// <param name="claim">The claim.</param> /// <param name="paymentResults">The payment result list.</param> /// <param name="isCarveOut">if set to <c>true</c> [is carve out].</param> /// <returns></returns> private List <PaymentResult> ApplyPerCaseWithMaxCases(IEvaluateableClaim claim, List <PaymentResult> paymentResults, bool isCarveOut) { //Check whether payment type contains rev codee as selection bool isRevCodeAvailable = !string.IsNullOrEmpty(PaymentTypePerCase.RevCode); //Check whether payment type contains cpt code as selection bool isCptCodeAvailable = !string.IsNullOrEmpty(PaymentTypePerCase.HcpcsCode); //update payment result list paymentResults = UpdatePaymentResult(paymentResults, isCarveOut); //Select payment results with valid line selection and adjudication amount is null List <PaymentResult> validPaymentResults = paymentResults.Where( currentPaymentResult => currentPaymentResult.Line.HasValue && PaymentTypePerCase.ValidLineIds.Contains(currentPaymentResult.Line.Value) && currentPaymentResult.AdjudicatedValue == null).ToList(); foreach (int line in validPaymentResults.Select(currentPaymentResult => (int)currentPaymentResult.Line).ToList()) { ClaimCharge chargeData = claim.ClaimCharges.FirstOrDefault(currentClaimCharge => currentClaimCharge.Line == line); if (paymentResults.Any( currentPaymentResult => currentPaymentResult.Line.HasValue && currentPaymentResult.Line.Value == line && currentPaymentResult.AdjudicatedValue == null) && chargeData != null) { //get current rev/cpt/thrudate selection paymentResults = GetCurrentSelection(claim, paymentResults, isRevCodeAvailable, chargeData, isCptCodeAvailable, validPaymentResults); } } return(paymentResults); }
/// <summary> /// Gets the valid payment result. /// </summary> /// <param name="validPaymentResults">The valid payment results.</param> /// <param name="claimCharge">The claim charge.</param> /// <param name="first">The first.</param> /// <returns></returns> private int GetValidPaymentResult(IEnumerable <PaymentResult> validPaymentResults, ClaimCharge claimCharge, int first) { PaymentResult paymentResult = validPaymentResults.FirstOrDefault( currentPaymentResult => currentPaymentResult.Line == claimCharge.Line && currentPaymentResult.AdjudicatedValue == null); if (paymentResult != null) { paymentResult.AdjudicatedValue = first == 1 ? PaymentTypePerVisit.Rate : 0.0; first++; paymentResult.ClaimStatus = (byte)Enums.AdjudicationOrVarianceStatuses.Adjudicated; paymentResult.PaymentTypeId = (byte)Enums.PaymentTypeCodes.PerVisit; paymentResult.ServiceTypeId = PaymentTypePerVisit.ServiceTypeId; } return(first); }
/// <summary> /// Applies the total charge at line level. /// </summary> /// <param name="paymentResults">The payment results.</param> /// <param name="currentClaimCharge">The current claim charge.</param> /// <param name="isCarveOut">if set to <c>true</c> [is carve out].</param> /// <param name="lineId">The line identifier.</param> /// <param name="totalCharge">The total charge.</param> /// <param name="claim"></param> private void ApplyTotalChargeAtLineLevel(List <PaymentResult> paymentResults, ClaimCharge currentClaimCharge, bool isCarveOut, int lineId, double totalCharge, IEvaluateableClaim claim) { PaymentResult paymentResult = paymentResults.Any( result => result.ServiceTypeId == PaymentTypeStopLoss.ServiceTypeId && result.Line == currentClaimCharge.Line) ? paymentResults.FirstOrDefault( result => result.ServiceTypeId == PaymentTypeStopLoss.ServiceTypeId && result.Line == currentClaimCharge.Line) : GetPaymentResult(paymentResults, isCarveOut, currentClaimCharge.Line); //Update PaymentResult and set matching ServiceTypeId,PaymentTypeDetailId & PaymentTypeId Utilities.UpdatePaymentResult(paymentResult, PaymentTypeStopLoss.ServiceTypeId, PaymentTypeStopLoss.PaymentTypeDetailId, PaymentTypeStopLoss.PaymentTypeId); if (paymentResult != null) { if (PaymentTypeStopLoss.Threshold.HasValue && PaymentTypeStopLoss.Percentage.HasValue) { paymentResult.AdjudicatedValue = (currentClaimCharge.Line == lineId) ? PaymentTypeStopLoss.IsExcessCharge ? ((totalCharge - PaymentTypeStopLoss.Threshold.Value) / 100) * PaymentTypeStopLoss.Percentage.Value : (PaymentTypeStopLoss .Percentage.Value / 100) * totalCharge : 0; paymentResult.ClaimStatus = (byte)Enums.AdjudicationOrVarianceStatuses.Adjudicated; Utilities.UpdateStopLossDetails(paymentResult, claim.SmartBox, PaymentTypeStopLoss, PaymentTypeStopLoss.IsFormulaError); } else { paymentResult.ClaimStatus = (byte)Enums.AdjudicationOrVarianceStatuses.AdjudicationErrorInvalidPaymentData; } } }
/// <summary> /// Updates the limit. /// </summary> /// <param name="claimPaymentResult">The claim payment result.</param> /// <param name="codeDetailsList">The codes.</param> /// <param name="claimCharge">The claim charge.</param> /// <param name="codeValue">The code value.</param> /// <param name="isMultiplierExist">if set to <c>true</c> [is multiplier exist].</param> private void UpdateLimit(PaymentResult claimPaymentResult, IEnumerable <CodeDetails> codeDetailsList, ClaimCharge claimCharge, string codeValue, bool isMultiplierExist) { if (PaymentTypeCustomTable.IsPerDayOfStay) { foreach ( CodeDetails claimCode in codeDetailsList.Where(p => p.Code == codeValue && p.Day == claimCharge.ServiceFromDate)) { claimCode.Limit -= Constants.One; claimPaymentResult.ServiceLineDate = claimCharge.ServiceFromDate; claimCode.Occurence += ((!PaymentTypeCustomTable.IsObserveServiceUnit && !isMultiplierExist && claimCharge.Units != null) ? claimCharge.Units.Value : Constants.One); } } else { foreach (CodeDetails claimCode in codeDetailsList) { if (claimCode.Code == codeValue) { claimCode.Limit -= Constants.One; claimCode.Occurence += ((!PaymentTypeCustomTable.IsObserveServiceUnit && !isMultiplierExist && claimCharge.Units != null) ? claimCharge.Units.Value : Constants.One); } } } }
/// <summary> /// Calculates the per day. /// </summary> /// <param name="paymentResults">The payment results.</param> /// <param name="groupCharge">The group charge.</param> /// <param name="validPaymentResults">The valid payment results.</param> /// <param name="claimCharge">The claimCharge.</param> /// <param name="itemIndex">The itemIndex.</param> /// <param name="claim"></param> /// <returns></returns> private int CalculatePerDay(ICollection <PaymentResult> paymentResults, double?groupCharge, IEnumerable <PaymentResult> validPaymentResults, ClaimCharge claimCharge, int itemIndex, IEvaluateableClaim claim) { ////Logic to apply stop loss if (groupCharge > 0 && (PaymentTypeStopLoss.Threshold != null && groupCharge > PaymentTypeStopLoss.Threshold.Value && PaymentTypeStopLoss.Percentage != null)) { PaymentResult paymentResult = validPaymentResults.FirstOrDefault( currentPaymentResult => currentPaymentResult.Line == claimCharge.Line && (currentPaymentResult.AdjudicatedValue == null || currentPaymentResult.ServiceTypeId == PaymentTypeStopLoss.ServiceTypeId)); if (paymentResult != null) { itemIndex = ApplyPerDayFormula(groupCharge, itemIndex, claim, paymentResult); } } else { PaymentResult paymentResult = validPaymentResults.FirstOrDefault( x => x.Line == claimCharge.Line && x.AdjudicatedValue == null && !x.IsInitialEntry); if (paymentResult != null) { paymentResults.Remove(paymentResult); } } return(itemIndex); }
/// <summary> /// Evaluates the line by occurence. /// </summary> /// <param name="claimPaymentResult">The claim payment result.</param> /// <param name="claim">The claim.</param> /// <param name="codeDetailsList">The codes.</param> /// <param name="claimCharge">The claim charge.</param> /// <param name="claimFieldDocValueDictionary">The claim field document value dictionary.</param> /// <param name="formula">The formula.</param> /// <param name="uploadedValue">The uploaded value.</param> private void EvaluateLineByOccurence(PaymentResult claimPaymentResult, IEvaluateableClaim claim, List <CodeDetails> codeDetailsList, ClaimCharge claimCharge, Dictionary <string, string> claimFieldDocValueDictionary, double?formula, ClaimFieldValue uploadedValue) { bool isMultiplierexist = PaymentTypeCustomTable.MultiplierFirst != null || PaymentTypeCustomTable.MultiplierSecond != null || PaymentTypeCustomTable.MultiplierThird != null || PaymentTypeCustomTable.MultiplierFourth != null || PaymentTypeCustomTable.MultiplierOther != null; for (int unit = 0; unit < ((!PaymentTypeCustomTable.IsObserveServiceUnit && !isMultiplierexist) ? 1 : claimCharge.Units); unit++) { CodeDetails codeDetails = new CodeDetails(); GetCodeAndOccurenceValue(uploadedValue, codeDetailsList, claimCharge, codeDetails); if ((PaymentTypeCustomTable.IsObserveServiceUnit && codeDetails.Limit > 0) || (PaymentTypeCustomTable.IsObserveServiceUnit && PaymentTypeCustomTable.ObserveServiceUnitLimit == null) || !PaymentTypeCustomTable.IsObserveServiceUnit) { switch (codeDetails.Occurence) { case 1: string multiplierFirstExpandedExpression = PaymentTypeCustomTable.MultiplierFirst ?? Constants.StringOne; CalculateAdjudicatedValue(claimPaymentResult, claim, codeDetailsList, claimCharge, multiplierFirstExpandedExpression, claimFieldDocValueDictionary, codeDetails.Code, codeDetails.Occurence, formula, isMultiplierexist); break; case 2: string multiplierSecondExpandedExpression = PaymentTypeCustomTable.MultiplierSecond ?? Constants.StringOne; CalculateAdjudicatedValue(claimPaymentResult, claim, codeDetailsList, claimCharge, multiplierSecondExpandedExpression, claimFieldDocValueDictionary, codeDetails.Code, codeDetails.Occurence, formula, isMultiplierexist); break; case 3: string multiplierThirdExpandedExpression = PaymentTypeCustomTable.MultiplierThird ?? Constants.StringOne; CalculateAdjudicatedValue(claimPaymentResult, claim, codeDetailsList, claimCharge, multiplierThirdExpandedExpression, claimFieldDocValueDictionary, codeDetails.Code, codeDetails.Occurence, formula, isMultiplierexist); break; case 4: string multiplierFourthExpandedExpression = PaymentTypeCustomTable.MultiplierFourth ?? Constants.StringOne; CalculateAdjudicatedValue(claimPaymentResult, claim, codeDetailsList, claimCharge, multiplierFourthExpandedExpression, claimFieldDocValueDictionary, codeDetails.Code, codeDetails.Occurence, formula, isMultiplierexist); break; default: string multiplierOthersExpandedExpression = PaymentTypeCustomTable.MultiplierOther ?? Constants.StringOne; CalculateAdjudicatedValue(claimPaymentResult, claim, codeDetailsList, claimCharge, multiplierOthersExpandedExpression, claimFieldDocValueDictionary, codeDetails.Code, codeDetails.Occurence, formula, isMultiplierexist); break; } } else if (claimPaymentResult.AdjudicatedValue == null) { claimPaymentResult.ClaimStatus = (byte)Enums.AdjudicationOrVarianceStatuses.Adjudicated; claimPaymentResult.AdjudicatedValue = 0.0; } } }
/// <summary> /// calculates and adds the result to payment dictionary /// </summary> /// <param name="claimPaymentResult">payment result of the claim</param> /// <param name="uploadedValue">uploaded excel values</param> /// <param name="claim">claim details</param> /// <param name="codeDetailsList">The codes.</param> /// <param name="claimCharge">The claim charge.</param> private void EvaluateAdjudicatedValue(PaymentResult claimPaymentResult, ClaimFieldValue uploadedValue, IEvaluateableClaim claim, List <CodeDetails> codeDetailsList = null, ClaimCharge claimCharge = null) { Utilities.UpdatePaymentResult(claimPaymentResult, PaymentTypeCustomTable.ServiceTypeId, PaymentTypeCustomTable.PaymentTypeDetailId, PaymentTypeCustomTable.PaymentTypeId); Dictionary <string, string> claimFieldDocValueDictionary = PrepareClaimFieldDocValueDictionary(uploadedValue); double convertedAmount; string[] expandedExpression = { PaymentTypeCustomTable.Expression }; List <string> validValues = new List <string>(); foreach (KeyValuePair <string, string> pair in claimFieldDocValueDictionary.OrderByDescending(key => key.Key.Length).Where(pair => expandedExpression[0].IndexOf(pair.Key, StringComparison.CurrentCultureIgnoreCase) >= 0)) { validValues.Add(pair.Value); expandedExpression[0] = Regex.Replace(expandedExpression[0], pair.Key, pair.Value, RegexOptions.IgnoreCase); } if (claimCharge != null && codeDetailsList != null) { double?formula = Utilities.EvaluateExpression(expandedExpression[0], claim, PaymentTypeCustomTable); EvaluateLineByOccurence(claimPaymentResult, claim, codeDetailsList, claimCharge, claimFieldDocValueDictionary, formula, uploadedValue); } else if (validValues.Any(x => !double.TryParse(x, out convertedAmount))) { claimPaymentResult.ClaimStatus = validValues.Any(string.IsNullOrEmpty) ? (byte)Enums.AdjudicationOrVarianceStatuses.AdjudicationErrorInvalidPaymentData : (byte)Enums.AdjudicationOrVarianceStatuses.UnAdjudicated; } else { claimPaymentResult.AdjudicatedValue = Utilities.EvaluateExpression(expandedExpression[0], claim, PaymentTypeCustomTable); claimPaymentResult.ClaimStatus = (byte)Enums.AdjudicationOrVarianceStatuses.Adjudicated; Utilities.UpdateCustomTableDetails(claimPaymentResult, claim.SmartBox, PaymentTypeCustomTable); } }
private ClaimFieldValue GetMatchedClaimFieldValues(IEvaluateableClaim claim, ClaimCharge claimCharge = null) { ClaimFieldValue claimFieldValue; switch (PaymentTypeCustomTable.ClaimFieldId) { case (byte)Enums.ClaimFieldTypes.Drg: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(claimField => PrePendZeros(claimField.Identifier) == PrePendZeros(claim.Drg)); break; case (byte)Enums.ClaimFieldTypes.BillType: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(claimField => claimField.Identifier.ToUpper(CultureInfo.InvariantCulture) == claim.BillType.ToUpper(CultureInfo.InvariantCulture)); break; case (byte)Enums.ClaimFieldTypes.PatientAccountNumber: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(claimField => claimField.Identifier.ToUpper(CultureInfo.InvariantCulture) == claim.PatAcctNum.ToUpper(CultureInfo.InvariantCulture)); break; case (byte)Enums.ClaimFieldTypes.PayerName: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(claimField => claimField.Identifier.ToUpperInvariant() == claim.PriPayerName.ToUpperInvariant()); break; case (byte)Enums.ClaimFieldTypes.InsuredId: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(claimField => claim.InsuredCodes.Any(x => x.CertificationNumber.ToUpperInvariant() == claimField.Identifier.ToUpperInvariant())); break; case (byte)Enums.ClaimFieldTypes.InsuredGroup: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(claimField => claim.InsuredCodes.Any(x => x.GroupNumber.ToUpperInvariant() == claimField.Identifier.ToUpperInvariant())); break; case (byte)Enums.ClaimFieldTypes.Icn: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(claimField => claimField.Identifier.ToUpperInvariant() == claim.Icn.ToUpperInvariant()); break; case (byte)Enums.ClaimFieldTypes.Mrn: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(claimField => claimField.Identifier.ToUpperInvariant() == claim.Mrn.ToUpperInvariant()); break; case (byte)Enums.ClaimFieldTypes.ReferringPhysician: claimFieldValue = GetReferringPhysicianClaimFieldValue(claim); break; case (byte)Enums.ClaimFieldTypes.RenderingPhysician: claimFieldValue = GetRenderingPhysicianClaimFieldValue(claim); break; case (byte)Enums.ClaimFieldTypes.AttendingPhysician: claimFieldValue = GetAttendingPhysicianClaimFieldValue(claim); break; case (byte)Enums.ClaimFieldTypes.IcdDiagnosis: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(claimField => claim.DiagnosisCodes.Any(x => x.IcddCode.ToUpperInvariant() == claimField.Identifier.ToUpperInvariant())); break; case (byte)Enums.ClaimFieldTypes.IcdProcedure: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(claimField => claim.ProcedureCodes.Any(x => x.IcdpCode.ToUpperInvariant() == claimField.Identifier.ToUpperInvariant())); break; case (byte)Enums.ClaimFieldTypes.ValueCodes: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(claimField => claim.ValueCodes.Any(x => x.Code.ToUpperInvariant() == claimField.Identifier.ToUpperInvariant())); break; case (byte)Enums.ClaimFieldTypes.OccurrenceCode: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(claimField => claim.OccurrenceCodes.Any(x => x.Code.ToUpperInvariant() == claimField.Identifier.ToUpperInvariant())); break; case (byte)Enums.ClaimFieldTypes.ConditionCodes: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(claimField => claim.ConditionCodes.Any(x => x.Code.ToUpperInvariant() == claimField.Identifier.ToUpperInvariant())); break; case (byte)Enums.ClaimFieldTypes.CustomField1: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.First(claimField => claim.CustomField1 == claimField.Identifier); break; case (byte)Enums.ClaimFieldTypes.CustomField2: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.First(claimField => claim.CustomField2 == claimField.Identifier); break; case (byte)Enums.ClaimFieldTypes.CustomField3: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.First(claimField => claim.CustomField4 == claimField.Identifier); break; case (byte)Enums.ClaimFieldTypes.CustomField4: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.First(claimField => claim.CustomField4 == claimField.Identifier); break; case (byte)Enums.ClaimFieldTypes.CustomField5: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.First(claimField => claim.CustomField5 == claimField.Identifier); break; case (byte)Enums.ClaimFieldTypes.CustomField6: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.First(claimField => claim.CustomField6 == claimField.Identifier); break; case (byte)Enums.ClaimFieldTypes.RevenueCode: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(currentClaimFieldValue => claimCharge != null && ((currentClaimFieldValue.Identifier.Length == 4 ? Regex.Replace(currentClaimFieldValue.Identifier, "^0?", string.Empty) : currentClaimFieldValue.Identifier) == claimCharge.RevCode)); break; case (byte)Enums.ClaimFieldTypes.HcpcsOrRateOrHipps: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues. FirstOrDefault(currentClaimFieldValue => claimCharge != null && (currentClaimFieldValue.Identifier.Equals(claimCharge.HcpcsCodeWithModifier, StringComparison.OrdinalIgnoreCase))); if (claimCharge != null && (claimFieldValue == null && claimCharge.HcpcsCodeWithModifier.Trim().Length != 5)) { claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues. FirstOrDefault(currentClaimFieldValue => (currentClaimFieldValue.Identifier.Equals(claimCharge.HcpcsCode, StringComparison.OrdinalIgnoreCase))); } break; case (byte)Enums.ClaimFieldTypes.PlaceOfService: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(currentClaimFieldValue => claimCharge != null && currentClaimFieldValue.Identifier.Equals(claimCharge.PlaceOfService, StringComparison.OrdinalIgnoreCase)); break; case (byte)Enums.ClaimFieldTypes.Los: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(claimField => claimField.Identifier == Convert.ToString(claim.Los, CultureInfo.InvariantCulture)); break; case (byte)Enums.ClaimFieldTypes.Age: claimFieldValue = PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.FirstOrDefault(claimField => claimField.Identifier == Convert.ToString(claim.Age, CultureInfo.InvariantCulture)); break; default: claimFieldValue = new ClaimFieldValue(); break; } return(claimFieldValue); }
/// <summary> /// Evaluates the type of the payment. /// </summary> /// <param name="paymentResults">The payment result.</param> /// <param name="claim">The claim.</param> /// <param name="claimCharge">The claim charge.</param> /// <param name="isCarveOut">if set to <c>true</c> [is carve out].</param> /// <param name="codeDetailsList">The per day of stays.</param> private void EvaluateLine(List <PaymentResult> paymentResults, IEvaluateableClaim claim, ClaimCharge claimCharge, bool isCarveOut, List <CodeDetails> codeDetailsList) { if (PaymentTypeCustomTable.ClaimFieldDoc != null && PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues != null && PaymentTypeCustomTable.ClaimFieldDoc.ClaimFieldValues.Count > 0) { string limitExpandedExpression = PaymentTypeCustomTable.ObserveServiceUnitLimit; ClaimFieldValue uploadedValue = GetMatchedClaimFieldValues(claim, claimCharge); if (uploadedValue != null) { PaymentResult paymentResult = GetPaymentResult(paymentResults, isCarveOut, claimCharge.Line); if (paymentResult != null) { claim.SmartBox.LC = claimCharge.Amount; Dictionary <string, string> claimFieldDocValueDictionary = PrepareClaimFieldDocValueDictionary(uploadedValue); int limit = 0; if (!string.IsNullOrWhiteSpace(PaymentTypeCustomTable.ObserveServiceUnitLimit)) { limitExpandedExpression = GetExpandedExpression(claimFieldDocValueDictionary, limitExpandedExpression); limit = (Convert.ToInt32(Utilities.EvaluateExpression(limitExpandedExpression, claim, PaymentTypeCustomTable, Constants.LimitOccurence))); } limit = (limit < 0) ? 0 : limit; //if limit is negative value then making it zero string code = uploadedValue.Identifier; if (PaymentTypeCustomTable.IsPerDayOfStay) { AddLimitsPerdayOfStay(claimCharge, codeDetailsList, code, limit); } else { AddLimitByCode(codeDetailsList, code, limit); } EvaluateAdjudicatedValue(paymentResult, uploadedValue, claim, codeDetailsList, claimCharge); } } } }
/// <summary> /// Applies the fee schedule. /// </summary> /// <param name="paymentResult">The payment result.</param> /// <param name="claimFieldValue">The claim field value.</param> /// <param name="claimCharge">The claim charge.</param> private void ApplyFeeSchedule(PaymentResult paymentResult, ClaimFieldValue claimFieldValue, ClaimCharge claimCharge) { double amount; if (!string.IsNullOrEmpty(claimFieldValue.Value) && Double.TryParse(claimFieldValue.Value, out amount)) { if (PaymentTypeFeeSchedule.FeeSchedule.HasValue) { double percentageAmount = (PaymentTypeFeeSchedule.FeeSchedule.Value / 100) * amount; paymentResult.AdjudicatedValue = (PaymentTypeFeeSchedule.IsObserveUnits) ? percentageAmount * claimCharge.Units : percentageAmount; paymentResult.ClaimStatus = (byte)Enums.AdjudicationOrVarianceStatuses.Adjudicated; } else { paymentResult.ClaimStatus = (byte)Enums.AdjudicationOrVarianceStatuses .AdjudicationErrorInvalidPaymentData; } } else { paymentResult.ClaimStatus = (byte)Enums.AdjudicationOrVarianceStatuses .AdjudicationErrorInvalidPaymentData; } }
public void UpdateEvaluateableClaimsTest() { // Arrange _target = new EvaluateableClaimLogic(); ConditionCode conditionCode = new ConditionCode { ClaimId = 123, Code = "0300" }; List <ConditionCode> conditionCodes = new List <ConditionCode> { conditionCode }; PatientData patientData = new PatientData { FirstName = "Jim" }; DiagnosisCode diagnosisCode = new DiagnosisCode { Instance = "P", ClaimId = 123, IcddCode = "0800" }; List <DiagnosisCode> diagnosisCodes = new List <DiagnosisCode> { diagnosisCode }; ClaimCharge claimCharge = new ClaimCharge { Line = 1, RevCode = "0123", Amount = 5556.2, }; // Act List <ClaimCharge> claimCharges = new List <ClaimCharge> { claimCharge }; EvaluateableClaim evaluateableClaim = new EvaluateableClaim { ClaimId = 123, StatementThru = Convert.ToDateTime("2012-01-12 00:00:00.000"), StatementFrom = Convert.ToDateTime("2012-01-12 00:00:00.000"), ConditionCodes = conditionCodes, PatientData = patientData, DiagnosisCodes = diagnosisCodes, ClaimCharges = claimCharges }; List <EvaluateableClaim> evaluateableClaimLists = new List <EvaluateableClaim> { evaluateableClaim }; List <EvaluateableClaim> actual = _target.UpdateEvaluateableClaims(evaluateableClaimLists); // Assert EvaluateableClaim updatedEvaluateableClaim = actual.FirstOrDefault(); if (updatedEvaluateableClaim != null) { CRecord cRecord = updatedEvaluateableClaim.MicrodynApcEditInput.CRecord; if (cRecord != null) { Assert.AreEqual(cRecord.PatientData, evaluateableClaim.PatientData); Assert.AreNotEqual(cRecord.ClaimId, evaluateableClaim.ClaimId); } DRecord dRecord = updatedEvaluateableClaim.MicrodynApcEditInput.DRecord; if (dRecord != null) { Assert.AreEqual(dRecord.PrincipalDiagnosisCode, evaluateableClaim.DiagnosisCodes.First().IcddCode); } LRecord lRecord = updatedEvaluateableClaim.MicrodynApcEditInput.LRecords.FirstOrDefault(); if (lRecord != null) { Assert.AreEqual(lRecord.RevenueCode, evaluateableClaim.ClaimCharges.First().RevCode); Assert.AreEqual(lRecord.LineItemId, evaluateableClaim.ClaimCharges.First().Line); } MedicareOutPatient medicareOutPatient = updatedEvaluateableClaim.MicrodynApcEditInput.MedicareOutPatientRecord; if (medicareOutPatient != null) { Assert.AreEqual(medicareOutPatient.ClaimId, evaluateableClaim.ClaimId); Assert.AreEqual(medicareOutPatient.BeneDeductible, 0); } } }