---
title: Calculate notifications for a model
summary: Evaluate every rule in a notification matrix against a model and collect the non-null results.
status: draft
owner: SAIF.Core Documentation Team
last_reviewed: 2026-09-24
library: SAIF.Services.ClaimInfoApi.Core
reference_type: package
operation_id: OP-CIA-01
trigger: Caller invokes NotificationRuleEngine.CalculateNotifications<T>
---

# Calculate notifications for a model

This operation is the public entry point of the notification rule engine. It iterates every `NotificationRule` in a caller-supplied `NotificationMatrix`, evaluates each against a caller-supplied model, and returns the non-null results keyed by rule position.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-CIA-01 |
| **Trigger** | A caller request (public static method). |
| **Inputs** | `model` of any type `T`; `matrix` (`NotificationMatrix`), specifically its `Rules` array. |
| **Outputs** | A `NotificationResult[]` with at most one entry per distinct rule `Key` (rule `Position`). |
| **Primary components** | `NotificationRuleEngine.CalculateNotifications<T>` |
| **Entry point** | `Services/SAIF.Services.ClaimInfoApi.Core/NotificationRuleEngine.cs` (lines 11–32) |

## Steps

1. Create an empty dictionary of outputs keyed by string.
2. Iterate `matrix.Rules` in array order.
   - If `matrix.Rules` is null, a `NullReferenceException` is thrown; there is no null guard.
3. For each rule, evaluate it against the model via [Evaluate one rule](op-cia-02-evaluate-one-rule.md) ([CIA-BR-002](../business-rules.md#cia-br-002-evaluation-type-is-resolved-from-rule-metadata) through [CIA-BR-006](../business-rules.md#cia-br-006-a-true-bool-rule-without-an-out-property-falls-back-to-a-constant-out-value)).
4. If the evaluated value is non-null, compute `key = rule.Key` (the `Position` as a string) and add or overwrite the `NotificationResult(rule, value)` for that key ([CIA-BR-001](../business-rules.md#cia-br-001-notification-outputs-are-keyed-by-rule-position), [CIA-BR-007](../business-rules.md#cia-br-007-only-non-null-results-become-notifications-and-the-last-one-at-a-position-wins)).
   - Last non-null result wins for a duplicate position.
5. If the value is null, skip the rule; it produces no output ([CIA-BR-007](../business-rules.md#cia-br-007-only-non-null-results-become-notifications-and-the-last-one-at-a-position-wins)).
6. Return `outputs.Values.ToArray()`.
   - Array order follows `Dictionary` enumeration order, which is not formally guaranteed*.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Trigger]) --> S1["Iterate matrix.Rules"]
	S1 --> S2["Evaluate rule<br>(OP-CIA-02)"]
	S2 --> D{"Value non-null?"}
	D -->|Yes| S3["Add/overwrite result<br>keyed by Position"]
	D -->|No| Skip["Skip rule"]
	S3 --> S1
	Skip --> S1
	S1 -->|all rules done| EndOk([Return NotificationResult array])
```

## Failure and edge-case behavior
- `matrix.Rules == null`: throws `NullReferenceException`; there is no guard against this.
- Duplicate rule positions: the last non-null value evaluated wins, silently discarding earlier values for the same position.

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

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

## Sources
- `Services/SAIF.Services.ClaimInfoApi.Core/NotificationRuleEngine.cs`
