diff --git a/apps/backoffice-v2/src/pages/MerchantMonitoringUploadMultiple/MerchantMonitoringUploadMultiple.page.tsx b/apps/backoffice-v2/src/pages/MerchantMonitoringUploadMultiple/MerchantMonitoringUploadMultiple.page.tsx
new file mode 100644
index 0000000000..6ffa7b7d8c
--- /dev/null
+++ b/apps/backoffice-v2/src/pages/MerchantMonitoringUploadMultiple/MerchantMonitoringUploadMultiple.page.tsx
@@ -0,0 +1,78 @@
+import { Input } from '@ballerine/ui';
+import { Link } from 'react-router-dom';
+import { ChevronLeft, Download } from 'lucide-react';
+import React, { FunctionComponent } from 'react';
+
+import { Card } from '@/common/components/atoms/Card/Card';
+import { Form } from '@/common/components/organisms/Form/Form';
+import { FormItem } from '@/common/components/organisms/Form/Form.Item';
+import { FormField } from '@/common/components/organisms/Form/Form.Field';
+import { FormLabel } from '@/common/components/organisms/Form/Form.Label';
+import { CardContent } from '@/common/components/atoms/Card/Card.Content';
+import { FormControl } from '@/common/components/organisms/Form/Form.Control';
+import { Button, buttonVariants } from '@/common/components/atoms/Button/Button';
+import { FormDescription } from '@/common/components/organisms/Form/Form.Description';
+import { useMerchantMonitoringUploadMultiplePageLogic } from '@/pages/MerchantMonitoringUploadMultiple/hooks/useMerchantMonitoringUploadMultiplePageLogic/useMerchantMonitoringUploadMultiplePageLogic';
+
+export const MerchantMonitoringUploadMultiplePage: FunctionComponent = () => {
+ const { form, onSubmit, onChange, locale, csvTemplateUrl } =
+ useMerchantMonitoringUploadMultiplePageLogic();
+
+ return (
+
+
+
+ Back to Reports
+
+
+ Upload Multiple Merchants
+
+
+
+
+
+
+
+ );
+};
diff --git a/apps/backoffice-v2/src/pages/MerchantMonitoringUploadMultiple/create-business-report-batch-schema.ts b/apps/backoffice-v2/src/pages/MerchantMonitoringUploadMultiple/create-business-report-batch-schema.ts
new file mode 100644
index 0000000000..ba63a61aa7
--- /dev/null
+++ b/apps/backoffice-v2/src/pages/MerchantMonitoringUploadMultiple/create-business-report-batch-schema.ts
@@ -0,0 +1,5 @@
+import { z } from 'zod';
+
+export const CreateBusinessReportBatchSchema = z.object({
+ merchantSheet: z.union([z.any(), z.undefined()]),
+});
diff --git a/apps/backoffice-v2/src/pages/MerchantMonitoringUploadMultiple/hooks/useMerchantMonitoringUploadMultiplePageLogic/batch-report-template.csv b/apps/backoffice-v2/src/pages/MerchantMonitoringUploadMultiple/hooks/useMerchantMonitoringUploadMultiplePageLogic/batch-report-template.csv
new file mode 100644
index 0000000000..90bfd7f0b0
--- /dev/null
+++ b/apps/backoffice-v2/src/pages/MerchantMonitoringUploadMultiple/hooks/useMerchantMonitoringUploadMultiplePageLogic/batch-report-template.csv
@@ -0,0 +1,4 @@
+websiteUrl,countryCode,lineOfBusiness,parentCompanyName,merchantName,correlationId
+https://www.ballerine.com,,,,,
+https://www.google.com,US,Search Engine,Alphabet Inc.,Google,1
+https://www.bbc.com,UK,Journalism,BBC Inc.,BBC,2
diff --git a/apps/backoffice-v2/src/pages/MerchantMonitoringUploadMultiple/hooks/useMerchantMonitoringUploadMultiplePageLogic/useMerchantMonitoringUploadMultiplePageLogic.tsx b/apps/backoffice-v2/src/pages/MerchantMonitoringUploadMultiple/hooks/useMerchantMonitoringUploadMultiplePageLogic/useMerchantMonitoringUploadMultiplePageLogic.tsx
new file mode 100644
index 0000000000..9cb81ca5ff
--- /dev/null
+++ b/apps/backoffice-v2/src/pages/MerchantMonitoringUploadMultiple/hooks/useMerchantMonitoringUploadMultiplePageLogic/useMerchantMonitoringUploadMultiplePageLogic.tsx
@@ -0,0 +1,66 @@
+import { z } from 'zod';
+import { t } from 'i18next';
+import { toast } from 'sonner';
+import { useCallback, useMemo } from 'react';
+import { useNavigate } from 'react-router-dom';
+import { SubmitHandler, useForm } from 'react-hook-form';
+
+import csvContent from './batch-report-template.csv?raw';
+import { useLocale } from '@/common/hooks/useLocale/useLocale';
+import { CreateBusinessReportBatchSchema } from '@/pages/MerchantMonitoringUploadMultiple/create-business-report-batch-schema';
+import { useCreateBusinessReportBatchMutation } from '@/domains/business-reports/hooks/mutations/useCreateBusinessReportBatchMutation/useCreateBusinessReportBatchMutation';
+
+export const useMerchantMonitoringUploadMultiplePageLogic = () => {
+ const form = useForm<{ merchantSheet: File | undefined }>({
+ defaultValues: {
+ merchantSheet: undefined,
+ },
+ });
+
+ const locale = useLocale();
+ const navigate = useNavigate();
+
+ const { mutate: mutateCreateBusinessReportBatch } = useCreateBusinessReportBatchMutation({
+ reportType: 'MERCHANT_REPORT_T1',
+ onSuccess: () => {
+ navigate(`/${locale}/merchant-monitoring`);
+ },
+ });
+
+ const onSubmit: SubmitHandler
> = ({
+ merchantSheet,
+ }) => {
+ if (!merchantSheet) {
+ toast.error(t(`toast:batch_business_report_creation.no_file`));
+
+ return;
+ }
+
+ mutateCreateBusinessReportBatch(merchantSheet);
+ };
+
+ const csvTemplateUrl = useMemo(() => {
+ const blob = new Blob([csvContent], { type: 'text/csv' });
+
+ return URL.createObjectURL(blob);
+ }, []);
+
+ const onChange = useCallback(
+ (event: React.ChangeEvent) => {
+ const files = event.target.files;
+
+ if (files && 'length' in files && files.length > 0 && files[0]) {
+ form.setValue('merchantSheet', files[0]);
+ }
+ },
+ [form],
+ );
+
+ return {
+ form,
+ locale,
+ onSubmit,
+ onChange,
+ csvTemplateUrl,
+ };
+};
diff --git a/apps/kyb-app/CHANGELOG.md b/apps/kyb-app/CHANGELOG.md
index 9e93398aae..40403fb718 100644
--- a/apps/kyb-app/CHANGELOG.md
+++ b/apps/kyb-app/CHANGELOG.md
@@ -1,5 +1,13 @@
# kyb-app
+## 0.3.44
+
+### Patch Changes
+
+- Updated dependencies
+ - @ballerine/common@0.9.26
+ - @ballerine/workflow-browser-sdk@0.6.37
+
## 0.3.43
### Patch Changes
diff --git a/apps/kyb-app/package.json b/apps/kyb-app/package.json
index 0f31e1e477..b09f196a05 100644
--- a/apps/kyb-app/package.json
+++ b/apps/kyb-app/package.json
@@ -1,7 +1,7 @@
{
"name": "@ballerine/kyb-app",
"private": true,
- "version": "0.3.43",
+ "version": "0.3.44",
"type": "module",
"scripts": {
"dev": "vite",
@@ -15,9 +15,9 @@
},
"dependencies": {
"@ballerine/blocks": "0.2.12",
- "@ballerine/common": "^0.9.25",
+ "@ballerine/common": "^0.9.26",
"@ballerine/ui": "0.5.22",
- "@ballerine/workflow-browser-sdk": "0.6.36",
+ "@ballerine/workflow-browser-sdk": "0.6.37",
"@lukemorales/query-key-factory": "^1.0.3",
"@radix-ui/react-icons": "^1.3.0",
"@rjsf/core": "^5.9.0",
diff --git a/examples/headless-example/CHANGELOG.md b/examples/headless-example/CHANGELOG.md
index 97d8376f48..a4644f0b88 100644
--- a/examples/headless-example/CHANGELOG.md
+++ b/examples/headless-example/CHANGELOG.md
@@ -1,5 +1,13 @@
# @ballerine/headless-example
+## 0.3.36
+
+### Patch Changes
+
+- Updated dependencies
+ - @ballerine/common@0.9.26
+ - @ballerine/workflow-browser-sdk@0.6.37
+
## 0.3.35
### Patch Changes
diff --git a/examples/headless-example/package.json b/examples/headless-example/package.json
index c8bd9b3fd1..85d946dce1 100644
--- a/examples/headless-example/package.json
+++ b/examples/headless-example/package.json
@@ -1,7 +1,7 @@
{
"name": "@ballerine/headless-example",
"private": true,
- "version": "0.3.35",
+ "version": "0.3.36",
"type": "module",
"scripts": {
"spellcheck": "cspell \"*\"",
@@ -34,8 +34,8 @@
"vite": "^4.5.3"
},
"dependencies": {
- "@ballerine/common": "0.9.25",
- "@ballerine/workflow-browser-sdk": "0.6.36",
+ "@ballerine/common": "0.9.26",
+ "@ballerine/workflow-browser-sdk": "0.6.37",
"@felte/reporter-svelte": "^1.1.5",
"@felte/validator-zod": "^1.0.13",
"@fontsource/inter": "^4.5.15",
diff --git a/packages/common/CHANGELOG.md b/packages/common/CHANGELOG.md
index 610bf3d20e..d4bbdd7d6d 100644
--- a/packages/common/CHANGELOG.md
+++ b/packages/common/CHANGELOG.md
@@ -1,5 +1,11 @@
# @ballerine/common
+## 0.9.26
+
+### Patch Changes
+
+- pushing fixes
+
## 0.9.25
### Patch Changes
diff --git a/packages/common/package.json b/packages/common/package.json
index 9235fc224d..62d8aff31d 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -2,7 +2,7 @@
"private": false,
"name": "@ballerine/common",
"author": "Ballerine ",
- "version": "0.9.25",
+ "version": "0.9.26",
"description": "common",
"module": "./dist/esm/index.js",
"main": "./dist/cjs/index.js",
diff --git a/packages/common/src/schemas/documents/merchant-screening-plugin-schema.ts b/packages/common/src/schemas/documents/merchant-screening-plugin-schema.ts
index a4ae48da40..e06b155eca 100644
--- a/packages/common/src/schemas/documents/merchant-screening-plugin-schema.ts
+++ b/packages/common/src/schemas/documents/merchant-screening-plugin-schema.ts
@@ -435,12 +435,12 @@ export const MerchantScreeningProcessedSchema = Type.Object({
export const MerchantScreeningPluginSchema = Type.Optional(
Type.Object({
- name: Type.Literal('merchantScreening'),
- status: TypeStringEnum(ProcessStatuses),
+ name: Type.Optional(Type.Literal('merchantScreening')),
+ status: Type.Optional(TypeStringEnum(ProcessStatuses)),
invokedAt: Type.Optional(Type.Number()),
vendor: Type.Optional(Type.Literal('mastercard')),
- logoUrl: Type.String(),
- raw: MerchantScreeningRawSchema,
- processed: MerchantScreeningProcessedSchema,
+ logoUrl: Type.Optional(Type.String()),
+ raw: Type.Optional(MerchantScreeningRawSchema),
+ processed: Type.Optional(MerchantScreeningProcessedSchema),
}),
);
diff --git a/packages/workflow-core/CHANGELOG.md b/packages/workflow-core/CHANGELOG.md
index d04cc6532d..05b4a476ea 100644
--- a/packages/workflow-core/CHANGELOG.md
+++ b/packages/workflow-core/CHANGELOG.md
@@ -1,5 +1,13 @@
# @ballerine/workflow-core
+## 0.6.37
+
+### Patch Changes
+
+- pushing fixes
+- Updated dependencies
+ - @ballerine/common@0.9.26
+
## 0.6.36
### Patch Changes
diff --git a/packages/workflow-core/package.json b/packages/workflow-core/package.json
index bb29ab7dd1..6b11bad9c9 100644
--- a/packages/workflow-core/package.json
+++ b/packages/workflow-core/package.json
@@ -1,7 +1,7 @@
{
"name": "@ballerine/workflow-core",
"author": "Ballerine ",
- "version": "0.6.36",
+ "version": "0.6.37",
"description": "workflow-core",
"module": "./dist/esm/index.js",
"main": "./dist/cjs/index.js",
@@ -31,7 +31,7 @@
"node": ">=12"
},
"dependencies": {
- "@ballerine/common": "0.9.25",
+ "@ballerine/common": "0.9.26",
"ajv": "^8.12.0",
"i18n-iso-countries": "^7.6.0",
"jmespath": "^0.16.0",
diff --git a/packages/workflow-core/src/lib/plugins/external-plugin/mastercard-merchant-screening-plugin.ts b/packages/workflow-core/src/lib/plugins/external-plugin/mastercard-merchant-screening-plugin.ts
index 6e53f3bbc2..27ab1635cd 100644
--- a/packages/workflow-core/src/lib/plugins/external-plugin/mastercard-merchant-screening-plugin.ts
+++ b/packages/workflow-core/src/lib/plugins/external-plugin/mastercard-merchant-screening-plugin.ts
@@ -35,7 +35,6 @@ export class MastercardMerchantScreeningPlugin extends ApiPlugin {
try {
const secrets = await this.secretsManager?.getAll?.();
const url = `${process.env.UNIFIED_API_URL}/merchant-screening/mastercard`;
- const method = 'POST';
const entity = isObject(context.entity) ? context.entity : {};
const countrySubdivisionSupportedCountries = ['US', 'CA'] as const;
const address = {
@@ -72,10 +71,11 @@ export class MastercardMerchantScreeningPlugin extends ApiPlugin {
logger.log('Mastercard Merchant Screening Plugin - Sending API request', {
url,
- method,
+ method: this.method,
});
- const apiResponse = await this.makeApiRequest(url, method, requestPayload, {
+ const apiResponse = await this.makeApiRequest(url, this.method, requestPayload, {
+ ...this.headers,
Authorization: `Bearer ${process.env.UNIFIED_API_TOKEN}`,
});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4f9cff54c5..7030bf60dd 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -64,7 +64,7 @@ importers:
specifier: 0.2.12
version: link:../../packages/blocks
'@ballerine/common':
- specifier: 0.9.25
+ specifier: 0.9.26
version: link:../../packages/common
'@ballerine/react-pdf-toolkit':
specifier: ^1.2.20
@@ -73,10 +73,10 @@ importers:
specifier: ^0.5.20
version: link:../../packages/ui
'@ballerine/workflow-browser-sdk':
- specifier: 0.6.36
+ specifier: 0.6.37
version: link:../../sdks/workflow-browser-sdk
'@ballerine/workflow-node-sdk':
- specifier: 0.6.36
+ specifier: 0.6.37
version: link:../../sdks/workflow-node-sdk
'@fontsource/inter':
specifier: ^4.5.15
@@ -422,13 +422,13 @@ importers:
specifier: 0.2.12
version: link:../../packages/blocks
'@ballerine/common':
- specifier: ^0.9.25
+ specifier: ^0.9.26
version: link:../../packages/common
'@ballerine/ui':
specifier: 0.5.22
version: link:../../packages/ui
'@ballerine/workflow-browser-sdk':
- specifier: 0.6.36
+ specifier: 0.6.37
version: link:../../sdks/workflow-browser-sdk
'@lukemorales/query-key-factory':
specifier: ^1.0.3
@@ -892,10 +892,10 @@ importers:
examples/headless-example:
dependencies:
'@ballerine/common':
- specifier: 0.9.25
+ specifier: 0.9.26
version: link:../../packages/common
'@ballerine/workflow-browser-sdk':
- specifier: 0.6.36
+ specifier: 0.6.37
version: link:../../sdks/workflow-browser-sdk
'@felte/reporter-svelte':
specifier: ^1.1.5
@@ -1828,7 +1828,7 @@ importers:
packages/workflow-core:
dependencies:
'@ballerine/common':
- specifier: 0.9.25
+ specifier: 0.9.26
version: link:../common
ajv:
specifier: ^8.12.0
@@ -2003,7 +2003,7 @@ importers:
sdks/web-ui-sdk:
dependencies:
'@ballerine/common':
- specifier: 0.9.25
+ specifier: 0.9.26
version: link:../../packages/common
'@zerodevx/svelte-toast':
specifier: ^0.8.0
@@ -2130,10 +2130,10 @@ importers:
sdks/workflow-browser-sdk:
dependencies:
'@ballerine/common':
- specifier: 0.9.25
+ specifier: 0.9.26
version: link:../../packages/common
'@ballerine/workflow-core':
- specifier: 0.6.36
+ specifier: 0.6.37
version: link:../../packages/workflow-core
xstate:
specifier: ^4.37.0
@@ -2272,7 +2272,7 @@ importers:
sdks/workflow-node-sdk:
dependencies:
'@ballerine/workflow-core':
- specifier: 0.6.36
+ specifier: 0.6.37
version: link:../../packages/workflow-core
json-logic-js:
specifier: ^2.0.2
@@ -2517,13 +2517,13 @@ importers:
specifier: 3.347.1
version: 3.347.1
'@ballerine/common':
- specifier: 0.9.25
+ specifier: 0.9.26
version: link:../../packages/common
'@ballerine/workflow-core':
- specifier: 0.6.36
+ specifier: 0.6.37
version: link:../../packages/workflow-core
'@ballerine/workflow-node-sdk':
- specifier: 0.6.36
+ specifier: 0.6.37
version: link:../../sdks/workflow-node-sdk
'@faker-js/faker':
specifier: ^7.6.0
@@ -2860,7 +2860,7 @@ importers:
specifier: ^4.0.0
version: 4.0.0(astro@3.3.3)(tailwindcss@3.3.5)(ts-node@10.9.1)
'@ballerine/common':
- specifier: ^0.9.25
+ specifier: ^0.9.26
version: link:../../packages/common
astro:
specifier: 3.3.3
@@ -9592,7 +9592,7 @@ packages:
magic-string: 0.27.0
react-docgen-typescript: 2.2.2(typescript@5.5.4)
typescript: 5.5.4
- vite: 5.3.5(@types/node@18.17.19)
+ vite: 5.3.5(@types/node@20.9.2)
dev: true
/@jridgewell/gen-mapping@0.3.3:
@@ -15945,7 +15945,7 @@ packages:
react: 18.2.0
react-docgen: 6.0.4
react-dom: 18.2.0(react@18.2.0)
- vite: 5.3.5(@types/node@18.17.19)
+ vite: 5.3.5(@types/node@20.9.2)
transitivePeerDependencies:
- '@preact/preset-vite'
- encoding
@@ -18715,7 +18715,7 @@ packages:
'@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.3)
magic-string: 0.27.0
react-refresh: 0.14.0
- vite: 5.3.5(@types/node@18.17.19)
+ vite: 5.3.5(@types/node@20.9.2)
transitivePeerDependencies:
- supports-color
dev: true
@@ -23489,7 +23489,7 @@ packages:
eslint-import-resolver-webpack:
optional: true
dependencies:
- '@typescript-eslint/parser': 5.62.0(eslint@8.54.0)(typescript@4.9.3)
+ '@typescript-eslint/parser': 5.62.0(eslint@8.54.0)(typescript@4.9.5)
debug: 3.2.7
eslint: 8.54.0
eslint-import-resolver-node: 0.3.9
@@ -23654,7 +23654,7 @@ packages:
'@typescript-eslint/parser':
optional: true
dependencies:
- '@typescript-eslint/parser': 5.62.0(eslint@8.54.0)(typescript@4.9.3)
+ '@typescript-eslint/parser': 5.62.0(eslint@8.54.0)(typescript@4.9.5)
array-includes: 3.1.7
array.prototype.findlastindex: 1.2.3
array.prototype.flat: 1.3.2
@@ -24026,7 +24026,7 @@ packages:
'@typescript-eslint/eslint-plugin':
optional: true
dependencies:
- '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.22.0)(typescript@5.5.4)
+ '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.22.0)(typescript@4.9.5)
eslint: 8.22.0
eslint-rule-composer: 0.3.0
dev: true
@@ -35469,7 +35469,7 @@ packages:
debug: 4.3.4(supports-color@8.1.1)
globrex: 0.1.2
tsconfck: 2.1.2(typescript@5.5.4)
- vite: 5.3.5(@types/node@18.17.19)
+ vite: 5.3.5(@types/node@20.9.2)
transitivePeerDependencies:
- supports-color
- typescript
diff --git a/sdks/web-ui-sdk/CHANGELOG.md b/sdks/web-ui-sdk/CHANGELOG.md
index 832876f15b..412743f5a7 100644
--- a/sdks/web-ui-sdk/CHANGELOG.md
+++ b/sdks/web-ui-sdk/CHANGELOG.md
@@ -1,5 +1,12 @@
# web-ui-sdk
+## 1.5.27
+
+### Patch Changes
+
+- Updated dependencies
+ - @ballerine/common@0.9.26
+
## 1.5.26
### Patch Changes
diff --git a/sdks/web-ui-sdk/package.json b/sdks/web-ui-sdk/package.json
index b3811f3986..cf676fe7ab 100644
--- a/sdks/web-ui-sdk/package.json
+++ b/sdks/web-ui-sdk/package.json
@@ -21,7 +21,7 @@
"types": "dist/index.d.ts",
"name": "@ballerine/web-ui-sdk",
"private": false,
- "version": "1.5.26",
+ "version": "1.5.27",
"type": "module",
"files": [
"dist"
@@ -96,7 +96,7 @@
"vitest": "^0.24.5"
},
"dependencies": {
- "@ballerine/common": "0.9.25",
+ "@ballerine/common": "0.9.26",
"@zerodevx/svelte-toast": "^0.8.0",
"compressorjs": "^1.1.1",
"deepmerge": "^4.3.0",
diff --git a/sdks/workflow-browser-sdk/CHANGELOG.md b/sdks/workflow-browser-sdk/CHANGELOG.md
index 7d59bbe40d..f87be49f9e 100644
--- a/sdks/workflow-browser-sdk/CHANGELOG.md
+++ b/sdks/workflow-browser-sdk/CHANGELOG.md
@@ -1,5 +1,13 @@
# @ballerine/workflow-browser-sdk
+## 0.6.37
+
+### Patch Changes
+
+- Updated dependencies
+ - @ballerine/workflow-core@0.6.37
+ - @ballerine/common@0.9.26
+
## 0.6.36
### Patch Changes
diff --git a/sdks/workflow-browser-sdk/package.json b/sdks/workflow-browser-sdk/package.json
index 531243cbc9..ab095c04f9 100644
--- a/sdks/workflow-browser-sdk/package.json
+++ b/sdks/workflow-browser-sdk/package.json
@@ -1,7 +1,7 @@
{
"name": "@ballerine/workflow-browser-sdk",
"author": "Ballerine ",
- "version": "0.6.36",
+ "version": "0.6.37",
"description": "workflow-browser-sdk",
"module": "./dist/esm/index.js",
"main": "./dist/cjs/index.js",
@@ -33,8 +33,8 @@
"node": ">=12"
},
"dependencies": {
- "@ballerine/common": "0.9.25",
- "@ballerine/workflow-core": "0.6.36",
+ "@ballerine/common": "0.9.26",
+ "@ballerine/workflow-core": "0.6.37",
"xstate": "^4.37.0"
},
"devDependencies": {
diff --git a/sdks/workflow-node-sdk/CHANGELOG.md b/sdks/workflow-node-sdk/CHANGELOG.md
index 0308dedbd7..d5b1e29b24 100644
--- a/sdks/workflow-node-sdk/CHANGELOG.md
+++ b/sdks/workflow-node-sdk/CHANGELOG.md
@@ -1,5 +1,12 @@
# @ballerine/workflow-node-sdk
+## 0.6.37
+
+### Patch Changes
+
+- Updated dependencies
+ - @ballerine/workflow-core@0.6.37
+
## 0.6.36
### Patch Changes
diff --git a/sdks/workflow-node-sdk/package.json b/sdks/workflow-node-sdk/package.json
index 941eba249b..f1d376eb5a 100644
--- a/sdks/workflow-node-sdk/package.json
+++ b/sdks/workflow-node-sdk/package.json
@@ -1,7 +1,7 @@
{
"name": "@ballerine/workflow-node-sdk",
"author": "Ballerine ",
- "version": "0.6.36",
+ "version": "0.6.37",
"description": "workflow-node-sdk",
"module": "./dist/esm/index.js",
"main": "./dist/cjs/index.js",
@@ -28,7 +28,7 @@
"node": ">=12"
},
"dependencies": {
- "@ballerine/workflow-core": "0.6.36",
+ "@ballerine/workflow-core": "0.6.37",
"json-logic-js": "^2.0.2",
"xstate": "^4.36.0"
},
diff --git a/services/workflows-service/CHANGELOG.md b/services/workflows-service/CHANGELOG.md
index 38bd2aa6f3..26cdd8bd3a 100644
--- a/services/workflows-service/CHANGELOG.md
+++ b/services/workflows-service/CHANGELOG.md
@@ -1,5 +1,14 @@
# @ballerine/workflows-service
+## 0.7.36
+
+### Patch Changes
+
+- Updated dependencies
+ - @ballerine/workflow-core@0.6.37
+ - @ballerine/common@0.9.26
+ - @ballerine/workflow-node-sdk@0.6.37
+
## 0.7.35
### Patch Changes
diff --git a/services/workflows-service/package.json b/services/workflows-service/package.json
index 22173eefe7..8aa11ef236 100644
--- a/services/workflows-service/package.json
+++ b/services/workflows-service/package.json
@@ -1,7 +1,7 @@
{
"name": "@ballerine/workflows-service",
"private": false,
- "version": "0.7.35",
+ "version": "0.7.36",
"description": "workflow-service",
"scripts": {
"spellcheck": "cspell \"*\"",
@@ -47,9 +47,9 @@
"@aws-sdk/client-secrets-manager": "^3.620.1",
"@aws-sdk/lib-storage": "3.347.1",
"@aws-sdk/s3-request-presigner": "3.347.1",
- "@ballerine/common": "0.9.25",
- "@ballerine/workflow-core": "0.6.36",
- "@ballerine/workflow-node-sdk": "0.6.36",
+ "@ballerine/common": "0.9.26",
+ "@ballerine/workflow-core": "0.6.37",
+ "@ballerine/workflow-node-sdk": "0.6.37",
"@faker-js/faker": "^7.6.0",
"@nestjs/axios": "^2.0.0",
"@nestjs/common": "^9.3.12",
diff --git a/services/workflows-service/prisma/data-migrations b/services/workflows-service/prisma/data-migrations
index 6def4e1235..3379373b90 160000
--- a/services/workflows-service/prisma/data-migrations
+++ b/services/workflows-service/prisma/data-migrations
@@ -1 +1 @@
-Subproject commit 6def4e12358d52f84ff92e083547b63b89d89393
+Subproject commit 3379373b907a01f250b93e729c34d38eb432079f
diff --git a/services/workflows-service/src/business-report/business-report.controller.internal.ts b/services/workflows-service/src/business-report/business-report.controller.internal.ts
index 4ebd6872f9..088fe25949 100644
--- a/services/workflows-service/src/business-report/business-report.controller.internal.ts
+++ b/services/workflows-service/src/business-report/business-report.controller.internal.ts
@@ -41,13 +41,17 @@ import { FileInterceptor } from '@nestjs/platform-express';
import { getDiskStorage } from '@/storage/get-file-storage-manager';
import { fileFilter } from '@/storage/file-filter';
import { RemoveTempFileInterceptor } from '@/common/interceptors/remove-temp-file.interceptor';
-import { CreateBatchBusinessReportDto } from '@/business-report/dto/create-batch-business-report.dto';
-import { ApiConsumes } from '@nestjs/swagger';
+import { CreateBusinessReportBatchBodyDto } from '@/business-report/dto/create-business-report-batch-body.dto';
+import { ApiBearerAuth, ApiConsumes } from '@nestjs/swagger';
import type { Response } from 'express';
import { IsBoolean } from 'class-validator';
+import { CreateBusinessReportBatchQueryParamsDto } from '@/business-report/dto/create-business-report-batch-query-params.dto';
+import { TCustomerWithDefinitionsFeatures } from '@/customer/types';
+@ApiBearerAuth()
+@swagger.ApiTags('Business Reports')
@common.Controller('internal/business-reports')
-// @swagger.ApiExcludeController()
+@swagger.ApiExcludeController()
export class BusinessReportControllerInternal {
constructor(
protected readonly businessReportService: BusinessReportService,
@@ -74,17 +78,10 @@ export class BusinessReportControllerInternal {
) {
const customer = await this.customerService.getByProjectId(currentProjectId);
- const { maxBusinessReports, withQualityControl } = customer.config || {};
-
- if (isNumber(maxBusinessReports) && maxBusinessReports > 0) {
- const businessReportsCount = await this.businessReportService.count({}, [currentProjectId]);
-
- if (businessReportsCount >= maxBusinessReports) {
- throw new BadRequestException(
- `You have reached the maximum number of business reports allowed (${maxBusinessReports}).`,
- );
- }
- }
+ const { withQualityControl } = await this.getCustomerMerchantMonitoringConfig(
+ customer,
+ currentProjectId,
+ );
let business: Pick | undefined;
const merchantNameWithDefault = merchantName || 'Not detected';
@@ -350,8 +347,7 @@ export class BusinessReportControllerInternal {
});
}
- @common.Post('/upload-batch')
- @Public()
+ @common.Post('/upload-batch/:type')
@swagger.ApiForbiddenResponse({ type: errors.ForbiddenException })
@ApiConsumes('multipart/form-data')
@UseInterceptors(
@@ -361,19 +357,23 @@ export class BusinessReportControllerInternal {
}),
RemoveTempFileInterceptor,
)
- async createBatchReport(
+ async createBusinessReportBatch(
@UploadedFile() file: Express.Multer.File,
- @Body() body: CreateBatchBusinessReportDto,
+ @Param() { type }: CreateBusinessReportBatchQueryParamsDto,
+ @Body() body: CreateBusinessReportBatchBodyDto,
@Res() res: Response,
@CurrentProject() currentProjectId: TProjectId,
) {
const customer = await this.customerService.getByProjectId(currentProjectId);
- const { withQualityControl } = customer.config || {};
+ const { maxBusinessReports, withQualityControl } =
+ await this.getCustomerMerchantMonitoringConfig(customer.config, currentProjectId);
const result = await this.businessReportService.processBatchFile({
- type: body.type,
- file: file,
+ type,
+ currentProjectId,
+ maxBusinessReports,
+ merchantSheet: file,
projectId: currentProjectId,
withQualityControl: IsBoolean(withQualityControl) ? withQualityControl : false,
});
@@ -382,4 +382,23 @@ export class BusinessReportControllerInternal {
res.setHeader('content-type', 'application/json');
res.send(result);
}
+
+ private async getCustomerMerchantMonitoringConfig(
+ config: TCustomerWithDefinitionsFeatures,
+ currentProjectId: string,
+ ) {
+ const { maxBusinessReports, withQualityControl } = config || {};
+
+ if (isNumber(maxBusinessReports) && maxBusinessReports > 0) {
+ const businessReportsCount = await this.businessReportService.count({}, [currentProjectId]);
+
+ if (businessReportsCount >= maxBusinessReports) {
+ throw new BadRequestException(
+ `You have reached the maximum number of business reports allowed (${maxBusinessReports}).`,
+ );
+ }
+ }
+
+ return { maxBusinessReports, withQualityControl };
+ }
}
diff --git a/services/workflows-service/src/business-report/business-report.service.ts b/services/workflows-service/src/business-report/business-report.service.ts
index 7c8769cc1a..01cb9f427e 100644
--- a/services/workflows-service/src/business-report/business-report.service.ts
+++ b/services/workflows-service/src/business-report/business-report.service.ts
@@ -131,27 +131,44 @@ export class BusinessReportService {
}
async processBatchFile({
- file,
type,
projectId,
+ merchantSheet,
+ currentProjectId,
+ maxBusinessReports,
withQualityControl,
}: {
- file: Express.Multer.File;
- type: BusinessReportType;
projectId: TProjectId;
+ type: BusinessReportType;
+ currentProjectId: string;
+ maxBusinessReports: number;
withQualityControl: boolean;
+ merchantSheet: Express.Multer.File;
}) {
const businessReportsRequests = await parseCsv({
- filePath: file.path,
+ filePath: merchantSheet.path,
schema: BusinessReportRequestSchema,
logger: this.logger,
});
+ const businessReportsCount = await this.count({}, [currentProjectId]);
+
+ if (businessReportsCount + businessReportsRequests.length > maxBusinessReports) {
+ const reportsLeft = maxBusinessReports - businessReportsCount;
+
+ throw new UnprocessableEntityException(
+ `Batch size is too large, there are too many reports (${reportsLeft} report${
+ reportsLeft > 1 ? 's' : ''
+ } left from a qouta of ${maxBusinessReports})`,
+ );
+ }
+
if (businessReportsRequests.length > 100) {
throw new UnprocessableEntityException('Batch size is too large');
}
const batchId = randomUUID();
+
await this.prisma.$transaction(
async transaction => {
const businessCreatePromises = businessReportsRequests.map(async businessReportRequest => {
diff --git a/services/workflows-service/src/business-report/dto/create-business-report-batch-body.dto.ts b/services/workflows-service/src/business-report/dto/create-business-report-batch-body.dto.ts
new file mode 100644
index 0000000000..13e3c11db5
--- /dev/null
+++ b/services/workflows-service/src/business-report/dto/create-business-report-batch-body.dto.ts
@@ -0,0 +1,10 @@
+import { ApiProperty } from '@nestjs/swagger';
+
+export class CreateBusinessReportBatchBodyDto {
+ @ApiProperty({
+ type: 'string',
+ format: 'binary',
+ description: 'CSV file for batch business report',
+ })
+ file!: Express.Multer.File;
+}
diff --git a/services/workflows-service/src/business-report/dto/create-batch-business-report.dto.ts b/services/workflows-service/src/business-report/dto/create-business-report-batch-query-params.dto.ts
similarity index 67%
rename from services/workflows-service/src/business-report/dto/create-batch-business-report.dto.ts
rename to services/workflows-service/src/business-report/dto/create-business-report-batch-query-params.dto.ts
index d0840970c5..5e6a9636bf 100644
--- a/services/workflows-service/src/business-report/dto/create-batch-business-report.dto.ts
+++ b/services/workflows-service/src/business-report/dto/create-business-report-batch-query-params.dto.ts
@@ -2,14 +2,7 @@ import { ApiProperty } from '@nestjs/swagger';
import { IsEnum } from 'class-validator';
import { BusinessReportType } from '@prisma/client';
-export class CreateBatchBusinessReportDto {
- @ApiProperty({
- type: 'string',
- format: 'binary',
- description: 'CSV file for batch business report',
- })
- file!: Express.Multer.File;
-
+export class CreateBusinessReportBatchQueryParamsDto {
@ApiProperty({
required: true,
type: String,
diff --git a/services/workflows-service/src/env.ts b/services/workflows-service/src/env.ts
index 4d63c817b3..ae9340498a 100644
--- a/services/workflows-service/src/env.ts
+++ b/services/workflows-service/src/env.ts
@@ -86,9 +86,10 @@ export const serverEnvSchema = {
.default('/dev/customers/')
.describe('AWS Secrets Manager prefix'),
- IN_MEMORY_SECRET_ACQUIRER_ID: z.string().optional(),
- IN_MEMORY_SECRET_PRIVATE_KEY: z.string().optional(),
- IN_MEMORY_SECRET_CONSUMER_KEY: z.string().optional(),
+ // IN_MEMORY is reserved for environment variables
+ IN_MEMORIES_SECRET_ACQUIRER_ID: z.string().optional(),
+ IN_MEMORIES_SECRET_PRIVATE_KEY: z.string().optional(),
+ IN_MEMORIES_SECRET_CONSUMER_KEY: z.string().optional(),
};
if (!process.env['ENVIRONMENT_NAME'] || process.env['ENVIRONMENT_NAME'] === 'local') {
diff --git a/services/workflows-service/src/secrets-manager/in-memory-secrets-manager.ts b/services/workflows-service/src/secrets-manager/in-memory-secrets-manager.ts
index 87e84ad10f..b93a5b0d82 100644
--- a/services/workflows-service/src/secrets-manager/in-memory-secrets-manager.ts
+++ b/services/workflows-service/src/secrets-manager/in-memory-secrets-manager.ts
@@ -3,11 +3,11 @@ import { env } from '@/env';
import { camelCase } from 'lodash';
const inMemoryEnvProvidedSecrets = Object.entries(env).reduce((acc, [key, value]) => {
- if (!key.startsWith('IN_MEMORY_SECRET_')) {
+ if (!key.startsWith('IN_MEMORIES_SECRET_')) {
return acc;
}
- const secretKey = key.replace('IN_MEMORY_SECRET_', '');
+ const secretKey = key.replace('IN_MEMORIES_SECRET_', '');
acc[camelCase(secretKey)] = value;
diff --git a/websites/docs/package.json b/websites/docs/package.json
index 578332adb6..52a8230971 100644
--- a/websites/docs/package.json
+++ b/websites/docs/package.json
@@ -17,7 +17,7 @@
"dependencies": {
"@astrojs/starlight": "0.11.1",
"@astrojs/tailwind": "^4.0.0",
- "@ballerine/common": "^0.9.25",
+ "@ballerine/common": "^0.9.26",
"astro": "3.3.3",
"sharp": "^0.32.4",
"shiki": "^0.14.3"