taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit aea71da861c99be16fcb98090fd07b6c46ade259
parent 0d46a621ebe25a5857f5dd91cd5e9db9a419f9f6
Author: Sebastian <sebasjm@gmail.com>
Date:   Thu, 24 Apr 2025 11:20:47 -0300

import new gana registry

Diffstat:
Mpackages/aml-backoffice-ui/src/pages/decision/Properties.tsx | 127+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Mpackages/taler-util/src/aml/aml-properties.ts | 106++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Mpackages/taler-util/src/taler-account-properties.ts | 18+++++++++---------
Mpackages/taler-util/src/taler-form-attributes.ts | 54------------------------------------------------------
4 files changed, 174 insertions(+), 131 deletions(-)

diff --git a/packages/aml-backoffice-ui/src/pages/decision/Properties.tsx b/packages/aml-backoffice-ui/src/pages/decision/Properties.tsx @@ -7,6 +7,7 @@ import { HttpStatusCode, LegitimizationRuleSet, PropertiesMapInfo, + TalerAmlProperties, TalerError, TalerFormAttributes, TOPS_AccountProperties, @@ -70,11 +71,11 @@ export function Properties({ account }: { account: string }): VNode { AmlSpaDialect.TESTING; const calculatedProps = calculatePropertiesBasedOnState( - lastDecision?.limits ?? DEFAULT_LIMITS_WHEN_NEW_ACCOUNT, - lastDecision?.properties ?? {}, - request, - dialect, - ); + lastDecision?.limits ?? DEFAULT_LIMITS_WHEN_NEW_ACCOUNT, + lastDecision?.properties ?? {}, + request, + dialect, + ); const merged = Object.entries(calculatedProps).reduce( (prev, [key, value]) => { @@ -177,54 +178,104 @@ function propertiesByDialect( // if (!dialect) return []; return [ { - id: TalerFormAttributes.AML_ACCOUNT_OPEN, + id: TalerAmlProperties.FILE_NOTE, + label: i18n.str`Current note on the GQG File`, + type: "text", + }, + { + id: TalerAmlProperties.CUSTOMER_LABEL, + label: i18n.str`Customer name or internal alias.`, + type: "text", + }, + { + id: TalerAmlProperties.ACCOUNT_OPEN, + label: i18n.str`Is account active for deposit and payments?`, + type: "toggle", + }, + { + id: TalerAmlProperties.ACCOUNT_IDLE, label: i18n.str`Is account active for deposit and payments?`, type: "toggle", }, { - id: TalerFormAttributes.AML_DOMESTIC_PEP, + id: TalerAmlProperties.PEP_DOMESTIC, label: i18n.str`Does account belong to a domestic PEP?`, type: "toggle", }, { - id: TalerFormAttributes.AML_FOREIGN_PEP, + id: TalerAmlProperties.PEP_FOREIGN, label: i18n.str`Does account belong to a foreign PEP?`, type: "toggle", }, { - id: TalerFormAttributes.AML_HIGH_RISK_BUSINESS, - label: i18n.str`Does account belong to a high risk business?`, + id: TalerAmlProperties.PEP_INTERNATIONAL_ORGANIZATION, + label: i18n.str`Does account belong to a international organization PEP?`, type: "toggle", }, { - id: TalerFormAttributes.AML_HIGH_RISK_COUNTRY, + id: TalerAmlProperties.HIGH_RISK_CUSTOMER, + label: i18n.str`Does account belong to a high risk customer?`, + type: "toggle", + }, + { + id: TalerAmlProperties.HIGH_RISK_COUNTRY, label: i18n.str`Does account belong to a person from a high risk country?`, type: "toggle", }, - // { - // id: TalerFormAttributes.AML_INVESTIGATION_ART6_COMPLETED, - // label: i18n.str`Was successfully investigated under Art 6 Gwg?`, - // type: "toggle", - // threeState: true, - // }, - // { - // id: TalerFormAttributes.AML_INVESTIGATION_ART6_FAILED, - // label: i18n.str`Was investigated under Art 6 Gwg and failed?`, - // type: "toggle", - // threeState: true, - // }, - // { - // id: TalerFormAttributes.AML_MROS_REPORTED_ART305, - // label: i18n.str`Was reported to MROS by obligation?`, - // type: "toggle", - // threeState: true, - // }, - // { - // id: TalerFormAttributes.AML_MROS_REPORTED_ART9, - // label: i18n.str`Was reported to MROS by right?`, - // type: "toggle", - // threeState: true, - // }, + { + id: TalerAmlProperties.INVESTIGATION_STATE, + label: i18n.str`The MROS reporting state for the account.`, + type: "choiceStacked", + choices: [ + { + label: i18n.str`None`, + value: "NONE", + }, + { + label: i18n.str`Pending investigation`, + value: "INVESTIGATION_PENDING", + }, + { + label: i18n.str`Investigated without suspicion`, + value: "INVESTIGATION_COMPLETED_WITHOUT_SUSPICION", + }, + { + label: i18n.str`Reported simple suspicion`, + value: "REPORTED_SUSPICION_SIMPLE", + }, + { + label: i18n.str`Reported substantaited suspicion`, + value: "REPORTED_SUSPICION_SUBSTANTIATED", + }, + ], + }, + { + id: TalerAmlProperties.INVESTIGATION_TRIGGER, + label: i18n.str`Informal reason why the AML investigation was triggered`, + type: "text", + }, + { + id: TalerAmlProperties.SANCTION_LIST_BEST_MATCH, + label: i18n.str`Identifies the sanction list entry that the account matched against`, + type: "text", + help: i18n.str`best match, does not mean it was a good match`, + }, + { + id: TalerAmlProperties.SANCTION_LIST_RATING, + label: i18n.str`Score for how good the sanction list match was`, + type: "integer", + }, + { + id: TalerAmlProperties.SANCTION_LIST_CONFIDENCE, + label: i18n.str`Score for how much supporting data we had for the sanction list match`, + type: "integer", + }, + { + id: TalerAmlProperties.SANCTION_LIST_SUPPRESS, + label: i18n.str`Suppress flagging this account when it creates a hit on a sanctions list, this is a false-positive`, + type: "toggle", + threeState: true, + }, ]; } @@ -243,6 +294,11 @@ function calculatePropertiesBasedOnState( ) as Record<string, unknown>; type Result = PartialRecord<UIHandlerId, string | boolean | undefined>; const initial: Result = {}; + + const formId = request.attributes?.formId + + if (!formId) return initial; + const FORM_ID = formId; function mergeProperties<T extends string>( iv: Result, @@ -251,6 +307,7 @@ function calculatePropertiesBasedOnState( ): Result { return list.reduce((result, prop) => { result[prop] = info[prop].deriveProperty( + FORM_ID, currentLimits, state, newNewAttributes, diff --git a/packages/taler-util/src/aml/aml-properties.ts b/packages/taler-util/src/aml/aml-properties.ts @@ -1,4 +1,4 @@ -import { AccountProperties } from "@gnu-taler/taler-util"; +import { AccountProperties, TalerAmlProperties } from "@gnu-taler/taler-util"; import { TalerFormAttributes } from "../taler-form-attributes.js"; import { LegitimizationRuleSet } from "../types-taler-kyc-aml.js"; @@ -7,21 +7,27 @@ import { LegitimizationRuleSet } from "../types-taler-kyc-aml.js"; */ export const TOPS_AccountProperties = [ - TalerFormAttributes.FILE_NOTE, - TalerFormAttributes.CUSTOMER_LABEL, - TalerFormAttributes.AML_ACCOUNT_OPEN, - TalerFormAttributes.AML_DOMESTIC_PEP, - TalerFormAttributes.AML_FOREIGN_PEP, - TalerFormAttributes.AML_INTERNATIONAL_ORG_PEP, - TalerFormAttributes.AML_HIGH_RISK_BUSINESS, - TalerFormAttributes.AML_HIGH_RISK_COUNTRY, - TalerFormAttributes.AML_MROS_STATE, + TalerAmlProperties.FILE_NOTE, + TalerAmlProperties.CUSTOMER_LABEL, + TalerAmlProperties.ACCOUNT_OPEN, + TalerAmlProperties.PEP_DOMESTIC, + TalerAmlProperties.PEP_FOREIGN, + TalerAmlProperties.PEP_INTERNATIONAL_ORGANIZATION, + TalerAmlProperties.HIGH_RISK_CUSTOMER, + TalerAmlProperties.HIGH_RISK_COUNTRY, + TalerAmlProperties.ACCOUNT_IDLE, + TalerAmlProperties.INVESTIGATION_TRIGGER, + TalerAmlProperties.INVESTIGATION_STATE, + TalerAmlProperties.SANCTION_LIST_BEST_MATCH, + TalerAmlProperties.SANCTION_LIST_RATING, + TalerAmlProperties.SANCTION_LIST_CONFIDENCE, + TalerAmlProperties.SANCTION_LIST_SUPPRESS, ] as const; /** * List of account properties required by GLS */ -export const GLS_AccountProperties = [TalerFormAttributes.FILE_NOTE] as const; +export const GLS_AccountProperties = [TalerAmlProperties.FILE_NOTE] as const; export type PropertiesMapInfo<T extends string> = { [name in T]: { @@ -36,9 +42,10 @@ export type PropertiesMapInfo<T extends string> = { * @returns */ deriveProperty: ( + formId: string, limits: LegitimizationRuleSet, state: AccountProperties, - newAttributes: Record<string, unknown>, + newAttributes: Record<keyof typeof TalerFormAttributes, unknown>, ) => string | boolean | undefined; }; }; @@ -46,48 +53,81 @@ export type PropertiesMapInfo<T extends string> = { export const TOPS_AML_PROPERTIES: PropertiesMapInfo< (typeof TOPS_AccountProperties)[number] > = { - AML_ACCOUNT_OPEN: { - deriveProperty(limits, state, attributes) { - return !!attributes[TalerFormAttributes.AML_ACCOUNT_OPEN]; + ACCOUNT_OPEN: { + deriveProperty(formId, limits, state, attributes) { + return undefined; + }, + }, + PEP_DOMESTIC: { + deriveProperty(formId, limits, state, attributes) { + if (formId === "vqf_902_1_officer") { + return !!attributes[TalerFormAttributes.PEP_DOMESTIC]; + } + return undefined + }, + }, + PEP_FOREIGN: { + deriveProperty(formId, limits, state, attributes) { + return !!attributes[TalerFormAttributes.PEP_FOREIGN]; }, }, - AML_DOMESTIC_PEP: { - deriveProperty(limits, state, attributes) { + PEP_INTERNATIONAL_ORGANIZATION: { + deriveProperty(formId, limits, state, attributes) { + return !!attributes[TalerFormAttributes.PEP_INTERNATIONAL_ORGANIZATION]; + }, + }, + HIGH_RISK_CUSTOMER: { + deriveProperty(formId, limits, state, attributes) { + return attributes[TalerFormAttributes.RISK_CLASSIFICATION_LEVEL] === "HIGH_RISK"; + }, + }, + HIGH_RISK_COUNTRY: { + deriveProperty(formId, limits, state, attributes) { + return attributes[TalerFormAttributes.COUNTRY_RISK_NATIONALITY_LEVEL] === "HIGH"; + }, + }, + ACCOUNT_IDLE: { + deriveProperty(formId, limits, state, attributes) { return undefined; }, }, - AML_FOREIGN_PEP: { - deriveProperty(limits, state, attributes) { + CUSTOMER_LABEL: { + deriveProperty(formId, limits, state, attributes) { return undefined; }, }, - AML_INTERNATIONAL_ORG_PEP: { - deriveProperty(limits, state, attributes) { + FILE_NOTE: { + deriveProperty(formId, limits, state, attributes) { return undefined; }, }, - AML_HIGH_RISK_BUSINESS: { - deriveProperty(limits, state, attributes) { + INVESTIGATION_STATE: { + deriveProperty(formId, limits, state, attributes) { return undefined; }, }, - AML_HIGH_RISK_COUNTRY: { - deriveProperty(limits, state, attributes) { + INVESTIGATION_TRIGGER: { + deriveProperty(formId, limits, state, attributes) { return undefined; }, }, - AML_MROS_STATE: { - deriveProperty(limits, state, attributes) { + SANCTION_LIST_BEST_MATCH: { + deriveProperty(formId, limits, state, attributes) { return undefined; }, }, - CUSTOMER_LABEL: { - deriveProperty(limits, state, attributes) { + SANCTION_LIST_CONFIDENCE: { + deriveProperty(formId, limits, state, attributes) { return undefined; }, }, - FILE_NOTE: { - deriveProperty(limits, state, attributes) { + SANCTION_LIST_RATING: { + deriveProperty(formId, limits, state, attributes) { + return undefined; + }, + }, + SANCTION_LIST_SUPPRESS: { + deriveProperty(formId, limits, state, attributes) { return undefined; }, }, @@ -97,8 +137,8 @@ export const GLS_AML_PROPERTIES: PropertiesMapInfo< (typeof GLS_AccountProperties)[number] > = { FILE_NOTE: { - deriveProperty(limits, state, attributes) { - return !!attributes[TalerFormAttributes.AML_ACCOUNT_OPEN]; + deriveProperty(formId, limits, state, attributes) { + return undefined; }, }, }; diff --git a/packages/taler-util/src/taler-account-properties.ts b/packages/taler-util/src/taler-account-properties.ts @@ -46,63 +46,63 @@ export const TalerAmlProperties = { * GANA Type: Boolean * Deployment: TOPS */ - AML_ACCOUNT_OPEN: "AML_ACCOUNT_OPEN" as const, + ACCOUNT_OPEN: "ACCOUNT_OPEN" as const, /** * Description: True if the customer is a domestic PEP. * * GANA Type: Boolean * Deployment: TOPS */ - AML_DOMESTIC_PEP: "AML_DOMESTIC_PEP" as const, + PEP_DOMESTIC: "PEP_DOMESTIC" as const, /** * Description: True if the customer is a foreign PEP. * * GANA Type: Boolean * Deployment: TOPS */ - AML_FOREIGN_PEP: "AML_FOREIGN_PEP" as const, + PEP_FOREIGN: "PEP_FOREIGN" as const, /** * Description: True if the customer is a international organization PEP. * * GANA Type: Boolean * Deployment: TOPS */ - AML_INTERNATIONAL_ORG_PEP: "AML_INTERNATIONAL_ORG_PEP" as const, + PEP_INTERNATIONAL_ORGANIZATION: "PEP_INTERNATIONAL_ORGANIZATION" as const, /** * Description: True if the customer is a high-risk business. * * GANA Type: Boolean * Deployment: TOPS */ - AML_HIGH_RISK_CUSTOMER: "AML_HIGH_RISK_CUSTOMER" as const, + HIGH_RISK_CUSTOMER: "HIGH_RISK_CUSTOMER" as const, /** * Description: True if the customer is associated with a high-risk country. * * GANA Type: Boolean * Deployment: TOPS */ - AML_HIGH_RISK_COUNTRY: "AML_HIGH_RISK_COUNTRY" as const, + HIGH_RISK_COUNTRY: "HIGH_RISK_COUNTRY" as const, /** * Description: The account has been marked as idle. * * GANA Type: Boolean * Deployment: TOPS */ - AML_ACCOUNT_IDLE: "AML_ACCOUNT_IDLE" as const, + ACCOUNT_IDLE: "ACCOUNT_IDLE" as const, /** * Description: The MROS reporting state for the account. * * GANA Type: 'NONE' | 'INVESTIGATION_PENDING' | 'INVESTIGATION_COMPLETED_WITHOUT_SUSPICION' | 'REPORTED_SUSPICION_SIMPLE' | 'REPORTED_SUSPICION_SUBSTANTIATED' * Deployment: TOPS */ - AML_INVESTIGATION_STATE: "AML_INVESTIGATION_STATE" as const, + INVESTIGATION_STATE: "INVESTIGATION_STATE" as const, /** * Description: Informal reason why the AML investigation was triggered. Examples include suspicious transaction or (automated) sanction list match * * GANA Type: String * Deployment: TOPS */ - AML_INVESTIGATION_TRIGGER: "AML_INVESTIGATION_TRIGGER" as const, + INVESTIGATION_TRIGGER: "INVESTIGATION_TRIGGER" as const, /** * Description: Identifies the sanction list entry that the account matched against (best match, does not mean it was a good match) * diff --git a/packages/taler-util/src/taler-form-attributes.ts b/packages/taler-util/src/taler-form-attributes.ts @@ -723,60 +723,6 @@ export const TalerFormAttributes = { */ DOWNLOADED_TERMS_OF_SERVICE: "DOWNLOADED_TERMS_OF_SERVICE" as const, /** - * Description: Current note on the GWG file. - * - * GANA Type: String - */ - FILE_NOTE: "FILE_NOTE" as const, - /** - * Description: Customer name or internal alias. - * - * GANA Type: String - */ - CUSTOMER_LABEL: "CUSTOMER_LABEL" as const, - /** - * Description: Boolean flag indicating whether the account has been opened. The definition of opening an account is deployment-specific. - * - * GANA Type: Boolean - */ - AML_ACCOUNT_OPEN: "AML_ACCOUNT_OPEN" as const, - /** - * Description: True if the customer is a domestic PEP. - * - * GANA Type: Boolean - */ - AML_DOMESTIC_PEP: "AML_DOMESTIC_PEP" as const, - /** - * Description: True if the customer is a foreign PEP. - * - * GANA Type: Boolean - */ - AML_FOREIGN_PEP: "AML_FOREIGN_PEP" as const, - /** - * Description: True if the customer is a international organization PEP. - * - * GANA Type: Boolean - */ - AML_INTERNATIONAL_ORG_PEP: "AML_INTERNATIONAL_ORG_PEP" as const, - /** - * Description: True if the customer is a high-risk business. - * - * GANA Type: Boolean - */ - AML_HIGH_RISK_BUSINESS: "AML_HIGH_RISK_BUSINESS" as const, - /** - * Description: True if the customer is associated with a high-risk country. - * - * GANA Type: Boolean - */ - AML_HIGH_RISK_COUNTRY: "AML_HIGH_RISK_COUNTRY" as const, - /** - * Description: The MROS reporting state for the account. - * - * GANA Type: String - */ - AML_MROS_STATE: "AML_MROS_STATE" as const, - /** * Description: Name of the form completed by the user. * * GANA Type: String