All benefits

Plan Facts Parsing Analysis · v1

Hospital Indemnity

Single-class parse covering hospital admission and ICU benefits, daily confinement, HSA compatibility, mental-health and pre-existing condition rules, plus four-tier composite rates.

Endpoint
POST /hospitalIndemnity
Parse method
parseQuoteHospitalIndemnity()
Source range
PlanfactService.php:1703–1921
Source pull
plansight - Bit Bucket Pull 4.26

Bottom line

Cross-write: Substance Abuse reads from Mental/Nervous source.

Lines 1830–1860: the Mental/Nervous Plan Facts field is read once and assigned to BOTH the hospitalIndemnityMentalNervousDisorders field AND hospitalIndemnityDrugAndAlchoholAbuse. If Plan Facts has a separate Substance Abuse field, it's silently dropped, and the Mental/Nervous value overwrites Substance Abuse data on the Quote. This is a real bug.

Per-class handling

Single-class. The parser reads $class = $data['Hospital Indemnity']['Classes'][0] at line 1710 and uses that one class for every subsequent lookup. No multi-class iteration.

What's mapped

Plan Facts fieldQuote fieldNotes
Plan NamenameDirect
Participation.[Class].Minimum Participation %hospitalIndemnityParticipationRequiredStrip %
Participation.[Class].Minimum Enrolled LiveshospitalIndemnityMinimumLivesNumeric
HSA Compatibility.[Class].HSA CompatibilityhospitalIndemnityHsaCompatible"true"/true → Yes (line 1742)
Wellness Benefit.[Class].EmployeehospitalIndemnityWellnessBenefitDirect
Admission Benefits.[Class].Hospital Admission Benefit AmounthospitalIndemnityHospitalAdmissionCurrency stripped
Admission Benefits.[Class].Hospital Admissions Per YearhospitalIndemnityAdmissionLimits"X per year"
Admission Benefits.[Class].ICU Admission Benefit AmounthospitalIndemnityIcuAdmissionCurrency stripped
Confinement Benefits.[Class].Daily Hospital Confinement Benefit AmounthospitalIndemnityHospitalConfinementCurrency stripped
Confinement Benefits.[Class].Daily Hospital Confinement Benefit DurationhospitalIndemnityHospitalMaxDaysDirect (e.g. "30 days")
Confinement Benefits.[Class].Daily ICU Confinement Benefit AmounthospitalIndemnityHospitalIcuConfinementCurrency stripped
Confinement Benefits.[Class].Daily ICU Confinement Benefit DurationhospitalIndemnityIcuMaxDaysDirect
Other Conditions.[Class].Pregnancy Waiting PeriodhospitalIndemnityMaternityWaitDirect
Other Conditions.[Class].Mental/NervoushospitalIndemnityMentalNervousDisordersCovered / Not Covered (line 1830)
Other Conditions.[Class].Mental/NervoushospitalIndemnityDrugAndAlchoholAbuseReads same source as above — should be Substance Abuse field (line 1847)
Pre-existing Conditions.[Class].Look-back PeriodhospitalIndemnityPreExistingConditionsLookbackDirect
Pre-existing Conditions.[Class].Exclusion PeriodhospitalIndemnityPreExistingConditionsExclusionDirect
Portability.[Class].PortabilityhospitalIndemnityPortabilityIncluded / Not Included
Rates.[Class].Employee Only / + Spouse / + Children / FamilyhospitalIndemnityEE, …ES, …EC, …EFCurrency stripped (line 1899)

Plan-level / not mapped

Potentially mapped incorrectly

Substance Abuse cross-writes from Mental/Nervous source PlanfactService.php:1847–1860

Lines 1830–1843 correctly read 'Other Conditions.' . $class . '.Mental/Nervous' and write to hospitalIndemnityMentalNervousDisorders. Lines 1847–1860 read the same source path again and write to hospitalIndemnityDrugAndAlchoholAbuse. If Plan Facts returns a separate Substance Abuse field, it's silently dropped; the Mental/Nervous value gets used in its place.

Cursor prompt
In app/Services/PlanfactService.php at lines 1847–1860, inside parseQuoteHospitalIndemnity(), the assignment for hospitalIndemnityDrugAndAlchoholAbuse reads from the same Plan Facts path as Mental/Nervous:
'Other Conditions.' . $class . '.Mental/Nervous'

This is almost certainly wrong. It should read from a separate Substance Abuse field — likely something like:
'Other Conditions.' . $class . '.Substance Abuse'
or:
'Other Conditions.' . $class . '.Substance Abuse and Mental Health'

Please:
1. Show me lines 1830–1860 — the Mental/Nervous and Substance Abuse blocks.
2. Look at sample Plan Facts response data (or the schema docs if available) to identify the correct Substance Abuse path key.
3. Fix the source path on lines 1847–1860 to use the correct key.
4. Then grep the rest of PlanfactService.php for any other places where the same source path appears in two consecutive blocks — there may be similar copy-paste errors. Report any you find.

Note the field name typo: "DrugAndAlchohol" should probably be "DrugAndAlcohol" — but DO NOT rename the field unless that's a separate ask, since it would touch the Quote model and form templates.
Rate keys assumed to be in fixed order PlanfactService.php:1899–1918

The rate parsing maps coverage tiers by position in the array (Employee Only → EE, +Spouse → ES, +Children → EC, Family → EF). If Plan Facts ever returns these keys in a different order, the alignment breaks silently. Worth confirming whether order is guaranteed.

Cursor prompt
In app/Services/PlanfactService.php at lines 1899–1918, inside parseQuoteHospitalIndemnity(), the rate parsing iterates the Rates array in order and maps positions to coverage tiers (EE, ES, EC, EF).

If Plan Facts ever returns the rate tiers in a different order (or with different/extra keys), the mapping silently misaligns.

Please:
1. Show me the current iteration logic.
2. Refactor it to look up rates by explicit coverage tier name ("Employee Only", "Employee plus Spouse", "Employee plus Children", "Family") rather than by array position.
3. If a known coverage tier is missing from the response, leave the corresponding Quote field empty rather than substituting a wrong value.
4. Show me the proposed change.

Manual-entry-only fields

Recommendations

  1. Fix the Substance Abuse cross-write 15 minutes

    Change line 1847's source path from Mental/Nervous to the correct Substance Abuse key.

  2. Make rate-tier lookup explicit by name Hour

    Replace position-based iteration with explicit name-based lookup so out-of-order responses don't silently misalign.

  3. Document HSA boolean parsing 5 minutes

    Line 1742–1747 accepts "true", true, "false". Add a comment listing the accepted values, or normalize at one entry point.

Code references

FileLinesPurpose
app/Services/PlanfactService.php259Hospital Indemnity endpoint config
app/Services/PlanfactService.php461Dispatch to parseQuoteHospitalIndemnity
app/Services/PlanfactService.php1703–1921Full parser
app/Services/PlanfactService.php1710Single-class selection
app/Services/PlanfactService.php1847–1860Substance Abuse cross-write
app/Services/PlanfactService.php1899–1918Rate position-based lookup