COBRA Administration
Source libraries: cobra (windows, admin DataWindows), cobradw (letter/notice
DataWindows and letter functions), cobrarpt (reports). 13 windows, 89 DataWindows.
Screen-by-screen detail is in the Screen catalog.
Purpose
Administers continuation-of-coverage (COBRA) for members of self-funded plans: it
captures qualifying events against a member's eligibility record, determines who is
entitled to an election letter and who the qualified beneficiaries (QBs) are,
generates and prints the statutory letter set (first notice, election letter and
form, conversion, unavailability, early-termination, etc.), records election
responses, maintains group-specific COBRA premium rates, receives premium check
payments, and terminates member eligibility when COBRA coverage ends
(cobra/w_cobra_administration, cobra/w_cobra_printqueue,
cobra/w_cobra_rate_maint, cobra/w_cobra_receive_premium).
Letter content is rendered by a separate "COBRA background process" that writes
the finished letter blobs into cobra_letter_data; the windows in these libraries
queue letter requests and print the finished blobs (comments in
cobra/n_cst_cobra_notification_gen, cobra/w_cobra_printqueue — "the actual
letter is generated in the COBRA background process").
The user guide confirms this split: the background process is a server-side application that continuously checks whether any letters need to be created or any terminations need to be performed; at guide time it created election, termination and notification letters (User Guide ch. 3).
Actors
Grounded in the system frame menu (homersys/m_sys_frame, m_cobra submenu:
COBRA Administration, Receive Premium, COBRA Reports, Delete COBRA, Letter Error
Maintenance, Letter Print Queue, COBRA Rates, Mailing Labels, Request
Notification/Conversion/Unavailability Letter):
- COBRA administrator — works events, creates letters, records responses,
terminates coverage (
cobra/w_cobra_administration). - Premium clerk — logs received premium checks (
cobra/w_cobra_receive_premium). - Print/mailroom operator — prints letter batches and certificates of mailing
(
cobra/w_cobra_printqueue,cobrarpt/w_cobra_printlabel_select). - Rate/billing maintainer — maintains group COBRA rates
(
cobra/w_cobra_rate_select,cobra/w_cobra_rate_maint). - Enrollment staff — fix relationship-code data that blocks letter generation;
auto-termination hands off to the enrollment screen
(
cobra/w_cobra_administrationpfc_save opensw_enrollment_maintenance). - The COBRA background process (external) — renders letter blobs into
cobra_letter_dataand logs failures tocobra_errors(cobra/w_cobra_printqueue,cobra/w_cobra_letter_errors); a server-side application that runs continuously, creates election/termination/notification letters, and performs deadline-driven terminations — see CBR-60..CBR-63 (User Guide ch. 3).
Key workflows
Evidenced end-to-end flow (each edge cited below):
- A→B: the qualifying-event code shown on the event header is
member_eligibilities.dep_exp_cd(cobra/d_cobra_event,cobra/w_cobra_administrationue_create_letters); event selection lists events with status(PENDING)/INCOMPLETE(cobra/d_cobra_event_select). - C→D: entering a QE date flips status from INCOMPLETE to (PENDING) and fires
ue_create_letters(cobra/w_cobra_administrationdw_header.itemchanged). - D: recipients/QBs and 18/36-month maximums per QE code
(
cobra/w_cobra_administrationwf_create_letters). - E→F: print queue reads blobs from
cobra_letter_datakeyed byletter_sys_key(cobra/w_cobra_printqueuepfc_print). - F→G: on print,
UPDATE cobra_letters SET sent_dt=…, print_flg='Y', response_cd='Pending', deadline_dt = greatest(sent+60, coverage_end+60)(cobra/w_cobra_printqueuepfc_print, ELECTION case). - H→I/J: response-code side effects (
cobra/w_cobra_administrationdw_detail4.itemchanged). - K:
cobra/w_cobra_receive_premiuminsertscobra_stub. - L→M: expiration-date edits trigger the auto-terminate prompt and
member_eligibilitiesupdate (cobra/w_cobra_administrationpfc_save,cobra/w_cobra_autoterm_response); audits reported fromcobra_terms(cobrarpt/d_cobra_termed_members_rpt).
Documented procedure: adding a dependent after the qualifying event
(User Guide ch. 3 — operational practice, not enforced by code.) When a dependent must be added to a subscriber's COBRA coverage after the qualifying event (e.g. a child born just before normal coverage ends):
- No claims processed under COBRA yet: print both screens for reference; delete the COBRA record; in enrollment, blank the subscriber eligibility expiration date, add the dependent on the Dependents tab and under each coverage election, then restore the expiration date and termination reason — restoring the reason regenerates the COBRA record automatically; finally re-enter the QE Notify and QE dates in COBRA Administration to regenerate the letter requests.
- Claims already processed (MIS-assisted): add the dependent in enrollment,
then manually insert a
cobra_qbrow (via TOAD) carrying the new dependent'smember_sys_keyasqb_member_sys_keyand the electing spouse's key aselect_member_sys_key; back in COBRA Administration the dependent appears under Qualified Beneficiaries On Letter — checking Coverage Elected with coverage levelSingleautomatically creates their own subscriber record in enrollment.
Business rules
Every statement below is testable and cited to the object that implements it.
Event capture and status
- CBR-1 A COBRA event is uniquely identified by subscriber key, dependent key,
and the effective date of the eligibility period in which the qualifying event
occurred (
qe_elig_eff_dt); the event header joinscobra_eventtomember_eligibilitieson exactly those columns (cobra/d_cobra_event). - CBR-2 Event status codes come from code table key
COBRSTAT(cobra/dddw_cobra_status,cobra/d_event_cd_select). Values used by code:(PENDING),ACTIVE,INACTIVE,INCOMPLETE(cobra/d_cobra_event_selectretrieval SQL;cobrarpt/d_cobra_term_rpt;cobrarpt/d_cobrarpt_arra). The user guide documents two further selectable statuses —ERNOCOBRA(employer has opted for no COBRA on this individual) andVOID(record marked as bad) — and glosses the others:(PENDING)= waiting for a response,ACTIVE= currently under COBRA,INACTIVE= terminated or old record,INCOMPLETE= missing necessary information such as the QE date (User Guide ch. 3). - CBR-3 If the QE date is cleared/blank the event status is set to
INCOMPLETE; when a QE date is entered the status is set to (PENDING) and
letter generation is triggered immediately
(
cobra/w_cobra_administrationdw_header.itemchanged). - CBR-4 The qualifying-event code is the eligibility record's dependent
expiration code (
member_eligibilities.dep_exp_cd), maintained in enrollment from code table keyMBREXP(cobra/w_cobra_administrationue_create_letters;enroll/dddw_enroll_eligibility_exp_codes). - CBR-5 Only one event header row may exist per event; adding a header row is
blocked when one already exists (
cobra/w_cobra_administrationdw_header.ue_preaddrow). Deletes are disabled on the header (dw_header.constructor,ib_Delete = FALSE). - CBR-6 The event-work queue lists all
(PENDING)/INCOMPLETEevents, plus events of any other status that already have election persons and QBs (cobra/d_cobra_event_select); users may filter by SSN, Member ID, Group ID and one or more status codes, and at least one status code must be selected (cobra/w_cobra_event_selectpfc_finddlg). - CBR-58 COBRA event/QB records are created automatically by the system
when the termination reason entered in enrollment amounts to a qualifying
event; users take no other action. Criteria by member class: subscribers —
every termination reason except Divorce, Family Separation and
Re-Enrollment; spouses — Family Separation, Subscriber Deceased and Divorce
only; other dependents — Loss of Student Status, Loss of Dependent Status,
Dependent Disabled and Medicare only (User Guide ch. 3). No
INSERT INTO cobra_eventexists in the PB source, so this automation is server-side (see open question 1, resolved).
Letter-recipient and qualified-beneficiary derivation
-
CBR-7 Recipient candidates are the family members holding coverage under a COBRA-eligible benefit (
coverages.cobra_elig_flg = 'Y') whose eligibility ends with the event period, with their currentRELATIONScategory value (subscriber rows are forced toSub; missing values becomeUnknown) (cobra/w_cobra_administrationwf_create_letterscursorcur_deps). -
CBR-8 Relationship values
Common LawandEx-Spouseare treated asSpouse(cobra/w_cobra_administrationwf_create_letters). -
CBR-9 Letter generation is blocked with an "Enrollment must fix" message when the family has more than one
Subrelationship or anyUnknownrelationship (cobra/w_cobra_administrationwf_create_letters). -
CBR-10 Recipients and QBs per qualifying-event code (
cobra/w_cobra_administrationwf_create_lettersCHOOSE CASE):QE codes Election letter to QBs on letter Maximum period Divorce,FamilySepSpouse only Spouse and Step Child only 36 months SubDecease,SubMedicarSpouse; each other dependent only if its address number differs from the spouse's Spouse letter: all non-Sub family; separate-address dependent letter: that dependent 36 months TermEmp,ReduceHrs,Layoff,Retired,SubDisable,LeaveMed,LeaveFam,LeaveMil,LeaveOther,Strike,RIF,EndFMLA,EndSickLv,InvTermEmp,VolTermEmpSubscriber; Spouse Subscriber letter: all family; Spouse letter: all non-Sub family 18 months LossStud,LossDep,DepDisable,AdultDepStThe affected dependent only That dependent only 36 months any other code error: "Qualifying Event … could not be correctly determined" — — -
CBR-11 QB continuation start date (
cobra_qb.eff_dt) = eligibility expiration date + 1 day (wf_create_letters:ldt_elig_exp_dt = RelativeDate(member_eligibilities.exp_dt, 1)). -
CBR-12 QB maximum expiration date (
cobra_qb.max_exp_dt) = QE date plus 18 or 36 months (per CBR-10) minus one day (wf_create_letters:of_RelativeMonth(qe_dt, 18|36)thenof_RelativeDateTime(…, -86400); same formula exposed to letters viacobradw/f_calc_period). -
CBR-13 New QB rows default
disability_notice_ind = 'N'anddisability_ind = 'N'(wf_create_letters;dw_detail2.ue_set_new_row). -
CBR-14 Disability extension: when a QB's
disability_indis set toYanddisability_notice_indis alreadyY,max_exp_dtis extended by 11 months (18 → 29 months) minus one day (cobra/w_cobra_administrationdw_detail2.itemchanged, casecobra_qb_disability_ind). The user guide (ch. 3) states the two disability checkboxes expand the maximum to "29 or 36 months" and that the feature was "not complete" when the guide was written; code implements only the 18 → 29 extension — discrepancy for SME confirmation (the guide likely predates the final implementation). -
CBR-15 If SSN is missing for a recipient the letter row carries the literal
Not available(wf_create_letters). -
CBR-16 A member may not be added twice as a QB on the same letter; a duplicate pick from the family window deletes the pending row with "already a qualified beneficiary on this letter" (
cobra/w_cobra_administrationue_add_qb). -
CBR-17 The family-member picker refuses to add the subscriber to a letter addressed to someone else ("Cannot add Subscriber to letter") (
cobra/w_select_family_memberscb_1.clicked). -
CBR-18 Family membership and relationships for the picker come from
family+ latestmember_cat_val(RELATIONS) rows (cobra/d_select_family_members).
Election window, responses and deadlines
- CBR-19 Election letter deadline: on printing an ELECTION letter,
cobra_letters.deadline_dtis set verbatim togreatest((sent_dt + 60), (coverage_end_dt + 60))— i.e. 60 days from the later of the sent date and the member's coverage end date (cobra/w_cobra_printqueuepfc_printELECTION update SQL; equivalently the letter form computesrelativedate(if(sent_dt > exp_dt, sent_dt, exp_dt), 60)(cobradwelection-letter computed field)). - CBR-20 First premium payment deadline = election response date + 45 days.
The administration screen displays it ("First Premium Payment Deadline")
whenever an ELECTION letter's response date is present
(
cobra/w_cobra_administrationdw_detail4.itemchangedcaseresponse_dt,dw_detail4.retrieveend:relativedate(response_dt, 45)). - CBR-21 Letter response codes come from code table key
COBRRESP(cobra/dddw_cobra_letter_responses,cobra/dddw_cobra_response_cds). Recording a response drives event status (cobra/w_cobra_administrationdw_detail4.itemchangedcaseresponse_cd):NoResponse→ INACTIVE;Waived→ INACTIVE;Pending→ (PENDING);Elected→ ACTIVE;IndivElect→ ACTIVE (individual set manually). - CBR-22 On
Elected, every QB row on the letter is markedelect_ind = 'Y'and its coverage level is set toFamilywhen the letter has more than one QB, elseSingle(dw_detail4.itemchanged). Operationally,Elected(andWaived) also require the response date to be recorded, and markingElectedadds a new eligibility period for a subscriber or builds a new subscriber when the electing member is a dependent (User Guide ch. 3; server-side build per CBR-59). - CBR-59 Before a dependent's election letter is marked
Elected, the dependent must have a social security number on file — the new subscriber record is built server-side by database triggerTU_COBRA_QB, which clones the prior member row located bysoc_sec_noand then attaches a waiting period; the insert is not guarded (nosql%rowcountcheck), so a missing SSN means no member row is created yet the trigger continues, leaving the waiting period with no member to attach to (User Guide ch. 3, incl. its future-enhancements defect note). - CBR-23 Entering a rescind date on a letter copies that date into
cobra_qb.eff_dtfor all QB rows on the letter (dw_detail4.itemchangedcaserescind_dt). - CBR-24 QB coverage-level values come from code table key
ELECTLEVEL(cobra/dddw_cobra_coverage_levels). - CBR-25 New letters get
letter_sys_keyfrom sequencecobra_letters_seqand defaultprint_flg = 'N'; an ELECTION letter also defaultsresponse_cd = 'NotPrinted'(dw_detail4.ue_set_new_row,dw_detail4.itemchangedcaseletter_type_cd).
Letter/notice generation mechanics (cobra_letters and friends)
Letter types offered on the administration screen come from code table key
COBRLETTER (cobra/dddw_cobra_letter_codes); the print-queue filter list is
hard-coded (cobra/dddw_letter_types): NOTIFY, ELECTION, CONVERSION,
BADPREM, INSIG, COUPONS, UNAVAIL, EARLYTERM, plus % (all). The admin
screen additionally recognizes TERM when typing a letter row
(dw_detail4.itemchanged writes "Termination Letter Generated by …").
| Letter | Trigger | Storage | Timing rules found in code |
|---|---|---|---|
| ELECTION | Automatic when QE date is entered (CBR-3, CBR-10); rows in cobra_letters + recipients in cobra_elect_persons + QBs in cobra_qb | Blob rendered by background process into cobra_letter_data (format_type = 'PSR', chained via related_letter_sys_key for the election form); older letters stored as delimited text imported into d_cobradw_election_letter_18/36_prior + d_cobradw_election_frm_comp_prior layouts (cobra/w_cobra_printqueue pfc_print) | 60-day election window (CBR-19); 45-day first premium (CBR-20); letter text: 30-day grace for subsequent premiums, disability extension to 29 months if SSA-determined within first 60 days of coverage and notified within 60 days, second-event notification within 60 days (cobradw/d_cobradw_election_18_body_* text/computed fields) |
| NOTIFY (first notice of COBRA rights) | Manual request via member search; inserts cobra_notification_requests (one per member; duplicates refused, return −10) (cobra/n_cst_cobra_notification_gen) | Blob in cobra_letter_data keyed by letter_sys_key from cobra_letters_seq | On print, stamps member_eligibilities.cobra_rights_sent_dt on the member's latest eligibility row; after printing, the operator chooses whether to delete the requests or leave them queued (cobra/w_cobra_printqueue pfc_print NOTIFY case) |
| CONVERSION (medical conversion) | Manual request; allowed only if the member elected COBRA under their own ID and the member's group has active enrollment option Conversion; duplicates refused (cobra/n_cst_cobra_conversion_gen) | Row inserted directly into cobra_letters (letter_type_cd='CONVERSION', response_cd='NotPrinted', format_type='PSR') | Issued only for QBs whose max_exp_dt > eff_dt and whose coverage has not expired (exp_dt IS NULL and exp_cd null/(none)) |
| UNAVAIL (unavailability of continuation coverage) | Manual request for a termed member who is not COBRA-qualified: requires an eligibility row expiring on the entered date (or termed COBRA-typed election coverages under a CobraADM group); upserts cobra_non_qual (cobra/n_cst_cobra_unavailability_letter_gen); also offered from enrollment termination (enroll/w_enrollment_maintenance wf_non_qual_event) | Blob in report_objects keyed by report_data_sys_key | Suppressed from the print queue while the family has an outstanding ELECTION letter with deadline_dt >= sysdate (cobra/d_cobra_printqueue_letters UNAVAIL branch); printing clears unprinted_flg and stamps print_dt |
| EARLYTERM (early termination letter) | Created outside these libraries into cobra_early_term_letters (PB CRUD shows only R/U — see open questions) | Blob in report_objects | Printing clears unprinted_flg, stamps print_dt, and prints a companion termed-members report (cobra/w_cobra_printqueue pfc_print EARLYTERM case; cobra/d_cobra_termed_rpt) |
| BADPREM ("Incorrect Premium"), NOTINSIG ("Not Insignificant"), COUPONS, TERM | Manually addable letter rows on the admin screen with generated descriptions (dw_detail4.itemchanged) | cobra_letters | Print queue explicitly refuses INSIG and COUPONS ("cannot be currently printed"); no print handler exists for TERM/BADPREM (cobra/w_cobra_printqueue pfc_print). Per the user guide, termination letters are created by the background process, and the QB expiration-date flow anticipated an automatically generated termination letter (User Guide ch. 3) — see open question 3 |
Supporting mechanics:
- CBR-26 Letters render to print only if their blob exists; rows whose
letter generation failed are excluded from the queue while a matching
cobra_errorsrow exists (cobra/d_cobra_printqueue_all,cobra/d_cobra_printqueue_letters,cobra/d_cobra_printqueue_notify—not exists (select * from cobra_errors …)). - CBR-27 The letter-error queue lists errors joined to members and events;
marking a row
corrected = 'Y'deletes it on save (cobra/w_cobra_letter_errorspfc_preupdate,cobra/d_cobradw_letter_errors). - CBR-28 The background feed of letters to render is:
cobra_lettersrows withresponse_cd = 'NotPrinted',sent_dtnull,print_flg = 'N', no error and no existing blob, unioned with notification requests (cobradw/d_cobradw_letters_to_print). - CBR-29 Printing any queue row marks it
print_flg = 'Y'and stamps the operator-entered sent date; for ELECTION/CONVERSION an existingsent_dtis only overwritten when the operator checks "UPDATE SENT DATE?" (cobra/w_cobra_printqueuepfc_print). - CBR-30 A USPS certificate of mailing is printed for mailed
election/conversion letters: no certificate below 3 addressees, pages padded
to 15 rows, batches over 15 split across pages; postage and certificate fee
amounts are table-driven from code table key
POSTAGE(valuesPostage,MailCert) (cobra/w_cobra_printqueuewf_certificatemailing,pfc_print;cobradw/d_cobradw_cert_mailing). - CBR-31 Election letters print duplex; the operator is prompted once per
session to set duplex/left-binding (
cobra/w_cobra_printqueuepfc_print). - CBR-32 Election form signature lines (subscriber / spouse / dependent) are
shown only for the member classes present on the form's line items (ids
A/B/other) (
cobra/w_cobra_printqueuepfc_printandue_certificate_reprint). - CBR-33 Deleting queue rows removes
cobra_notification_requestsandcobra_letter_datafor the selected letter keys after confirmation (cobra/w_cobra_printqueuepfc_deleterow). - CBR-34 The election letter's premium-periods block lists monthly payment
periods starting the day after existing benefits end and running through the
end of the month 105 days later (60-day election + 45-day first payment)
(
cobradw/f_premium_periods, used bycobradw/d_cobradw_elctionperiods).
Background process (automatic letter creation and termination)
The user guide documents the server-side component whose outputs the windows
consume (only its outputs — cobra_letter_data, cobra_errors,
cobra_early_term_letters — are visible in the PB source):
- CBR-60 The background process runs continuously, checking whether any letters need to be created or any terminations need to be performed; at guide time it created election letters, termination letters and notification letters (User Guide ch. 3). Conversion-letter creation in the background process, partial-payment notices and billing/termination logic were listed as future enhancements in the same chapter.
- CBR-61 The background process performs terminations when (a) 63 days have passed beyond the payment deadline, (b) the maximum deadline is reached, or (c) a response deadline is reached (User Guide ch. 3).
- CBR-62 The background process tracks the secondary 30-day billing cycle specified for the insignificant-amount rule (User Guide ch. 3).
- CBR-63 Background letter-generation failures fall into four documented categories — address errors, rate errors, group errors and missing-coverage errors. After an error is cleared (CBR-27) the background process acknowledges the clearing and re-tries the letter on its next run; if the error was cleared without an actual correction, the same error is recreated (User Guide ch. 3).
COBRA premium computation (rates + amounts)
- CBR-35 COBRA premium rates are kept per group in
cobra_rates_master(rate key, group, coverage level, effective/expiration dates,rate_amt, rate code, display description) with the covered benefit list incobra_rate_coverages(rate key → benefit coverage type/code) (cobra/d_cobra_rates_hdr,cobra/d_cobra_rates_dtl). - CBR-36 A rate's group cannot be changed after it is set ("create a new
rate for the desired group") (
cobra/w_cobra_rate_maintdw_header.itemchanged). - CBR-37 A rate must have a display description and at least one coverage
row to save; new/empty coverage rows are stripped first
(
cobra/w_cobra_rate_maintdw_header.ue_validate). - CBR-38 "Generate display text" builds the description as the slash-joined
list of the rate's coverage type codes (e.g.
Medical/Drugs/Dental) (cobra/w_cobra_rate_maintcb_4.clicked). - CBR-39 The election form offers each rate whose covered benefits match the
family's elected COBRA-eligible coverages for the member's group, effective at
the eligibility end date, showing coverage level,
rate_amtand rate period (cobradw/d_cobradw_election_frm_b; per-coverage lookup incobradw/d_cobra_rates_display). - CBR-40 No administrative-percentage arithmetic exists in this code: the
charged amount is the stored
rate_amt. The 102 % statutory cap (and higher cap during a disability extension, with months 19–29 premiums possibly increased) appears only as letter text (cobradwelection letter body: "may not exceed 102 percent…", "Premiums for months 19-29 may be increased…"). Loaded rates are therefore presumed to be gross (rate + admin allowance) — see open questions. - CBR-41 ARRA premium subsidy is documented in letter text and reporting
only: qualifying individuals (involuntary termination 9/1/2008–5/31/2010) pay
35 % of the premium for up to 15 months; subsidized members are identified by
member category
ARRASUBSID(cobradw/d_cobradw_election_frm_c_arratext;cobrarpt/d_cobrarpt_arra;cobrarpt/w_cobrarpt_select_criteriawf_cobraarrareport). - CBR-42 Rates can be copied to another group (skipping rows already present
with identical description, effective date, level and amount)
(
cobra/w_cobra_rate_selectwf_copy_rates). - CBR-43 Rates can be rolled forward: for every division under a group
(hierarchical
CONNECT BY), each rate effective on the original start date is duplicated with the new start date and an expiration of new start + 1 year − 1 day (cobra/w_cobra_rate_selectwf_copy_rates_forward).
Premium receipt
- CBR-44 A premium receipt records received date (defaults to today), paid-
through date, check number and amount, with
Partial PaymentandInsignificant Amt.flags, intocobra_stub(key from sequenceall_purpose_seq) (cobra/w_cobra_receive_premiumcb_save.clicked). - CBR-45 The payer is located by SSN or Member ID against members re-enrolled
from COBRA (
cobra_qb.new_qb_member_sys_key = members.member_sys_key). The paid-through date must fall inside the QB coverage window (eff_dt..exp_dt), or — when no such row matches — the receipt is accepted if it is on/before the first-payment deadlinenvl(response_dt + 45, deadline_dt)of an elected ELECTION letter (cobra/w_cobra_receive_premiumem_ssn.modified,em_member_id.modified). - CBR-46 When the identifier matches more than one elected COBRA the entry is
refused: "Member has elected COBRA more than once. Look under spouse also."
(
cobra/w_cobra_receive_premium). The user guide (ch. 3) states that when more than one COBRA event exists for the member "a screen will appear allowing the user to choose which event to apply payment" — discrepancy for SME confirmation (code refuses rather than offering a chooser). The guide also directs that payment adjustments be made only in the participant's detail window. - CBR-47 All receipt fields are mandatory (identifier, paid-through date,
check number, non-zero amount) (
cb_save.clickedvalidations). - CBR-48 On the administration payments grid, checking the significant-amount
flag (
sig_ind = 'Y') stampsinsig_dtwith the current date/time (cobra/w_cobra_administrationdw_detail3.itemchanged). Adding a payment row there opens the Receive Premium window pre-keyed to the selected QB (or the recipient's SSN) and re-retrieves on return (dw_detail3.pfc_addrow).
Coverage termination
- CBR-49 QB expiration-reason codes come from code table key
COBRA, with a synthetic(None)first entry; clearing the expiration date resets the reason to(none)(cobra/dddw_cobra_termcodes;cobra/w_cobra_administrationdw_detail2.itemchanged,dw_detail2.pfc_retrievedddw). - CBR-50 Editing a QB expiration date flags the row (
exp_mod_flg = 'Y'). On save: if the expiration equals the coverage start − 1 day (coverage never used) the user is offered the enrollment screen; otherwise a three-way prompt is shown — Auto Terminate / Open Enrollment / Ignore (cobra/w_cobra_administrationpfc_save;cobra/w_cobra_autoterm_response). - CBR-51 Auto-terminate sets
member_eligibilities.exp_dtto the COBRA expiration date for the QB's family record (dependent coverages are expired by a database trigger — comment in code); it is skipped when blocking election rows exist for the eligibility period, and the whole batch rolls back on any error ("AutoTermination not successful") (pfc_save). - CBR-52 Termination candidates are reported when (a) an election letter is
7+ days past
deadline_dtwith no response ("Election Forms Not Recieved"), (b) an active event's QB passedmax_exp_dt("End of COBRA Eligibility") (cobrarpt/d_cobra_term_rpt). - CBR-53 A COBRA event can be deleted by SSN + QE eligibility effective date;
deleting
cobra_eventcascades to all child tables (comment: "all other tables are cascade delete"); the SSN must pass user security and resolve to a single member (cobra/w_cobra_member_delete). The user guide frames this as a data-correction utility — for terminations that were reversed or incorrectly input — and notes the functionality "will be moved into the background as soon as possible" (User Guide ch. 3). - CBR-54 Auto-terminations are audited in
cobra_terms(old/new expiration date and code, user, date) and reported by date range (cobrarpt/d_cobra_termed_members_rpt).
Interplay with enrollment (members on COBRA)
- CBR-55 An elected QB is re-enrolled as their own subscriber:
cobra_qbcarriesnew_qb_member_sys_key, and payment/reporting joins treat that key as the member on COBRA (cobra/w_cobra_receive_premium;cobrarpt/d_cobrarpt_active_list;cobrarpt/d_cobra_term_rpt). - CBR-56 Enrollment termination offers to create a COBRA unavailability
letter when the termed member has COBRA-typed coverages under a group with the
CobraADMenrollment option (enroll/w_enrollment_maintenancewf_non_qual_event, usingcobradw/d_cobra_non_qual_events). - CBR-57 Only groups holding the
CobraADMenrollment option (or under hard-coded master groupsSFPI/M/III) participate in COBRA reporting and the ARRA group pick-list (cobrarpt/w_cobrarpt_select_criteriadddw cased_cobrarpt_arra;cobra/n_cst_cobra_unavailability_letter_gen).
Data + CRUD
COBRA-owned tables (columns as extracted; _re/analysis/schema.json):
| Table | Purpose | cobra | cobradw | cobrarpt |
|---|---|---|---|---|
cobra_event | Qualifying event header (sub/dep keys, qe_elig_eff_dt, qe_dt, qe_notify_dt, status_cd) | CRUD | R | R |
cobra_elect_persons | Election-letter recipients per event | CRUD | R | R |
cobra_qb | Qualified beneficiaries (eff/exp/max dates, elect + disability flags, coverage level, new_qb_member_sys_key) | CRUD | R | R |
cobra_letters | Letter register (type, sent/deadline/response/rescind dates, response code, print flag, dw_object, format_type, batch) | CRUD | R | R |
cobra_letter_data | Rendered letter blobs (+ related_letter_sys_key chain) | R (blob read; delete of rows in print queue) | R | R |
cobra_notification_requests | First-notice queue per member | CRUD | R | R |
cobra_errors | Letter-generation error queue | CRUD | R | R |
cobra_non_qual | Unavailability letters (elig-exp date, print state) | CRU | CRUD | — |
cobra_early_term_letters | Early-termination letters (term date, print state) | RU | R | — |
cobra_stub | Premium check receipts | CRUD | — | R |
cobra_rates_master / cobra_rate_coverages | Group premium rates and covered benefits | CRUD / CUD | R | R |
cobra_rates | Legacy rates table, report-only | — | — | R |
cobra_terms | Auto-termination audit | — | — | R |
Shared tables read: members, family, member_eligibilities (also updated
by cobra: exp_dt on auto-term, cobra_rights_sent_dt on NOTIFY print),
member_cat_val (RELATIONS, ARRASUBSID), elections,
election_coverages, coverages (cobra_elig_flg), group_coverages
(cobra_type_cd: NOCOBRA/BOTH/COBRAONLY), group_enroll_opts
(CobraADM, Conversion), groups, addresses, codes, report_objects,
batch_reports (report catalog rows, report_type = 'COBRA').
Sequences: cobra_letters_seq, cobra_rates_master_seq, cobra_stub_seq
(legacy, commented out), all_purpose_seq
(cobra/w_cobra_administration, cobra/w_cobra_rate_maint,
cobra/w_cobra_receive_premium).
Code tables (key → use): COBRSTAT event status; MBREXP qualifying-event
codes; COBRLETTER letter types; COBRRESP letter responses; COBRA QB
termination reasons; ELECTLEVEL coverage levels; POSTAGE postage/certificate
fees (cobra/dddw_*, cobra/w_cobra_printqueue).
Reports (cobrarpt catalog)
The report list is data-driven from batch_reports where
report_type = 'COBRA' (cobrarpt/dddw_cobrarpt_types,
cobrarpt/d_cobrarpt_report_types); the criteria window special-cases these
DataWindows (cobrarpt/w_cobrarpt_select_criteria,
cobrarpt/w_cobrarpt_display):
| Report DataWindow | Content | Criteria |
|---|---|---|
d_cobra_ee_status | Per-group COBRA employee status: event status, letter sent/response, QB dates, paid-through, per-benefit coverage levels | Group multi-select |
d_cobra_rates_bygroup | Rate book for selected groups (rates not expired as of date) | Groups + "Not Expired as of" date |
d_cobra_rates_missing | COBRA-eligible group coverages (cobra_type_cd BOTH/COBRAONLY) with no current rate | Groups + date |
d_cobra_termed_members_rpt | Auto-terminated members from cobra_terms (old/new exp date+code, user) | From/thru dates |
d_cobrarpt_payment_checklist | Premium checks received on a date (cobra_stub by recv_dt) | Mail-received date |
d_cobrarpt_elect_printed | Election letters sent on a date, with deadlines | Sent date |
d_cobrarpt_elect_to_print | Election letters not yet printed (print_flg = 'N', no errors) | none |
d_cobrarpt_arra | ARRA premium-subsidy activity for ARRASUBSID members (rates vs paid amounts, subscriber/dependent counts); can be run for all groups with active subsidized members | Groups + from/thru dates |
d_cobrarpt_active_list | Active COBRA participants with most recent paid-through date | none |
d_cobra_term_rpt | Termination candidates: no election response 7 days past deadline; QBs past max_exp_dt; expired eligibility | none |
d_cobra_events_wo_qe_dt | Events missing a QE date, scoped to the user's group security | user id (implicit) |
d_cobra_first_notification_requests | Outstanding first-notice requests with subscriber/member names | none |
d_cobra_rates_rpt | Legacy cobra_rates table listing | group list |
d_cobra_labels (via cobradw/n_cobra_functions.of_printlabels) | Mailing labels for active QBs (elected Single dependents, or the electing member) with an election letter; label offset and page-break-per-division options | Group multi-select (cobrarpt/w_cobra_printlabel_select) |
d_cobra_notification_rpt, d_cobra_unavailability_rpt, d_cobra_termed_rpt | Companion audit reports auto-printed after NOTIFY / UNAVAIL / EARLYTERM print batches | printed member keys (cobra/w_cobra_printqueue pfc_print) |
Migration notes
COBRA is a deadline-regulated domain. All date-window logic found in code, verbatim:
- Election deadline:
deadline_dt = to_date( greatest((:ldt_today+60), (:ldt_coverage_end_dt+60)) )(cobra/w_cobra_printqueuepfc_print); letter-side equivalentrelativedate( if( cobra_letters_sent_dt > member_eligibilities_exp_dt, cobra_letters_sent_dt, member_eligibilities_exp_dt ), 60 )(cobradw election letter computed field). - First payment:
st_45.Text = string(relativedate(ldt_date,45),'mm/dd/yyyy')(cobra/w_cobra_administration); acceptance check:idt_received_through_date <= NVL( ( cobra_letters.response_dt + 45 ), cobra_letters.deadline_dt )(cobra/w_cobra_receive_premium). - Maximum period:
date(gnv_app.inv_datetime.of_RelativeDateTime( datetime(gnv_app.inv_datetime.of_RelativeMonth(date(ldt_qe_dt),36)), -86400))(and18) (cobra/w_cobra_administrationwf_create_letters); disability extensionof_RelativeMonth(date(ldt_max_cur),11)− 1 day (dw_detail2.itemchanged). - Premium-period horizon:
ld_105_after_dt = lnv_datetime.of_lastdayofmonth(RelativeDate(ld_initial_dt,105))(cobradw/f_premium_periods). - Termination report trigger:
sysdate >= cobra_letters.deadline_dt + 7(cobrarpt/d_cobra_term_rpt). - Letter-text-only rules (not enforced in code, must become system rules in the
target): 30-day grace for subsequent premiums; 60-day windows for reporting
divorce/separation/dependent-loss events, SSA disability determinations and
second qualifying events; 30-day notice when SSA finds the QB no longer
disabled; special-enrollment 30-day windows (
cobradw/d_cobradw_election_18_body_*).
Other migration-relevant observations:
- Event status is read/written by positional index into the status dropdown
(
code_value[1]=(PENDING),[2]=ACTIVE,[3]=INACTIVE,[4]=INCOMPLETE), so behavior silently depends oncodes.code_display_seqordering (cobra/w_cobra_administrationdw_header.itemchanged,dw_detail4.itemchanged). Replace with value-based logic. - Letter rendering is split between this app and an external background process
communicating via
cobra_letters/cobra_letter_data/cobra_errors; printing parses letter blobs (PSR files written toc:\temp.psr) and, for legacy rows, splits a delimited text blob on markersHEDHEDHEDHED,BODBODBODBOD,PERPERPERPER,DY1DY1DY1DY1,EFAEFAEFAEFA,EFBEFBEFBEFB(cobra/w_cobra_printqueuepfc_print). None of this should survive migration; letters need a template service. pfc_saveusesif ll_foundrow > 1afterFind(...), so a modified QB found at row 1 does not trigger the auto-term prompt — likely a defect to confirm, not to re-implement (cobra/w_cobra_administrationpfc_save).- Hard-coded values: master groups
SFPI/M/III(reports, labels), placeholder date12/07/1941used as a null-date sentinel in queue unions, far-future sentinels01/01/2500,12/31/2049,12/31/2050, TPA address text in letter bodies (cobrarpt/w_cobrarpt_select_criteria,cobra/d_cobra_printqueue_all,cobradwletter DWs). - Eligibility auto-termination relies on a database trigger to expire
coverages ("coverages will be termed by trigger") — that trigger is outside
the PB source and must be re-specified (
cobra/w_cobra_administrationpfc_save). - A second server-side trigger,
TU_COBRA_QB, builds the new subscriber when a QB elects: it clones the previous member row located bysoc_sec_no, then adds a waiting period. Known defect documented in the guide: the insert intomembersis not checked (sql%rowcount), so an electing member with no SSN yields no member row while the trigger continues, orphaning the waiting-period insert; the recommended fix was front-end SSN enforcement plus a guard in the trigger (User Guide ch. 3, future enhancements). Both triggers must be recovered from the Oracle DDL. - The guide's future-enhancements list (priority-ordered 4-13-2000) explains several half-built features visible in code: rates on election letters (since implemented — CBR-39), insignificant-amount logic and coupons/billing (INSIG and COUPONS letter types are still refused by the print queue), partial-payment notices and background termination logic (billing), conversion-letter creation in the background process, print-queue mods (request/delete notifications from the queue), generating a QE event from the COBRA windows, exit-without-save options, report corrections, and a view-only participant address on the admin screen (User Guide ch. 3).
- ARRA subsidy handling is reporting/letter-text only; if it is truly dead (post-2010) it can be dropped with SME sign-off.
Open questions
- Who creates
cobra_eventrows? — RESOLVED (mechanism); trigger DDL pending. The user guide confirms creation is fully automatic: when the termination reason entered in enrollment meets the qualifying-event criteria (CBR-58), "the system will automatically generate a 'QB' record" with no further user action, and the documented dependent-add workaround regenerates the record simply by re-entering the termination reason in enrollment (User Guide ch. 3). Since no PB code inserts the row, the mechanism is a database trigger on eligibility maintenance (the guide names the companion triggerTU_COBRA_QBfor the election side). The exact trigger source still needs Oracle DDL recovery. - The COBRA background process — RESOLVED (role and rules); source
pending. A server-side application that runs continuously, creating
election, termination and notification letters and performing
deadline-driven terminations, including the 63-days-past-payment-deadline
rule and the secondary 30-day insignificant-amount cycle (CBR-60..CBR-62)
(User Guide ch. 3); it renders the blobs the print queue consumes and
writes
cobra_errorsin the four categories of CBR-63. Its source is not in the PB extraction — how it selects the 18- vs 36-month election layout, setsformat_type, and createscobra_early_term_lettersmust be confirmed from the recovered server-side code. - TERM and BADPREM letters — PARTIALLY RESOLVED. The guide states the
background process creates termination letters, and the QB expiration flow
anticipated an automatically generated termination letter; partial-payment
notices (the likely BADPREM output) and full background termination/billing
logic were still listed as future enhancements (User Guide ch. 3).
Whether TERM printing was ever wired end-to-end needs SME confirmation —
pfc_printhas no CHOOSE branch for either type (INSIG and COUPONS are explicitly refused). - Admin percentage: rates are charged exactly as stored (
rate_amt); is the 2 % administration fee expected to be baked into loaded rates, and is the 150 % disability-extension premium (months 19–29) handled manually? cobra_stubvs billing — PARTIALLY RESOLVED. The background process, not the client, was responsible for non-payment terminations (63 days past the payment deadline) and for tracking the secondary 30-day insignificant-amount cycle (CBR-61/CBR-62); coupons/billing, payment reports and partial-payment notices were future enhancements (User Guide ch. 3). No amount-due computation existed client-side; how much of the billing roadmap was ever built must come from the recovered background process source.d_cobra_stubDataWindow (cobra/d_cobra_stub.srd) appears unused by any window read (payments grid usesd_cobra_payments); confirm dead.exp_mod_flgfind starting at row 2 (if ll_foundrow > 1inpfc_save) — defect or intentional?- Positional status-code indexing (COBRSTAT display order) — confirm the
production
codesordering matches the assumed (PENDING)/ACTIVE/INACTIVE/ INCOMPLETE sequence before writing migration mappings. cobra_rates(legacy) vscobra_rates_master— is the old table still populated, or isd_cobra_rates_rptdead?- Retroactive-termination enforcement — PARTIALLY RESOLVED. Non-payment termination is automated: the background process terminates 63 days past the payment deadline (CBR-61) (User Guide ch. 3) — a hold-back beyond the letter's 30-day grace. The effective date the termination is applied with (retroactive to the last paid day, per the letter text, or the processing date) still needs SME confirmation.