---
title: Retention date calculation
summary: Computes quarter-aligned archive and delete cutoff dates for policy units, and derives a default experience-rating modification factor for non-ERP rating plans, via extension methods on Date and clsPolicyPeriodRatingPlan.
status: draft
owner: SAIF
last_reviewed: 2026-07-30
library: SAIF.Business.UnitStat
reference_type: package
operation_id: OP-US-08
trigger: Caller invokes the UnitArchiveDate, UnitDeleteDate, QuarterStartDate, or ERModFactor extension method
---

# Retention date calculation

`Extensions.vb` provides small extension methods used to compute data-retention cutoffs for Unit Stat policy units and to normalize a missing experience-rating modification (ER Mod) factor to a safe default. These are pure calculation helpers with no database access.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-US-08 |
| **Trigger** | Caller invokes `d.UnitArchiveDate()`, `d.UnitDeleteDate()`, `d.QuarterStartDate()`, or `target.ERModFactor()` |
| **Inputs** | A `Date` (for the date extensions) or a `clsPolicyPeriodRatingPlan` instance (for `ERModFactor`) |
| **Outputs** | A calculated archive or delete cutoff `Date`, a quarter-start `Date`, or a `Decimal` ER Mod factor |
| **Primary components** | `Extensions.UnitArchiveDate`, `Extensions.UnitDeleteDate`, `Extensions.QuarterStartDate`, `Extensions.ERModFactor` |
| **Entry point** | `Business\SAIF.Business.UnitStat\Extensions.vb` |

## Steps

1. **Quarter alignment.** `QuarterStartDate(d)` computes the first day of the calendar quarter containing `d`: it truncates `(Month(d) - 1) / 3` to find the zero-based quarter index, converts that back to a starting month (`1`, `4`, `7`, or `10`), and returns `<month>/1/<year>` for the input date's year.
2. **Archive cutoff.** `UnitArchiveDate(d)` returns `QuarterStartDate(d)` minus 155 months — used to determine the cutoff before which policy units are considered eligible for archiving ([BR-US-025](../business-rules.md#br-us-025-units-within-155-months-of-the-current-quarter-start-date-are-archived-units-more-than-30-years-old-are-deleted)).
3. **Delete cutoff.** `UnitDeleteDate(d)` returns `QuarterStartDate(d)` minus 30 years — used to determine the cutoff before which policy units are considered eligible for permanent deletion ([BR-US-025](../business-rules.md#br-us-025-units-within-155-months-of-the-current-quarter-start-date-are-archived-units-more-than-30-years-old-are-deleted)).
4. **ER Mod factor default.** `ERModFactor(target As clsPolicyPeriodRatingPlan)` returns `target.ERMod` converted to `Decimal` if it is not `Nothing`, otherwise returns `1` (100%) — this normalizes policy periods on non-ERP (non-experience-rated) rating plans, which have no ER Mod value, to behave as if their modification factor were neutral (1.00) rather than null, so that downstream rating-plan comparisons or calculations do not need separate null-handling logic for ERP versus non-ERP periods.
5. **No orchestrating caller found in this library.** The functions that would actually apply `UnitArchiveDate`/`UnitDeleteDate` to a set of policy units and act on them (archiving/purging jobs) are not present in this library's traced source; these extension methods are exposed as reusable utilities but the archiving/deletion process itself is external to this library.**

## Process flow

```mermaid
flowchart TD
	Start([Caller invokes an extension method]) --> Which{Which extension?}
	Which -->|QuarterStartDate| Quarter[Truncate month to<br>quarter start: Jan, Apr, Jul, or Oct 1]
	Which -->|UnitArchiveDate| ArchiveCalc[QuarterStartDate minus 155 months]
	Which -->|UnitDeleteDate| DeleteCalc[QuarterStartDate minus 30 years]
	Which -->|ERModFactor| ERModCheck{Target.ERMod is Nothing?}
	ERModCheck -->|Yes| DefaultMod([Return 1.00])
	ERModCheck -->|No| ActualMod([Return Target.ERMod as Decimal])
```

## Failure and edge-case behavior

- No code in this library was found that consumes `UnitArchiveDate` or `UnitDeleteDate` to actually perform archiving or deletion; these two extension methods define the retention math but the orchestrating batch/archival process, if it exists, is outside this library's traced source.**
- `ERModFactor` treats a missing (`Nothing`) `ERMod` as exactly `1.00`; any caller that needs to distinguish "no ER Mod applicable" from "ER Mod is exactly 1.00" cannot do so through this extension alone.

## Related documentation

- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [SQL catalog](../sql/index.md)
- [Database tables](../database-tables.md)

> **Note:** Statements marked with `*` were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts. Statements
> marked with `**` could not be confirmed; treat as unknown until verified.

## Sources

- `Business\SAIF.Business.UnitStat\Extensions.vb`
- `Business\SAIF.Business.UnitStat\Constants.vb`
