commit c08a54a06fc880d546dac901b2a739813192dc6c
parent 657784c93318232ac509a426bf055eed9be81884
Author: Florian Dold <florian@dold.me>
Date: Mon, 21 Jul 2025 14:36:04 +0200
aml: sort events properly, show full payto
Diffstat:
3 files changed, 39 insertions(+), 14 deletions(-)
diff --git a/packages/aml-backoffice-ui/src/pages/AccountDetails.tsx b/packages/aml-backoffice-ui/src/pages/AccountDetails.tsx
@@ -17,7 +17,6 @@ import {
AbsoluteTime,
assertUnreachable,
HttpStatusCode,
- LegitimizationMeasureDetails,
TalerError,
TalerExchangeApi,
TalerFormAttributes,
@@ -31,19 +30,17 @@ import {
} from "@gnu-taler/web-util/browser";
import { format } from "date-fns";
import { h, VNode } from "preact";
+import { Fragment } from "preact/jsx-runtime";
import { ErrorLoadingWithDebug } from "../components/ErrorLoadingWithDebug.js";
import { ShowDecisionLimitInfo } from "../components/ShowDecisionLimitInfo.js";
+import { ShowDefaultRules } from "../components/ShowDefaultRules.js";
+import { ShowLegistimizationInfo } from "../components/ShowLegitimizationInfo.js";
import { useAccountInformation } from "../hooks/account.js";
import { DecisionRequest } from "../hooks/decision-request.js";
import { useAccountDecisions } from "../hooks/decisions.js";
-import { ShowDefaultRules } from "../components/ShowDefaultRules.js";
-import { Fragment } from "preact/jsx-runtime";
+import { useCurrentLegitimizations } from "../hooks/legitimizations.js";
import { useServerMeasures } from "../hooks/server-info.js";
import { BANK_RULES, WALLET_RULES } from "./decision/Rules.js";
-import { useCurrentLegitimizations } from "../hooks/legitimizations.js";
-import { computeMeasureInformation } from "../utils/computeAvailableMesaures.js";
-import { CurrentMeasureTable } from "../components/MeasuresTable.js";
-import { ShowLegistimizationInfo } from "../components/ShowLegitimizationInfo.js";
const TALER_SCREEN_ID = 116;
@@ -98,7 +95,15 @@ export function AccountDetails({
return <ErrorLoadingWithDebug error={legistimizations} />;
}
- const { details: collectionEvents } = details.body;
+ const collectionEvents = details.body.details;
+
+ collectionEvents.sort((a, b) =>
+ AbsoluteTime.cmp(
+ AbsoluteTime.fromProtocolTimestamp(a.collection_time),
+ AbsoluteTime.fromProtocolTimestamp(b.collection_time),
+ ),
+ );
+
const activeDecision = history.body.find((d) => d.is_active);
const restDecisions = !activeDecision
? history.body
@@ -155,12 +160,28 @@ export function AccountDetails({
return (
<div class="min-w-60">
- <header class="flex items-center justify-between border-b border-white/5 px-4 py-4 sm:px-6 sm:py-6 lg:px-8 gap-2">
+ <header class="flex flex-col justify-between border-b border-white/5 px-4 py-4 sm:px-6 sm:py-6 lg:px-8 gap-2">
<h1 class="text-base font-semibold leading-7 text-black">
- <i18n.Translate>Case history for account:</i18n.Translate>
+ <i18n.Translate>Case history for selected account</i18n.Translate>
</h1>
- <div>{account}</div>
- <CopyButton class="" getContent={() => account} />
+ <div>
+ <p>
+ <span class="font-bold">
+ <i18n.Translate>ID:</i18n.Translate>
+ </span>{" "}
+ {account} <CopyButton class="" getContent={() => account} />
+ </p>
+ <p>
+ <span class="font-bold">
+ <i18n.Translate>Payto:</i18n.Translate>
+ </span>{" "}
+ {activeDecision?.full_payto ?? "N/A"}{" "}
+ <CopyButton
+ class=""
+ getContent={() => activeDecision?.full_payto ?? "N/A"}
+ />
+ </p>
+ </div>
</header>
{!activeDecision || !activeDecision.to_investigate ? undefined : (
@@ -180,7 +201,7 @@ export function AccountDetails({
</h1>
<p class="mt-1 text-sm leading-6 text-gray-600">
<i18n.Translate>
- Every event when the user was asked information.
+ Every attribute collection event (via form upload or KYC provider).
</i18n.Translate>
</p>
</div>
diff --git a/packages/aml-backoffice-ui/src/pages/AccountList.tsx b/packages/aml-backoffice-ui/src/pages/AccountList.tsx
@@ -156,7 +156,7 @@ export function AccountList({
scope="col"
class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-80"
>
- <i18n.Translate>Account Id</i18n.Translate>
+ <i18n.Translate>Account Identification</i18n.Translate>
</th>
<th
scope="col"
@@ -180,6 +180,7 @@ export function AccountList({
>
{r.h_payto}
</a>
+ <p class="text-gray-500 text-xs">{r.full_payto}</p>
</div>
</td>
<td class="whitespace-nowrap px-3 py-5 text-sm text-gray-900">
diff --git a/packages/taler-util/src/types-taler-exchange.ts b/packages/taler-util/src/types-taler-exchange.ts
@@ -2146,6 +2146,8 @@ export interface AmlDecision {
// Identifies a GNU Taler wallet or an affected bank account.
h_payto: PaytoHash;
+ full_payto?: string;
+
// True if the underlying payto://-URI is for a wallet
// Since protocol **v25**.
is_wallet: boolean;
@@ -2719,6 +2721,7 @@ export const codecForKycDetail = (): Codec<KycDetail> =>
export const codecForAmlDecision = (): Codec<AmlDecision> =>
buildCodecForObject<AmlDecision>()
.property("h_payto", codecForString())
+ .property("full_payto", codecOptional(codecForString()))
.property("rowid", codecForNumber())
.property("is_wallet", codecForBoolean())
.property("justification", codecOptional(codecForString()))