Skip to content

Benefit period and schedule management

Every recurring benefit payment is described by one or more dated periods, an optional future-payment schedule, and a single pay remark. This operation covers the shared classes those payments (documented separately under Timeloss payment issuance and the award operations) build on to describe what is being paid and when.

Field Value
Operation ID OP-CP-03
Trigger clsBenefitPeriodCollection.GetClaimBenefitPeriodCollection(dpi, claimID, benefitPaymentID); clsBenefitSchedule.GetClaimBenefitSchedule(...); clsBenefitRemark.GetBenefitRemark(dpi, benefitPayeeSeqNum)
Inputs IDataPortalInfo, ClaimID, BenefitPaymentID, BenefitPayeeSeqNum, NextIssueDate (schedule-by-date lookup), user-entered dates/amounts/day counts/remark code
Outputs Persisted rows via pk82394_claim_benefit procedures; in-memory collections with aggregate totals; a projected payment list; broken-rule/error messages
Primary components clsBenefitPeriod, clsBenefitPeriodCollection, clsBenefitSchedule, clsBenefitScheduleCollection, clsBenefitRemark
Entry point Business\SAIF.Business.Claim.Payment\Periods\clsBenefitPeriod.vb

Steps

  1. Retrieve the period collection (SQL-047). GetClaimBenefitPeriodCollection and NewClaimBenefitPeriodCollection both call RetrieveObject — "New" does not create an empty in-memory collection, it re-reads the database. (CL_BENEFIT_PERIOD is not separately catalogued in database-tables.md.)
  2. Hydrate each period. Load/Fill map amounts, dates, interest, offset, retro-reserve, and TD-day fields, then derive display text from the payment category (TD, VocTD, SupTD).
  3. Create a new period (SQL-004, DUAL). CreatePeriod() obtains a new sequence value only when the parent BenefitPaymentID is non-zero — a period created without a parent payment gets no identity.
  4. Load previously-paid history for the period (BR-CP-013). LoadPreviousPaidProperites reads matching paid history from CL_FINANCIAL_TRANS/CL_FINANCIAL_TRANS_DTL (uncatalogued inline query, described here without a SQL-ID link since no matching catalog entry exists), excluding penalty and interest-cost transactions; supplemental periods are matched by reimbursement program 7 instead of payment category. A match is only honored when the paid periods' minimum begin date and maximum end date exactly equal the period's from/thru dates with no day gaps between them — otherwise previously-paid amount and days are both zeroed.
  5. Validate the period (BR-CP-011). Seven rules run: benefit-amount reconciliation, from-date on or before thru-date, TD days and previous TD days in half-day increments, zero TD days for supplemental periods, and two previously-paid-consistency warnings.
  6. Check for overlapping periods (BR-CP-012). clsBenefitPeriodCollection.HasOverlappingPeriods flags any two periods sharing a payment category whose date ranges overlap; PeriodsMatchingDates separately finds periods of a different category with identical dates.
  7. Save a period. Save() returns False immediately when BenefitPeriodID = 0 rather than attempting a database call.
  8. Insert/update/delete the period. All three paths call pk82394_claim_benefit procedures against CL_BENEFIT_PERIOD (SQL-014 create, SQL-097 update, SQL-120 delete).
  9. On a rows-affected value other than 1: "Insert Failed" (insert) or DBContentionError (update/delete) (BR-CP-001).
  10. Retrieve the schedule (SQL-050). A multi-row result silently keeps only the last row loaded, since each Fill overwrites the object in place. (CL_BENEFIT_SCHEDULE is not separately catalogued in database-tables.md.)
  11. Retrieve the schedule collection. Branches between a claim-scoped procedure and a next-issue-date-scoped procedure depending on which parameter is populated; the DPI-only overload leaves both unset and falls into the by-date branch with an empty date.
  12. Build a payment schedule (BR-CP-014). CreateSchedule/BuildPaymentProjections computes the from/thru/issue date for each future payment; every issue date after the first rolls back to the previous work day, while the first is never adjusted.
  13. Validate the schedule (BR-CP-014). Rule_CheckMaxFuturePayments rejects a schedule whose remaining payment count exceeds the configured maximum (14 when loaded through the collection); the broken rule carries an empty message.
  14. Insert/update/delete the schedule (SQL-016 create, SQL-099 update, SQL-122 delete).
    • On a rows-affected value other than 1: "Insert Failed" / DBContentionError (BR-CP-001). Unlike the period, a successful update does not advance the update number or mark the object clean — a likely defect.
  15. Retrieve the pay remark (SQL-049). Missing remarks are not an error; AfterRetrieve seeds a new, empty remark placeholder.
  16. Validate and save the remark (BR-CP-015). A non-blank code must exist among unexpired rows in the remark-code table (SQL-048); saving with a blank code marks the remark deleted instead of updating it.
  17. Insert/update/delete the remark (SQL-015 create, SQL-098 update, SQL-121 delete).
    • On a rows-affected value other than 1: "Insert Failed" / DBContentionError (BR-CP-001).

Process flow

flowchart TD
    Start([Benefit payment aggregate<br>created, retrieved, or saved]) --> Which{Period, schedule,<br>or remark?}
    Which -->|Period| Retr[Retrieve/create period]
    Retr --> Prev[Load previously-paid history:<br>exact, gap-free match required]
    Prev --> Validate{Period rules pass?}
    Validate -->|No| Blocked([Broken rules returned])
    Validate -->|Yes| Overlap{Overlaps another<br>same-category period?}
    Overlap -->|Yes| Flag([Caller warned/blocked])
    Overlap -->|No| SavePeriod[Insert/update/delete period]
    Which -->|Schedule| BuildSched[Build payment projections:<br>roll issue dates to work days]
    BuildSched --> MaxCheck{RemainingPaymentCount<br>within max?}
    MaxCheck -->|No| SchedBlocked([Broken rule, empty message])
    MaxCheck -->|Yes| SaveSched[Insert/update/delete schedule]
    Which -->|Remark| RemarkCode{Remark code blank?}
    RemarkCode -->|Yes| DeleteRemark[Mark remark deleted]
    RemarkCode -->|No| CheckCode{Code active<br>and on file?}
    CheckCode -->|No| RemarkBlocked([Broken rule: invalid remark])
    CheckCode -->|Yes| SaveRemark[Insert/update remark]
    SavePeriod --> Rows{RowsAffected = 1?}
    SaveSched --> Rows
    SaveRemark --> Rows
    Rows -->|No| Contention([Insert Failed / DB contention error])
    Rows -->|Yes| Done([Persisted])

Failure and edge-case behavior

  • A period created without a parent payment (BenefitPaymentID = 0) never gets a sequence value and Save() silently returns False — no error message is added.
  • The schedule's successful update path does not call MarkOld() or advance the update number, unlike the period and remark equivalents — repeated saves against the same in-memory object may re-send a stale update number.
  • clsBenefitPeriodCollection and clsBenefitScheduleCollection are strictly retrieve-only; their Criteria throws InvalidSQLProperty for Create/Insert/Update/Delete — each period/schedule instance owns its own persistence.
  • HasPreviouslyPaid3DW and the underlying claim-status checks depend on clsClaimData (SAIF.Business.View.Claim), which is not yet migrated to the new documentation format; see that library's operations-processes.md for the three-day-wait claim context this method reads.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.

Sources

  • Business\SAIF.Business.Claim.Payment\Periods\clsBenefitPeriod.vb
  • Business\SAIF.Business.Claim.Payment\Periods\clsBenefitPeriodCollection.vb
  • Business\SAIF.Business.Claim.Payment\Payments\TimelossPayments\clsBenefitSchedule.vb
  • Business\SAIF.Business.Claim.Payment\Payments\TimelossPayments\clsBenefitScheduleCollection.vb
  • Business\SAIF.Business.Claim.Payment\clsBenefitRemark.vb