Skip to content

Commit 69cd6b9

Browse files
authored
Merchant Monitoring migration (#2819)
* wip * fix: fixes * fix: fixes * fix: fixes * fix: fixes * fix: fixes
1 parent 5682ecf commit 69cd6b9

File tree

48 files changed

+767
-1210
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+767
-1210
lines changed

apps/backoffice-v2/src/common/api-client/api-client.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const apiClient: IApiClient = async ({ endpoint, method, options, schema,
1818
url: `${env.VITE_API_URL}/${endpoint}`,
1919
method,
2020
options: {
21+
timeout: 20_000,
2122
...options,
2223
credentials: 'include',
2324
},
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
export const MERCHANT_REPORT_STATUSES_MAP = {
2+
draft: 'draft',
3+
'in-progress': 'in-progress',
4+
completed: 'completed',
5+
'quality-control': 'quality-control',
6+
failed: 'failed',
7+
} as const;
8+
9+
export type MerchantReportStatus = keyof typeof MERCHANT_REPORT_STATUSES_MAP;
10+
11+
export const MERCHANT_REPORT_STATUSES = Object.values(MERCHANT_REPORT_STATUSES_MAP);
12+
13+
export const MERCHANT_REPORT_TYPES_MAP = {
14+
MERCHANT_REPORT_T1: 'MERCHANT_REPORT_T1',
15+
ONGOING_MERCHANT_REPORT_T1: 'ONGOING_MERCHANT_REPORT_T1',
16+
} as const;
17+
18+
export type MerchantReportType = keyof typeof MERCHANT_REPORT_TYPES_MAP;
19+
20+
export const MERCHANT_REPORT_TYPES = Object.values(MERCHANT_REPORT_TYPES_MAP);
21+
22+
export const MERCHANT_REPORT_VERSIONS_MAP = {
23+
'1': '1',
24+
'2': '2',
25+
} as const;
26+
27+
export type MerchantReportVersion = keyof typeof MERCHANT_REPORT_VERSIONS_MAP;
28+
29+
export const MERCHANT_REPORT_VERSIONS = Object.values(MERCHANT_REPORT_VERSIONS_MAP);

apps/backoffice-v2/src/domains/business-reports/fetchers.ts

Lines changed: 38 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2,76 +2,54 @@ import { z } from 'zod';
22
import { apiClient } from '@/common/api-client/api-client';
33
import { Method } from '@/common/enums';
44
import { handleZodError } from '@/common/utils/handle-zod-error/handle-zod-error';
5-
import { TBusinessReportType } from '@/domains/business-reports/types';
65
import qs from 'qs';
7-
import { ObjectValues, Severities } from '@ballerine/common';
86
import { toast } from 'sonner';
97
import { t } from 'i18next';
10-
11-
export const BusinessReportStatus = {
12-
NEW: 'new',
13-
IN_PROGRESS: 'in_progress',
14-
COMPLETED: 'completed',
15-
} as const;
16-
17-
export type TBusinessReportStatus = ObjectValues<typeof BusinessReportStatus>;
18-
19-
export type TBusinessReportStatuses = TBusinessReportStatus[];
20-
21-
export const BusinessReportStatuses = [
22-
BusinessReportStatus.NEW,
23-
BusinessReportStatus.IN_PROGRESS,
24-
BusinessReportStatus.COMPLETED,
25-
] as const satisfies readonly TBusinessReportStatus[];
26-
27-
export const SeveritySchema = z.preprocess(value => {
28-
if (value === 'moderate') {
29-
return 'medium';
30-
}
31-
32-
if (value === 'positive') {
33-
return 'low';
34-
}
35-
36-
return value;
37-
}, z.enum(Severities));
8+
import {
9+
MERCHANT_REPORT_STATUSES,
10+
MERCHANT_REPORT_TYPES,
11+
MERCHANT_REPORT_VERSIONS,
12+
MerchantReportType,
13+
MerchantReportVersion,
14+
} from '@/domains/business-reports/constants';
3815

3916
export const BusinessReportSchema = z
4017
.object({
4118
id: z.string(),
42-
type: z.string(),
19+
reportType: z.enum([MERCHANT_REPORT_TYPES[0]!, ...MERCHANT_REPORT_TYPES.slice(1)]),
4320
createdAt: z.string().datetime(),
4421
updatedAt: z.string().datetime(),
4522
riskScore: z.number().nullable(),
46-
status: z.enum(BusinessReportStatuses),
47-
report: z.object({
48-
isAlert: z.boolean().optional(),
49-
reportFileId: z.union([z.string(), z.undefined()]),
50-
data: z.union([z.record(z.string(), z.unknown()), z.undefined()]),
23+
status: z.enum([MERCHANT_REPORT_STATUSES[0]!, ...MERCHANT_REPORT_STATUSES.slice(1)]),
24+
parentCompanyName: z.string().nullable(),
25+
merchantId: z.string(),
26+
workflowVersion: z.enum([MERCHANT_REPORT_VERSIONS[0]!, ...MERCHANT_REPORT_VERSIONS.slice(1)]),
27+
isAlert: z.boolean().nullable(),
28+
website: z.object({
29+
id: z.string(),
30+
url: z.string().url(),
31+
createdAt: z
32+
.string()
33+
.datetime()
34+
.transform(value => new Date(value)),
35+
updatedAt: z
36+
.string()
37+
.datetime()
38+
.transform(value => new Date(value)),
5139
}),
52-
business: z
53-
.object({
54-
id: z.string(),
55-
companyName: z.string(),
56-
country: z.string().nullable(),
57-
website: z.string().nullable(),
58-
})
59-
.nullable(),
40+
data: z.record(z.string(), z.unknown()).nullish(),
6041
})
61-
.optional()
6242
.transform(data => ({
6343
...data,
64-
companyName:
65-
data?.report.data?.websiteCompanyAnalysis?.companyName || data?.business?.companyName,
66-
website: data?.report.data?.websiteCompanyAnalysis?.website.url || data?.business?.website,
44+
companyName: data?.parentCompanyName,
45+
website: data?.website.url,
46+
data: data.status === 'completed' ? data?.data : null,
6747
}));
6848

6949
export const BusinessReportsSchema = z.object({
70-
businessReports: z.array(BusinessReportSchema),
71-
meta: z.object({
72-
totalItems: z.number().nonnegative(),
73-
totalPages: z.number().nonnegative(),
74-
}),
50+
data: z.array(BusinessReportSchema),
51+
totalItems: z.number().nonnegative(),
52+
totalPages: z.number().nonnegative(),
7553
});
7654

7755
export type TBusinessReport = z.infer<typeof BusinessReportSchema>;
@@ -83,7 +61,7 @@ export const fetchLatestBusinessReport = async ({
8361
reportType,
8462
}: {
8563
businessId: string;
86-
reportType: TBusinessReportType;
64+
reportType: MerchantReportType;
8765
}) => {
8866
const [data, error] = await apiClient({
8967
endpoint: `business-reports/latest?businessId=${businessId}&type=${reportType}`,
@@ -98,7 +76,7 @@ export const fetchBusinessReports = async ({
9876
reportType,
9977
...params
10078
}: {
101-
reportType: TBusinessReportType;
79+
reportType: MerchantReportType;
10280
page: {
10381
number: number;
10482
size: number;
@@ -144,16 +122,16 @@ export const createBusinessReport = async ({
144122
| {
145123
websiteUrl: string;
146124
operatingCountry?: string;
147-
reportType: TBusinessReportType;
148-
workflowVersion: '1' | '2' | '3';
125+
reportType: MerchantReportType;
126+
workflowVersion: MerchantReportVersion;
149127
companyName: string;
150128
isExample: boolean;
151129
}
152130
| {
153131
websiteUrl: string;
154132
operatingCountry?: string;
155-
reportType: TBusinessReportType;
156-
workflowVersion: '1' | '2' | '3';
133+
reportType: MerchantReportType;
134+
workflowVersion: MerchantReportVersion;
157135
businessCorrelationId: string;
158136
isExample: boolean;
159137
}) => {
@@ -188,7 +166,7 @@ export const createBusinessReportBatch = async ({
188166
}: {
189167
merchantSheet: File;
190168
isExample: boolean;
191-
reportType: TBusinessReportType;
169+
reportType: MerchantReportType;
192170
workflowVersion: string;
193171
}) => {
194172
if (isExample) {

apps/backoffice-v2/src/domains/business-reports/hooks/mutations/useCreateBusinessReportBatchMutation/useCreateBusinessReportBatchMutation.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@ import { toast } from 'sonner';
33
import { useMutation, useQueryClient } from '@tanstack/react-query';
44

55
import { HttpError } from '@/common/errors/http-error';
6-
import { TBusinessReportType } from '@/domains/business-reports/types';
76
import { createBusinessReportBatch } from '@/domains/business-reports/fetchers';
87
import { useCustomerQuery } from '@/domains/customer/hook/queries/useCustomerQuery/useCustomerQuery';
98
import { isObject } from '@ballerine/common';
9+
import { MerchantReportType } from '@/domains/business-reports/constants';
1010

1111
export const useCreateBusinessReportBatchMutation = ({
1212
reportType,
1313
workflowVersion,
1414
onSuccess,
1515
}: {
16-
reportType: TBusinessReportType;
16+
reportType: MerchantReportType;
1717
workflowVersion: string;
1818
onSuccess?: <TData>(data: TData) => void;
1919
}) => {
@@ -22,13 +22,17 @@ export const useCreateBusinessReportBatchMutation = ({
2222
const { data: customer } = useCustomerQuery();
2323

2424
return useMutation({
25-
mutationFn: (merchantSheet: File) =>
26-
createBusinessReportBatch({
25+
mutationFn: async (merchantSheet: File) => {
26+
await createBusinessReportBatch({
2727
reportType,
2828
workflowVersion,
2929
merchantSheet,
3030
isExample: customer?.config?.isExample ?? false,
31-
}),
31+
});
32+
33+
// Artificial delay to ensure report is created in Unified API's DB
34+
await new Promise(resolve => setTimeout(resolve, 3000));
35+
},
3236
onSuccess: data => {
3337
void queryClient.invalidateQueries();
3438

apps/backoffice-v2/src/domains/business-reports/hooks/mutations/useCreateBusinessReportMutation/useCreateBusinessReportMutation.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const useCreateBusinessReportMutation = ({
1818
const workflowVersion = customer?.features?.createBusinessReport?.options.version ?? '2';
1919

2020
return useMutation({
21-
mutationFn: ({
21+
mutationFn: async ({
2222
websiteUrl,
2323
operatingCountry,
2424
companyName,
@@ -33,16 +33,20 @@ export const useCreateBusinessReportMutation = ({
3333
websiteUrl: string;
3434
operatingCountry: string;
3535
businessCorrelationId: string;
36-
}) =>
37-
createBusinessReport({
36+
}) => {
37+
await createBusinessReport({
3838
websiteUrl,
3939
operatingCountry,
4040
companyName,
4141
businessCorrelationId,
4242
reportType,
4343
workflowVersion,
4444
isExample: customer?.config?.isExample ?? false,
45-
}),
45+
});
46+
47+
// Artificial delay to ensure report is created in Unified API's DB
48+
await new Promise(resolve => setTimeout(resolve, 3000));
49+
},
4650
onSuccess: data => {
4751
if (customer?.config?.isExample) {
4852
return;

apps/backoffice-v2/src/domains/business-reports/hooks/queries/useBusinessReportsQuery/useBusinessReportsQuery.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { TBusinessReportType } from '@/domains/business-reports/types';
21
import { useIsAuthenticated } from '@/domains/auth/context/AuthProvider/hooks/useIsAuthenticated/useIsAuthenticated';
32
import { useQuery } from '@tanstack/react-query';
43
import { businessReportsQueryKey } from '@/domains/business-reports/query-keys';
54
import { isString } from '@/common/utils/is-string/is-string';
5+
import { MerchantReportType } from '@/domains/business-reports/constants';
66

77
export const useBusinessReportsQuery = ({
88
reportType,
@@ -12,7 +12,7 @@ export const useBusinessReportsQuery = ({
1212
sortBy,
1313
sortDir,
1414
}: {
15-
reportType: TBusinessReportType;
15+
reportType: MerchantReportType;
1616
search: string;
1717
page: number;
1818
pageSize: number;

apps/backoffice-v2/src/domains/business-reports/hooks/queries/useLatestBusinessReportQuery/useLatestBusinessReportQuery.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import { useIsAuthenticated } from '@/domains/auth/context/AuthProvider/hooks/us
22
import { useQuery } from '@tanstack/react-query';
33
import { isString } from '@/common/utils/is-string/is-string';
44
import { businessReportsQueryKey } from '@/domains/business-reports/query-keys';
5-
import { TBusinessReportType } from '@/domains/business-reports/types';
5+
import { MerchantReportType } from '@/domains/business-reports/constants';
66

77
export const useLatestBusinessReportQuery = ({
88
businessId,
99
reportType,
1010
}: {
1111
businessId: string;
12-
reportType: TBusinessReportType;
12+
reportType: MerchantReportType;
1313
}) => {
1414
const isAuthenticated = useIsAuthenticated();
1515

apps/backoffice-v2/src/domains/business-reports/query-keys.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
fetchBusinessReports,
66
fetchLatestBusinessReport,
77
} from '@/domains/business-reports/fetchers';
8-
import { TBusinessReportType } from '@/domains/business-reports/types';
8+
import { MerchantReportType } from '@/domains/business-reports/constants';
99

1010
export const businessReportsQueryKey = createQueryKeys('business-reports', {
1111
list: ({
@@ -15,7 +15,7 @@ export const businessReportsQueryKey = createQueryKeys('business-reports', {
1515
sortDir,
1616
...params
1717
}: {
18-
reportType: TBusinessReportType;
18+
reportType: MerchantReportType;
1919
search: string;
2020
page: number;
2121
pageSize: number;
@@ -36,13 +36,7 @@ export const businessReportsQueryKey = createQueryKeys('business-reports', {
3636
return fetchBusinessReports(data);
3737
},
3838
}),
39-
latest: ({
40-
businessId,
41-
reportType,
42-
}: {
43-
businessId: string;
44-
reportType: TBusinessReportType;
45-
}) => ({
39+
latest: ({ businessId, reportType }: { businessId: string; reportType: MerchantReportType }) => ({
4640
queryKey: [{ businessId, reportType }],
4741
queryFn: () => fetchLatestBusinessReport({ businessId, reportType }),
4842
}),

apps/backoffice-v2/src/domains/business-reports/types.ts

Lines changed: 0 additions & 2 deletions
This file was deleted.

apps/backoffice-v2/src/domains/workflows/fetchers.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ export const BaseWorkflowByIdSchema = z.object({
106106
})
107107
.passthrough()
108108
.optional(),
109+
merchantMonitoring: z
110+
.object({
111+
reportId: z.string().nullish(),
112+
})
113+
.passthrough()
114+
.nullish(),
109115
})
110116
.passthrough()
111117
.optional(),

0 commit comments

Comments
 (0)