Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const MerchantMonitoringTracker = ({
return (
<Tracker workflow={workflow} plugins={plugins} processes={processes}>
<Tracker.Item
title="Merchant Monitoring"
title="Web Presence"
value={MERCHANT_MONITORING_PROCESS_NAME}
subitems={items}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { parsePhoneNumber } from 'libphonenumber-js';
*/
export const getPhoneNumberFormatter = (value: string) => {
try {
if (!/^(?!-)(?!\+?$)(?!-+$)(?!.*-\+)(?!.*--)\+?[\d-]+(?<!-)$/.test(value)) {
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Document the complex regex pattern for maintainability.

The regex validation is a good addition to prevent invalid inputs like emails from being processed as phone numbers. However, the pattern is quite complex with multiple negative lookaheads and lookbehinds, making it difficult to understand and maintain.

Consider adding a comment explaining the regex logic or extracting it to a named constant:

+// Regex to validate phone number format:
+// - Must not start or end with hyphen
+// - Must not be empty or just a plus sign
+// - Must not contain double hyphens or hyphen before plus
+// - Must contain only digits, hyphens, and optional leading plus
+const PHONE_NUMBER_PATTERN = /^(?!-)(?!\+?$)(?!-+$)(?!.*-\+)(?!.*--)\+?[\d-]+(?<!-)$/;
+
 export const getPhoneNumberFormatter = (value: string) => {
   try {
-    if (!/^(?!-)(?!\+?$)(?!-+$)(?!.*-\+)(?!.*--)\+?[\d-]+(?<!-)$/.test(value)) {
+    if (!PHONE_NUMBER_PATTERN.test(value)) {
       return;
     }
🤖 Prompt for AI Agents
In
apps/backoffice-v2/src/common/utils/get-phone-number-formatter/get-phone-number-formatter.ts
around lines 9 to 11, the regex pattern used for phone number validation is
complex and hard to understand. To improve maintainability, add a clear comment
above the regex explaining its purpose and the key parts of the pattern.
Alternatively, extract the regex into a well-named constant with a descriptive
name and add the explanatory comment there.


return parsePhoneNumber(value);
} catch {
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { describe, it, expect } from 'vitest';
import { getPhoneNumberFormatter } from './get-phone-number-formatter';

describe('getPhoneNumberFormatter', () => {
describe('when an email is passed', () => {
it('should return undefined', () => {
// Arrange
const value = '[email protected]';

// Act
const result = getPhoneNumberFormatter(value);

// Assert
expect(result).toBeUndefined();
});
});

describe('when a phone number with a country code is passed', () => {
it('should return a formatter', () => {
// Arrange
const value = '+9720526253312';

// Act
const result = getPhoneNumberFormatter(value);

// Assert
expect(result).toBeDefined();
});
});

describe('when a hyphenated phone number is passed', () => {
it('should return a formatter', () => {
// Arrange
const value = '+972-052-625-3312';

// Act
const result = getPhoneNumberFormatter(value);

// Assert
expect(result).toBeDefined();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const DynamicMetricsSection = ({
<Separator className="h-[1px] w-full bg-gray-300" />

<div className="flex items-center justify-between">
<h3 className={'text-xl font-medium'}>Merchant Monitoring Risk Analytics</h3>
<h3 className={'text-xl font-medium'}>Web Presence Risk Analytics</h3>

<DateRangePicker
toDate={new Date()}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const PortfolioRiskStatistics: FunctionComponent<
<div className={'grid grid-cols-3 gap-6'}>
<div className={'min-h-[27.5rem] rounded-xl bg-[#F6F6F6] p-2'}>
<Card className={'flex h-full flex-col px-3'}>
<CardHeader className={'pb-1 font-bold'}>Merchant Monitoring Risk</CardHeader>
<CardHeader className={'pb-1 font-bold'}>Web Presence Risk</CardHeader>
<CardContent>
<p className={'mb-8'}>Risk levels of all merchant monitoring reports.</p>
<div className={'flex flex-col items-center space-y-4 pt-3'}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export const VENDOR_DETAILS = {
},
},
'merchant-monitoring': {
title: 'Merchant Monitoring',
title: 'Web Presence',
description: 'Ongoing merchant monitoring and risk assessment',
vendors: {
ballerine: {
Expand All @@ -147,7 +147,7 @@ export const VENDOR_DETAILS = {
vendor: 'ballerine',
pluginKind: 'merchant-monitoring',
stateNames: ['run_merchant_monitoring'],
displayName: 'Merchant Monitoring',
displayName: 'Web Presence',
errorAction: 'MERCHANT_MONITORING_FAILED',
successAction: 'MERCHANT_MONITORING_SUCCESS',
merchantMonitoringQualityControl: false,
Expand All @@ -167,7 +167,7 @@ export const VENDOR_DETAILS = {
vendor: 'mastercard',
pluginKind: 'mastercard-merchant-screening',
stateNames: ['run_vendor_data'],
displayName: 'Merchant Screening',
displayName: 'MATCH Screening',
errorAction: 'VENDOR_DONE',
successAction: 'VENDOR_DONE',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ export const BALLERINE_API_PLUGIN_FACTORY = {
[BALLERINE_API_PLUGINS['merchant-monitoring']]: {
[MERCHANT_MONITORING_VENDORS['ballerine']]: (options: MerchantMonirotingOptions) => ({
name: 'merchantMonitoring',
displayName: 'Merchant Monitoring',
displayName: 'Web Presence',
pluginKind: 'api',
url: `{secret.UNIFIED_API_URL}/merchants/analysis`,
method: 'POST',
Expand Down
2 changes: 1 addition & 1 deletion services/workflows-service/prisma/data-migrations
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ export const generateWorkflowDefinition = ({
name: 'merchantMonitoring',
pluginKind: 'merchant-monitoring',
vendor: 'ballerine',
displayName: 'Merchant Monitoring',
displayName: 'Web Presence',
stateNames: ['run_merchant_monitoring', 'rerun_vendor_data'],
successAction: 'VENDOR_DONE',
errorAction: 'VENDOR_DONE',
Expand All @@ -277,7 +277,7 @@ export const generateWorkflowDefinition = ({
},
{
name: 'merchantScreening',
displayName: 'Merchant Screening',
displayName: 'MATCH Screening',
pluginKind: 'mastercard-merchant-screening',
stateNames: ['run_vendor_data', 'rerun_vendor_data'],
successAction: 'VENDOR_DONE',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ export const generateWorkflowDefinition = ({
name: 'merchantMonitoring',
pluginKind: 'merchant-monitoring',
vendor: 'ballerine',
displayName: 'Merchant Monitoring',
displayName: 'Web Presence',
stateNames: ['run_merchant_monitoring', 'rerun_vendor_data'],
successAction: 'VENDOR_DONE',
errorAction: 'VENDOR_DONE',
Expand All @@ -279,7 +279,7 @@ export const generateWorkflowDefinition = ({
},
{
name: 'merchantScreening',
displayName: 'Merchant Screening',
displayName: 'MATCH Screening',
pluginKind: 'mastercard-merchant-screening',
stateNames: ['run_vendor_data', 'rerun_vendor_data'],
successAction: 'VENDOR_DONE',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ export const generateWorkflowDefinitionWithAssociated = ({
name: 'merchantMonitoring',
pluginKind: 'merchant-monitoring',
vendor: 'ballerine',
displayName: 'Merchant Monitoring',
displayName: 'Web Presence',
stateNames: ['run_merchant_monitoring'],
successAction: 'MERCHANT_MONITORING_SUCCESS',
errorAction: 'MERCHANT_MONITORING_FAILED',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ export class WorkflowControllerExternal {
},
})
@swagger.ApiOperation({
summary: `The /run endpoint initiates and executes various workflows based on initial data and configurations. Supported workflows include KYB, KYC, KYB with UBOs, KYB with Associated Companies, Ongoing Sanctions, and Merchant Monitoring. To start a workflow, provide workflowId, context (with entity and documents), and config (with checks) in the request body. Customization is possible through the config object. The response includes workflowDefinitionId, workflowRuntimeId, ballerineEntityId, and entities. Workflow execution is asynchronous, with progress tracked via webhook notifications.`,
summary: `The /run endpoint initiates and executes various workflows based on initial data and configurations. Supported workflows include KYB, KYC, KYB with UBOs, KYB with Associated Companies, Ongoing Sanctions, and Web Presence. To start a workflow, provide workflowId, context (with entity and documents), and config (with checks) in the request body. Customization is possible through the config object. The response includes workflowDefinitionId, workflowRuntimeId, ballerineEntityId, and entities. Workflow execution is asynchronous, with progress tracked via webhook notifications.`,
})
@UseCustomerAuthGuard()
@common.HttpCode(200)
Expand Down Expand Up @@ -302,7 +302,7 @@ export class WorkflowControllerExternal {
},
},
},
'Merchant Monitoring': {
'Web Presence': {
value: {
workflowId: '0k3j3k3g3h3i3j3k3g3h3i3',
context: {
Expand Down