Operational Dashboard - Changes & Fixes

This page covers the changes and fixes provided to Operational Dashboard for IPF Release 2025.3.0

Breaking Changes

Angular 19 Upgrade

As of 2025.3 the Operational Dashboard and all related modules have been updated to Angular 19.

To migrate:

@iconsolutions/audit

  • Bump npm module to "@iconsolutions/audit": "^1910.0.2 " in package.json

@iconsolutions/cluster-health

  • Bump npm module to "@iconsolutions/cluster-health": "^1910.0.2 " in package.json

@iconsolutions/common

  • Bump npm module to "@iconsolutions/common": "^1910.0.2 " in package.json

@iconsolutions/ods

  • Bump npm module to "@iconsolutions/ods": "^1910.0.2 " in package.json

@iconsolutions/htm

  • Bump npm module to "@iconsolutions/htm": "^1910.0.2 " in package.json

@iconsolutions/metrics

  • Bump npm module to "@iconsolutions/metrics": "^1910.0.2 " in package.json

@iconsolutions/permissions

  • Bump npm module to "@iconsolutions/permissions": "^1910.0.2 " in package.json

@iconsolutions/processing-settings

  • Bump npm module to "@iconsolutions/processing-settings": "^1910.0.2 " in package.json

@iconsolutions/version-info

  • Bump npm module to "@iconsolutions/version-info": "^1910.0.2 " in package.json

Migration to PrimeNG for Common Components

Certain common components now use PrimeNG. To ensure everything works correctly, these packages must be installed:

  • "primeng": "^19.1.4"

  • "primeicons": "^7.0.0"

  • "@primeng/themes": "^19.1.4"

To install, run the following command:

npm install primeng@^19.1.4 primeicons@^7.0.0 @primeng/themes@^19.1.4

Summary Search CSV Export

The export to CSV for the summary search results has been changed to support custom summary fields. This adds additional fields to a summary export, and those fields potentially change depending on the summaries that are included in the export.

Whilst implementing this, we noticed a potential bug that is more likely with custom summary fields. Fixing that bug unfortunately results in changes to the behaviour of the CSV export.

All changes are listed below with before/after examples.

Null Values

Null values are exported as null, not a quoted single space.

Example:

header1,header2,header3,header4
" ","value"," ","another value"

becomes

header1,header2,header3,header4
,"value",,"another value"

Quoted Values

Not all headers and values are quoted. Only those with spaces, commas, or those that are particularly long.

"header1","header 2","returnedInterbankSettlementAmountCurrency"
"nospaces","value with spaces","value,with,commas"

becomes

header1,"header 2","returnedInterbankSettlementAmountCurrency"
nospaces,"value with spaces","value,with,commas"

CSV Separator And Whitespace Support

Summary values may contain commas and whitespace such as newlines. Until this change these values would’ve resulted in an invalid CSV.

header1,header2
"a","b","c","d","e"

becomes

header1,header2
"a,b,c","d,e"

Column Ordering

The columns in the CSV export are lexicographically ordered. The previous behaviour depended on the order of fields in some generated code which could change. The new ordering should be more stable.

header1,header2,header10,headerZ,headerA
1,2,3,4,5

becomes

header1,header10,header2,headerA,headerZ
1,3,2,5,4

Custom Summary Fields

Custom summary fields are included in the CSV export. The fields are always last in the output after all the default columns, and are also lexicographically ordered.

A side effect of including these fields is that the CSV export can be different depending on the summaries included within it. Not all summaries will contain the same custom fields.

unitOfWorkId,createdAt
uow1,"17/03/2022 08:53:16Z"
uow2,"18/03/2022 08:53:16Z"

becomes

unitOfWorkId,createdAt,customBoolean,customNumber,customString,customZ
uow1,"17/03/2022 08:53:16Z",true,42,"some value",
uow2,"18/03/2022 08:53:16Z",false,,,"value for custom field z"

Removed datetimeInput from Date Formats Config

The datetimeInput property has been removed from the date formats config as it is no longer used in the UI. With the move to PrimeNG datepicker, the datetime input format is no longer required as the date pickers only support hours, minutes, and seconds. The time has been set to a 24h clock by default.

Reason Code List Update

The Reason Code list in the ops-gui-service-ng configuration has been updated to include new reason codes as well as remove obsolete ones.

The structure of the reason code object was updated as well to include a new property called definitionKey, which allows you to define a translation key for the reason code definition. If no definitionKey value is provided, then the definition value is used as a fallback. However, the definitionKey property needs to be added to the config, even if left empty. The definitionKey string should be "definition.<reason-code>", where <reason-code> is the reason code itself. You can see an example below.

Example of new reason code config:

reason-codes = [
    {
      reasonCode = "AB06",
      definition = "Transaction stopped due to timeout at the Instructed Agent.",
      definitionKey = "definition.AB06",
      source = "ISO"
    },
    {
      reasonCode = "AB07",
      definition = "Agent of message is not online. Generic usage if it cannot be determined who exactly is not online.",
      definitionKey = "definition.AB07",
      source = "ISO"
    },
    {
      reasonCode = "AB08",
      definition = "Creditor Agent is not online.",
      definitionKey = "definition.AB08",
      source = "ISO"
    }
]

New

Flow Visualisation in ODS

We’ve introduced a new “Lifecycle” tab on the view screen for payments, recalls, bulks, and batches. This tab provides an alternative to the existing “Details” tab, focusing on a visual representation of how a specific payment, recall, bulk, or batch moved through the system. It includes a quick-filter search box to allow users to quickly find specific steps in the flow.

Fixed

Changed

  • supportingData now displayed in HTM Task view (PAY-14654)

taskDetails.supportingData can now be displayed in HTM Task View by adding the relevant values to the HTM custom page configuration.

  • Custom summary fields are included in the CSV export. Supporting this functionality introduces some potentially breaking changes, see the breaking changes section for more information.

This is a breaking change as the type of taskDetails in the HTM State has changed from TaskDetails to ParsedTaskDetails.

The only change between these models is that previously, taskDetails.supportingData.value was a string. It is now an object.

ParsedTaskDetails {
    // all other fields are unchanged

    supportingData?: {
        type?: string;
        value?: object;
    }
}
  • Add executionResultData to HTM Task (PAY-13686)

The execution form is now predefined and can be included by adding a card containing only predefined = "EXECUTION_FORM" to any panel:

panels = [
  {
    cards = [
      {
        predefined = "EXECUTION_FORM"
      }
    ]
  }
]

The input from all other form groups is added to executionResultData in the execute request.

Please refer to the HTM Page Config Documentation for more details.

Reason Code List Update

The Reason Code list in the ops-gui-service-ng configuration has been updated to include new reason codes as well as remove obsolete ones.

The structure of the reason code object was updated as well to include a new property called definitionKey, which allows you to define a translation key for the reason code definition. If no definitionKey is provided, then the definition value is used as a fallback. The definitionKey string should be "definition.<reason-code>", where <reason-code> is the reason code itself. You can see an example below.

Example of new reason code config:

reason-codes = [
    {
      reasonCode = "AB06",
      definition = "Transaction stopped due to timeout at the Instructed Agent.",
      definitionKey = "definition.AB06",
      source = "ISO"
    },
    {
      reasonCode = "AB07",
      definition = "Agent of message is not online. Generic usage if it cannot be determined who exactly is not online.",
      definitionKey = "definition.AB07",
      source = "ISO"
    },
    {
      reasonCode = "AB08",
      definition = "Creditor Agent is not online.",
      definitionKey = "definition.AB08",
      source = "ISO"
    }
]

Moved ODS Search Forms to Config to Support Custom Fields

The search forms for ODS search pages (payment, recall, bulk, and batch) have been moved to config to allow for custom fields to be added. Any custom fields that you add to the search forms must be prefixed with 'custom_' for example custom_customSearchableStringField. All search forms should be added to one config property called search-forms, which is an array of search form objects. In the example below, we show the config for the payment search form. If you wanted to add recall, bulk or batch search forms, you can follow the same structure as the payment search form and change the searchType to either recall, bulk or batch.

If no config is provided, the default search forms will be used.

Example config for payment search form:

search-forms = [
    {
      searchType: "payment",
      formSections: [
        {
          id: "ids",
          name: "heading.ids",
          size: "DOUBLE",
          fields: [
            {
              id: "uowId",
              name: "formField.unitOfWorkId",
              type: "STRING"
            },
            {
              id: "clientRequestId",
              name: "formField.clientRequestId",
              type: "STRING"
            },
            {
              id: "instructionId",
              name: "formField.instructionId",
              type: "STRING"
            },
            {
              id: "transactionId",
              name: "formField.transactionId",
              type: "STRING"
            },
            {
              id: "uetr",
              name: "formField.uetr",
              type: "STRING"
            },
            {
              name: "formField.alternativeIdentifierName",
              type: "ALTERNATIVE_IDENTIFIER"
            },
            {
              id: "alternativeIdentifierValue",
              name: "formField.alternativeIdentifierValue",
              type: "STRING"
            },
            {
              id: "relatedUnitOfWorkId",
              name: "formField.relatedUnitOfWorkId",
              type: "STRING"
            }
          ]
        },
        {
          id: "summary",
          name: "heading.summaryInfo",
          size: "SINGLE",
          fields: [
            {
              name: "formField.reasonCode",
              type: "REASON_CODE"
            },
            {
              name: "formField.globalStatus",
              type: "GLOBAL_STATUS"
            },
            {
              name: "formField.transactionType",
              type: "TRANSACTION_TYPE"
            },
            {
              id: "csm",
              name: "formField.csm",
              type: "STRING"
            }
          ]
        },
        {
          id: "dates",
          name: "heading.dates",
          fields: [
            {
              id: "date",
              name: "formField.date",
              type: "PAYMENT_DATES"
            }
          ]
        },
        {
          id: "amounts",
          name: "heading.amounts",
          fields: [
            {
              id: "amount",
              name: "formField.amount",
              type: "PAYMENT_AMOUNTS"
            }
          ]
        },
        {
          id: "debtor",
          name: "heading.debtorDetails",
          size: "SINGLE",
          fields: [
            {
              id: "debtorName",
              name: "formField.debtorName",
              type: "STRING"
            },
            {
              id: "debtorAccount",
              name: "formField.debtorAccount",
              type: "STRING"
            },
            {
              id: "debtorAgentBIC",
              name: "formField.debtorAgentBIC",
              type: "STRING"
            },
            {
              id: "debtorBIC",
              name: "formField.debtorBIC",
              type: "STRING"
            }
          ]
        },
        {
          id: "creditor",
          name: "heading.creditorDetails",
          size: "SINGLE",
          fields: [
            {
              id: "creditorName",
              name: "formField.creditorName",
              type: "STRING"
            },
            {
              id: "creditorAccount",
              name: "formField.creditorAccount",
              type: "STRING"
            },
            {
              id: "creditorAgentBIC",
              name: "formField.creditorAgentBIC",
              type: "STRING"
            },
            {
              id: "creditorBIC",
              name: "formField.creditorBIC",
              type: "STRING"
            }
          ]
        },
        {
          id: "accounts",
          name: "heading.accountDetails",
          size: "SINGLE",
          fields: [
            {
              id: "creditAccount",
              name: "formField.creditAccount",
              type: "STRING"
            },
            {
              id: "debitAccount",
              name: "formField.debitAccount",
              type: "STRING"
            },
            {
              id: "customSearchableStringField",
              name: "formField.customField1",
              type: "STRING"
            },
            {
              id: "customSearchableStringField2",
              name: "formField.customField2",
              type: "STRING"
            },
            {
              id: "customSearchableStringField3",
              name: "formField.customField3",
              type: "STRING"
            }
          ]
        }
      ]
    }
]

Explanation of fields:

Name

Description

searchType: String

The type of search form you want to configure. This can be payment, recall, bulk, or batch.

formSections: FormSection[]

The form section to be displayed. A FormSection is a group of form fields that appear in the search form.

id: String

The unique identifier for the form section.

name: String

The name of the form section. This is the title that will be displayed on the UI and it should be a translation key.

size: Size

This is the size of the form section. It is a Size enum that can either be SINGLE or DOUBLE. SINGLE will take up one column and DOUBLE will take up more than one column.

fields: FormField[]

The form fields to be displayed in the form section. A FormField is a single field that appears in the search form.

id: String

The unique identifier for the form field. This should be the same as the field name in the PDS or MDS that is returned from the backend.

name: String

The name of the form field. This is the label that will be displayed on the UI and it should be a translation key.

type: FormFieldType

The type of the form field. It is a FieldType enum that can be one of the following: STRING, ALTERNATIVE_IDENTIFIER, REASON_CODE, GLOBAL_STATUS, TRANSACTION_TYPE, PAYMENT_DATES, PAYMENT_AMOUNTS, RECALL_DATES, RECALL_AMOUNTS, BULK_DATES, BULK_AMOUNTS, BATCH_DATES, BATCH_AMOUNTS, CHECKBOX, NUMBER, DATE, DATETIME

There are different date and amount types for payment, recall, bulk, and batch, which is why there are different field types for each of these e.g. PAYMENT_DATES, RECALL_DATES, BULK_DATES, BATCH_DATES, PAYMENT_AMOUNTS, RECALL_AMOUNTS, BULK_AMOUNTS, BATCH_AMOUNTS. The dates and amounts should be in their own section as based on the date or amount type selected, different fields will be shown in the UI.

The ALTERNATIVE_IDENTIFIER, REASON_CODE, TRANSACTION_TYPE, and GLOBAL_STATUS field types will show an autocomplete or dropdown field in the UI with the values defined in the config for alternative identifiers, reason codes, transaction types, and global statuses respectively.

Translations

The following translation keys have been added or updated in this release:

odsSearch

Add:

{
    "text": {
         "ariaQuickFilter": "Text input to filter flow events"
    },
    "formField": {
        "quickFilter": "Quick Filter"
    },
    "tab": {
        "lifecycle": "Lifecycle"
    }
}

common

Change:

{
    "formField": {
        "dateFrom": "Date From",
        "dateTo": "Date To"
    }
}

To:

{
    "formField": {
        "dateRange": "Date Range",
    }
}

Add:

{
    "button": {
        "goBack": "Go Back"
    },
    "error": {
        "error": "Error",
    },
    "heading": {
        "unsavedChanges": "Unsaved Changes"
    },
    "text": {
        "ariaFilterLabel": "Filter items",
        "rowIsClickableMessage": "This row is clickable and navigates to {{item}}",
        "unsavedChangesMessage": "Your changes have not been saved. Are you sure you want to leave?"
    }
}

metrics

Change:

{
    "formField": {
        "timestampFrom": "Timestamp From",
        "timestampTo": "Timestamp To",
    }
}

To:

{
    "formField": {
        "timestampFrom": "Timestamp From:",
        "timestampTo": "Timestamp To:",
    }
}

htm

Change:

{
    "columnHeader": {
        "fromDueDate": "From Due Date",
        "toDueDate": "To Due Date",
    }
}

To:

{
    "columnHeader": {
        "fromDueDateTime": "From Due Date",
        "toDueDateTime": "To Due Date",
    }
}

mdsSearch

Add:

{
    "columnHeader": {
        "unitOfWorkId": "Unit of Work ID",
        "clientRequestId": "Client Request ID",
        "actions": "Actions"
    },
    "tooltip": {
        "linkToUnitOfWork": "Link to Unit of Work",
        "viewChildren": "View Children",
        "exploreChildren": "Explore Children"
    }
}

permissions

Change:

{
    "roleDescriptions": {
        "ROLE_DPS_PE_C": "View Processing Entity within Processing Settings module.",
        "ROLE_DPS_PE_R": "Create Processing Entity within Processing Settings module.",
    }
}

To:

{
    "roleDescriptions": {
        "ROLE_DPS_PE_C": "Create Processing Entity within Processing Settings module.",
        "ROLE_DPS_PE_R": "View Processing Entity within Processing Settings module.",
    }
}

processingSettings

Add:

{
    "formField": {
         "deleteReason": "Deletion Reason"
    }
}