---
title: Pharmacy eligibility CRUD
summary: Inserts or updates a pharmacy eligibility report record for a claim, tracking transmission timestamps and applying an optimistic-concurrency check.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Business.Claim.Entry
reference_type: package
operation_id: OP-CE-09
trigger: clsPharmacyEligibilityReport.BeforeInsert / BeforeUpdate during Save()
---

# Pharmacy eligibility CRUD

`clsPharmacyEligibilityReport` tracks whether a claim is eligible for pharmacy benefits and when that eligibility status was last transmitted to the pharmacy benefit manager (MedImpact). This operation covers the insert and update lifecycle for that record, including the update-date defaulting rule and a version-tracking detail that should be verified before relying on the persisted `UpdateNum` value.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-CE-09 |
| **Trigger** | `Save()` on a `clsPharmacyEligibilityReport` object, routed to `BeforeInsert` (new) or `BeforeUpdate` (existing) |
| **Inputs** | `ClaimID`, eligibility status code, effective date, optional update-date override, transmit-date fields |
| **Outputs** | Inserted or updated `CL_PHARMACY_ELIGIBILITY_REPORT` row |
| **Primary components** | `clsPharmacyEligibilityReport.BeforeInsert`, `clsPharmacyEligibilityReport.BeforeUpdate` |
| **Entry point** | `Business\SAIF.Business.Claim.Entry\clsPharmacyEligibility.vb` |

## Steps

1. **Insert a new eligibility report.** `BeforeInsert` binds `ClaimID`, eligibility status, effective date, and transmit-date fields, and issues the insert against `CL_PHARMACY_ELIGIBILITY_REPORT` ([SQL-014](../sql/SQL-014.md), [CL_PHARMACY_ELIGIBILITY_REPORT](../database-tables.md#cl_pharmacy_eligibility_report)).
2. **Determine the update date on update** ([BR-CE-010](../business-rules.md#br-ce-010-pharmacy-eligibility-update-date-must-use-override-or-default-to-current-timestamp)). `BeforeUpdate` uses the caller-supplied update-date override if one was provided; otherwise it defaults to the current timestamp.
3. **Increment `UpdateNum` in memory.** Before binding the update, `BeforeUpdate` sets the in-memory `UpdateNum` to the prior value plus one (line ~139–140 of `clsPharmacyEligibility.vb`).
4. **Bind and execute the update statement.** The update SQL itself also computes `UPDATE_NUM = :UpdateNum + 1` ([SQL-026](../sql/SQL-026.md), [CL_PHARMACY_ELIGIBILITY_REPORT](../database-tables.md#cl_pharmacy_eligibility_report)), binding the already-incremented in-memory `UpdateNum` from step 3 and adding one to it again in the SQL itself.
   - **Confirmed defect**: because the VB layer increments `UpdateNum` before binding it, and the UPDATE statement's `SET UPDATE_NUM = :UpdateNum + 1` clause adds one more on top of the bound (already-incremented) value, the persisted `UPDATE_NUM` becomes `old value + 2` per update rather than `old value + 1`, double-incrementing the version counter on every save.
5. **Check rows-affected for concurrency.** If the update's rows-affected value is not `1`, an `UpdateError` broken rule is added indicating a concurrency conflict ([BR-CE-011](../business-rules.md#br-ce-011-optimistic-concurrency-update-fails-if-rowsaffected-1)).
6. **Return the saved object** with the (possibly double-incremented) `UpdateNum`.

## Process flow

```mermaid
flowchart TD
	Start([Save called on pharmacy<br>eligibility report]) --> New{New record?}
	New -->|Yes| Insert[Insert CL_PHARMACY_ELIGIBILITY_REPORT row]
	New -->|No| DateCheck{Update-date<br>override supplied?}
	DateCheck -->|Yes| UseOverride[Use supplied update date]
	DateCheck -->|No| UseNow[Default update date<br>to current timestamp]
	UseOverride --> IncMem[Increment UpdateNum<br>in memory]
	UseNow --> IncMem
	IncMem --> Update[Update row;<br>SQL also adds 1 to UpdateNum]
	Update --> Rows{RowsAffected = 1?}
	Rows -->|No| Conflict([Raise UpdateError])
	Rows -->|Yes| Return([Return saved report])
	Insert --> Return
```

## Failure and edge-case behavior

- **Double-increment defect (confirmed)**: `UpdateNum` advances by 2 per update rather than 1, because both the VB `BeforeUpdate` logic and the bound UPDATE statement each add one to the value. Over repeated updates this will cause the in-memory `UpdateNum` a caller expects to diverge from the persisted `UPDATE_NUM`, which can trigger spurious optimistic-concurrency failures on a subsequent save if the caller re-reads and reuses a stale expected value.
- The update-date defaulting rule ([BR-CE-010](../business-rules.md#br-ce-010-pharmacy-eligibility-update-date-must-use-override-or-default-to-current-timestamp)) means two updates issued in the same instant without an override could produce identical timestamps, which downstream reporting logic (see [Pharmacy report retrieval](pharmacy-report-retrieval.md)) treats as "unchanged" for change-only extraction purposes.*

## 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.

## Sources

- `Business\SAIF.Business.Claim.Entry\clsPharmacyEligibility.vb`
