Skip to content

Commit a21352c

Browse files
feat: misc fixes and add whitelisting on review (#688)
1 parent 3a23fb4 commit a21352c

File tree

10 files changed

+48
-20
lines changed

10 files changed

+48
-20
lines changed

packages/app-builder/src/components/Sanctions/MatchCard.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { type SanctionCheckMatch } from '@app-builder/models/sanction-check';
22
import { SanctionCheckReviewModal } from '@app-builder/routes/ressources+/cases+/review-sanction-match';
33
import { useOrganizationUsers } from '@app-builder/services/organization/organization-users';
4+
import { getFullName } from '@app-builder/services/user';
45
import { formatDateTime, useFormatLanguage } from '@app-builder/utils/format';
56
import { useState } from 'react';
67
import { useTranslation } from 'react-i18next';
@@ -85,7 +86,7 @@ export const MatchCard = ({
8586
<SanctionCheckReviewModal
8687
open={isInReview}
8788
onClose={() => setIsInReview(false)}
88-
sanctionMatchId={match.id}
89+
sanctionMatch={match}
8990
/>
9091
</div>
9192
);
@@ -99,6 +100,7 @@ function CommentLine({
99100
const language = useFormatLanguage();
100101
const { getOrgUserById } = useOrganizationUsers();
101102
const user = getOrgUserById(comment.authorId);
103+
const fullName = getFullName(user);
102104

103105
return (
104106
<div key={comment.id} className="flex flex-col gap-2">
@@ -109,7 +111,7 @@ function CommentLine({
109111
lastName={user?.lastName}
110112
/>
111113
<span className="flex items-baseline gap-1">
112-
Roger Grand
114+
{fullName}
113115
<time className="text-grey-50 text-xs" dateTime={comment.createdAt}>
114116
{formatDateTime(comment.createdAt, { language })}
115117
</time>

packages/app-builder/src/components/Sanctions/StatusTag.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { type SanctionCheckMatch } from '@app-builder/models/sanction-check';
22
import clsx from 'clsx';
33
import { useTranslation } from 'react-i18next';
4-
import { Tag } from 'ui-design-system';
4+
import { Tag, type TagProps } from 'ui-design-system';
55
import { Icon } from 'ui-icons';
66

77
import { sanctionsI18n } from './sanctions-i18n';
@@ -10,7 +10,8 @@ const statusTagColors = {
1010
pending: 'orange',
1111
no_hit: 'grey',
1212
confirmed_hit: 'red',
13-
} as const;
13+
skipped: 'grey',
14+
} satisfies Record<SanctionCheckMatch['status'], TagProps['color']>;
1415

1516
export type StatusTagProps = {
1617
status: SanctionCheckMatch['status'];

packages/app-builder/src/locales/ar/sanctions.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,5 +108,7 @@
108108
"refine_modal.schema.vehicle": "عربة",
109109
"entity.schema.airplane": "طائرة",
110110
"entity.schema.vessel": "إناء",
111-
"refine_modal.schema.legalentity": "الكيان القانوني"
111+
"refine_modal.schema.legalentity": "الكيان القانوني",
112+
"match.status.skipped": "تخطي",
113+
"match.unique_counterparty_identifier": "معرف فريد للطرف المقابل"
112114
}

packages/app-builder/src/locales/en/sanctions.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
"match.status.pending": "To review",
3434
"match.status.no_hit": "No match",
3535
"match.status.confirmed_hit": "Match confirmed",
36+
"match.status.skipped": "Skipped",
37+
"match.unique_counterparty_identifier": "Unique counterpary Identifier",
3638
"entity.property.name": "Name",
3739
"entity.property.position": "Position",
3840
"entity.property.religion": "Religion",

packages/app-builder/src/locales/fr/sanctions.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,5 +108,7 @@
108108
"refine_modal.no_match_label": "Aucune correspondance possible n'a été trouvée avec votre recherche.",
109109
"refine_modal.schema.vehicle": "Véhicule",
110110
"entity.schema.airplane": "Avion",
111-
"entity.schema.vessel": "Navire"
111+
"entity.schema.vessel": "Navire",
112+
"match.status.skipped": "Sauté",
113+
"match.unique_counterparty_identifier": "Identifiant unique de contrepartie"
112114
}

packages/app-builder/src/models/sanction-check.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ export type SanctionCheckStatus =
2323
| 'confirmed_hit'
2424
| 'no_hit'
2525
| 'error';
26-
export type SanctionCheckMatchStatus = 'pending' | 'confirmed_hit' | 'no_hit';
26+
export type SanctionCheckMatchStatus =
27+
| 'pending'
28+
| 'confirmed_hit'
29+
| 'no_hit'
30+
| 'skipped';
2731
export type SanctionCheckEntitySchema = (typeof entitySchemas)[number];
2832

2933
export type SanctionCheckMatchPayload = {
@@ -56,6 +60,7 @@ export type SanctionCheckMatch = {
5660
queryIds: string[];
5761
status: SanctionCheckMatchStatus;
5862
// datasets: unknown[];
63+
uniqueCounterpartyIdentifier?: string;
5964
payload: SanctionCheckMatchPayload;
6065
comments: {
6166
id: string;
@@ -74,6 +79,7 @@ export function adaptSanctionCheckMatch(
7479
queryIds: dto.query_ids,
7580
status: dto.status,
7681
payload: adapatSanctionCheckMatchPayload(dto.payload),
82+
uniqueCounterpartyIdentifier: dto.unique_counterparty_identifier,
7783
comments: R.map(dto.comments, (comment) => ({
7884
id: comment.id,
7985
authorId: comment.author_id,

packages/app-builder/src/repositories/SanctionCheckRepository.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ export interface SanctionCheckRepository {
2222
listDatasets(): Promise<OpenSanctionsCatalog>;
2323
updateMatchStatus(args: {
2424
matchId: string;
25-
status: Exclude<SanctionCheckMatchStatus, 'pending'>;
25+
status: Extract<SanctionCheckMatchStatus, 'no_hit' | 'confirmed_hit'>;
2626
comment?: string;
27+
whitelist?: boolean;
2728
}): Promise<SanctionCheckMatch>;
2829
searchSanctionCheckMatches(args: {
2930
decisionId: string;
@@ -53,11 +54,12 @@ export function makeGetSanctionCheckRepository() {
5354
adaptSanctionCheck,
5455
);
5556
},
56-
updateMatchStatus: async ({ matchId, status, comment }) => {
57+
updateMatchStatus: async ({ matchId, status, comment, whitelist }) => {
5758
return adaptSanctionCheckMatch(
5859
await marbleCoreApiClient.updateSanctionCheckMatch(matchId, {
5960
status,
6061
comment,
62+
whitelist,
6163
}),
6264
);
6365
},

packages/app-builder/src/routes/ressources+/cases+/review-sanction-match.tsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Callout } from '@app-builder/components';
22
import { setToastMessage } from '@app-builder/components/MarbleToaster';
33
import { StatusRadioGroup } from '@app-builder/components/Sanctions/StatusRadioGroup';
4+
import { type SanctionCheckMatch } from '@app-builder/models/sanction-check';
45
import { serverServices } from '@app-builder/services/init.server';
56
import { useCallbackRef } from '@app-builder/utils/hooks';
67
import { getRoute } from '@app-builder/utils/routes';
@@ -10,7 +11,7 @@ import { useFetcher } from '@remix-run/react';
1011
import { type UpdateSanctionCheckMatchDto } from 'marble-api';
1112
import { useEffect, useState } from 'react';
1213
import { useTranslation } from 'react-i18next';
13-
import { Button, ModalV2, TextArea } from 'ui-design-system';
14+
import { Button, ModalV2, Switch, TextArea } from 'ui-design-system';
1415
import { z } from 'zod';
1516

1617
const schema = z.object({
@@ -62,11 +63,11 @@ export async function action({ request }: ActionFunctionArgs) {
6263
export const SanctionCheckReviewModal = ({
6364
open,
6465
onClose: _onClose,
65-
sanctionMatchId,
66+
sanctionMatch,
6667
}: {
6768
open: boolean;
6869
onClose: () => void;
69-
sanctionMatchId: string;
70+
sanctionMatch: SanctionCheckMatch;
7071
}) => {
7172
const { t } = useTranslation(['common', 'sanctions']);
7273
const [currentStatus, setCurrentStatus] = useState<
@@ -98,7 +99,7 @@ export const SanctionCheckReviewModal = ({
9899
method="post"
99100
action={getRoute('/ressources/cases/review-sanction-match')}
100101
>
101-
<input name="matchId" type="hidden" value={sanctionMatchId} />
102+
<input name="matchId" type="hidden" value={sanctionMatch.id} />
102103
<div className="flex flex-col gap-2">
103104
<div className="text-m">
104105
{t('sanctions:review_modal.status_label')}
@@ -117,17 +118,21 @@ export const SanctionCheckReviewModal = ({
117118
<TextArea name="comment" />
118119
</div>
119120
{/* TODO: Whitelisting */}
120-
{/* {currentStatus === 'no_hit' ? (
121+
{currentStatus === 'no_hit' &&
122+
!!sanctionMatch.uniqueCounterpartyIdentifier ? (
121123
<div className="flex flex-col gap-2">
122124
<span className="flex items-center gap-2">
123-
<Switch name="whitelist" /> {t('sanctions:review_modal.whitelist_label')}
125+
<Switch name="whitelist" />{' '}
126+
{t('sanctions:review_modal.whitelist_label')}
124127
</span>
125128
<div className="border-grey-90 bg-grey-98 flex flex-col gap-2 rounded border p-2">
126-
<span className="font-semibold">IBAN</span>
127-
<span>FR76 4061 8801 5200 0500 9263 912</span>
129+
<span className="font-semibold">
130+
{t('sanctions:match.unique_counterparty_identifier')}
131+
</span>
132+
<span>{sanctionMatch.uniqueCounterpartyIdentifier}</span>
128133
</div>
129134
</div>
130-
) : null} */}
135+
) : null}
131136
<div className="flex flex-1 flex-row gap-2">
132137
<ModalV2.Close
133138
render={

packages/marble-api/openapis/marblecore-api.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5182,9 +5182,11 @@ components:
51825182
type: string
51835183
status:
51845184
type: string
5185-
enum: ['pending', 'confirmed_hit', 'no_hit']
5185+
enum: ['pending', 'confirmed_hit', 'no_hit', 'skipped']
51865186
datasets:
51875187
type: array
5188+
unique_counterparty_identifier:
5189+
type: string
51885190
payload:
51895191
$ref: '#/components/schemas/SanctionCheckMatchPayloadDto'
51905192
comments:
@@ -5404,6 +5406,8 @@ components:
54045406
enum: ['confirmed_hit', 'no_hit']
54055407
comment:
54065408
type: string
5409+
whitelist:
5410+
type: boolean
54075411
UpdateScenarioIterationBody:
54085412
type: object
54095413
properties:

packages/marble-api/src/generated/marblecore-api.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,8 +507,9 @@ export type SanctionCheckMatchDto = {
507507
id: string;
508508
entity_id: string;
509509
query_ids: string[];
510-
status: "pending" | "confirmed_hit" | "no_hit";
510+
status: "pending" | "confirmed_hit" | "no_hit" | "skipped";
511511
datasets: any;
512+
unique_counterparty_identifier?: string;
512513
payload: SanctionCheckMatchPayloadDto;
513514
comments: {
514515
id: string;
@@ -546,6 +547,7 @@ export type SanctionCheckFileDto = {
546547
export type UpdateSanctionCheckMatchDto = {
547548
status: "confirmed_hit" | "no_hit";
548549
comment?: string;
550+
whitelist?: boolean;
549551
};
550552
export type SanctionCheckRefineDto = object;
551553
export type UpdateScenarioIterationRuleBodyDto = {

0 commit comments

Comments
 (0)