---
title: PPD award reference lookups
summary: Loads and caches the permanent partial disability body part table and the scheduled and unscheduled degree award rate tables, and calculates award amounts from them.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Business.Claim
reference_type: package
operation_id: OP-BC-14
trigger: A caller requests PPD body parts or a degree award amount through the PPD module accessors
---

# PPD award reference lookups

Permanent partial disability awards are priced from three reference tables: the body part table, which says whether a body part is scheduled and how many degrees it can carry; the scheduled degree award table, which gives a flat rate per degree effective from a date; and the unscheduled degree award table, which prices degrees in bands so that higher degree counts earn progressively different rates. This operation loads all three, caches them in module-level statics so the round trip happens once per process, and exposes the calculations that turn a degree count and an effective date into an award amount.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-BC-14 |
| **Trigger** | `PPD.GetBodyParts(dataPortalInfo, refresh)`, `PPD.GetScheduledDegreeAwards(dataPortalInfo, refresh)`, `PPD.GetUnScheduledDegreeAwards(dataPortalInfo, refresh)`, then `GetAwardAmount` on the returned table |
| **Inputs** | A data portal info; an optional refresh flag; for the award calculations, an effective date and — for unscheduled awards — a number of degrees |
| **Outputs** | A body part code table keyed by body part code; a date-keyed scheduled rate table; a date-keyed table of unscheduled degree bands; a calculated award amount; a step-by-step calculation proof for unscheduled awards |
| **Primary components** | `mdlPPD.GetBodyParts`, `mdlPPD.GetScheduledDegreeAwards`, `mdlPPD.GetUnScheduledDegreeAwards`, `clsPPDBodyParts`, `clsPPDScheduledDegreeAwards.GetAwardAmount`, `clsPPDUnscheduledDegreeAwards.GetAwardAmount` |
| **Entry point** | `Business\SAIF.Business.Claim\mdlPPD.vb` |

## Steps

1. **Serve the cached table when possible.** Each module accessor holds the loaded table in a static local. The table is built on the first call, and rebuilt only when the caller passes the refresh flag, so subsequent callers pay no database cost.
2. **Load the body part table.** `clsPPDBodyParts` runs a result-set query selecting every column of the PPD body part code table ([SQL-009](../sql/SQL-009-saif-business-claim.md), [CL_PPD_BODY_PART_CODE](../database-tables.md#cl_ppd_body_part_code)).
   - Each row becomes a body part entry carrying the code, the description, an opposition flag converted to a boolean, the maximum scheduled degree count, a scheduled indicator derived from a scheduled/unscheduled code of `S`, and the sentence format description used when writing award language.
3. **Load the scheduled degree rates.** `clsPPDScheduledDegreeAwards` selects the effective date and the award amount per degree from the scheduled degree award table and stores them in a date-sorted map ([SQL-010](../sql/SQL-010-saif-business-claim.md), [CL_PPD_SCHED_DEGREE_AWARD](../database-tables.md#cl_ppd_sched_degree_award)).
4. **Price a scheduled award.** `GetAwardAmount` walks the date-sorted rates and returns the amount from the last entry whose effective date is on or before the supplied date, so an award is always priced at the rate in force when it became effective; when no rate qualifies, zero is returned ([BR-017](../business-rules.md#br-017-scheduled-ppd-awards-use-the-latest-rate-effective-on-or-before-the-award-date)).
5. **Load the unscheduled degree bands.** `clsPPDUnscheduledDegreeAwards` selects the upper degree boundary, the award amount per degree, and the effective date from the unscheduled degree award table, ordered by effective date and then by degree, and groups the rows into a date-sorted map of ordered bands ([SQL-011](../sql/SQL-011-saif-business-claim.md), [CL_PPD_UNSCHED_DEGREE_AWARD](../database-tables.md#cl_ppd_unsched_degree_award)).
6. **Price an unscheduled award across bands.** `GetAwardAmount` selects the band set effective on the award date and then walks the bands in ascending degree order, assigning as many of the remaining degrees as the band can absorb, multiplying them by that band's rate, and accumulating the running total until no degrees remain ([BR-018](../business-rules.md#br-018-unscheduled-ppd-awards-accumulate-across-cumulative-degree-bands)).
   - Each iteration records a proof entry capturing the step number, the degrees still to be allocated, the band's upper boundary, the band's rate, the degrees allocated to that band, the amount contributed, and the running total.
7. **Return the calculation proof.** The proof collection accompanies the calculated amount so a caller can display or audit exactly how a multi-band award was derived.

## Process flow

The following diagram visualizes the load-and-calculate flow.

```mermaid
flowchart TD
	Start([Caller requests a PPD<br>reference table]) --> Cache{Cached and<br>refresh not requested?}
	Cache -->|Yes| Serve([Return the cached table])
	Cache -->|No| Which{Which table?}
	Which -->|Body parts| Bp[Select the PPD body<br>part code table]
	Which -->|Scheduled| Sch[Select effective date<br>and rate per degree]
	Which -->|Unscheduled| Uns[Select degree boundary, rate<br>and effective date by date and degree]
	Bp --> Store[Store in the module<br>level static cache]
	Sch --> Store
	Uns --> Store
	Store --> Calc{Award amount requested?}
	Calc -->|Scheduled| Last[Take the last rate effective<br>on or before the award date]
	Calc -->|Unscheduled| Band[Allocate degrees across bands<br>in ascending degree order]
	Band --> Proof[Record a proof entry<br>for each band]
	Proof --> More{Degrees remaining?}
	More -->|Yes| Band
	More -->|No| Total([Return amount and proof])
	Last --> Amt([Return the amount,<br>or zero if no rate qualifies])
```

## Failure and edge-case behavior

- The caches are module-level statics with no expiry, so a rate table changed in the database is not seen until a caller explicitly requests a refresh or the process restarts.
- A scheduled award dated before the earliest effective rate is priced at zero rather than raising an error, so an out-of-range date silently produces a free award.
- Unscheduled award pricing depends on the bands being loaded in ascending degree order within each effective date; the ordering is imposed by the query rather than re-checked in code.*
- A degree count exceeding the highest band's boundary leaves degrees unallocated once the bands are exhausted, so the returned amount understates such an award.*
- The body part table's scheduled indicator is derived from a single-character code, so any value other than the scheduled marker is treated as unscheduled.
- These objects only read reference data; none of them exposes a write path, so rate maintenance happens outside this library.

## 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\mdlPPD.vb`
- `Business\SAIF.Business.Claim\clsPPDBodyParts.vb`
- `Business\SAIF.Business.Claim\clsPPDScheduledDegreeAwards.vb`
- `Business\SAIF.Business.Claim\clsPPDUnscheduledDegreeAwards.vb`
