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

# Address Data API

Table `5523606` `bdev.Address Data` is the tenant's directory of addresses already validated or confirmed by a user.

It answers a repeated validation without a service call, and it publishes a small set of procedures another extension can call directly.

```pascal
    addressData: Record "bdev.Address Data";
```

<Callout type="info" title="A table, not a codeunit">
These procedures are instance methods on the `bdev.Address Data` record variable itself, not on a separate API codeunit. Most of them read or change the row the variable is currently positioned on.
</Callout>

## Fields

| Field | Type | Description |
| ----- | ---- | ----------- |
| `Address` | Text[100] | Street and house number. Part of the primary key, not editable after insert. |
| `Address 2` | Text[50] | Additional address information. Part of the primary key. |
| `Post Code` | Code[20] | Part of the primary key. |
| `City` | Text[30] | Part of the primary key. |
| `County` | Text[30] | Part of the primary key. |
| `Country/Region Code` | Code[10] | Part of the primary key. |
| `Address Validation Status` | Option | `Not Validated`, `Manually Checked` or `Validated`. See [Status](#status). |
| `Last Date Validated` | Date | Set automatically whenever the status changes to anything other than `Not Validated`. |
| `Usage` | Integer (FlowField) | How many source records currently point at this address. |

The six address fields together form the primary key, so two rows with the same address never exist. Changing any of them resets `Address Validation Status` to `Not Validated`.

## Status

```pascal
    Rec."Address Validation Status"::"Not Validated"
    Rec."Address Validation Status"::"Manually Checked"
    Rec."Address Validation Status"::Validated
```

A row starts as `Not Validated` on insert. It becomes `Validated` when the validation service has confirmed it and `Manually Checked` when a user confirms it by hand on the **Address Data** page. Both count as validated for [IsValidated](#isvalidated) and [IsKnownAddress](#isknownaddressrecord).

## IsValidated()

Four overloads answer whether an address is already validated, without calling the service.

```pascal
    procedure IsValidated(): Boolean
    procedure IsValidated(addressBuffer: Record "bdev.Address Validation Buffer" temporary): Boolean
    procedure IsValidated(recordVariant: Variant): Boolean
    procedure IsValidated(recordVariant: Variant; addressOptionOrdinal: Integer): Boolean
```

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| (none) | | Checks the status of the row `Rec` is currently positioned on. |
| `addressBuffer` | Record "bdev.Address Validation Buffer" temporary | Looks up the row with this address and checks its status. `false` when no such row exists. |
| `recordVariant` | Variant | A record of one of the tables the app supports (see [Address Validation API](address-validation-api.mdx#validaterecord)). The app builds the address from it first. |
| `addressOptionOrdinal` | Integer | Which address on the record to use, for a table that carries more than one (for example a sales document's sell-to, ship-to and bill-to addresses). |

**Returns** `true` when the matching row has status `Manually Checked` or `Validated`.

## IsKnownAddress(Record)

```pascal
    procedure IsKnownAddress(var addressBuffer: Record "bdev.Address Validation Buffer" temporary): Boolean
```

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `addressBuffer` | Record "bdev.Address Validation Buffer" temporary | The address to look up. On a match, `Rec` is positioned on the found row and `addressBuffer` is filled with its values. |

**Returns** `true` when the address is already known and validated. This is the lookup the app itself runs before calling the service: a hit here means the address does not need to go to the service again.

## AddOrUpdate(...)

Inserts the address if it is not yet known, or finds the existing row, and records that `source` uses it. Four overloads, depending on whether the address comes from a validation buffer or from the dictionary [Address Prediction API](address-prediction-api.mdx) returns, and on whether the source record carries more than one address.

```pascal
    procedure AddOrUpdate(addressBuffer: Record "bdev.Address Validation Buffer" temporary; source: Variant)
    procedure AddOrUpdate(addressBuffer: Record "bdev.Address Validation Buffer" temporary; source: Variant; addressOptionOrdinal: Integer)
    procedure AddOrUpdate(addressBuffer: Dictionary of [Text, Text]; source: Variant)
    procedure AddOrUpdate(addressBuffer: Dictionary of [Text, Text]; source: Variant; addressOptionOrdinal: Integer)
```

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `addressBuffer` | Record "bdev.Address Validation Buffer" temporary, or Dictionary of [Text, Text] | The address to add or update. An address with neither `Address`, `Address 2`, `Post Code` nor `City` filled is ignored. |
| `source` | Variant | The record that uses this address, for the `Usage` count. Pass a record of `bdev.Address Data` itself to skip the usage link. |
| `addressOptionOrdinal` | Integer | Which address on `source` this is, for a table with more than one. Omit it, or pass `-1`, for a table with a single address. |

This call does not validate the address and does not change its status - it only makes sure the address exists in the directory and is linked to `source`. Call [SetValidatedManually](#setvalidatedmanually) afterwards if you know by other means that the address is correct.

## SetValidatedManually()

```pascal
    procedure SetValidatedManually()
```

Sets the status of the row `Rec` is positioned on to `Manually Checked` and saves it. Use this after `AddOrUpdate` when your own process has already confirmed the address is correct and a service call is not needed.

## ResetValidation()

```pascal
    procedure ResetValidation()
```

Sets the status of the row `Rec` is positioned on back to `Not Validated` and saves it. The next automatic or manual validation then calls the service again instead of answering from the directory.

### Example

```pascal
    procedure MarkBrokerAddressAsChecked(var broker: Record Broker)
    var
        addressData: Record "bdev.Address Data";
        address: Record "bdev.Address Validation Buffer" temporary;
    begin
        address.Init();
        address."Primary Key" := CreateGuid();
        address.Address := broker.Address;
        address."Address 2" := broker."Address 2";
        address."Post Code" := broker."Post Code";
        address.City := broker.City;
        address.County := broker.County;
        address."Country/Region Code" := broker."Country/Region Code";

        if (addressData.IsKnownAddress(address)) then
            exit;

        addressData.AddOrUpdate(address, broker);
        addressData.SetValidatedManually();
    end;
```

<Callout type="caution" title="AddOrUpdate does not validate">
`AddOrUpdate` only records that an address exists and who uses it. If the address has not gone through [Address Validation API](address-validation-api.mdx) and you have not called `SetValidatedManually`, its status stays `Not Validated` and `IsValidated`/`IsKnownAddress` answer accordingly.
</Callout>

## See also

- [365 business Address Validation - Overview](readme.mdx)
- [Address Validation API](address-validation-api.mdx)
- [Checking orders from an external system](examples/validate-api-orders.mdx)
- [Documentation - 365 business Address Validation](../../en-us/365-business-address-validation/index.mdx)
