import { Callout } from "zudoku/ui/Callout";

# Extensibility Events

The `bdev.Sanction Screen Integ.` codeunit (`5524125`) is the integration point for extending the screening. It publishes events to enrich or correct the data before it is sent to the data sources, and to skip the screening for individual records.

These events fire for **every** screened entity, including sources added by another extension.

## OnBeforeMatchRecord - Event

The `OnBeforeMatchRecord` event is raised before the screening record is sent to the data sources. Use this event to enrich or correct the screening record, or to skip the screening for individual records by setting `isHandled` to `true`.

```pascal
    /// <summary>
    /// Event that is raised before the actual matching is performed.
    /// This event can be used to modify the screening record before it is sent for matching, or to skip
    /// the matching for the screening record.
    /// </summary>
    /// <param name="screeningRecord">The screening record that is about to be matched.</param>
    /// <param name="isHandled">Set to true to skip the matching for the screening record. No matches are created and the screening is logged as skipped.</param>
    [IntegrationEvent(false, false)]
    local procedure OnBeforeMatchRecord(var screeningRecord: Record "bdev.Sanction Screening Model"; var isHandled: Boolean)
    begin
    end;
```

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `screeningRecord` | Record "bdev.Sanction Screening Model" | The screening record that is about to be matched. Changes to the record are used for the screening. |
| `isHandled` | Boolean | Set to `true` to skip the screening for this record. |

<Callout type="tip" title="Good to know">
`OnBeforeMatchRecord` has been introduced with 365 business Sanction Screen version 18.2.<br/>
    <br/>
    Please consider update 365 business Sanction Screen to get access to the event.
</Callout>

### Skipping the screening

When a subscriber sets `isHandled` to `true`, no request is sent to the data sources and no match entries are created. The screening is written to the `Sanction Screening Log` with the status `Skipped`, so that the skip can be audited.

A skipped screening does not report the source record as screened:

 - `GetLastScreeningResult` and `GetLastDateOfScreening` ignore skipped screenings and keep returning the last screening that has actually been performed.
 - The screening indicator keeps showing the record as unscreened, and the behavior configured in the `Unscreened Entity Status` field of the `Sanction Screen Setup` still applies to sales and purchase documents.
 - The audit report lists the record under the exceptions, as a screening that was skipped rather than as one that was performed.

<Callout type="caution" title="Compliance">
Skipping the screening means that the source record is not checked against the sanction and PEP data sources. Make sure that skipping a record is covered by your compliance requirements.
</Callout>

#### Stating why a record was skipped

As of version 18.3 a subscriber can state the reason for the skip in the `Skip Reason` field of the screening record. The reason is written to the `Status Details` of the log entry and is printed in the [audit report](../../en-us/365-business-sanction-screen/audit-report.mdx) next to the skipped screening. Without a reason the log entry only says that an extension skipped the screening, which is of little use to an auditor asking why.

| Field | Type | Description |
| ----- | ---- | ----------- |
| `Skip Reason` | Text[250] | Why the screening was skipped. Optional; a generic text is logged when it is left empty. |

#### Example

The following example skips the screening for customers that are marked as `Blocked`, as they cannot be used in business transactions anyway, and states why:

```pascal
codeunit 50000 "My Sanction Screen Subscriber"
{
    [EventSubscriber(ObjectType::Codeunit, Codeunit::"bdev.Sanction Screen Integ.", 'OnBeforeMatchRecord', '', true, true)]
    local procedure SkipBlockedCustomersOnBeforeMatchRecord(var screeningRecord: Record "bdev.Sanction Screening Model"; var isHandled: Boolean)
    var
        customer: Record Customer;
    begin
        if (screeningRecord."Source Type" <> Enum::"bdev.Sanction Screening Source"::Customer) then
            exit;

        if (not customer.GetBySystemId(screeningRecord."Source System ID")) then
            exit;

        isHandled := (customer.Blocked <> Enum::"Customer Blocked"::" ");
        if (isHandled) then
            screeningRecord."Skip Reason" := BlockedCustomerSkipReasonLbl;
    end;

    var
        BlockedCustomerSkipReasonLbl: Label 'The customer is blocked and cannot be used in business transactions.';
}
```

## OnAfterInitializeModelFromSource - Event

The `OnAfterInitializeModelFromSource` event is raised after the screening record has been initialized from the source record. Use this event to add data of the source record to the screening record, for example data of your own table extension.

```pascal
    /// <summary>
    /// Event that is raised after the screening record has been initialized from the source record.
    /// This event can be used to modify the screening record after it has been initialized from the source record.
    /// </summary>
    /// <param name="screeningRecord">The screening record that has been initialized from the source record.</param>
    /// <param name="sourceRecordVariant">The variant containing the source record.</param>
    [IntegrationEvent(false, false)]
    local procedure OnAfterInitializeModelFromSource(var screeningRecord: Record "bdev.Sanction Screening Model"; sourceRecordVariant: Variant)
    begin
    end;
```

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `screeningRecord` | Record "bdev.Sanction Screening Model" | The screening record that has been initialized from the source record. |
| `sourceRecordVariant` | Variant | The variant containing the source record, for example a `Customer` or a `Sales Header` record. |

<Callout type="info" title="What you add here becomes evidence">
The screened attributes are recorded on the screening log entry and printed in the audit report. Data you add through this event therefore appears in the evidence document as part of what was checked - which is the point, but worth knowing before you add anything personal that does not belong there.
</Callout>

## OnAfterUpdateIndicator - Event

The screening indicator factbox raises `OnAfterUpdateIndicator` while it builds the checklist it shows on a card. Use it to add checklist items of your own, for example the result of a check your extension performs alongside the sanction screening.

```pascal
    [IntegrationEvent(false, false)]
    local procedure OnAfterUpdateIndicator(var checklistItems: Record "bdev.OS Control Checklist Item"; screeningResult: Record "bdev.OS Screening Result" temporary)
    begin
    end;
```

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `checklistItems` | Record "bdev.OS Control Checklist Item" | The checklist the indicator shows. Insert your own items here. |
| `screeningResult` | Record "bdev.OS Screening Result" | The result of the last screening of the record the card shows. |

The indicator only shows a checklist when it holds more than one item, so a single added item replaces nothing and shows nothing on its own.

## OnBeforeMatch - Event (deprecated)

<Callout type="caution" title="Deprecated">
`OnBeforeMatch` is obsolete as of 365 business Sanction Screen version 18.2. Use [OnBeforeMatchRecord](#onbeforematchrecord---event) instead, which additionally allows to skip the screening.
</Callout>

The `OnBeforeMatch` event is raised before the screening record is sent to the data sources and only allows to modify the screening record. It is still raised for existing subscribers, right before `OnBeforeMatchRecord`.

```pascal
    /// <summary>
    /// Event that is raised before the actual matching is performed.
    /// This event can be used to modify the screening record before it is sent for matching.
    /// </summary>
    /// <param name="screeningRecord">The screening record that is about to be matched.</param>
    [Obsolete('This event is obsolete. Use the OnBeforeMatchRecord event instead, which additionally allows to skip the matching.', '18.2')]
    [IntegrationEvent(false, false)]
    local procedure OnBeforeMatch(var screeningRecord: Record "bdev.Sanction Screening Model")
    begin
    end;
```

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `screeningRecord` | Record "bdev.Sanction Screening Model" | The screening record that is about to be matched. |

## See also

- [365 business Sanction Screen - Overview](readme.mdx)
- [Sanction Screening Source](sanction-screening-source.mdx)
- [Documentation - 365 business Sanction Screen](../../en-us/365-business-sanction-screen/index.mdx)
