diff --git a/apps/web/Components/Output/Validation.jsx b/apps/web/Components/Output/Validation.jsx
index 6435e2b..c66cff2 100644
--- a/apps/web/Components/Output/Validation.jsx
+++ b/apps/web/Components/Output/Validation.jsx
@@ -25,12 +25,12 @@ const AlertWrapper = styled(Box)`
function getElementsErrors($calculation) {
return Object.values($calculation.$validation).map((validation) => {
- const elementErrors = validation.getMessages();
+ const elementErrors = validation.getErrors();
const elementTitle = validation.params.err_title;
- return elementErrors.map((error) => (
+ return elementErrors.map(({ key, message }) => (
-
+
));
});
@@ -38,18 +38,22 @@ function getElementsErrors($calculation) {
function getPaymentsTableErrors($tables) {
const { payments } = $tables;
- const messages = payments.validation.getMessages();
+ const errors = payments.validation.getErrors();
const title = payments.validation.params.err_title;
- return messages.map((text) => );
+ return errors.map(({ key, message }) => (
+
+ ));
}
function getInsuranceTableErrors($tables) {
const { insurance } = $tables;
- const messages = insurance.validation.getMessages();
+ const errors = insurance.validation.getErrors();
const title = insurance.validation.params.err_title;
- return messages.map((text) => );
+ return errors.map(({ key, message }) => (
+
+ ));
}
const Errors = observer(() => {
diff --git a/apps/web/config/process/default.ts b/apps/web/config/process/default.ts
index 25c9010..37b6f8e 100644
--- a/apps/web/config/process/default.ts
+++ b/apps/web/config/process/default.ts
@@ -1,40 +1,40 @@
-import * as addProduct from '@/process/add-product';
+// import * as addProduct from '@/process/add-product';
import * as bonuses from '@/process/bonuses';
-import * as calculate from '@/process/calculate';
-import * as configurator from '@/process/configurator';
-import * as createKP from '@/process/create-kp';
-import * as fingap from '@/process/fingap';
-import * as gibdd from '@/process/gibdd';
+// import * as calculate from '@/process/calculate';
+// import * as configurator from '@/process/configurator';
+// import * as createKP from '@/process/create-kp';
+// import * as fingap from '@/process/fingap';
+// import * as gibdd from '@/process/gibdd';
import { useProcess } from '@/process/hooks';
-import * as insurance from '@/process/insurance';
-import * as leadOpportunity from '@/process/lead-opportunity';
-import * as leasingObject from '@/process/leasing-object';
-import * as leasingWithoutKasko from '@/process/leasing-without-kasko';
-import * as loadKP from '@/process/load-kp';
-import * as payments from '@/process/payments';
-import * as price from '@/process/price';
-import * as subsidy from '@/process/subsidy';
-import * as subsidyImportProgram from '@/process/subsidy-import-program';
-import * as supplierAgent from '@/process/supplier-agent';
-import * as usedPl from '@/process/used-pl';
+// import * as insurance from '@/process/insurance';
+// import * as leadOpportunity from '@/process/lead-opportunity';
+// import * as leasingObject from '@/process/leasing-object';
+// import * as leasingWithoutKasko from '@/process/leasing-without-kasko';
+// import * as loadKP from '@/process/load-kp';
+// import * as payments from '@/process/payments';
+// import * as price from '@/process/price';
+// import * as subsidy from '@/process/subsidy';
+// import * as subsidyImportProgram from '@/process/subsidy-import-program';
+// import * as supplierAgent from '@/process/supplier-agent';
+// import * as usedPl from '@/process/used-pl';
export default function useReactions() {
- useProcess(leadOpportunity);
- useProcess(loadKP);
- useProcess(calculate);
- useProcess(supplierAgent);
- useProcess(price);
- useProcess(fingap);
- useProcess(leasingWithoutKasko);
- useProcess(subsidy);
- useProcess(leasingObject);
- useProcess(configurator);
- useProcess(createKP);
+ // useProcess(leadOpportunity);
+ // useProcess(loadKP);
+ // useProcess(calculate);
+ // useProcess(supplierAgent);
+ // useProcess(price);
+ // useProcess(fingap);
+ // useProcess(leasingWithoutKasko);
+ // useProcess(subsidy);
+ // useProcess(leasingObject);
+ // useProcess(configurator);
+ // useProcess(createKP);
useProcess(bonuses);
- useProcess(usedPl);
- useProcess(subsidyImportProgram);
- useProcess(payments);
- useProcess(gibdd);
- useProcess(addProduct);
- useProcess(insurance);
+ // useProcess(usedPl);
+ // useProcess(subsidyImportProgram);
+ // useProcess(payments);
+ // useProcess(gibdd);
+ // useProcess(addProduct);
+ // useProcess(insurance);
}
diff --git a/apps/web/process/bonuses/reactions/lib/helper.ts b/apps/web/process/bonuses/lib/helper.ts
similarity index 97%
rename from apps/web/process/bonuses/reactions/lib/helper.ts
rename to apps/web/process/bonuses/lib/helper.ts
index 4b4ae16..8599393 100644
--- a/apps/web/process/bonuses/reactions/lib/helper.ts
+++ b/apps/web/process/bonuses/lib/helper.ts
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/naming-convention */
-import type { ProcessContext } from '../../../types';
+import type { ProcessContext } from '../../types';
import { getUser } from '@/api/user/query';
import type { ElementsTypes } from '@/Components/Calculation/config/map/values';
import { STALE_TIME } from '@/constants/request';
diff --git a/apps/web/process/bonuses/reactions/common.ts b/apps/web/process/bonuses/reactions/common.ts
index 93a4fdc..550f205 100644
--- a/apps/web/process/bonuses/reactions/common.ts
+++ b/apps/web/process/bonuses/reactions/common.ts
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/naming-convention */
import type { ProcessContext } from '../../types';
-import helper from './lib/helper';
+import helper from '../lib/helper';
import { makeDisposable } from '@/../../packages/tools';
import * as CRMTypes from '@/graphql/crm.types';
import dayjs from 'dayjs';
diff --git a/apps/web/process/bonuses/reactions/validation.ts b/apps/web/process/bonuses/reactions/validation.ts
index 961c169..b6dc370 100644
--- a/apps/web/process/bonuses/reactions/validation.ts
+++ b/apps/web/process/bonuses/reactions/validation.ts
@@ -1,23 +1,32 @@
-import helper from './lib/helper';
+import { createValidationSchema } from '../validation';
+import type { Elements } from '@/Components/Calculation/config/map/values';
import type { ProcessContext } from '@/process/types';
+import ValidationHelper from '@/stores/validation/helper';
import { reaction } from 'mobx';
-import { round } from 'tools';
+import { uid } from 'radash';
+
+const key = uid(7);
export default function reactions(context: ProcessContext) {
const { store } = context;
const { $calculation } = store;
- const { getCoefficient } = helper(context);
+ const validationSchema = createValidationSchema(context);
+ const helper = new ValidationHelper();
reaction(
() => $calculation.$values.getValues(['product', 'saleBonus']),
- async ({ product: productId, saleBonus }) => {
- const coefficient = await getCoefficient(productId);
- const maxBonus = (coefficient?.evo_sot_coefficient || 0) * 100;
+ async (values) => {
+ helper.removeErrors();
+ const validationResult = await validationSchema.safeParseAsync(values);
- $calculation.element('tbxSaleBonus').validate({
- invalid: round(saleBonus, 2) > round(maxBonus, 2),
- message: 'Размер бонуса МПЛ не может быть выше установленного по СОТ',
- });
+ if (!validationResult.success) {
+ validationResult.error.errors.forEach(({ path, message }) => {
+ (path as Elements[]).forEach((elementName) => {
+ const removeError = $calculation.element(elementName).setError({ key, message });
+ if (removeError) helper.add(removeError);
+ });
+ });
+ }
}
);
}
diff --git a/apps/web/process/bonuses/validation.ts b/apps/web/process/bonuses/validation.ts
new file mode 100644
index 0000000..826bae9
--- /dev/null
+++ b/apps/web/process/bonuses/validation.ts
@@ -0,0 +1,24 @@
+import type { ProcessContext } from '../types';
+import helper from './lib/helper';
+import ValuesSchema from '@/config/schema/values';
+import { round } from 'tools';
+import { z } from 'zod';
+
+export function createValidationSchema(context: ProcessContext) {
+ const { getCoefficient } = helper(context);
+
+ return ValuesSchema.pick({ product: true, saleBonus: true }).superRefine(
+ async ({ product, saleBonus }, ctx) => {
+ const coefficient = await getCoefficient(product);
+ const maxBonus = (coefficient?.evo_sot_coefficient || 0) * 100;
+
+ if (round(saleBonus, 2) > round(maxBonus, 2)) {
+ ctx.addIssue({
+ code: z.ZodIssueCode.custom,
+ message: 'Размер бонуса МПЛ не может быть выше установленного по СОТ',
+ path: ['tbxSaleBonus'],
+ });
+ }
+ }
+ );
+}
diff --git a/apps/web/process/calculate/reactions/validation.ts b/apps/web/process/calculate/reactions/validation.ts
index 1ace7fb..6de15b4 100644
--- a/apps/web/process/calculate/reactions/validation.ts
+++ b/apps/web/process/calculate/reactions/validation.ts
@@ -21,6 +21,7 @@ export default function reactions({ store }: ProcessContext) {
const hasElementsErrors = Object.values($calculation.$validation).some(
(validation) => validation.hasErrors
);
+
const hasPaymentsErrors = $tables.payments.validation.hasErrors;
const hasInsuranceErrors = $tables.insurance.validation.hasErrors;
const hasFingapErrors = $tables.fingap.validation.hasErrors;
diff --git a/apps/web/stores/calculation/index.ts b/apps/web/stores/calculation/index.ts
index 42816cb..ab662c5 100644
--- a/apps/web/stores/calculation/index.ts
+++ b/apps/web/stores/calculation/index.ts
@@ -1,4 +1,4 @@
-import type { RemoveError, ValidationParams } from '../validation/types';
+import type { ValidationParams } from '../validation/types';
import OptionsStore from './options';
import StatusStore from './statuses';
import ValuesStore from './values';
@@ -56,6 +56,10 @@ export default class CalculationStore {
return this.$values.getValue(valueName) as Values.ElementsTypes[E];
},
+ removeError: (params: Pick) => {
+ this.$validation[elementName]?.removeError(params);
+ },
+
reset: () => {
const valueName = getValueName(elementName);
this.$values.resetValue(valueName);
@@ -80,6 +84,12 @@ export default class CalculationStore {
return this.element(elementName);
},
+ setError: (params: ValidationParams) => {
+ if (!this.$validation[elementName]) this.createElementValidation(elementName);
+
+ return this.$validation[elementName]?.setError(params);
+ },
+
setOptions: (options: Array>) => {
this.$options.setOptions(elementName, options);
@@ -98,20 +108,5 @@ export default class CalculationStore {
return this.element(elementName);
},
-
- validate: ({ invalid, message, silent, helper }: ValidationParams) => {
- if (!this.$validation[elementName]) this.createElementValidation(elementName);
-
- let removeError: RemoveError | undefined;
-
- if (invalid) {
- removeError = this.$validation[elementName]?.addError(message, silent);
- if (helper && removeError) helper.add(removeError);
- } else {
- this.$validation[elementName]?.removeError(message);
- }
-
- return removeError;
- },
});
}
diff --git a/apps/web/stores/calculation/validation/hooks.js b/apps/web/stores/calculation/validation/hooks.js
index 9ae1faa..7a8a06e 100644
--- a/apps/web/stores/calculation/validation/hooks.js
+++ b/apps/web/stores/calculation/validation/hooks.js
@@ -2,9 +2,8 @@ import { useStore } from '@/stores/hooks';
export function useValidation(elementName) {
const { $calculation } = useStore();
- const messages = $calculation.$validation[elementName]?.getMessages();
-
- if (messages?.length) {
+ const hasErrors = $calculation.$validation?.[elementName]?.hasErrors;
+ if (hasErrors) {
return {
help: 'Некорректные данные',
isValid: false,
diff --git a/apps/web/stores/validation/index.ts b/apps/web/stores/validation/index.ts
index e9c86b7..5b9ca5a 100644
--- a/apps/web/stores/validation/index.ts
+++ b/apps/web/stores/validation/index.ts
@@ -1,32 +1,38 @@
-import type { RemoveError, ValidationConfig } from './types';
+import type { RemoveError, ValidationConfig, ValidationError, ValidationParams } from './types';
import { makeAutoObservable } from 'mobx';
import notification from 'ui/elements/notification';
export default class Validation {
private params: ValidationConfig;
- private messages: Set;
+ private errors: Set;
constructor(config: ValidationConfig) {
this.params = config;
- this.messages = new Set();
+ this.errors = new Set();
makeAutoObservable(this);
}
public get hasErrors() {
- return this.messages.size > 0;
+ return this.errors.size > 0;
}
- public getMessages() {
- return [...this.messages];
+ public getErrors() {
+ return [...this.errors];
}
- public removeError = (message: string) => {
- this.messages.delete(message);
- if (this.messages.size === 0) notification.close(this.params.err_key);
+ public removeError = ({ key }: Pick) => {
+ const error = [...this.errors].find((x) => x.key === key);
+ if (error) this.errors.delete(error);
+ if (this.errors.size === 0) notification.close(this.params.err_key);
};
- public addError = (message: string, silent?: boolean) => {
- if (!silent && !this.messages.has(message)) {
+ public setError = ({ key, message, silent }: ValidationParams) => {
+ const error = [...this.errors].find((x) => x.key === key);
+ if (error) this.removeError({ key });
+
+ this.errors.add({ key, message });
+
+ if (!silent) {
notification.error({
description: message,
key: this.params.err_key,
@@ -34,13 +40,11 @@ export default class Validation {
});
}
- this.messages.add(message);
-
- return (() => this.removeError(message)) as RemoveError;
+ return (() => this.removeError({ key })) as RemoveError;
};
public clearErrors = () => {
- this.messages.clear();
+ this.errors.clear();
notification.close(this.params.err_key);
};
}
diff --git a/apps/web/stores/validation/types.ts b/apps/web/stores/validation/types.ts
index 4c27464..888cd7e 100644
--- a/apps/web/stores/validation/types.ts
+++ b/apps/web/stores/validation/types.ts
@@ -1,15 +1,10 @@
-import type ValidationHelper from './helper';
-
export type ValidationConfig = {
err_key: string;
err_title: string;
};
-export type ValidationParams = {
- helper?: ValidationHelper;
- invalid: boolean;
- message: string;
- silent?: boolean;
-};
+export type ValidationError = { key: string; message: string };
+
+export type ValidationParams = ValidationError & { silent?: boolean };
export type RemoveError = () => void;