---
title: Filtering the Account Master Using Account Codes
description: "In Assette, it is common for firms to create custom Data Blocks that source data from system-defined blocks, such as the [Account Master Data Block](https://learn.assette.com/docs/account-master-data-block/). In this article, we'll refer to any such custom Data Block that queries the Account…"
url: "https://learn.assette.com/docs/filtering-accountmaster-with-account-code/"
updated: "2025-04-09"
category: Developers / Data Blocks / Data Blocks by Functionality / Account Master
---

# Filtering the Account Master Using Account Codes

In Assette, it is common for firms to create custom Data Blocks that source data from system-defined blocks, such as the [Account Master Data Block](https://learn.assette.com/docs/account-master-data-block/). In this article, we'll refer to any such custom Data Block that queries the Account Master Data Block simply as "CustomBlock". The CustomBlock Data Block is intended represent a Data Block which retrieves information for a single account based on user input.

This article explains why this happens, how to handle it properly, and how the behavior changes depending on whether you're using one or multiple filtering parameters.

## Understanding the Account Master Data Block

The [Account Master Data Block](https://learn.assette.com/docs/account-master-data-block/) is a [System Data Block](https://learn.assette.com/docs/system-data-blocks-overview/) provided by Assette. It includes complex logic to support a wide variety of filtering use cases across products, strategies, countries, and more. It is used behind the scenes by many components, and its behavior is intentionally flexible.

However, because of this flexibility, its filtering logic can behave differently based on the parameters passed to it — especially these three:

- Code
- AccountCode
- AccountCodeList

## How Code, AccountCode, and AccountCodeList Interact

When you pass parameters to AccountMaster, it goes through internal pre-processing logic that determines how the filtering will be applied. Here's how these parameters influence the final behavior:

### Code

This is the **main identifier** used by AccountMaster Data Block to retrieve specific accounts.

If `Code` contains **multiple values** (e.g., `"12345,67890"` or `"12345|67890"`), the logic assumes it is a list and **moves the value to `AccountCodeList`**. `Code` is then cleared to avoid ambiguity. As seen in the Account Master Data Block:

```
if Code != "" and "," in Code:
    AccountCodeList = str(Code).replace(",", "|")
    Code = ""
elif Code != "" and "|" in Code:
    AccountCodeList = Code
    Code = ""
```

### AccountCode

- This is typically the parameter passed from a user interface or calling block when the user selects a single account.
- Inside AccountMaster, if AccountCode is populated, it is **automatically copied to the `Code` parameter** if `Code` is not already set.

```
if (params.get("AccountCode") or "") != "":
    Code = params.get("AccountCode")
    if (params.get("Code") or "") == "":
        params["Code"] = Code
```

### AccountCodeList

- This parameter is used when multiple accounts are being requested.
- If `Code` is treated as a list, it ends up here. This means your intended single-account filter could be **silently broadened**, causing AccountMaster to return multiple accounts.

## The Role of Custom Data Blocks

Many firms use a custom block, referred to here as "CustomBlock", which is responsible for returning **details about a single account**. This block typically reads from AccountMaster and extracts specific fields like AccountID, Name, StrategyName, ProductCode, or RepAccountCode. This version assumes that the read() call will return exactly **one record**, which is often **not the case** due to the behavior described above.

A typical simplified definition of CustomBlock might look like this:

```
errors = []
data = {}

account_detail_keyset = {"AccountID", "Name", "StrategyName", "ProductCode", "RepAccountCode"}

try:
    account_master = read("AccountMaster", {"Code": str(params["AccountCode"])})["data"][0]
    for key in account_detail_keyset:
        if key in account_master:
            data[key] = account_master[key]
except:
    errors.append("Error reading AccountMaster block.")

response["data"] = data
response["errors"] = errors
```

## Problem Scenario: Only One Parameter Is Used

When only one filtering parameter is passed — such as AccountCode — the results can be unpredictable if the value is misinterpreted by AccountMaster.

```
{
"AccountCode": "bblcvmodel"
}
```

If "bblcvmodel" is interpreted as a list (e.g., if it accidentally includes a comma or pipe), it is moved to AccountCodeList, and Code is cleared. As a result, the AccountMaster block performs a broad search, possibly returning multiple accounts. In your custom CustomBlock, the line:

```
account_master = read("AccountMaster", {"Code": str(params["AccountCode"])})["data"][0]
```

will return the **first record**, which may not be the correct account.

## Solution: Filter the Result Locally in CustomBlock

To ensure correctness, especially when only one parameter is being used, you should:

1. Allow `AccountMaster` to return multiple results.
2. Apply local filtering in your CustomBlock block to find the specific match.

### Updated Logic

```
account_master_data = read("AccountMaster", {"Code": str(params["AccountCode"])})["data"]

account_master = next(
    (item for item in account_master_data if item.get("Code") == str(params["AccountCode"])),
    None
)

if account_master:
    for key in bg_account_detail_keyset:
        if key in account_master:
            data[key] = account_master[key]
```

This ensures that even if AccountMaster returns multiple records, you only use the one that matches the provided AccountCode.

## When Two or More Parameters Are Used

If you provide multiple parameters — such as both ProductCode and StrategyName — the filtering behavior in AccountMaster becomes more targeted.

```
filters =
    "ProductCode": "EQUITY",
    "Strategy": "Core"
}
account_master_data = read("AccountMaster", filters)["data"]
```

In this case, `AccountMaster` will try to return only those accounts that match **both conditions**. However, even this may not guarantee a **single result**, depending on your data.

You should still apply local filtering inside CustomBlock if you're looking for a specific account:

```
account_master = next(
    (item for item in account_master_data
     if item.get("ProductCode") == "EQUITY" and item.get("StrategyName") == "Core"),
    None
)
```

## Dynamic Parameter Handling

You can dynamically construct your filter dictionary based on the parameters the user provides:

```
filters = {}
if params.get("ProductCode"):
    filters["ProductCode"] = params["ProductCode"]
if params.get("StrategyName"):
    filters["Strategy"] = params["StrategyName"]
if params.get("AccountCode"):
    filters["Code"] = params["AccountCode"]

account_master_data = read("AccountMaster", filters)["data"]
```

This keeps your logic flexible and scalable without assuming which parameters will always be available.

## Best Practices

The following table summarized the various scenarios discussed above and provided the recommended approach in each case.

| Scenario | Recommended Approach |
| --- | --- |
| Only AccountCode used | Pass `Code` to AccountMaster, **filter locally** in CustomBlock |
| Only non-unique param used (e.g., `StrategyName`) | Pass it as filter, **expect multiple**, **filter locally** |
| Multiple parameters used | Pass all filters, still **validate locally** in case of multiple results |
| Want strict match on single account | Always apply `next(... for item in data if item["Code"] == ...)` |
| Relying solely on `["data"][0]` | **Not recommended** — may return wrong account |
