ODS Search

The ODS search module will let you search payments via a series of different fields (ID’s, party details and summary info).

Configuration

Config

This config is used for the customisation of certain elements in the ODS search module.

Adding Custom Journey Types: Clients can add custom journey types (e.g., sepa-instant) by simply adding a new entry to the journeys map in the configuration. For more details, see Adding Custom Journey Types

Search Forms

The search forms config is organised by journey type within a journeys map. Each journey type (payment, recall, bulk, batch, or custom) can have its own search form configuration.

You can choose what sections and fields are shown in the search forms by adding or removing them from the config. You can choose from any field present in an IPF PDS or a custom PDS and MDS. Any custom fields that you add to the search forms must be prefixed with 'custom_' for example custom_customSearchableStringField.

Here is an example of the search form config for a payment search screen:

# Journey-specific configurations
# Each journey type has its own search-form configuration
journeys {
  # Payment journey configuration
  payment {
    search-form {
      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: "custom_customSearchableStringField"
              name: "formField.customField1"
              type: "STRING"
            },
            {
              id: "custom_customSearchableStringField2"
              name: "formField.customField2"
              type: "STRING"
            },
            {
              id: "custom_customSearchableStringField3"
              name: "formField.customField3"
              type: "STRING"
            }
          ]
        }
      ]
    }
  }

  # Example: Custom journey type (e.g., SEPA Instant)
  # sepa-instant {
  #   search-form {
  #     searchType: "sepa-instant"
  #     formSections: [
  #       {
  #         id: "ids"
  #         name: "heading.ids"
  #         size: "DOUBLE"
  #         fields: [
  #           {
  #             id: "uowId"
  #             name: "formField.unitOfWorkId"
  #             type: "STRING"
  #           },
  #           {
  #             id: "instantPaymentId"
  #             name: "formField.instantPaymentId"
  #             type: "STRING"
  #           }
  #         ]
  #       }
  #     ]
  #   }
  # }
}

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, DATES, AMOUNTS, CHECKBOX, NUMBER, DATE, DATETIME

GLOBAL_STATUS, AMOUNTS and DATES are configured using the date-types, amount-types and global-statuses config properties within each journey type

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.

Global Statuses

The global statuses config is organized within the journeys map, where each journey type must have its own global-statuses array. Valid journey types include: payment, recall, bulk, batch, and any custom journey types you add. This means that you can configure custom global statuses for each of the different journey types independently. For example, you can configure different global statuses for payments under journeys.payment.global-statuses in the config.

Each status object has two fields: name and category.

  • name is the label shown in the UI (for example: "Pending").

  • category must be one of the 6 allowed categories: PENDING, ACCEPTED, REJECTED, MANUAL_ACTION_REQUIRED, SCHEDULED, CANCELLED. The categories come from the default global state set.

You can find more information on global states here. There can be more than one status in each category.

Categories have been introduced because they drive certain screen behaviours in the UI. For example, only payments with a non-terminal and non-manual global status category i.e. PENDING and SCHEDULED will be able to be cancelled.

# Journey-specific configurations
# Each journey type must have its own global-statuses configuration
journeys {
  # Payment journey configuration
  payment {
    global-statuses = [
      {
        name: "PENDING",
        category: "PENDING"
      },
      {
        name: "ACCEPTED",
        category: "ACCEPTED"
      },
      {
        name: "COMPLETED",
        category: "ACCEPTED"
      },
      {
        name: "REJECTED",
        category: "REJECTED"
      },
      {
        name: "MANUAL_ACTION_REQUIRED",
        category: "MANUAL_ACTION_REQUIRED"
      },
      {
        name: "SCHEDULED",
        category: "SCHEDULED"
      },
      {
        name: "CANCELLED",
        category: "CANCELLED"
      }
    ]
  }

  # Recall journey configuration
  recall {
    global-statuses = [
      {
        name: "PENDING",
        category: "PENDING"
      },
      {
        name: "ACCEPTED",
        category: "ACCEPTED"
      },
      {
        name: "COMPLETED",
        category: "ACCEPTED"
      },
      {
        name: "REJECTED",
        category: "REJECTED"
      },
      {
        name: "MANUAL_ACTION_REQUIRED",
        category: "MANUAL_ACTION_REQUIRED"
      },
      {
        name: "SCHEDULED",
        category: "SCHEDULED"
      },
      {
        name: "CANCELLED",
        category: "CANCELLED"
      }
    ]
  }

  # Bulk journey configuration
  bulk {
    global-statuses = [
      {
        name: "PENDING",
        category: "PENDING"
      },
      {
        name: "ACCEPTED",
        category: "ACCEPTED"
      },
      {
        name: "COMPLETED",
        category: "ACCEPTED"
      },
      {
        name: "REJECTED",
        category: "REJECTED"
      },
      {
        name: "MANUAL_ACTION_REQUIRED",
        category: "MANUAL_ACTION_REQUIRED"
      },
      {
        name: "SCHEDULED",
        category: "SCHEDULED"
      },
      {
        name: "CANCELLED",
        category: "CANCELLED"
      }
    ]
  }

  # Batch journey configuration
  batch {
    global-statuses = [
      {
        name: "PENDING",
        category: "PENDING"
      },
      {
        name: "ACCEPTED",
        category: "ACCEPTED"
      },
      {
        name: "COMPLETED",
        category: "ACCEPTED"
      },
      {
        name: "REJECTED",
        category: "REJECTED"
      },
      {
        name: "MANUAL_ACTION_REQUIRED",
        category: "MANUAL_ACTION_REQUIRED"
      },
      {
        name: "SCHEDULED",
        category: "SCHEDULED"
      },
      {
        name: "CANCELLED",
        category: "CANCELLED"
      }
    ]
  }

  # Example: Custom journey type (e.g., SEPA Instant)
  # sepa-instant {
  #   global-statuses = [
  #     {
  #       name: "PENDING",
  #       category: "PENDING"
  #     },
  #     {
  #       name: "COMPLETED",
  #       category: "ACCEPTED"
  #     }
  #   ]
  # }
}

Date and Amount Types

Date and amount types per journey can be configured with the date-types and amount-types properties within each journey type to determine what appears in dropdowns in the UI. You can change the order in which these types appear in the dropdowns by changing the order in which they appear in the config.

For example, this would configure payment and recall within the journeys map:

journeys {
  payment {
    date-types = [
      "CREATED_AT",
      "MESSAGE_RECEIVED_AT",
      "INTERBANK_SETTLEMENT_DATE"
    ]
  }
  recall {
    date-types = [
      "CREATED_AT",
      "ORIGINAL_INTERBANK_SETTLEMENT_DATE"
    ]
  }
}

If you want the message received at type to appear at the top of the list, you would change it to be like this:

payment {
  date-types = [
    "MESSAGE_RECEIVED_AT",
    "CREATED_AT",
    "INTERBANK_SETTLEMENT_DATE"
  ]
}

Details Default

The property 'details-defaults' is used to handle the behaviour of the payment details screen and should be configured within each journey type:

journeys {
  payment {
    details-defaults = {
      "showGraphs": true,
      "flows": {
        "opened": "latest",
        "sort": "asc",
      },
      "events": {
        "opened": "all",
        "sort": "asc",
      }
    }
  }
}

Where 'showGraphs' handles whether the graphs are shown by default

'opened' handles if you want to have certain flows opened by default ('latest', 'all', 'none')

'sort' handles the order in which the flows/events are sorted ('desc', 'asc')

Columns

The table-columns property is configured within each journey type to determine which columns are shown in the search results table on the search page for that specific journey type. The columns will be shown in the order they are defined in the config, so if you want to change the order of the columns, you can do so by changing the order in which they appear in the config.

The paths attribute accepts an array of strings, where the value correlates to the path within the object that is expected. If the path isn’t provided, the name will be used as default

e.g. for an object like below

{
    "createdAt": "01/01/2025",
    "field1": "value1",
    "field2": "value2",
    "object1": {
        "field3": "value3"
    }
}

The paths property:

paths: ["createdAt"]

Will get the value ["01/01/2025"]

And the paths property:

paths: ["field1", "object1.field3"]

Will get the value ["value1", "value3"]. Where each of the string values will be separated by a line break in the table.

There are six types you can choose from

STRING

A standard text value

NUMBER

A standard number value

CURRENCY

A value that will be formatted to a currency value

DATE

A value that will be formatted to date and show date only

DATETIME

A value that will be formatted to date and include time

PRE_DEFINED

An inbuilt column definition that will handle more complicated columns (see definitions)

For the PRE_DEFINED columns, you can use these by providing both the type and the appropriate name.

Type

Description

Notes

amount

This will display transactionAmount, instructedAmount, convertedTransactionAmount or originalInterbankSettlementAmount, returnedInterbankSettlementAmount, convertedTransactionAmount depending on the journey type

It will also display an appropriate tooltip

bankingAccount

This will display debitAccount and creditAccount with prefixes

totalInterbankSettlementAmount

This will display totalInterbankSettlementAmount with totalInterbankSettlementAmountCurrency for the currency

agentDetails

This will display instructingAgent and instructedAgent

It will also display with a prefix of 'Instructing' and 'Instructed'

reasonCode

This will display the reasonCode with a tooltip containing its description

The columns are defined as follows:

# Journey-specific configurations
# Each journey type has its own table-columns configuration
journeys {
  payment {
    table-columns = [
      {
        name: "createdAt",
        type: "DATETIME"
      },
      {
        name: "transactionType",
        type: "STRING"
      },
      {
        name: "csm",
        type: "STRING"
      },
      {
        name: "amount",
        type: "PRE_DEFINED"
      },
      {
        name: "clientRequestId",
        type: "STRING"
      },
      {
        name: "debtor",
        type: "STRING",
        paths: ["debtorName", "debtorAccount", "debtorBic", "debtorAgentBic"]
      },
      {
        name: "creditor",
        type: "STRING",
        paths: ["creditorName", "creditorAccount", "creditorBic", "creditorAgentBic"]
      },
      {
        name: "bankingAccount",
        type: "STRING",
        paths: ["debitAccount", "creditAccount"]
      },
      {
        name: "globalStatus",
        type: "STRING"
      },
      {
        name: "reasonCode",
        type: "PRE_DEFINED"
      }
    ]
  }

  recall {
    table-columns = [
      {
        name: "createdAt",
        type: "DATETIME"
      },
      {
        name: "agentDetails",
        type: "PRE_DEFINED"
      },
      {
        name: "originalEndToEndId",
        type: "STRING"
      },
      {
        name: "originalTransactionId",
        type: "STRING"
      },
      {
        name: "amount",
        type: "PRE_DEFINED"
      },
      {
        name: "originalInterbankSettlementDate",
        type: "DATE"
      },
      {
        name: "debtor",
        type: "STRING",
        paths: ["debtorName", "debtorAccount", "debtorBic", "debtorAgentBic"]
      },
      {
        name: "creditor",
        type: "STRING",
        paths: ["creditorName", "creditorAccount", "creditorBic", "creditorAgentBic"]
      }
    ]
  }

  bulk {
    table-columns = [
      {
        name: "createdAt",
        type: "DATETIME"
      },
      {
        name: "agentDetails",
        type: "PRE_DEFINED"
      },
      {
        name: "totalInterbankSettlementAmount"
        type: "PRE_DEFINED"
      },
      {
        name: "transactionType",
        type: "STRING"
      },
      {
        name: "csm",
        type: "STRING"
      },
      {
        name: "clientRequestId",
        type: "STRING"
      },
      {
        name: "globalStatus",
        type: "STRING"
      },
      {
        name: "reasonCode",
        type: "PRE_DEFINED"
      }
    ]
  }

  batch {
    table-columns = [
      {
        name: "createdAt",
        type: "DATETIME"
      },
      {
        name: "transactionType",
        type: "STRING"
      },
      {
        name: "clientRequestId",
        type: "STRING"
      },
      {
        name: "debtor",
        type: "STRING",
        paths: ["debtorName", "debtorAccount", "debtorBic", "debtorAgentBic"]
      },
      {
        name: "globalStatus",
        type: "STRING"
      },
      {
        name: "reasonCode",
        type: "PRE_DEFINED"
      }
    ]
  }
}

ODS Page Size

ODS search results default settings. The maximum number of search results returning from ODS is set to 1000.

ods-page-results = {
    size = 1000
}

Alternative Identifiers

Custom alternative identifiers for Summary Info search fields need to be added to the alternative-identifiers property within each journey type if they are to be used as part of the autocomplete for that search field:

# Alternative identifiers should be configured within each journey type
journeys {
  payment {
    alternative-identifiers = [
      {
        searchBy: "CLIENT_REQUEST_ID",
        displayName: "Client Request ID"
      }
    ]
  }
}

Reason Codes

Reason codes from common config can be overwritten for this module by supplying your own payment-search-reason-codes.conf.

The reason code object has a definitionKey property 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.

In the dropdown on the UI, the reason code will be displayed along with the translated definition or the fallback definition. E.g. "Reason Code 1 — This is the reason code definition".

Example of 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"
    }
]

For information on adding custom translations to the Operational Dashboard, see Operational Dashboard Translation Customisation.

Currency Codes

Currency codes from common config can be overwritten for this module by supplying your own payment-search-currency-codes.conf.

In the dropdown on the UI, the currency will be displayed along with the alphabetic code. E.g. "Alphabetic Code — Currency".

Example of currency code config:

currency-codes = [
        {
            "alphabeticCode": "AFN",
            "currency": "Afghani"
        },
        {
            "alphabeticCode": "EUR",
            "currency": "Euro"
        },
        {
            "alphabeticCode": "ALL",
            "currency": "Lek"
        }
]

Date Formats

Date Formats from common config can be overwritten for this module by supplying your own payment-search-date-formats.conf. If you don’t provide any values, the dates will be the UK standard.

Date formats are set per Processing Entity.

Example of date format config:

date-formats = {
  BANK_ENTITY_1 = {
    dateInput = "DD/MM/YYYY",
    dateDisplay = "dd/MM/YYYY",
    datetimeDisplay = "dd/MM/YYYY"
  },
  BANK_ENTITY_2 = {
    dateInput = "DD/MM/YYYY",
    dateDisplay = "dd/MM/YYYY",
    datetimeDisplay = "dd/MM/YYYY"
  }
}

Summary Configuration

This configuration will determine how to render and layout the various summary pages for unit of works in the UI. One set of configuration is required per summary type - payment, recall, bulk, batch

The evaluated layout can be retrieved from /api/ods/summary/{unitOfWorkId}

The configurable values are as follows:

Property Description

Summary

layout.<summary-type>

The set of cards to be rendered on the screen for the given summary type. This will be what is loaded when a user clicks on an invidual unit of work in the UI

Cards

layout.<summary-type>.cardNameTranslationKey

The translation key to be used by transloco for the card title. This will be added to the translation root key. e.g. t(payment-summary.debtorinformation)

layout.<summary-type>.translationRoot

The translation root for the transloco translation file. e.g. payment-summary

layout.<summary-type>.type

Type of card to use from the dynamic summary page. 3 current types list, gridList and relatedSummaries. Default is list

layout.<summary-type>.width

How many columns this card should take. Default is 1 and max is 6

layout.<summary-type>.data

The translation root for the transloco translation file. e.g. payment-summary

Items

layout.<summary-type>.data.<index>.translationKey

The translation key to be used by transloco for the card title. This will be added to the translation root key. e.g. t(payment-summary.debtorinformation)

layout.<summary-type>.data.<index>.type

The type of the value. Defaults to text but will include modifier such as status, reason code, bold, etc.

  • subtitle: Subtitle will be displayed as a title in the card, any following items in the list will appear under this subtitle until another one is specified.

  • text: Plain text that will ellipsis if too long and be copiable by the user.

  • date: Display as a date,

  • datetime: Display as date and time, clicking on this item will convert the date time to a duration of how long ago the date time was.

  • bold: Bolds the text.

  • status: Status will display the text, if the item has a warning value then a warning icon will be displayed along side it.

  • reasonCode: Reason code will reference the config for a relevant reason code and show some text alongside it when hovered over.

layout.<summary-type>.data.<index>.valuePath

The location of the value on the /details/{unit of work id} api of ODS. This path is defined using SPEL. e.g. "transactionData.customerCreditTransferInitiation.pmtInf[0].cdtTrfTxInf[0].pmtId.endToEndId" and can either be input as a single string or an array of strings if the value is conditional, input in preferential order with the first index being the highest preference i.e. ["firstChoicePath", "secondChoicePath].

layout.<summary-type>.data.<index>.fallbackValue

A string to use should the value be missing in the details response. Defaults to N/A

If you want any other data to come after alternative identifiers in a card, then make sure you add a subtitle in the following config to keep the data separate.

The source file for defaults is called summary-layout.conf and can be overridden in the client project by supplying your own summary-layout.conf.

layout = {
  payment = [
    {
      cardNameTranslationKey: "paymentTitle",
      translationRoot: "summary.processingIds",
      type: "list",
      width: 2,
      data: [
        {
          translationKey: "uowId",
          type: "text",
          valuePath: "summary.unitOfWorkId",
        },
        {
          translationKey: "clientRequestId",
          type: "text",
          valuePath: "summary.clientRequestId",
        },
        {
          translationKey: "transactionId",
          type: "text",
          valuePath: "summary.transactionId",
        },
        {
          translationKey: "instructingId",
          type: "text",
          valuePath: "summary.instructionId",
        },
        {
          translationKey: "uetr",
          type: "text",
          valuePath: "summary.uetr",
        },
        {
          translationKey: "alternativeIds",
          type: "altIds"
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.processingDates",
      type: "list",
      width: 2,
      data: [
        {
          translationKey: "created",
          type: "date",
          valuePath: "summary.createdAt",
        },
        {
          translationKey: "instructed",
          type: "date",
          valuePath: "summary.instructionReceivedAt",
        },
        {
          translationKey: "executionStarted",
          type: "date",
          valuePath: "summary.executionStartedAt",
        },
        {
          translationKey: "settled",
          type: "date",
          valuePath: "summary.settlementCompletedAt",
        },
        {
          translationKey: "acceptance",
          type: "date",
          valuePath: "summary.acceptanceDateTime",
        },
        {
          translationKey: "interbankSettlement",
          type: "date",
          valuePath: "summary.interbankSettlementDate",
        },
        {
          translationKey: "timeZone",
          type: "text",
          valuePath: "summary.timeZone",
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.relatedSummaries",
      type: "relatedSummaries",
      width: 2,
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.executionStatus",
      type: "gridList",
      width: 3,
      data: [
        {
          translationKey: "csm",
          type: "text",
          valuePath: "summary.csm",
        },
        {
          translationKey: "priority",
          type: "text",
          valuePath: "summary.priority",
        },
        {
          translationKey: "processingEntity",
          type: "text",
          valuePath: "summary.processingEntity",
        },
        {
          translationKey: "globalStatus",
          type: "status",
          valuePath: "summary.globalStatus",
        },
        {
          translationKey: "reasonCode",
          type: "reasonCode",
          valuePath: "summary.reasonCode",
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.processingAmounts",
      type: "gridList",
      width: 3,
      data: [
        {
          translationKey: "instructedAmount",
          type: "amount",
          valuePath: "summary.instructedAmount",
        },
        {
          translationKey: "instructedAmount",
          type: "currency",
          valuePath: "summary.instructedAmountCurrency",
        },
        {
          translationKey: "transactionAmount",
          type: "amount",
          valuePath: "summary.transactionAmount",
        },
        {
          translationKey: "transactionAmount",
          type: "currency",
          valuePath: "summary.transactionAmountCurrency",
        },
        {
          translationKey: "convertedAmount",
          type: "amount",
          valuePath: "summary.convertedTransactionAmount",
        },
        {
          translationKey: "convertedAmount",
          type: "currency",
          valuePath: "summary.convertedTransactionAmountCurrency",
        },
        {
          translationKey: "exchangeRate",
          type: "text",
          valuePath: "summary.exchangeRate",
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.debtorDetails",
      type: "list",
      width: 2,
      data: [
        {
          translationKey: "debtorName",
          type: "text",
          valuePath: "summary.debtorName",
        },
        {
          translationKey: "debtorIban",
          type: "text",
          valuePath: "summary.debtorAccount",
        },
        {
          translationKey: "debtorBic",
          type: "text",
          valuePath: "summary.debtorBic",
        },
        {
          translationKey: "debtorAgentBic",
          type: "text",
          valuePath: "summary.debtorAgentBic",
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.creditorDetails",
      type: "list",
      width: 2,
      data: [
        {
          translationKey: "creditorName",
          type: "text",
          valuePath: "summary.creditorName",
        },
        {
          translationKey: "creditorIban",
          type: "text",
          valuePath: "summary.creditorAccount",
        },
        {
          translationKey: "creditorBic",
          type: "text",
          valuePath: "summary.creditorBic",
        },
        {
          translationKey: "creditorAgentBic",
          type: "text",
          valuePath: "summary.creditorAgentBic",
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.settlementNotificationInformation",
      type: "list",
      width: 2,
      data: [
        {
          translationKey: "debitAccount",
          type: "text",
          valuePath: "summary.debitAccount",
        },
        {
          translationKey: "creditAccount",
          type: "text",
          valuePath: "summary.creditAccount",
        },
        {
          translationKey: "debitAmount",
          type: "amount",
          valuePath: "summary.debitAmount",
        },
        {
          translationKey: "debitAmount",
          type: "currency",
          valuePath: "summary.debitAmountCurrency",
        },
        {
          translationKey: "creditAmount",
          type: "amount",
          valuePath: "summary.creditAmount",
        },
        {
          translationKey: "creditAmount",
          type: "currency",
          valuePath: "summary.creditAmountCurrency",
        },
      ]
    }
  ],
  recall = [
    {
      cardNameTranslationKey: "recallTitle",
      translationRoot: "summary.processingIds",
      type: "list",
      width: 2,
      data: [
        {
          translationKey: "uowId",
          type: "text",
          valuePath: "summary.unitOfWorkId",
        },
        {
          translationKey: "clientRequestId",
          type: "text",
          valuePath: "summary.clientRequestId",
        },
        {
          translationKey: "originalMessageId",
          type: "text",
          valuePath: "summary.originalMessageId",
        },
        {
          translationKey: "originalInstructionId",
          type: "text",
          valuePath: "summary.originalInstructionId",
        },
        {
          translationKey: "originalEndToEndId",
          type: "text",
          valuePath: "summary.originalEndToEndId",
        },
        {
          translationKey: "originalTransactionId",
          type: "text",
          valuePath: "summary.originalTransactionId",
        },
        {
          translationKey: "cancellationId",
          type: "text",
          valuePath: "summary.cancellationId",
        },
        {
          translationKey: "returnId",
          type: "text",
          valuePath: "summary.returnId",
        },
        {
          translationKey: "alternativeIds",
          type: "altIds"
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.processingDates",
      type: "list",
      width: 2,
      data: [
        {
          translationKey: "created",
          type: "date",
          valuePath: "summary.createdAt",
        },
        {
          translationKey: "messageReceived",
          type: "date",
          valuePath: "summary.messageReceivedAt",
        },
        {
          translationKey: "settled",
          type: "date",
          valuePath: "summary.interbankSettlementDate",
        },
        {
          translationKey: "originalInterbankSettlement",
          type: "date",
          valuePath: "summary.originalInterbankSettlementDate",
        },
        {
          translationKey: "timeZone",
          type: "text",
          valuePath: "summary.timeZone",
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.relatedSummaries",
      type: "relatedSummaries",
      width: 2,
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.executionStatus",
      type: "gridList",
      width: 3,
      data: [
        {
          translationKey: "csm",
          type: "text",
          valuePath: "summary.csm",
        },
        {
          translationKey: "priority",
          type: "text",
          valuePath: "summary.priority",
        },
        {
          translationKey: "processingEntity",
          type: "text",
          valuePath: "summary.processingEntity",
        },
        {
          translationKey: "globalStatus",
          type: "status",
          valuePath: "summary.globalStatus",
        },
        {
          translationKey: "reasonCode",
          type: "reasonCode",
          valuePath: "summary.reasonCode",
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.processingAmounts",
      type: "gridList",
      width: 3,
      data: [
        {
          translationKey: "returnedInterbankSettlementAmount",
          type: "amount",
          valuePath: "summary.returnedInterbankSettlementAmount",
        },
        {
          translationKey: "returnedInterbankSettlementAmount",
          type: "currency",
          valuePath: "summary.returnedInterbankSettlementAmountCurrency",
        },
        {
          translationKey: "originalInterbankSettlementAmount",
          type: "amount",
          valuePath: "summary.originalInterbankSettlementAmount",
        },
        {
          translationKey: "originalInterbankSettlementAmount",
          type: "currency",
          valuePath: "summary.originalInterbankSettlementAmountCurrency",
        },
        {
          translationKey: "chargeAmount",
          type: "amount",
          valuePath: "summary.chargeAmount",
        },
        {
          translationKey: "chargeAmount",
          type: "currency",
          valuePath: "summary.chargeAmountCurrency",
        },
        {
          translationKey: "convertedAmount",
          type: "amount",
          valuePath: "summary.convertedTransactionAmount",
        },
        {
          translationKey: "convertedAmount",
          type: "currency",
          valuePath: "summary.convertedTransactionAmountCurrency",
        },
        {
          translationKey: "exchangeRate",
          type: "text",
          valuePath: "summary.exchangeRate",
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.debtorDetails",
      type: "list",
      width: 2,
      data: [
        {
          translationKey: "debtorName",
          type: "text",
          valuePath: "summary.debtorName",
        },
        {
          translationKey: "debtorIban",
          type: "text",
          valuePath: "summary.debtorAccount",
        },
        {
          translationKey: "debtorAgentBic",
          type: "text",
          valuePath: "summary.debtorAgentBic",
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.creditorDetails",
      type: "list",
      width: 2,
      data: [
        {
          translationKey: "creditorName",
          type: "text",
          valuePath: "summary.creditorName",
        },
        {
          translationKey: "creditorIban",
          type: "text",
          valuePath: "summary.creditorAccount",
        },
        {
          translationKey: "creditorAgentBic",
          type: "text",
          valuePath: "summary.creditorAgentBic",
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.agentDetails",
      type: "list",
      width: 2,
      data: [
        {
          translationKey: "instructingAgent",
          type: "text",
          valuePath: "summary.instructingAgent",
        },
        {
          translationKey: "instructedAgent",
          type: "text",
          valuePath: "summary.instructedAgent",
        },
      ]
    }
  ]
  bulk = [
    {
      cardNameTranslationKey: "bulkTitle",
      translationRoot: "summary.processingIds",
      type: "list",
      width: 2,
      data: [
        {
          translationKey: "uowId",
          type: "text",
          valuePath: "summary.unitOfWorkId",
        },
        {
          translationKey: "clientRequestId",
          type: "text",
          valuePath: "summary.clientRequestId",
        },
        {
          translationKey: "messageId",
          type: "text",
          valuePath: "summary.messageId",
        },
        {
          translationKey: "alternativeIds",
          type: "altIds"
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.processingDates",
      type: "list",
      width: 2,
      data: [
        {
          translationKey: "created",
          type: "date",
          valuePath: "summary.createdAt",
        },
        {
          translationKey: "messageReceived",
          type: "date",
          valuePath: "summary.messageReceivedAt",
        },
        {
          translationKey: "interbankSettlement",
          type: "date",
          valuePath: "summary.interbankSettlementDate",
        },
        {
          translationKey: "timeZone",
          type: "text",
          valuePath: "summary.timeZone",
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.relatedSummaries",
      type: "relatedSummaries",
      width: 2,
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.executionStatus",
      type: "gridList",
      width: 3,
      data: [
        {
          translationKey: "csm",
          type: "text",
          valuePath: "summary.csm",
        },
        {
          translationKey: "priority",
          type: "text",
          valuePath: "summary.priority",
        },
        {
          translationKey: "processingEntity",
          type: "text",
          valuePath: "summary.processingEntity",
        },
        {
          translationKey: "globalStatus",
          type: "status",
          valuePath: "summary.globalStatus",
        },
        {
          translationKey: "reasonCode",
          type: "reasonCode",
          valuePath: "summary.reasonCode",
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.processingAmounts",
      type: "gridList",
      width: 3,
      data: [
        {
          translationKey: "totalInterbankSettlementAmount",
          type: "amount",
          valuePath: "summary.totalInterbankSettlementAmount",
        },
        {
          translationKey: "totalInterbankSettlementAmount",
          type: "currency",
          valuePath: "summary.totalInterbankSettlementAmountCurrency",
        },
        {
          translationKey: "controlSum",
          type: "text",
          valuePath: "summary.controlSum",
        },
        {
          translationKey: "numberOfTransactions",
          type: "text",
          valuePath: "summary.numberOfTransactions",
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.agentDetails",
      type: "list",
      width: 6,
      data: [
        {
          translationKey: "instructingAgent",
          type: "text",
          valuePath: "summary.instructingAgent",
        },
        {
          translationKey: "instructedAgent",
          type: "text",
          valuePath: "summary.instructedAgent",
        },
        {
          translationKey: "initiatingPartyName",
          type: "text",
          valuePath: "summary.initiatingPartyName",
        },
      ]
    }
  ]
  batch = [
    {
      cardNameTranslationKey: "batchTitle",
      translationRoot: "summary.processingIds",
      type: "list",
      width: 2,
      data: [
        {
          translationKey: "uowId",
          type: "text",
          valuePath: "summary.unitOfWorkId",
        },
        {
          translationKey: "clientRequestId",
          type: "text",
          valuePath: "summary.clientRequestId",
        },
        {
          translationKey: "paymentInformationId",
          type: "text",
          valuePath: "summary.paymentInformationId",
        }
        {
          translationKey: "alternativeIds",
          type: "altIds"
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.processingDates",
      type: "list",
      width: 2,
      data: [
        {
          translationKey: "created",
          type: "date",
          valuePath: "summary.createdAt",
        },
        {
          translationKey: "timeZone",
          type: "text",
          valuePath: "summary.timeZone",
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.relatedSummaries",
      type: "relatedSummaries",
      width: 2,
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.executionStatus",
      type: "gridList",
      width: 6,
      data: [
        {
          translationKey: "csm",
          type: "text",
          valuePath: "summary.csm",
        },
        {
          translationKey: "priority",
          type: "text",
          valuePath: "summary.priority",
        },
        {
          translationKey: "processingEntity",
          type: "text",
          valuePath: "summary.processingEntity",
        },
        {
          translationKey: "globalStatus",
          type: "status",
          valuePath: "summary.globalStatus",
        },
        {
          translationKey: "reasonCode",
          type: "reasonCode",
          valuePath: "summary.reasonCode",
        }
      ]
    },
    {
      cardNameTranslationKey: "title",
      translationRoot: "summary.debtorDetails",
      type: "list",
      width: 6,
      data: [
        {
          translationKey: "debtorName",
          type: "text",
          valuePath: "summary.debtorName",
        },
        {
          translationKey: "debtorIban",
          type: "text",
          valuePath: "summary.debtorAccount",
        },
        {
          translationKey: "debtorAgentBic",
          type: "text",
          valuePath: "summary.debtorAgentBic",
        }
      ]
    },
  ]
}

Within your application you will want to define your translations correctly. So for the example of a layout config:

 layout = {
  payment = [
    {
      cardNameTranslationKey: "paymentTitle",
      translationRoot: "summary.processingIds",
      type: "list",
      width: 2,
      data: [
        {
          translationKey: "uowId",
          type: "text",
          valuePath: "summary.unitOfWorkId",
        }
      ]
    }
  ]
}

You will want to define your translation file as follows:

"summary": {
      "processingIds": {
          "paymentTitle": "Test"
      },
      "unitOfWorkId": "12345"
  }

MDS Search Configuration

This configuration will determine how to render and layout the various MDS search page tables in MDS Search module on the GUI. This has to be done per MDS object that you want to be displayed on your MDS search page

The evaluated layout can be retrieved from /api/ods/mds-info

The configurable values are as follows:

Property Description

Name

mds.name

The name of the MDS Object for which you want to provide the table headers for in the MDS Search page.

Response Digest

mds.responseDigest.name

The key to the translation in the transloco translation file for the name of the header you want to be represented in the MDS Search table for a given MDS Object.

mds.responseDigest.paths

The location of the values you want to display in your rows of the designated header taken from the ods/all/mds-objects/{type} api response. This path is defined using dot-based JSON path. e.g. "object.headers.unitOfWorkId"

mds.responseDigest.type

The type of the value.

  • STRING: Plain text that will ellipsis if too long and be copiable by the user.

  • AMOUNT: Two value paths need to be supplied a value and a currency, and this will be converted to an amount displayed in the result table.

  • INTEGER: Value path to be displayed as a number.

  • BOOLEAN: Value path to be displayed as a boolean in the result table.

  • DATE: Display as a date,

  • DATETIME: Display as date and time.

  • ARRAY: Value paths to be displayed collectively as a column of results within a row.

  • REASONCODE: Reason code will reference the config for a relevant reason code and show some text alongside it when hovered over.

The source file for defaults is called mds-response-fields.conf and can be overridden in the client project by supplying your own mds-response-fields.conf.

{
  mds = [
    {
      name = "PAIN_001",
      responseDigest = [
        {
          name = "unitOfWorkId"
          paths = ["object.headers.unitOfWorkId"]
          type = "STRING"
        },
        {
          name = "clientRequestId"
          paths = ["object.headers.clientRequestId"]
          type = "STRING"
        },
        {
          name = "mdsObjectId"
          paths = ["object.payload.mdsObjectId.id"]
          type = "STRING"
        },
        {
          name = "initiatingParty"
          paths = [
            "object.payload.content.grpHdr.initgPty.nm",
            "object.payload.content.grpHdr.initgPty.id.orgId.anyBIC"
          ]
          type = "ARRAY"
        }
      ]
    },
    {
      name = "PAIN_001_PAYMENT_INSTRUCTION",
      responseDigest = [
        {
          name = "unitOfWorkId"
          paths = ["object.headers.unitOfWorkId"]
          type = "STRING"
        },
        {
          name = "clientRequestId"
          paths = ["object.headers.clientRequestId"]
          type = "STRING"
        },
        {
          name = "parentMdsObjectId"
          paths = ["object.payload.parentMdsObjectId.id"]
          type = "STRING"
        },
        {
          name = "debtor"
          paths = [
            "object.payload.content.dbtr.nm",
            "object.payload.content.dbtrAcct.id.iban",
            "object.payload.content.dbtr.id.orgId.anyBIC"
          ]
          type = "ARRAY"
        }
      ]
    },
    {
      name = "PAIN_001_CREDIT_TRANSFER_TRANSACTION",
      responseDigest = [
        {
          name = "unitOfWorkId"
          paths = ["object.headers.unitOfWorkId"]
          type = "STRING"
        },
        {
          name = "clientRequestId"
          paths = ["object.headers.clientRequestId"]
          type = "STRING"
        },
        {
          name = "parentMdsObjectId"
          paths = ["object.payload.parentMdsObjectId.id"]
          type = "STRING"
        },
        {
          name = "creditor"
          paths = [
            "object.payload.content.cdtr.nm",
            "object.payload.content.cdtrAcct.id.iban",
            "object.payload.content.cdtr.id.orgId.anyBIC"
          ]
          type = "ARRAY"
        }
      ]
    },
    {
      name = "PACS_008",
      responseDigest = [
        {
          name = "unitOfWorkId"
          paths = ["object.headers.unitOfWorkId"]
          type = "STRING"
        },
        {
          name = "clientRequestId"
          paths = ["object.headers.clientRequestId"]
          type = "STRING"
        },
        {
          name = "mdsObjectId"
          paths = ["object.payload.mdsObjectId.id"]
          type = "STRING"
        },
        {
          name = "instructingAgent"
          paths = [
            "object.payload.content.grpHdr.instgAgt.finInstnId.nm",
            "object.payload.content.grpHdr.instgAgt.finInstnId.bicfi"
          ]
          type = "ARRAY"
        }
      ]
    },
    {
      name = "PACS_008_CREDIT_TRANSFER_TRANSACTION",
      responseDigest = [
        {
          name = "unitOfWorkId"
          paths = ["object.headers.unitOfWorkId"]
          type = "STRING"
        },
        {
          name = "clientRequestId"
          paths = ["object.headers.clientRequestId"]
          type = "STRING"
        },
        {
          name = "parentMdsObjectId"
          paths = ["object.payload.parentMdsObjectId.id"]
          type = "STRING"
        },
        {
          name = "transactionId"
          paths = ["object.payload.content.pmtId.txId"]
          type = "STRING"
        },
        {
          name = "debtor"
          paths = [
            "object.payload.content.dbtr.nm",
            "object.payload.content.dbtrAcct.id.iban",
            "object.payload.content.dbtr.orgId.anyBIC"
          ]
          type = "ARRAY"
        },
        {
          name = "creditor"
          paths = [
            "object.payload.content.cdtr.nm",
            "object.payload.content.cdtrAcct.id.othr.id",
            "object.payload.content.cdtr.orgId.anyBIC"
          ]
          type = "ARRAY"
        },
        {
          name = "instructingAgent"
          paths = [
            "object.payload.content.instgAgt.finInstnId.nm",
            "object.payload.content.instgAgt.finInstnId.bicfi"
          ]
          type = "ARRAY"
        }
      ]
    },
    {
      name = "PACS_004",
      responseDigest = [
        {
          name = "unitOfWorkId"
          paths = ["object.headers.unitOfWorkId"]
          type = "STRING"
        },
        {
          name = "clientRequestId"
          paths = ["object.headers.clientRequestId"]
          type = "STRING"
        },
        {
          name = "messageId"
          paths = ["object.payload.content.msgId"]
          type = "STRING"
        },
        {
          name = "mdsObjectId"
          paths = ["object.payload.mdsObjectId.id"]
          type = "STRING"
        },
        {
          name = "instructingAgent"
          paths = [
            "object.payload.content.instgAgt.finInstnId.nm",
            "object.payload.content.instgAgt.finInstnId.bicfi"
          ]
          type = "ARRAY"
        }
      ]
    },
    {
      name = "PACS_004_PAYMENT_TRANSACTION",
      responseDigest = [
        {
          name = "unitOfWorkId"
          paths = ["object.headers.unitOfWorkId"]
          type = "STRING"
        },
        {
          name = "clientRequestId"
          paths = ["object.headers.clientRequestId"]
          type = "STRING"
        },
        {
          name = "parentMdsObjectId"
          paths = ["object.payload.parentMdsObjectId.id"]
          type = "STRING"
        },
        {
          name = "originalMessageId"
          paths = ["object.payload.content.orgnlGrpInf.orgnlMsgId"]
          type = "STRING"
        },
        {
          name = "reasonCode"
          paths = ["object.payload.content.rtrRsnInf[0].rsn.cd"]
          type = "REASONCODE"
        },
        {
          name = "debtor"
          paths = [
            "object.payload.content.orgnlTxRef.dbtr.pty.nm",
            "object.payload.content.orgnlTxRef.dbtrAcct.id.iban",
            "object.payload.content.orgnlTxRef.dbtr.pty.orgId.anyBIC"
          ]
          type = "ARRAY"
        },
        {
          name = "creditor"
          paths = [
            "object.payload.content.rtrChain.cdtr.pty.nm",
            "object.payload.content.orgnlTxRef.cdtrAcct.id.iban",
            "object.payload.content.rtrChain.cdtr.pty.id.orgId.anyBIC"
          ]
          type = "ARRAY"
        }
      ]
    }
  ]
}

Unknown Processing Entity Configuration

In some circumstances, certain System Events and Message Logs routed to the Operational Dashboard do not have an identifiable processing entity. This can happen for a variety of reasons. Two common examples are:

System Events

An inbound message from a payment scheme fails schema validation. Currently, scheme packs do not determine the processing entity for inbound payments.

Message Logs

Transport failure events emitted by a connector.

In these cases, they will be assigned to UNKNOWN.

In order for a user to view such items, UNKNOWN should be included with ROLE_PAYMENT alongside any other processing entities in users.conf.

To prevent issues such as users creating processing settings against this UNKNOWN processing entity, it is recommended that ROLE_PAYMENT is the only role assigned to it.

users = [
  {
    username: "user"
    password: "password"
    roles: {
      UNKNOWN = [ROLE_PAYMENT]
      OTHER_PROCESSING_ENTITY = [...]
    }
  }
]

For more information about searching for System Events and Message Logs assigned to UNKNOWN, see here.

Adding Custom Journey Types

The ODS module supports adding custom journey types without requiring code changes. Simply add a new entry to the journeys map in your configuration with all the properties your custom journey type needs.

Custom journey types can define their own:

  • Search forms (search-form)

  • Table columns (table-columns)

  • Global statuses (global-statuses)

  • Date types (date-types)

  • Amount types (amount-types)

  • Alternative identifiers (alternative-identifiers)

  • Transaction types (transaction-types)

  • Details defaults (details-defaults)

Note: system-event-names is a top-level property (outside the journeys object) that is shared across all journey types.

Example: Adding a SEPA Instant Journey Type

ipf.business-operations.payment-search {
  system-event-names = [
    "ActionInvoked",
    "ActionRetriesExhausted",
    # ... other event names
  ]

  journeys {
    payment { ... } # existing
    recall { ... }  # existing
    bulk { ... }    # existing
    batch { ... }   # existing

    # NEW: Custom journey type
    sepa-instant {
      alternative-identifiers = [
        {
          searchBy: "CLIENT_REQUEST_ID",
          displayName: "Client Request ID"
        }
      ]

      transaction-types = ["Credit", "Debit"]

      details-defaults {
        showGraphs = true
        flows {
          opened = "latest"
          sort = "asc"
        }
        events {
          opened = "all"
          sort = "asc"
        }
      }

      search-form {
        searchType: "sepa-instant"
        formSections: [
          # custom form fields
        ]
      }

      table-columns = [
        # custom table columns
      ]

      global-statuses = [
        # custom statuses
      ]

      date-types = [
        "CREATED_AT",
        "INSTANT_SETTLEMENT_TIME"
      ]

      amount-types = [
        "INSTANT_AMOUNT"
      ]
    }
  }
}