visproj commited on
Commit
d78bfb0
·
verified ·
1 Parent(s): 81a9b80

Update providers/cms_pricing_provider.py

Browse files
Files changed (1) hide show
  1. providers/cms_pricing_provider.py +420 -420
providers/cms_pricing_provider.py CHANGED
@@ -1,420 +1,420 @@
1
- """CMS Pricing Provider for Medicare fee schedules and cost transparency."""
2
-
3
- import logging
4
- from typing import List, Dict, Any, Callable
5
- import httpx
6
-
7
- from ..core.base_provider import BaseProvider
8
- from ..core.decorators import safe_json_return
9
- from . import register_provider
10
-
11
- logger = logging.getLogger(__name__)
12
-
13
- # Sample Medicare fee schedule data
14
- MEDICARE_FEE_SCHEDULE = {
15
- "99213": {
16
- "description": "Office visit, established patient, level 3",
17
- "medicare_payment": 93.47,
18
- "facility_rate": 93.47,
19
- "non_facility_rate": 131.20,
20
- "rvu": 1.92
21
- },
22
- "99214": {
23
- "description": "Office visit, established patient, level 4",
24
- "medicare_payment": 131.20,
25
- "facility_rate": 131.20,
26
- "non_facility_rate": 183.19,
27
- "rvu": 2.80
28
- },
29
- "43239": {
30
- "description": "Upper GI endoscopy with biopsy",
31
- "medicare_payment": 248.54,
32
- "facility_rate": 248.54,
33
- "non_facility_rate": 450.00,
34
- "rvu": 5.28
35
- },
36
- "45378": {
37
- "description": "Colonoscopy, diagnostic",
38
- "medicare_payment": 365.00,
39
- "facility_rate": 365.00,
40
- "non_facility_rate": 650.00,
41
- "rvu": 7.75
42
- },
43
- "70450": {
44
- "description": "CT scan, head without contrast",
45
- "medicare_payment": 178.00,
46
- "facility_rate": 178.00,
47
- "non_facility_rate": 320.00,
48
- "rvu": 3.78
49
- },
50
- "70553": {
51
- "description": "MRI brain with contrast",
52
- "medicare_payment": 485.00,
53
- "facility_rate": 485.00,
54
- "non_facility_rate": 875.00,
55
- "rvu": 10.30
56
- },
57
- "80053": {
58
- "description": "Comprehensive metabolic panel",
59
- "medicare_payment": 14.00,
60
- "facility_rate": 14.00,
61
- "non_facility_rate": 18.00,
62
- "rvu": 0.30
63
- },
64
- "85025": {
65
- "description": "Complete blood count with differential",
66
- "medicare_payment": 11.00,
67
- "facility_rate": 11.00,
68
- "non_facility_rate": 14.00,
69
- "rvu": 0.23
70
- },
71
- "71046": {
72
- "description": "Chest X-ray, 2 views",
73
- "medicare_payment": 38.00,
74
- "facility_rate": 38.00,
75
- "non_facility_rate": 62.00,
76
- "rvu": 0.81
77
- }
78
- }
79
-
80
- # Sample procedure cost estimates
81
- PROCEDURE_COST_ESTIMATES = {
82
- "colonoscopy": {
83
- "procedure": "Diagnostic Colonoscopy",
84
- "hcpcs_code": "45378",
85
- "average_cost": 2750,
86
- "low_estimate": 1500,
87
- "high_estimate": 4500,
88
- "medicare_rate": 365,
89
- "factors": ["Facility type", "Anesthesia", "Biopsy performed", "Location"]
90
- },
91
- "mri": {
92
- "procedure": "MRI Scan",
93
- "hcpcs_code": "70553",
94
- "average_cost": 1420,
95
- "low_estimate": 400,
96
- "high_estimate": 3500,
97
- "medicare_rate": 485,
98
- "factors": ["Body part", "With/without contrast", "Facility type"]
99
- },
100
- "ct scan": {
101
- "procedure": "CT Scan",
102
- "hcpcs_code": "70450",
103
- "average_cost": 820,
104
- "low_estimate": 300,
105
- "high_estimate": 1800,
106
- "medicare_rate": 178,
107
- "factors": ["Body part", "With/without contrast", "Emergency vs scheduled"]
108
- },
109
- "blood test": {
110
- "procedure": "Comprehensive Metabolic Panel",
111
- "hcpcs_code": "80053",
112
- "average_cost": 45,
113
- "low_estimate": 15,
114
- "high_estimate": 120,
115
- "medicare_rate": 14,
116
- "factors": ["Lab facility", "Stat vs routine", "Insurance negotiated rate"]
117
- },
118
- "x-ray": {
119
- "procedure": "Chest X-Ray",
120
- "hcpcs_code": "71046",
121
- "average_cost": 125,
122
- "low_estimate": 50,
123
- "high_estimate": 300,
124
- "medicare_rate": 38,
125
- "factors": ["Number of views", "Facility type", "Interpretation included"]
126
- },
127
- "office visit": {
128
- "procedure": "Office Visit - Established Patient",
129
- "hcpcs_code": "99213",
130
- "average_cost": 150,
131
- "low_estimate": 100,
132
- "high_estimate": 300,
133
- "medicare_rate": 93,
134
- "factors": ["Complexity level", "Time spent", "Geographic location"]
135
- }
136
- }
137
-
138
- # Sample facility comparison data
139
- FACILITY_COSTS = {
140
- "45378": [ # Colonoscopy
141
- {"facility": "University Hospital", "gross_charge": 4500, "negotiated_rate": 2800, "cash_price": 2500},
142
- {"facility": "Community Medical Center", "gross_charge": 3200, "negotiated_rate": 2100, "cash_price": 1800},
143
- {"facility": "Ambulatory Surgery Center", "gross_charge": 2800, "negotiated_rate": 1600, "cash_price": 1500},
144
- ],
145
- "70450": [ # CT Scan
146
- {"facility": "University Hospital", "gross_charge": 1800, "negotiated_rate": 820, "cash_price": 600},
147
- {"facility": "Community Medical Center", "gross_charge": 1200, "negotiated_rate": 650, "cash_price": 500},
148
- {"facility": "Imaging Center", "gross_charge": 900, "negotiated_rate": 450, "cash_price": 400},
149
- ],
150
- "70553": [ # MRI
151
- {"facility": "University Hospital", "gross_charge": 3500, "negotiated_rate": 1800, "cash_price": 1500},
152
- {"facility": "Community Medical Center", "gross_charge": 2800, "negotiated_rate": 1400, "cash_price": 1200},
153
- {"facility": "Imaging Center", "gross_charge": 2200, "negotiated_rate": 1000, "cash_price": 900},
154
- ]
155
- }
156
-
157
- # Procedure code database
158
- PROCEDURE_CODES = [
159
- {"code": "99213", "description": "Office visit, established patient, level 3", "category": "Evaluation & Management"},
160
- {"code": "99214", "description": "Office visit, established patient, level 4", "category": "Evaluation & Management"},
161
- {"code": "99215", "description": "Office visit, established patient, level 5", "category": "Evaluation & Management"},
162
- {"code": "99203", "description": "Office visit, new patient, level 3", "category": "Evaluation & Management"},
163
- {"code": "45378", "description": "Colonoscopy, diagnostic", "category": "Gastroenterology"},
164
- {"code": "43239", "description": "Upper GI endoscopy with biopsy", "category": "Gastroenterology"},
165
- {"code": "70450", "description": "CT scan, head without contrast", "category": "Radiology"},
166
- {"code": "70553", "description": "MRI brain with contrast", "category": "Radiology"},
167
- {"code": "71046", "description": "Chest X-ray, 2 views", "category": "Radiology"},
168
- {"code": "80053", "description": "Comprehensive metabolic panel", "category": "Laboratory"},
169
- {"code": "85025", "description": "Complete blood count with differential", "category": "Laboratory"},
170
- {"code": "82947", "description": "Glucose blood test", "category": "Laboratory"},
171
- {"code": "83036", "description": "Hemoglobin A1C", "category": "Laboratory"},
172
- ]
173
-
174
-
175
- @register_provider("cms_pricing")
176
- class CMSPricingProvider(BaseProvider):
177
- """Provider for Medicare pricing and cost transparency data."""
178
-
179
- def __init__(self, client: httpx.AsyncClient):
180
- super().__init__("cms_pricing", client)
181
-
182
- async def initialize(self) -> None:
183
- """Initialize CMS pricing provider."""
184
- logger.info("CMS Pricing provider initialized")
185
-
186
- def get_tools(self) -> List[Callable]:
187
- """Return all CMS pricing tools."""
188
- return [
189
- self.cms_get_medicare_fee,
190
- self.cms_estimate_procedure_cost,
191
- self.cms_search_procedure_codes,
192
- self.cms_compare_facility_costs,
193
- self.cms_estimate_out_of_pocket,
194
- ]
195
-
196
- @safe_json_return
197
- async def cms_get_medicare_fee(
198
- self,
199
- hcpcs_code: str,
200
- locality: str = "National"
201
- ) -> Dict[str, Any]:
202
- """
203
- Get Medicare fee schedule pricing for a procedure by HCPCS/CPT code.
204
-
205
- Args:
206
- hcpcs_code: HCPCS procedure code (e.g., "99213", "43239")
207
- locality: Geographic locality (default: "National")
208
-
209
- Returns:
210
- Medicare reimbursement rates with facility vs non-facility pricing
211
- """
212
- result = MEDICARE_FEE_SCHEDULE.get(hcpcs_code, {
213
- "description": f"Procedure {hcpcs_code}",
214
- "medicare_payment": 150.00,
215
- "facility_rate": 150.00,
216
- "non_facility_rate": 200.00,
217
- "rvu": 3.0,
218
- "note": "Sample data - actual rates vary by locality and year"
219
- })
220
-
221
- result["hcpcs_code"] = hcpcs_code
222
- result["locality"] = locality
223
- result["year"] = 2024
224
-
225
- return result
226
-
227
- @safe_json_return
228
- async def cms_estimate_procedure_cost(
229
- self,
230
- procedure_name: str,
231
- region: str = "National",
232
- insurance_type: str = "Medicare"
233
- ) -> Dict[str, Any]:
234
- """
235
- Estimate typical cost range for a procedure in a geographic region.
236
-
237
- Args:
238
- procedure_name: Common procedure name (e.g., "colonoscopy", "MRI", "blood test")
239
- region: Geographic region (default: "National")
240
- insurance_type: Type of insurance (Medicare, Commercial, Cash)
241
-
242
- Returns:
243
- Estimated cost range with average, low, and high estimates
244
- """
245
- procedure_key = procedure_name.lower()
246
- result = PROCEDURE_COST_ESTIMATES.get(procedure_key, {
247
- "procedure": procedure_name.title(),
248
- "hcpcs_code": "Unknown",
249
- "average_cost": 500,
250
- "low_estimate": 200,
251
- "high_estimate": 1000,
252
- "medicare_rate": 150,
253
- "factors": ["Procedure complexity", "Facility type", "Geographic location"]
254
- })
255
-
256
- result["region"] = region
257
- result["insurance_type"] = insurance_type
258
- result["note"] = "Estimates based on national averages. Actual costs vary significantly by provider and location."
259
-
260
- # Adjust for insurance type
261
- if insurance_type.lower() == "commercial":
262
- result["estimated_patient_cost"] = result["average_cost"]
263
- elif insurance_type.lower() == "medicare":
264
- result["estimated_patient_cost"] = result["medicare_rate"] * 1.2 # 20% coinsurance
265
- elif insurance_type.lower() == "cash":
266
- result["estimated_patient_cost"] = result["average_cost"] * 0.7 # Cash discount
267
-
268
- return result
269
-
270
- @safe_json_return
271
- async def cms_search_procedure_codes(
272
- self,
273
- query: str,
274
- limit: int = 10
275
- ) -> Dict[str, Any]:
276
- """
277
- Search for HCPCS/CPT codes by procedure description or category.
278
-
279
- Args:
280
- query: Search term (e.g., "office visit", "colonoscopy")
281
- limit: Maximum number of results (default: 10)
282
-
283
- Returns:
284
- List of matching procedures with codes, descriptions, and categories
285
- """
286
- query_lower = query.lower()
287
- matches = [
288
- p for p in PROCEDURE_CODES
289
- if query_lower in p["description"].lower() or query_lower in p["category"].lower()
290
- ]
291
-
292
- return {
293
- "query": query,
294
- "results": matches[:limit],
295
- "total": len(matches)
296
- }
297
-
298
- @safe_json_return
299
- async def cms_compare_facility_costs(
300
- self,
301
- procedure_code: str,
302
- facilities: List[str] = None
303
- ) -> Dict[str, Any]:
304
- """
305
- Compare procedure costs across different healthcare facilities.
306
-
307
- Args:
308
- procedure_code: HCPCS/CPT code
309
- facilities: List of facility names (uses sample data if not provided)
310
-
311
- Returns:
312
- Cost comparison showing gross charges, negotiated rates, and cash prices
313
- """
314
- facilities_data = FACILITY_COSTS.get(procedure_code, [
315
- {"facility": "Sample Facility A", "gross_charge": 2000, "negotiated_rate": 1200, "cash_price": 1000},
316
- {"facility": "Sample Facility B", "gross_charge": 1500, "negotiated_rate": 900, "cash_price": 800},
317
- {"facility": "Sample Facility C", "gross_charge": 1800, "negotiated_rate": 1000, "cash_price": 900},
318
- ])
319
-
320
- # Calculate savings
321
- cash_prices = [f["cash_price"] for f in facilities_data]
322
- lowest_cash = min(cash_prices)
323
- highest_cash = max(cash_prices)
324
- potential_savings = highest_cash - lowest_cash
325
-
326
- return {
327
- "procedure_code": procedure_code,
328
- "facilities": facilities_data,
329
- "comparison": {
330
- "lowest_cash_price": lowest_cash,
331
- "highest_cash_price": highest_cash,
332
- "potential_savings": potential_savings,
333
- "average_cash_price": sum(cash_prices) / len(cash_prices)
334
- },
335
- "note": "Sample data for demonstration. Actual facility prices vary. Patients should request price estimates directly."
336
- }
337
-
338
- @safe_json_return
339
- async def cms_estimate_out_of_pocket(
340
- self,
341
- procedure_code: str,
342
- insurance_scenario: str = "Medicare",
343
- deductible_met: bool = False
344
- ) -> Dict[str, Any]:
345
- """
346
- Estimate patient out-of-pocket costs for common insurance scenarios.
347
-
348
- Args:
349
- procedure_code: HCPCS/CPT code
350
- insurance_scenario: Insurance type (Medicare, Commercial High Deductible, Commercial PPO, Cash)
351
- deductible_met: Whether annual deductible has been met
352
-
353
- Returns:
354
- Estimated patient financial responsibility
355
- """
356
- # Get base Medicare cost
357
- medicare_data = await self.cms_get_medicare_fee(procedure_code)
358
- base_cost = medicare_data.get("medicare_payment", 200)
359
-
360
- # Define insurance scenarios
361
- scenarios = {
362
- "Medicare": {
363
- "coinsurance": 0.20,
364
- "copay": 0,
365
- "description": "Medicare Part B (20% coinsurance after deductible)",
366
- "deductible": 240 # 2024 Part B deductible
367
- },
368
- "Commercial PPO": {
369
- "coinsurance": 0.20,
370
- "copay": 0,
371
- "description": "Commercial PPO (20% coinsurance after deductible)",
372
- "deductible": 2000,
373
- "multiplier": 2.5 # Commercial pays ~2.5x Medicare
374
- },
375
- "Commercial High Deductible": {
376
- "coinsurance": 0.30,
377
- "copay": 0,
378
- "description": "High Deductible Health Plan (30% coinsurance)",
379
- "deductible": 5000,
380
- "multiplier": 2.5
381
- },
382
- "Cash": {
383
- "coinsurance": 0,
384
- "copay": 0,
385
- "description": "Cash/Self-pay (negotiated rate)",
386
- "deductible": 0,
387
- "multiplier": 1.8 # Cash discount from commercial
388
- }
389
- }
390
-
391
- scenario = scenarios.get(insurance_scenario, scenarios["Medicare"])
392
-
393
- # Calculate costs
394
- allowed_amount = base_cost * scenario.get("multiplier", 1.0)
395
-
396
- if deductible_met:
397
- patient_responsibility = allowed_amount * scenario["coinsurance"] + scenario["copay"]
398
- else:
399
- # Patient pays deductible first, then coinsurance on remainder
400
- if allowed_amount <= scenario["deductible"]:
401
- patient_responsibility = allowed_amount
402
- else:
403
- remaining = allowed_amount - scenario["deductible"]
404
- patient_responsibility = scenario["deductible"] + (remaining * scenario["coinsurance"])
405
-
406
- return {
407
- "procedure_code": procedure_code,
408
- "procedure_description": medicare_data.get("description", "Unknown procedure"),
409
- "insurance_scenario": insurance_scenario,
410
- "deductible_met": deductible_met,
411
- "cost_breakdown": {
412
- "allowed_amount": round(allowed_amount, 2),
413
- "deductible": scenario["deductible"],
414
- "coinsurance_rate": f"{int(scenario['coinsurance'] * 100)}%",
415
- "estimated_patient_responsibility": round(patient_responsibility, 2),
416
- "insurance_pays": round(allowed_amount - patient_responsibility, 2)
417
- },
418
- "scenario_details": scenario["description"],
419
- "note": "Estimates only. Actual costs depend on specific plan benefits and negotiated rates."
420
- }
 
1
+ """CMS Pricing Provider for Medicare fee schedules and cost transparency."""
2
+
3
+ import logging
4
+ from typing import List, Dict, Any, Callable
5
+ import httpx
6
+
7
+ from core.base_provider import BaseProvider
8
+ from core.decorators import safe_json_return
9
+ from providers import register_provider
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ # Sample Medicare fee schedule data
14
+ MEDICARE_FEE_SCHEDULE = {
15
+ "99213": {
16
+ "description": "Office visit, established patient, level 3",
17
+ "medicare_payment": 93.47,
18
+ "facility_rate": 93.47,
19
+ "non_facility_rate": 131.20,
20
+ "rvu": 1.92
21
+ },
22
+ "99214": {
23
+ "description": "Office visit, established patient, level 4",
24
+ "medicare_payment": 131.20,
25
+ "facility_rate": 131.20,
26
+ "non_facility_rate": 183.19,
27
+ "rvu": 2.80
28
+ },
29
+ "43239": {
30
+ "description": "Upper GI endoscopy with biopsy",
31
+ "medicare_payment": 248.54,
32
+ "facility_rate": 248.54,
33
+ "non_facility_rate": 450.00,
34
+ "rvu": 5.28
35
+ },
36
+ "45378": {
37
+ "description": "Colonoscopy, diagnostic",
38
+ "medicare_payment": 365.00,
39
+ "facility_rate": 365.00,
40
+ "non_facility_rate": 650.00,
41
+ "rvu": 7.75
42
+ },
43
+ "70450": {
44
+ "description": "CT scan, head without contrast",
45
+ "medicare_payment": 178.00,
46
+ "facility_rate": 178.00,
47
+ "non_facility_rate": 320.00,
48
+ "rvu": 3.78
49
+ },
50
+ "70553": {
51
+ "description": "MRI brain with contrast",
52
+ "medicare_payment": 485.00,
53
+ "facility_rate": 485.00,
54
+ "non_facility_rate": 875.00,
55
+ "rvu": 10.30
56
+ },
57
+ "80053": {
58
+ "description": "Comprehensive metabolic panel",
59
+ "medicare_payment": 14.00,
60
+ "facility_rate": 14.00,
61
+ "non_facility_rate": 18.00,
62
+ "rvu": 0.30
63
+ },
64
+ "85025": {
65
+ "description": "Complete blood count with differential",
66
+ "medicare_payment": 11.00,
67
+ "facility_rate": 11.00,
68
+ "non_facility_rate": 14.00,
69
+ "rvu": 0.23
70
+ },
71
+ "71046": {
72
+ "description": "Chest X-ray, 2 views",
73
+ "medicare_payment": 38.00,
74
+ "facility_rate": 38.00,
75
+ "non_facility_rate": 62.00,
76
+ "rvu": 0.81
77
+ }
78
+ }
79
+
80
+ # Sample procedure cost estimates
81
+ PROCEDURE_COST_ESTIMATES = {
82
+ "colonoscopy": {
83
+ "procedure": "Diagnostic Colonoscopy",
84
+ "hcpcs_code": "45378",
85
+ "average_cost": 2750,
86
+ "low_estimate": 1500,
87
+ "high_estimate": 4500,
88
+ "medicare_rate": 365,
89
+ "factors": ["Facility type", "Anesthesia", "Biopsy performed", "Location"]
90
+ },
91
+ "mri": {
92
+ "procedure": "MRI Scan",
93
+ "hcpcs_code": "70553",
94
+ "average_cost": 1420,
95
+ "low_estimate": 400,
96
+ "high_estimate": 3500,
97
+ "medicare_rate": 485,
98
+ "factors": ["Body part", "With/without contrast", "Facility type"]
99
+ },
100
+ "ct scan": {
101
+ "procedure": "CT Scan",
102
+ "hcpcs_code": "70450",
103
+ "average_cost": 820,
104
+ "low_estimate": 300,
105
+ "high_estimate": 1800,
106
+ "medicare_rate": 178,
107
+ "factors": ["Body part", "With/without contrast", "Emergency vs scheduled"]
108
+ },
109
+ "blood test": {
110
+ "procedure": "Comprehensive Metabolic Panel",
111
+ "hcpcs_code": "80053",
112
+ "average_cost": 45,
113
+ "low_estimate": 15,
114
+ "high_estimate": 120,
115
+ "medicare_rate": 14,
116
+ "factors": ["Lab facility", "Stat vs routine", "Insurance negotiated rate"]
117
+ },
118
+ "x-ray": {
119
+ "procedure": "Chest X-Ray",
120
+ "hcpcs_code": "71046",
121
+ "average_cost": 125,
122
+ "low_estimate": 50,
123
+ "high_estimate": 300,
124
+ "medicare_rate": 38,
125
+ "factors": ["Number of views", "Facility type", "Interpretation included"]
126
+ },
127
+ "office visit": {
128
+ "procedure": "Office Visit - Established Patient",
129
+ "hcpcs_code": "99213",
130
+ "average_cost": 150,
131
+ "low_estimate": 100,
132
+ "high_estimate": 300,
133
+ "medicare_rate": 93,
134
+ "factors": ["Complexity level", "Time spent", "Geographic location"]
135
+ }
136
+ }
137
+
138
+ # Sample facility comparison data
139
+ FACILITY_COSTS = {
140
+ "45378": [ # Colonoscopy
141
+ {"facility": "University Hospital", "gross_charge": 4500, "negotiated_rate": 2800, "cash_price": 2500},
142
+ {"facility": "Community Medical Center", "gross_charge": 3200, "negotiated_rate": 2100, "cash_price": 1800},
143
+ {"facility": "Ambulatory Surgery Center", "gross_charge": 2800, "negotiated_rate": 1600, "cash_price": 1500},
144
+ ],
145
+ "70450": [ # CT Scan
146
+ {"facility": "University Hospital", "gross_charge": 1800, "negotiated_rate": 820, "cash_price": 600},
147
+ {"facility": "Community Medical Center", "gross_charge": 1200, "negotiated_rate": 650, "cash_price": 500},
148
+ {"facility": "Imaging Center", "gross_charge": 900, "negotiated_rate": 450, "cash_price": 400},
149
+ ],
150
+ "70553": [ # MRI
151
+ {"facility": "University Hospital", "gross_charge": 3500, "negotiated_rate": 1800, "cash_price": 1500},
152
+ {"facility": "Community Medical Center", "gross_charge": 2800, "negotiated_rate": 1400, "cash_price": 1200},
153
+ {"facility": "Imaging Center", "gross_charge": 2200, "negotiated_rate": 1000, "cash_price": 900},
154
+ ]
155
+ }
156
+
157
+ # Procedure code database
158
+ PROCEDURE_CODES = [
159
+ {"code": "99213", "description": "Office visit, established patient, level 3", "category": "Evaluation & Management"},
160
+ {"code": "99214", "description": "Office visit, established patient, level 4", "category": "Evaluation & Management"},
161
+ {"code": "99215", "description": "Office visit, established patient, level 5", "category": "Evaluation & Management"},
162
+ {"code": "99203", "description": "Office visit, new patient, level 3", "category": "Evaluation & Management"},
163
+ {"code": "45378", "description": "Colonoscopy, diagnostic", "category": "Gastroenterology"},
164
+ {"code": "43239", "description": "Upper GI endoscopy with biopsy", "category": "Gastroenterology"},
165
+ {"code": "70450", "description": "CT scan, head without contrast", "category": "Radiology"},
166
+ {"code": "70553", "description": "MRI brain with contrast", "category": "Radiology"},
167
+ {"code": "71046", "description": "Chest X-ray, 2 views", "category": "Radiology"},
168
+ {"code": "80053", "description": "Comprehensive metabolic panel", "category": "Laboratory"},
169
+ {"code": "85025", "description": "Complete blood count with differential", "category": "Laboratory"},
170
+ {"code": "82947", "description": "Glucose blood test", "category": "Laboratory"},
171
+ {"code": "83036", "description": "Hemoglobin A1C", "category": "Laboratory"},
172
+ ]
173
+
174
+
175
+ @register_provider("cms_pricing")
176
+ class CMSPricingProvider(BaseProvider):
177
+ """Provider for Medicare pricing and cost transparency data."""
178
+
179
+ def __init__(self, client: httpx.AsyncClient):
180
+ super().__init__("cms_pricing", client)
181
+
182
+ async def initialize(self) -> None:
183
+ """Initialize CMS pricing provider."""
184
+ logger.info("CMS Pricing provider initialized")
185
+
186
+ def get_tools(self) -> List[Callable]:
187
+ """Return all CMS pricing tools."""
188
+ return [
189
+ self.cms_get_medicare_fee,
190
+ self.cms_estimate_procedure_cost,
191
+ self.cms_search_procedure_codes,
192
+ self.cms_compare_facility_costs,
193
+ self.cms_estimate_out_of_pocket,
194
+ ]
195
+
196
+ @safe_json_return
197
+ async def cms_get_medicare_fee(
198
+ self,
199
+ hcpcs_code: str,
200
+ locality: str = "National"
201
+ ) -> Dict[str, Any]:
202
+ """
203
+ Get Medicare fee schedule pricing for a procedure by HCPCS/CPT code.
204
+
205
+ Args:
206
+ hcpcs_code: HCPCS procedure code (e.g., "99213", "43239")
207
+ locality: Geographic locality (default: "National")
208
+
209
+ Returns:
210
+ Medicare reimbursement rates with facility vs non-facility pricing
211
+ """
212
+ result = MEDICARE_FEE_SCHEDULE.get(hcpcs_code, {
213
+ "description": f"Procedure {hcpcs_code}",
214
+ "medicare_payment": 150.00,
215
+ "facility_rate": 150.00,
216
+ "non_facility_rate": 200.00,
217
+ "rvu": 3.0,
218
+ "note": "Sample data - actual rates vary by locality and year"
219
+ })
220
+
221
+ result["hcpcs_code"] = hcpcs_code
222
+ result["locality"] = locality
223
+ result["year"] = 2024
224
+
225
+ return result
226
+
227
+ @safe_json_return
228
+ async def cms_estimate_procedure_cost(
229
+ self,
230
+ procedure_name: str,
231
+ region: str = "National",
232
+ insurance_type: str = "Medicare"
233
+ ) -> Dict[str, Any]:
234
+ """
235
+ Estimate typical cost range for a procedure in a geographic region.
236
+
237
+ Args:
238
+ procedure_name: Common procedure name (e.g., "colonoscopy", "MRI", "blood test")
239
+ region: Geographic region (default: "National")
240
+ insurance_type: Type of insurance (Medicare, Commercial, Cash)
241
+
242
+ Returns:
243
+ Estimated cost range with average, low, and high estimates
244
+ """
245
+ procedure_key = procedure_name.lower()
246
+ result = PROCEDURE_COST_ESTIMATES.get(procedure_key, {
247
+ "procedure": procedure_name.title(),
248
+ "hcpcs_code": "Unknown",
249
+ "average_cost": 500,
250
+ "low_estimate": 200,
251
+ "high_estimate": 1000,
252
+ "medicare_rate": 150,
253
+ "factors": ["Procedure complexity", "Facility type", "Geographic location"]
254
+ })
255
+
256
+ result["region"] = region
257
+ result["insurance_type"] = insurance_type
258
+ result["note"] = "Estimates based on national averages. Actual costs vary significantly by provider and location."
259
+
260
+ # Adjust for insurance type
261
+ if insurance_type.lower() == "commercial":
262
+ result["estimated_patient_cost"] = result["average_cost"]
263
+ elif insurance_type.lower() == "medicare":
264
+ result["estimated_patient_cost"] = result["medicare_rate"] * 1.2 # 20% coinsurance
265
+ elif insurance_type.lower() == "cash":
266
+ result["estimated_patient_cost"] = result["average_cost"] * 0.7 # Cash discount
267
+
268
+ return result
269
+
270
+ @safe_json_return
271
+ async def cms_search_procedure_codes(
272
+ self,
273
+ query: str,
274
+ limit: int = 10
275
+ ) -> Dict[str, Any]:
276
+ """
277
+ Search for HCPCS/CPT codes by procedure description or category.
278
+
279
+ Args:
280
+ query: Search term (e.g., "office visit", "colonoscopy")
281
+ limit: Maximum number of results (default: 10)
282
+
283
+ Returns:
284
+ List of matching procedures with codes, descriptions, and categories
285
+ """
286
+ query_lower = query.lower()
287
+ matches = [
288
+ p for p in PROCEDURE_CODES
289
+ if query_lower in p["description"].lower() or query_lower in p["category"].lower()
290
+ ]
291
+
292
+ return {
293
+ "query": query,
294
+ "results": matches[:limit],
295
+ "total": len(matches)
296
+ }
297
+
298
+ @safe_json_return
299
+ async def cms_compare_facility_costs(
300
+ self,
301
+ procedure_code: str,
302
+ facilities: List[str] = None
303
+ ) -> Dict[str, Any]:
304
+ """
305
+ Compare procedure costs across different healthcare facilities.
306
+
307
+ Args:
308
+ procedure_code: HCPCS/CPT code
309
+ facilities: List of facility names (uses sample data if not provided)
310
+
311
+ Returns:
312
+ Cost comparison showing gross charges, negotiated rates, and cash prices
313
+ """
314
+ facilities_data = FACILITY_COSTS.get(procedure_code, [
315
+ {"facility": "Sample Facility A", "gross_charge": 2000, "negotiated_rate": 1200, "cash_price": 1000},
316
+ {"facility": "Sample Facility B", "gross_charge": 1500, "negotiated_rate": 900, "cash_price": 800},
317
+ {"facility": "Sample Facility C", "gross_charge": 1800, "negotiated_rate": 1000, "cash_price": 900},
318
+ ])
319
+
320
+ # Calculate savings
321
+ cash_prices = [f["cash_price"] for f in facilities_data]
322
+ lowest_cash = min(cash_prices)
323
+ highest_cash = max(cash_prices)
324
+ potential_savings = highest_cash - lowest_cash
325
+
326
+ return {
327
+ "procedure_code": procedure_code,
328
+ "facilities": facilities_data,
329
+ "comparison": {
330
+ "lowest_cash_price": lowest_cash,
331
+ "highest_cash_price": highest_cash,
332
+ "potential_savings": potential_savings,
333
+ "average_cash_price": sum(cash_prices) / len(cash_prices)
334
+ },
335
+ "note": "Sample data for demonstration. Actual facility prices vary. Patients should request price estimates directly."
336
+ }
337
+
338
+ @safe_json_return
339
+ async def cms_estimate_out_of_pocket(
340
+ self,
341
+ procedure_code: str,
342
+ insurance_scenario: str = "Medicare",
343
+ deductible_met: bool = False
344
+ ) -> Dict[str, Any]:
345
+ """
346
+ Estimate patient out-of-pocket costs for common insurance scenarios.
347
+
348
+ Args:
349
+ procedure_code: HCPCS/CPT code
350
+ insurance_scenario: Insurance type (Medicare, Commercial High Deductible, Commercial PPO, Cash)
351
+ deductible_met: Whether annual deductible has been met
352
+
353
+ Returns:
354
+ Estimated patient financial responsibility
355
+ """
356
+ # Get base Medicare cost
357
+ medicare_data = await self.cms_get_medicare_fee(procedure_code)
358
+ base_cost = medicare_data.get("medicare_payment", 200)
359
+
360
+ # Define insurance scenarios
361
+ scenarios = {
362
+ "Medicare": {
363
+ "coinsurance": 0.20,
364
+ "copay": 0,
365
+ "description": "Medicare Part B (20% coinsurance after deductible)",
366
+ "deductible": 240 # 2024 Part B deductible
367
+ },
368
+ "Commercial PPO": {
369
+ "coinsurance": 0.20,
370
+ "copay": 0,
371
+ "description": "Commercial PPO (20% coinsurance after deductible)",
372
+ "deductible": 2000,
373
+ "multiplier": 2.5 # Commercial pays ~2.5x Medicare
374
+ },
375
+ "Commercial High Deductible": {
376
+ "coinsurance": 0.30,
377
+ "copay": 0,
378
+ "description": "High Deductible Health Plan (30% coinsurance)",
379
+ "deductible": 5000,
380
+ "multiplier": 2.5
381
+ },
382
+ "Cash": {
383
+ "coinsurance": 0,
384
+ "copay": 0,
385
+ "description": "Cash/Self-pay (negotiated rate)",
386
+ "deductible": 0,
387
+ "multiplier": 1.8 # Cash discount from commercial
388
+ }
389
+ }
390
+
391
+ scenario = scenarios.get(insurance_scenario, scenarios["Medicare"])
392
+
393
+ # Calculate costs
394
+ allowed_amount = base_cost * scenario.get("multiplier", 1.0)
395
+
396
+ if deductible_met:
397
+ patient_responsibility = allowed_amount * scenario["coinsurance"] + scenario["copay"]
398
+ else:
399
+ # Patient pays deductible first, then coinsurance on remainder
400
+ if allowed_amount <= scenario["deductible"]:
401
+ patient_responsibility = allowed_amount
402
+ else:
403
+ remaining = allowed_amount - scenario["deductible"]
404
+ patient_responsibility = scenario["deductible"] + (remaining * scenario["coinsurance"])
405
+
406
+ return {
407
+ "procedure_code": procedure_code,
408
+ "procedure_description": medicare_data.get("description", "Unknown procedure"),
409
+ "insurance_scenario": insurance_scenario,
410
+ "deductible_met": deductible_met,
411
+ "cost_breakdown": {
412
+ "allowed_amount": round(allowed_amount, 2),
413
+ "deductible": scenario["deductible"],
414
+ "coinsurance_rate": f"{int(scenario['coinsurance'] * 100)}%",
415
+ "estimated_patient_responsibility": round(patient_responsibility, 2),
416
+ "insurance_pays": round(allowed_amount - patient_responsibility, 2)
417
+ },
418
+ "scenario_details": scenario["description"],
419
+ "note": "Estimates only. Actual costs depend on specific plan benefits and negotiated rates."
420
+ }