Calculation type

BilateralSurgeryV2Adjustment

Configurable bilateral-surgery adjustment: finds charges whose schedule-type rollup indicator has a configured percentage multiplier, confirms bilaterality either via a modifier-50 code or via matching left/right (LT/RT) modifier pairs on the same procedure code, then scales each affected charge's already-computed allowed amount by the configured percentage; the LT/RT partner charge is zeroed and its AmountCharged folded onto the primary.

15
uses
1
customers
Adjustment
category
Charge
applies at

What it computes

FindAffectedCharges: for i=1..NumCharges-1, charge qualifies if not IgnoreCharge, not matching any ExclusionCodes, and rollups[i]?.Code has an entry in BilateralPercentageMultipliers. ProcessChargeModifiers walks qualifying charges in ascending charge-index order: if charge has modifier 50 -> added to affectedCharges (primary). Else if it has LT or RT and a LATER (higher-index) qualifying charge with the same procedure code has the missing counterpart modifier -> that later charge is added to pairedCharges[laterIndex] = earlierIndex (earlier index becomes primary/150%, later becomes zeroed). allCharges = affectedCharges union pairedCharges.Keys, then reordered by SortBy for processing (SortBy only controls adjustment-application order, NOT which twin becomes primary -- that is fixed by ascending charge-array index at pairing time). GetAdjustedAmount: if chargeIndex in pairedCharges (i.e. it is the secondary) -> 0; else if in affectedCharges -> originalAmount * percentage/100 via MoneyMath.Multiply, where percentage comes from rollups.Where(r => r.Member == procedureCode).First().Code looked up via TryGetIndicatorPercentage (unguarded First(), no OrDefault). AdjustCharges: for each processed index, if adjustedAmount != detail.Amount, Adjust(); AND if that index is a key in pairedCharges, fold: primary.AmountCharged += secondary.AmountCharged; secondary.AmountCharged = 0.

Parameters

KeyMeaning
ScheduleTypeSchedule type key used to look up the code-rollup indicator (bilateral surgery status) per charge, via IBilateralSurgeryScheduleRepo (adjustment as IScheduleTypeCalculation).
ModifierDimensionDimension key (default "Modifier") on which codes "50" (bilateral), "RT", and "LT" are looked up on each charge.
SortBySortChargesBy enum controlling only the ORDER charges are processed for the Adjust() call (default AmountAllowed) -- does not affect which of a LT/RT pair is the 150% primary vs the zeroed secondary.
BilateralPercentageMultipliersDictionary mapping rollup indicator string to a percentage multiplier; V2's own constructor sets the default to {"1": 150.0} (overwriting the base class MedicareBilateralSurgeryAdjustment's default of {"0":150,"1":150,"2":150,"3":200} which runs first in the ctor chain).
ExclusionCodesList of DimensionMember codes; any charge carrying one of these is excluded from eligibility entirely (checked in DoesAdjustmentApply).
BaseCodes/PercentagesObsolete legacy fields retained only for backward compatibility; SetIndicatorPercentages() converts them into BilateralPercentageMultipliers only if that dictionary is empty.

Gotchas

1) Percentage lookup in GetAdjustedAmount uses rollups.Where(r => r?.Member == procedureCode).First() -- an UNGUARDED First() with no fallback, unlike the eligibility check (rollups[chargeIndex]?.Code, index-based and null-safe). If no rollup record's Member matches the charge's procedure code exactly, this throws InvalidOperationException at adjustment time rather than skipping the charge. 2) The AmountCharged fold-in and the actual zeroing of the secondary/paired charge both happen only when the SECONDARY index is processed in AdjustCharges (pairedCharges.TryGetValue only succeeds for the key/secondary, not the primary) and are gated by `adjustedAmount != detail.Amount`; if the secondary charge's allowed amount is already exactly 0 going into this adjustment, that guard is false and the fold/zero never fires even though pairing was detected. 3) Which charge of an LT/RT pair becomes the 150% 'primary' vs. the zeroed 'secondary' is fixed by ascending Charges[] array index at pairing time (ProcessChargeModifiers iterates potentialAffectedCharges in that order), NOT by the configurable SortBy -- SortBy only reorders the later Adjust() application.

In the source

class · /home/cary/src/mdc/MdClarity/MDClarity/MDClarityCore/Backend/PricingEngine/Adjustments/BilateralSurgeryV2Adjustment.cs:10
calculator · /home/cary/src/mdc/MdClarity/MDClarity/MDClarityCore/Backend/PricingEngine/Adjustments/Calculators/BilateralSurgeryV2AdjustmentCalculator.cs:11
dispatch · CalculationEngine.cs:803

CORRECTED: draft's high-level formula (percentage lookup, modifier-50 vs LT/RT pairing, AmountCharged fold) was directionally right and confirmed against BilateralSurgeryV2Adjustment.cs, MedicareBilateralSurgeryAdjustment.cs and BilateralSurgeryV2AdjustmentCalculator.cs, but it omitted: the unguarded First() percentage lookup, the ascending-index (not SortBy) determination of primary vs. secondary, and the fold-in's dependence on the secondary's own zero-guard. Draft's key_attrs default of BilateralPercentageMultipliers={"1":150.0} is correct for V2 specifically (V2's own ctor overwrites the base class's {"0":150,"1":150,"2":150,"3":200} default) -- worth stating explicitly since a reader skimming only the base class would get the wrong default.

Who uses it

RIA15