Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(plugins): add commercial credit check plugin and related updates #3024

Merged
merged 7 commits into from
Feb 8, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export const pluginsWhiteList = [
'merchantMonitoring',
'merchantScreening',
'bankAccountVerification',
'commercialCreditCheck',
tomer-shvadron marked this conversation as resolved.
Show resolved Hide resolved
] as const;

export const DEFAULT_PROCESS_TRACKER_PROCESSES = ['collection-flow', 'third-party', 'ubos'];
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { useCallback, useMemo } from 'react';

import { createBlocksTyped } from '@/lib/blocks/create-blocks-typed/create-blocks-typed';

export const useBankAccountVerificationBlock = ({ pluginsOutput }) => {
const getCell = useCallback(() => {
if (
Object.keys(pluginsOutput?.bankAccountVerification?.data.clientResponsePayload ?? {}).length
) {
const data = {
...pluginsOutput.bankAccountVerification.data.responseHeader.overallResponse,
decisionElements:
pluginsOutput.bankAccountVerification.data.clientResponsePayload.decisionElements,
orchestrationDecisions:
pluginsOutput.bankAccountVerification.data.clientResponsePayload.orchestrationDecisions,
};

return {
id: 'nested-details',
type: 'details',
hideSeparator: true,
value: {
data: Object.entries(data)
?.filter(([property]) => !['tenantID', 'clientReferenceId'].includes(property))
.map(([title, value]) => ({
title,
value,
})),
},
props: {
config: {
sort: { predefinedOrder: ['decision', 'decisionText'] },
},
},
} satisfies Extract<
Parameters<ReturnType<typeof createBlocksTyped>['addCell']>[0],
{
type: 'details';
}
>;
}
}, [pluginsOutput]);
tomer-shvadron marked this conversation as resolved.
Show resolved Hide resolved

return useMemo(() => {
tomer-shvadron marked this conversation as resolved.
Show resolved Hide resolved
const cell = getCell();

if (!cell) {
return [];
}

return createBlocksTyped()
.addBlock()
.addCell({
type: 'block',
value: createBlocksTyped()
.addBlock()
.addCell({
id: 'nested-details-heading',
type: 'heading',
value: 'Bank Account Verification',
})
.addCell({
id: 'nested-details-subheading',
type: 'subheading',
value: 'Experian-Provided Data',
props: {
className: 'mb-4',
},
})
.addCell(cell)
.build()
.flat(1),
})
.build();
}, [getCell]);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useCallback, useMemo } from 'react';

import { createBlocksTyped } from '@/lib/blocks/create-blocks-typed/create-blocks-typed';

export const useCommercialCreditCheckBlock = ({ pluginsOutput }) => {
tomer-shvadron marked this conversation as resolved.
Show resolved Hide resolved
const getCell = useCallback(() => {
if (Object.keys(pluginsOutput?.commercialCreditCheck?.data ?? {}).length) {
return {
id: 'nested-details',
type: 'details',
hideSeparator: true,
value: {
data: Object.entries(pluginsOutput.commercialCreditCheck.data).map(([title, value]) => ({
title,
value,
})),
},
props: {
config: {
sort: { predefinedOrder: ['CommercialName', 'RegNumber'] },
},
},
} satisfies Extract<
Parameters<ReturnType<typeof createBlocksTyped>['addCell']>[0],
{
type: 'details';
}
>;
}
}, [pluginsOutput]);

return useMemo(() => {
const cell = getCell();

if (!cell) {
return [];
}

return createBlocksTyped()
.addBlock()
.addCell({
type: 'block',
value: createBlocksTyped()
.addBlock()
.addCell({
id: 'nested-details-heading',
type: 'heading',
value: 'Commercial Credit Check',
})
.addCell({
id: 'nested-details-subheading',
type: 'subheading',
value: 'Experian-Provided Data',
props: {
className: 'mb-4',
},
})
.addCell(cell)
.buildFlat(),
})
.build();
}, [getCell]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@ import { createBlocksTyped } from '@/lib/blocks/create-blocks-typed/create-block
import { WarningFilledSvg } from '@ballerine/ui';

export const useKybRegistryInfoBlock = ({ pluginsOutput, workflow }) => {
const isBankAccountVerification = useMemo(
() => !!pluginsOutput?.bankAccountVerification,
[pluginsOutput?.bankAccountVerification],
);

const getCell = useCallback(() => {
if (Object.keys(pluginsOutput?.businessInformation?.data?.[0] ?? {}).length) {
return {
Expand All @@ -33,39 +28,6 @@ export const useKybRegistryInfoBlock = ({ pluginsOutput, workflow }) => {
>;
}

if (Object.keys(pluginsOutput?.bankAccountVerification?.clientResponsePayload ?? {}).length) {
const data = {
...pluginsOutput?.bankAccountVerification?.responseHeader.overallResponse,
decisionElements:
pluginsOutput?.bankAccountVerification?.clientResponsePayload.decisionElements,
orchestrationDecisions:
pluginsOutput?.bankAccountVerification?.clientResponsePayload.orchestrationDecisions,
};

return {
id: 'nested-details',
type: 'details',
hideSeparator: true,
value: {
data: Object.entries(data)
?.filter(([property]) => {
console.log(property);

return !['tenantID', 'clientReferenceId'].includes(property);
})
.map(([title, value]) => ({
title,
value,
})),
},
} satisfies Extract<
Parameters<ReturnType<typeof createBlocksTyped>['addCell']>[0],
{
type: 'details';
}
>;
}

const message =
pluginsOutput?.businessInformation?.message ??
pluginsOutput?.businessInformation?.data?.message;
Expand Down Expand Up @@ -132,12 +94,12 @@ export const useKybRegistryInfoBlock = ({ pluginsOutput, workflow }) => {
.addCell({
id: 'nested-details-heading',
type: 'heading',
value: isBankAccountVerification ? 'Bank Account Verification' : 'Registry Information',
value: 'Registry Information',
})
.addCell({
id: 'nested-details-subheading',
type: 'subheading',
value: `${isBankAccountVerification ? 'Experian' : 'Registry'}-Provided Data`,
value: 'Registry-Provided Data',
props: {
className: 'mb-4',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ export const getTabsToBlocksMap = ({
amlWithContainerBlock,
merchantScreeningBlock,
manageUbosBlock,
bankAccountVerificationBlock,
commercialCreditCheckBlock,
] = blocks;

const defaultTabsMap = {
Expand All @@ -76,6 +78,8 @@ export const getTabsToBlocksMap = ({
...kybRegistryInfoBlock,
...companySanctionsBlock,
...bankingDetailsBlock,
...bankAccountVerificationBlock,
...commercialCreditCheckBlock,
],
[Tab.STORE_INFO]: [
...storeInfoBlock,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ import { useRemoveDecisionTaskByIdMutation } from '@/domains/entities/hooks/muta
import { useApproveTaskByIdMutation } from '@/domains/entities/hooks/mutations/useApproveTaskByIdMutation/useApproveTaskByIdMutation';
import { directorAdapter } from '@/lib/blocks/components/DirectorBlock/hooks/useDirectorBlock/helpers';
import { createDirectorsBlocks } from '@/lib/blocks/components/DirectorBlock/hooks/useDirectorBlock/create-directors-blocks';
import { useBankAccountVerificationBlock } from '@/lib/blocks/hooks/useBankAccountVerificationBlock/useBankAccountVerificationBlock';
import { useCommercialCreditCheckBlock } from '@/lib/blocks/hooks/useCommercialCreditCheckBlock/useCommercialCreditCheckBlock';

const registryInfoWhitelist = ['open_corporates'] as const;

Expand Down Expand Up @@ -173,6 +175,14 @@ export const useDefaultBlocksLogic = () => {
workflow,
});

const bankAccountVerificationBlock = useBankAccountVerificationBlock({
pluginsOutput: workflow?.context?.pluginsOutput,
});

const commercialCreditCheckBlock = useCommercialCreditCheckBlock({
pluginsOutput: workflow?.context?.pluginsOutput,
});

const parentDocumentBlocks = useDocumentBlocks({
workflow,
parentMachine: workflow?.context?.parentMachine,
Expand Down Expand Up @@ -511,7 +521,9 @@ export const useDefaultBlocksLogic = () => {
});

const allBlocks = useMemo(() => {
if (!workflow?.context?.entity) return [];
if (!workflow?.context?.entity) {
return [];
}

return [
websiteMonitoringBlock,
Expand Down Expand Up @@ -543,6 +555,8 @@ export const useDefaultBlocksLogic = () => {
amlWithContainerBlock,
merchantScreeningBlock,
manageUbosBlock,
bankAccountVerificationBlock,
commercialCreditCheckBlock,
];
}, [
associatedCompaniesBlock,
Expand Down Expand Up @@ -575,6 +589,8 @@ export const useDefaultBlocksLogic = () => {
merchantScreeningBlock,
workflow?.context?.entity,
manageUbosBlock,
bankAccountVerificationBlock,
commercialCreditCheckBlock,
]);

const { blocks, tabs } = useCaseBlocks({
Expand Down
3 changes: 3 additions & 0 deletions packages/workflow-core/src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { BallerineApiPlugin } from './plugins/external-plugin/ballerine-api-plug
import { BallerineEmailPlugin } from './plugins/external-plugin/ballerine-email-plugin';
import { IndividualsSanctionsV2Plugin } from './plugins/external-plugin/individuals-sanctions-v2-plugin/individuals-sanctions-v2-plugin';
import { BankAccountVerificationPlugin } from './plugins/external-plugin/bank-account-verification-plugin/bank-account-verification-plugin';
import { CommercialCreditCheckPlugin } from './plugins/external-plugin/commercial-credit-check-plugin/commercial-credit-check-plugin';

export const PluginKind = {
KYC: 'kyc',
Expand All @@ -20,6 +21,7 @@ export const PluginKind = {
MASTERCARD_MERCHANT_SCREENING: 'mastercard-merchant-screening',
INDIVIDUAL_SANCTIONS_V2: 'individual-sanctions-v2',
BANK_ACCOUNT_VERIFICATION: 'bank-account-verification',
COMMERCIAL_CREDIT_CHECK: 'commercial-credit-check',
} as const;

export const pluginsRegistry = {
Expand All @@ -31,6 +33,7 @@ export const pluginsRegistry = {
[PluginKind.MASTERCARD_MERCHANT_SCREENING]: MastercardMerchantScreeningPlugin,
[PluginKind.INDIVIDUAL_SANCTIONS_V2]: IndividualsSanctionsV2Plugin,
[PluginKind.BANK_ACCOUNT_VERIFICATION]: BankAccountVerificationPlugin,
[PluginKind.COMMERCIAL_CREDIT_CHECK]: CommercialCreditCheckPlugin,
[BALLERINE_API_PLUGINS['individual-sanctions']]: BallerineApiPlugin,
[BALLERINE_API_PLUGINS['company-sanctions']]: BallerineApiPlugin,
[BALLERINE_API_PLUGINS['ubo']]: BallerineApiPlugin,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ type TBankAccountVerificationPluginPayload = {
};
};

const BankAccountVerificationResponseSchema = z.record(z.string(), z.unknown());
tomer-shvadron marked this conversation as resolved.
Show resolved Hide resolved

export class BankAccountVerificationPlugin extends ApiPlugin {
public static pluginType = 'http';
public payload: TBankAccountVerificationPluginPayload;
Expand All @@ -94,7 +96,7 @@ export class BankAccountVerificationPlugin extends ApiPlugin {
const env = validateEnv(this.pluginName);

try {
const url = `${env.UNIFIED_API_URL}/bank-account-verification/commercial`;
const url = `${env.UNIFIED_API_URL}/bank-account-verification`;

const payload = getPayloadPropertiesValue({
properties: this.payload,
Expand Down Expand Up @@ -142,7 +144,7 @@ export class BankAccountVerificationPlugin extends ApiPlugin {
}

const res = await apiResponse.json();
const responseBody = z.record(z.string(), z.unknown()).parse(res);
const responseBody = BankAccountVerificationResponseSchema.parse(res);

if (this.successAction) {
return this.returnSuccessResponse(this.successAction, {
Expand Down
Loading