add human estimation conditions
This commit is contained in:
parent
735ccb757c
commit
c8e6474edd
3 changed files with 103 additions and 57 deletions
|
|
@ -55,47 +55,48 @@ BASE_TIERS = {
|
|||
}
|
||||
|
||||
HEIGHT_WEIGHT_TABLE = {
|
||||
(4, 2): (60, 124),
|
||||
(4, 3): (63, 129),
|
||||
(4, 4): (65, 135),
|
||||
(4, 5): (68, 140),
|
||||
(4, 6): (71, 145),
|
||||
(4, 7): (73, 151),
|
||||
(4, 8): (76, 156),
|
||||
(4, 9): (79, 162),
|
||||
(4, 10): (81, 167),
|
||||
(4, 11): (84, 173),
|
||||
(5, 0): (87, 179),
|
||||
(5, 1): (90, 185),
|
||||
(5, 2): (93, 191),
|
||||
(5, 3): (96, 197),
|
||||
(5, 4): (99, 204),
|
||||
(5, 5): (102, 210),
|
||||
(5, 6): (105, 217),
|
||||
(5, 7): (109, 223),
|
||||
(5, 8): (112, 230),
|
||||
(5, 9): (115, 237),
|
||||
(5, 10): (118, 244),
|
||||
(5, 11): (122, 251),
|
||||
(6, 0): (125, 258),
|
||||
(6, 1): (129, 265),
|
||||
(6, 2): (132, 273),
|
||||
(6, 3): (136, 280),
|
||||
(6, 4): (140, 288),
|
||||
(6, 5): (143, 295),
|
||||
(6, 6): (147, 303),
|
||||
(6, 7): (151, 311),
|
||||
(6, 8): (155, 319),
|
||||
(6, 9): (159, 327),
|
||||
(6, 10): (163, 335),
|
||||
(6, 11): (167, 343),
|
||||
(7, 0): (171, 351),
|
||||
(7, 1): (175, 360),
|
||||
(7, 2): (179, 368),
|
||||
(7, 3): (183, 377),
|
||||
(7, 4): (187, 386),
|
||||
(4, 2): (54, 60, 125, 151),
|
||||
(4, 3): (56, 63, 130, 156),
|
||||
(4, 4): (59, 65, 136, 162),
|
||||
(4, 5): (60, 68, 141, 169),
|
||||
(4, 6): (63, 71, 146, 175),
|
||||
(4, 7): (65, 73, 152, 182),
|
||||
(4, 8): (67, 76, 157, 188),
|
||||
(4, 9): (70, 79, 163, 195),
|
||||
(4, 10): (72, 81, 168, 202),
|
||||
(4, 11): (75, 84, 174, 209),
|
||||
(5, 0): (77, 87, 180, 216),
|
||||
(5, 1): (80, 90, 186, 223),
|
||||
(5, 2): (83, 93, 192, 230),
|
||||
(5, 3): (85, 96, 199, 238),
|
||||
(5, 4): (88, 99, 205, 245),
|
||||
(5, 5): (91, 102, 211, 253),
|
||||
(5, 6): (93, 105, 218, 261),
|
||||
(5, 7): (96, 109, 224, 269),
|
||||
(5, 8): (99, 112, 231, 277),
|
||||
(5, 9): (102, 115, 238, 285),
|
||||
(5, 10): (105, 118, 245, 293),
|
||||
(5, 11): (108, 122, 252, 302),
|
||||
(6, 0): (111, 125, 259, 310),
|
||||
(6, 1): (114, 129, 266, 319),
|
||||
(6, 2): (117, 132, 274, 327),
|
||||
(6, 3): (121, 136, 281, 336),
|
||||
(6, 4): (124, 140, 289, 345),
|
||||
(6, 5): (127, 143, 296, 354),
|
||||
(6, 6): (130, 147, 304, 364),
|
||||
(6, 7): (134, 151, 312, 374),
|
||||
(6, 8): (137, 155, 320, 383),
|
||||
(6, 9): (140, 159, 328, 393),
|
||||
(6, 10): (144, 163, 336, 403),
|
||||
(6, 11): (147, 167, 344, 413),
|
||||
(7, 0): (151, 171, 352, 423),
|
||||
(7, 1): (155, 175, 361, 433),
|
||||
(7, 2): (158, 179, 369, 443),
|
||||
(7, 3): (162, 183, 378, 453),
|
||||
(7, 4): (166, 187, 387, 464),
|
||||
}
|
||||
|
||||
|
||||
UNINSURABLE_MEDICATIONS = [
|
||||
"abacavir",
|
||||
"abarelix",
|
||||
|
|
@ -348,17 +349,23 @@ class EstimationService:
|
|||
today = date.today()
|
||||
return today.year - born.year - ((today.month, today.day) < (born.month, born.day))
|
||||
|
||||
async def calculate_rx_spend(self, phq: PHQ, applicant_id: int) -> float:
|
||||
async def calculate_rx_spend(self, phq: PHQ, applicant_id: int) -> (float, list[str]):
|
||||
rx_spend = 0
|
||||
review_reasons = []
|
||||
for medication in phq.medications:
|
||||
if medication.applicant != applicant_id:
|
||||
continue
|
||||
try:
|
||||
drug_name = medication.name.lower()
|
||||
drug_url = search_drug(drug_name)
|
||||
if not drug_url:
|
||||
review_reasons.append(f"Drug not found: {drug_name}")
|
||||
continue
|
||||
drug_dosage = float(medication.dosage)
|
||||
print(f"{drug_name} | {drug_url} | {drug_dosage}")
|
||||
drug_price = await fetch_drug_with_dosage(drug_url, drug_dosage)
|
||||
if not drug_price:
|
||||
review_reasons.append(f"Dosage {drug_dosage} for drug {drug_name} not found")
|
||||
continue
|
||||
|
||||
if medication.frequency in ["Once daily", "At bedtime"]:
|
||||
month_times = 30
|
||||
|
|
@ -375,13 +382,14 @@ class EstimationService:
|
|||
elif medication.frequency == "Every other day":
|
||||
month_times = 15
|
||||
else:
|
||||
review_reasons.append(f"Unclear frequency of drug {medication.name}: {medication.frequency}")
|
||||
month_times = 1
|
||||
|
||||
rx_spend += drug_price.unit_price * month_times
|
||||
except Exception as e:
|
||||
print(f"Error calculating rx spend for {medication.name}: {e}")
|
||||
pass
|
||||
return rx_spend
|
||||
return rx_spend, review_reasons
|
||||
|
||||
def get_tier(self, coverage: int, rx_spend: float) -> Optional[Tier]:
|
||||
tiers = [
|
||||
|
|
@ -431,9 +439,16 @@ class EstimationService:
|
|||
|
||||
async def estimate_insurance(self, applicants: list[Applicant], phq: PHQ, plans: list[Plan]):
|
||||
estimation_results = []
|
||||
is_review = False
|
||||
review_reasons = []
|
||||
dtq_reasons = []
|
||||
accept_reasons = []
|
||||
|
||||
is_dtq, reason = self.check_dtq(phq)
|
||||
if not is_dtq:
|
||||
is_dtq, reason = await self.check_dtq_ai(phq)
|
||||
if reason:
|
||||
dtq_reasons.append(reason)
|
||||
|
||||
max_age = max(self.calculate_age(applicant.dob) for applicant in applicants)
|
||||
for base_age, tier in BASE_TIERS.items():
|
||||
|
|
@ -453,27 +468,42 @@ class EstimationService:
|
|||
if applicant_age >= 65:
|
||||
is_dtq = True
|
||||
reason = "Age is over 65"
|
||||
dtq_reasons.append(reason)
|
||||
|
||||
if (applicant.heightFt, applicant.heightIn) in HEIGHT_WEIGHT_TABLE:
|
||||
weight_min, weight_max = HEIGHT_WEIGHT_TABLE[(applicant.heightFt, applicant.heightIn)]
|
||||
if applicant.weight < weight_min:
|
||||
w1, w2, w3, w4 = HEIGHT_WEIGHT_TABLE[(applicant.heightFt, applicant.heightIn)]
|
||||
if applicant.weight < w1:
|
||||
is_dtq = True
|
||||
reason = "Declined due to low BMI of one or more applicants"
|
||||
elif applicant.weight > weight_max:
|
||||
dtq_reasons.append(reason)
|
||||
elif w1 <= applicant.weight < w2:
|
||||
is_review = True
|
||||
review_reasons.append("low BMI of one or more applicants")
|
||||
elif w3 <= applicant.weight < w4:
|
||||
is_review = True
|
||||
review_reasons.append("high BMI of one or more applicants")
|
||||
elif applicant.weight >= w4:
|
||||
is_dtq = True
|
||||
reason = "Declined due to high BMI of one or more applicants"
|
||||
|
||||
rx_spend_applicant = await self.calculate_rx_spend(phq, applicant_id)
|
||||
dtq_reasons.append(reason)
|
||||
|
||||
rx_spend_applicant, rx_review_reasons = await self.calculate_rx_spend(phq, applicant_id)
|
||||
if rx_review_reasons:
|
||||
is_review = True
|
||||
review_reasons += rx_review_reasons
|
||||
|
||||
rx_spend += rx_spend_applicant
|
||||
|
||||
applicant_new_tier = self.get_tier(plan_coverage, rx_spend_applicant)
|
||||
if applicant_new_tier is None:
|
||||
is_dtq = True
|
||||
reason = "Declined due to high Rx spend"
|
||||
dtq_reasons.append(reason)
|
||||
|
||||
if applicant_new_tier and applicant_new_tier > applicant_tier:
|
||||
applicant_tier = applicant_new_tier
|
||||
reason = f"Rx spend increased tier to {applicant_new_tier}."
|
||||
accept_reasons.append(reason)
|
||||
|
||||
estimation_results.append(
|
||||
EstimationResult(
|
||||
|
|
@ -490,6 +520,7 @@ class EstimationService:
|
|||
plan_price_id = self.get_plan_price(plans[0], base_tier, plan_coverage)
|
||||
|
||||
if is_dtq:
|
||||
reason = "\n".join(dtq_reasons)
|
||||
return EstimationResponse(
|
||||
status="rejected",
|
||||
details=EstimationDetails(
|
||||
|
|
@ -499,6 +530,18 @@ class EstimationService:
|
|||
),
|
||||
results=estimation_results
|
||||
)
|
||||
|
||||
if is_review:
|
||||
reason = "\n".join(review_reasons)
|
||||
return EstimationResponse(
|
||||
status="human_review",
|
||||
details=EstimationDetails(
|
||||
dtq=is_dtq,
|
||||
reason=reason,
|
||||
price_id=plan_price_id,
|
||||
),
|
||||
results=estimation_results
|
||||
)
|
||||
|
||||
new_tier = self.get_tier(plan_coverage, rx_spend)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue