diff --git a/.env b/.env
index eb78342..71125d0 100644
--- a/.env
+++ b/.env
@@ -2,9 +2,6 @@
USE_DEV_COLORS=
BASE_PATH=
-####### USERS ########
-USERS_SUPER=["akalinina","vchikalkin"]
-
####### URLS ########
URL_GET_USER_DIRECT=
URL_CRM_GRAPHQL_DIRECT=
diff --git a/apps/web/Components/Calculation/Form/Insurance/FinGAPTable/index.jsx b/apps/web/Components/Calculation/Form/Insurance/FinGAPTable/index.jsx
index 3547673..459bcb6 100644
--- a/apps/web/Components/Calculation/Form/Insurance/FinGAPTable/index.jsx
+++ b/apps/web/Components/Calculation/Form/Insurance/FinGAPTable/index.jsx
@@ -12,12 +12,18 @@ const Grid = styled(Flex)`
`;
const Validation = observer(() => {
- const store = useStore();
+ const { $tables, $process } = useStore();
- const errors = store.$tables.fingap.validation.getErrors();
+ const errors = $tables.fingap.validation.getErrors();
if (errors?.length) {
- return ;
+ return (
+
+ );
}
return null;
diff --git a/apps/web/Components/Calculation/Form/Insurance/InsuranceTable/index.jsx b/apps/web/Components/Calculation/Form/Insurance/InsuranceTable/index.jsx
index 24ef8af..1a362ea 100644
--- a/apps/web/Components/Calculation/Form/Insurance/InsuranceTable/index.jsx
+++ b/apps/web/Components/Calculation/Form/Insurance/InsuranceTable/index.jsx
@@ -17,12 +17,18 @@ const TableWrapper = styled.div`
`;
const Validation = observer(() => {
- const store = useStore();
+ const { $tables, $process } = useStore();
- const errors = store.$tables.insurance.validation.getErrors();
+ const errors = $tables.insurance.validation.getErrors();
if (errors?.length) {
- return ;
+ return (
+
+ );
}
return null;
diff --git a/apps/web/Components/Calculation/Form/Payments/PaymentsTable/index.jsx b/apps/web/Components/Calculation/Form/Payments/PaymentsTable/index.jsx
index a8fd83b..7659990 100644
--- a/apps/web/Components/Calculation/Form/Payments/PaymentsTable/index.jsx
+++ b/apps/web/Components/Calculation/Form/Payments/PaymentsTable/index.jsx
@@ -30,13 +30,19 @@ const TablesGroupGrid = styled(Box)`
`;
const Validation = observer(() => {
- const store = useStore();
- const { payments } = store.$tables;
+ const { $tables, $process } = useStore();
+ const { payments } = $tables;
const errors = payments.validation.getErrors();
if (errors?.length) {
- return ;
+ return (
+
+ );
}
return null;
diff --git a/apps/web/Components/Calculation/Form/Unlimited/config.ts b/apps/web/Components/Calculation/Form/Unlimited/config.ts
new file mode 100644
index 0000000..2c5cc34
--- /dev/null
+++ b/apps/web/Components/Calculation/Form/Unlimited/config.ts
@@ -0,0 +1,12 @@
+import type { FormTabRows } from '../../lib/render-rows';
+
+export const id = 'unlimited';
+export const title = 'Без ограничений';
+
+export const rows: FormTabRows = [
+ [['cbxDisableChecks', 'selectUser']],
+ [['selectTarif', 'tbxCreditRate', 'selectRate']],
+ [['tbxMinPriceChange', 'tbxMaxPriceChange']],
+ [['tbxImporterRewardPerc', 'tbxImporterRewardRub']],
+ [['tbxBonusCoefficient', 'tbxComissionRub', 'tbxComissionPerc']],
+];
diff --git a/apps/web/Components/Calculation/Form/Unlimited/index.jsx b/apps/web/Components/Calculation/Form/Unlimited/index.jsx
new file mode 100644
index 0000000..91f340f
--- /dev/null
+++ b/apps/web/Components/Calculation/Form/Unlimited/index.jsx
@@ -0,0 +1,12 @@
+import renderFormRows from '../../lib/render-rows';
+import { id, rows, title } from './config';
+
+function Unlimited() {
+ return renderFormRows(rows);
+}
+
+export default {
+ Component: Unlimited,
+ id,
+ title,
+};
diff --git a/apps/web/Components/Calculation/Form/index.jsx b/apps/web/Components/Calculation/Form/index.jsx
index 175cb11..7ba84b9 100644
--- a/apps/web/Components/Calculation/Form/index.jsx
+++ b/apps/web/Components/Calculation/Form/index.jsx
@@ -5,12 +5,22 @@ import Leasing from './Leasing';
import LeasingObject from './LeasingObject';
import Payments from './Payments';
import SupplierAgent from './SupplierAgent';
+import Unlimited from './Unlimited';
import Background from '@/Components/Layout/Background';
import { min } from '@/styles/mq';
import styled from 'styled-components';
import Tabs from 'ui/elements/layout/Tabs';
-const formTabs = [Leasing, Payments, LeasingObject, SupplierAgent, Insurance, AddProduct, CreateKP];
+const formTabs = [
+ Leasing,
+ Payments,
+ LeasingObject,
+ SupplierAgent,
+ Insurance,
+ AddProduct,
+ CreateKP,
+ Unlimited,
+];
const Wrapper = styled(Background)`
padding: 4px 6px;
@@ -32,17 +42,19 @@ const ComponentWrapper = styled.div`
}
`;
-function Form() {
+function Form({ prune }) {
return (
- {formTabs.map(({ id, title, Component }) => (
-
-
-
-
-
- ))}
+ {formTabs
+ .filter((tab) => !prune?.includes(tab.id))
+ .map(({ id, title, Component }) => (
+
+
+
+
+
+ ))}
);
diff --git a/apps/web/Components/Calculation/builders/build-action.tsx b/apps/web/Components/Calculation/builders/build-action.tsx
index 5b165b3..c2074d0 100644
--- a/apps/web/Components/Calculation/builders/build-action.tsx
+++ b/apps/web/Components/Calculation/builders/build-action.tsx
@@ -1,5 +1,5 @@
import type { Elements } from '../config/map/actions';
-import { useProcessContext } from '@/process/hooks';
+import { useProcessContext } from '@/process/hooks/common';
import { useStatus } from '@/stores/calculation/statuses/hooks';
import { observer } from 'mobx-react-lite';
import type { ComponentType } from 'react';
diff --git a/apps/web/Components/Calculation/builders/build-options.tsx b/apps/web/Components/Calculation/builders/build-options.tsx
index e08f34b..63bbec8 100644
--- a/apps/web/Components/Calculation/builders/build-options.tsx
+++ b/apps/web/Components/Calculation/builders/build-options.tsx
@@ -19,13 +19,13 @@ export default function buildOptions(
return observer((props: T) => {
const [value, setValue] = useStoreValue(valueName);
const status = useStatus(elementName);
- const { isValid, help } = useValidation(elementName);
+ const { validateStatus, help } = useValidation(elementName);
const options = useOptions(elementName);
return (
(
return observer((props: T) => {
const [value, setValue] = useStoreValue(valueName);
const status = useStatus(elementName);
- const { isValid, help } = useValidation(elementName);
+ const { validateStatus, help } = useValidation(elementName);
return (
= {
direction: 'vertical',
},
},
+ selectUser: {
+ showSearch: true,
+ optionFilterProp: 'label',
+ },
};
export default props;
diff --git a/apps/web/Components/Calculation/config/elements-titles.ts b/apps/web/Components/Calculation/config/elements-titles.ts
index ba37e87..81b3f67 100644
--- a/apps/web/Components/Calculation/config/elements-titles.ts
+++ b/apps/web/Components/Calculation/config/elements-titles.ts
@@ -125,6 +125,7 @@ const titles: Record = {
tbxBonusCoefficient: 'Коэффициент снижения бонуса',
selectLeasingWithoutKasko: 'Лизинг без КАСКО',
tbxVIN: 'VIN',
+ selectUser: 'Пользователь',
/** Link Elements */
linkDownloadKp: '',
diff --git a/apps/web/Components/Calculation/config/elements-types.ts b/apps/web/Components/Calculation/config/elements-types.ts
index 8142aa5..de258b4 100644
--- a/apps/web/Components/Calculation/config/elements-types.ts
+++ b/apps/web/Components/Calculation/config/elements-types.ts
@@ -162,6 +162,7 @@ const types = wrapElementsTypes({
tbxBonusCoefficient: t.Value,
selectLeasingWithoutKasko: t.Options,
tbxVIN: t.Value,
+ selectUser: t.Options,
labelLeaseObjectRisk: t.Readonly,
tbxInsKaskoPriceLeasePeriod: t.Readonly,
diff --git a/apps/web/Components/Calculation/config/map/values.ts b/apps/web/Components/Calculation/config/map/values.ts
index 5271277..d3fe420 100644
--- a/apps/web/Components/Calculation/config/map/values.ts
+++ b/apps/web/Components/Calculation/config/map/values.ts
@@ -128,6 +128,7 @@ const elementsToValues = wrapElementsMap({
tbxMinPriceChange: 'minPriceChange',
tbxBonusCoefficient: 'bonusCoefficient',
tbxVIN: 'vin',
+ selectUser: 'user',
/** Readonly Elements */
labelLeaseObjectRisk: 'leaseObjectRiskName',
diff --git a/apps/web/Components/Layout/Logo.jsx b/apps/web/Components/Layout/Logo.jsx
index 509569f..7edee39 100644
--- a/apps/web/Components/Layout/Logo.jsx
+++ b/apps/web/Components/Layout/Logo.jsx
@@ -1,10 +1,13 @@
/* eslint-disable react/forbid-component-props */
import styles from './Logo.module.css';
+import { useStore } from '@/stores/hooks';
+import getColors from '@/styles/colors';
import { min } from '@/styles/mq';
+import { observer } from 'mobx-react-lite';
import Image from 'next/image';
import logo from 'public/assets/images/logo-primary.svg';
import styled from 'styled-components';
-import { Flex } from 'ui';
+import { Flex, Tag } from 'ui';
const ImageWrapper = styled.div`
width: 100px;
@@ -26,13 +29,41 @@ const LogoText = styled.h3`
}
`;
+const TagWrapper = styled.div`
+ font-family: 'Montserrat';
+ font-weight: 500;
+ * {
+ font-size: 0.7rem;
+ }
+`;
+
+const { COLOR_PRIMARY } = getColors();
+
+const UnlimitedTag = observer(() => {
+ const { $process } = useStore();
+ if ($process.has('Unlimited')) {
+ return (
+
+
+ без ограничений
+
+
+ );
+ }
+
+ return false;
+});
+
function Logo() {
return (
- Лизинговый Калькулятор
+
+ Лизинговый Калькулятор
+
+
);
}
diff --git a/apps/web/Components/Layout/Page.jsx b/apps/web/Components/Layout/Page.jsx
new file mode 100644
index 0000000..b2a6439
--- /dev/null
+++ b/apps/web/Components/Layout/Page.jsx
@@ -0,0 +1,27 @@
+import { min } from '@/styles/mq';
+import styled from 'styled-components';
+import { Box } from 'ui/grid';
+
+export const Grid = styled(Box)`
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+
+ ${min('laptop')} {
+ display: grid;
+ align-items: flex-start;
+ grid-template-columns: 2fr 1fr;
+ }
+
+ ${min('laptop-hd')} {
+ grid-template-columns: 2fr 1fr 1.5fr;
+ }
+
+ ${min('desktop')} {
+ margin: 8px 5%;
+ }
+
+ ${min('desktop-xl')} {
+ margin: 8px 10%;
+ }
+`;
diff --git a/apps/web/Components/Output/Validation.jsx b/apps/web/Components/Output/Validation.jsx
index c66cff2..e5397a4 100644
--- a/apps/web/Components/Output/Validation.jsx
+++ b/apps/web/Components/Output/Validation.jsx
@@ -23,41 +23,61 @@ const AlertWrapper = styled(Box)`
margin: 0 0 5px 0;
`;
-function getElementsErrors($calculation) {
+function getElementsErrors({ $calculation, $process }) {
return Object.values($calculation.$validation).map((validation) => {
const elementErrors = validation.getErrors();
const elementTitle = validation.params.err_title;
return elementErrors.map(({ key, message }) => (
-
+
));
});
}
-function getPaymentsTableErrors($tables) {
+function getPaymentsTableErrors({ $tables, $process }) {
const { payments } = $tables;
const errors = payments.validation.getErrors();
const title = payments.validation.params.err_title;
return errors.map(({ key, message }) => (
-
+
+
+
));
}
-function getInsuranceTableErrors($tables) {
+function getInsuranceTableErrors({ $tables, $process }) {
const { insurance } = $tables;
const errors = insurance.validation.getErrors();
const title = insurance.validation.params.err_title;
return errors.map(({ key, message }) => (
-
+
+
+
));
}
const Errors = observer(() => {
- const { $calculation, $tables } = useStore();
+ const store = useStore();
+ const { $calculation, $tables } = store;
const hasElementsErrors = Object.values($calculation.$validation).some(
(validation) => validation.hasErrors
@@ -69,9 +89,9 @@ const Errors = observer(() => {
return ;
}
- const elementsErrors = getElementsErrors($calculation);
- const paymentsErrors = getPaymentsTableErrors($tables);
- const insuranceErrors = getInsuranceTableErrors($tables);
+ const elementsErrors = getElementsErrors(store);
+ const paymentsErrors = getPaymentsTableErrors(store);
+ const insuranceErrors = getInsuranceTableErrors(store);
const errors = [...elementsErrors, ...paymentsErrors, ...insuranceErrors];
diff --git a/apps/web/Components/Output/index.jsx b/apps/web/Components/Output/index.jsx
index c15e8fd..055e5ce 100644
--- a/apps/web/Components/Output/index.jsx
+++ b/apps/web/Components/Output/index.jsx
@@ -2,11 +2,39 @@ import PaymentsTable from './PaymentsTable';
import Results from './Results';
import Validation from './Validation';
import Background from '@/Components/Layout/Background';
+import { useStore } from '@/stores/hooks';
import { min } from '@/styles/mq';
+import { observer } from 'mobx-react-lite';
import styled from 'styled-components';
-import Tabs from 'ui/elements/layout/Tabs';
+import { Badge, Tabs } from 'ui';
const outputTabs = [PaymentsTable, Results, Validation];
+const items = outputTabs.map(({ Component, id, title }) => {
+ let Label = () => title;
+
+ if (id === 'validation') {
+ Label = observer(() => {
+ const { $calculation, $tables } = useStore();
+ const hasErrors =
+ $calculation.hasErrors ||
+ $tables.fingap.hasErrors ||
+ $tables.insurance.hasErrors ||
+ $tables.payments.hasErrors;
+
+ return (
+
+ {title}
+
+ );
+ });
+ }
+
+ return {
+ children: ,
+ key: id,
+ label: ,
+ };
+});
const Wrapper = styled(Background)`
padding: 4px 10px;
@@ -21,13 +49,7 @@ const Wrapper = styled(Background)`
function Output() {
return (
-
- {outputTabs.map(({ id, title, Component }) => (
-
-
-
- ))}
-
+
);
}
diff --git a/apps/web/api/core/types/calculate.ts b/apps/web/api/core/types/calculate.ts
index 77887b5..72d500a 100644
--- a/apps/web/api/core/types/calculate.ts
+++ b/apps/web/api/core/types/calculate.ts
@@ -138,8 +138,13 @@ const AdditionalDataSchema = z.object({
export type AdditionalData = z.infer;
+const flagsSchema = z.object({
+ DISABLE_CHECKS_RESULTS: z.boolean(),
+});
+
export const RequestCalculateSchema = z.object({
additionalData: AdditionalDataSchema,
+ flags: flagsSchema.optional(),
preparedPayments: PreparedPaymentSchema,
preparedValues: PreparedValuesSchema,
});
diff --git a/apps/web/api/user/tools.ts b/apps/web/api/user/tools.ts
index 3539d54..815775c 100644
--- a/apps/web/api/user/tools.ts
+++ b/apps/web/api/user/tools.ts
@@ -1,13 +1,8 @@
import type { User } from './types';
-import { publicRuntimeConfigSchema } from '@/config/schema/runtime-config';
-import getConfig from 'next/config';
-
-const { publicRuntimeConfig } = getConfig();
-const { USERS_SUPER } = publicRuntimeConfigSchema.parse(publicRuntimeConfig);
+import { usersSuper } from '@/config/users';
export function love(user: User) {
- const superUsers: string[] = JSON.parse(USERS_SUPER);
- if (superUsers?.includes(user.username)) user.displayName += '🧡';
+ if (usersSuper?.includes(user.username)) user.displayName += '🧡';
return user;
}
diff --git a/apps/web/config/default-options.ts b/apps/web/config/default-options.ts
index 10c5b9b..ab4c2a5 100644
--- a/apps/web/config/default-options.ts
+++ b/apps/web/config/default-options.ts
@@ -493,6 +493,7 @@ const defaultOptions: CalculationOptions = {
tbxBonusCoefficient: [],
selectLeasingWithoutKasko: [],
tbxVIN: [],
+ selectUser: [],
};
export default defaultOptions;
diff --git a/apps/web/config/default-statuses.ts b/apps/web/config/default-statuses.ts
index ec3c327..dbdcb41 100644
--- a/apps/web/config/default-statuses.ts
+++ b/apps/web/config/default-statuses.ts
@@ -86,6 +86,7 @@ const defaultStatuses: CalculationStatuses = {
selectTelematic: 'Default',
selectTownRegistration: 'Default',
selectTracker: 'Default',
+ selectUser: 'Default',
tbxAddEquipmentPrice: 'Default',
tbxBonusCoefficient: 'Default',
tbxCalcBrokerRewardSum: 'Disabled',
diff --git a/apps/web/config/default-values.ts b/apps/web/config/default-values.ts
index 5050599..1f7bb79 100644
--- a/apps/web/config/default-values.ts
+++ b/apps/web/config/default-values.ts
@@ -137,6 +137,7 @@ const defaultValues: CalculationValues = {
vehicleTaxInYear: 0,
withTrailer: false,
vin: null,
+ user: null,
};
export default defaultValues;
diff --git a/apps/web/config/process/default.ts b/apps/web/config/process/default.ts
deleted file mode 100644
index b3c88a4..0000000
--- a/apps/web/config/process/default.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-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 { 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 recalc from '@/process/recalc';
-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(bonuses);
- useProcess(usedPl);
- useProcess(subsidyImportProgram);
- useProcess(payments);
- useProcess(gibdd);
- useProcess(addProduct);
- useProcess(insurance);
- useProcess(recalc);
-}
diff --git a/apps/web/config/process/index.ts b/apps/web/config/process/index.ts
deleted file mode 100644
index ab201ad..0000000
--- a/apps/web/config/process/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default as useDefaultReactions } from './default';
diff --git a/apps/web/config/schema/env.js b/apps/web/config/schema/env.js
index 358a120..3508c8e 100644
--- a/apps/web/config/schema/env.js
+++ b/apps/web/config/schema/env.js
@@ -10,7 +10,6 @@ const envSchema = z.object({
URL_CRM_GRAPHQL_DIRECT: z.string(),
URL_GET_USER_DIRECT: z.string(),
USE_DEV_COLORS: z.unknown().optional().transform(Boolean),
- USERS_SUPER: z.string().optional().default(''),
});
module.exports = envSchema;
diff --git a/apps/web/config/schema/runtime-config.js b/apps/web/config/schema/runtime-config.js
index 40bf145..1f59d27 100644
--- a/apps/web/config/schema/runtime-config.js
+++ b/apps/web/config/schema/runtime-config.js
@@ -3,7 +3,6 @@ const envSchema = require('./env');
const publicRuntimeConfigSchema = envSchema.pick({
BASE_PATH: true,
USE_DEV_COLORS: true,
- USERS_SUPER: true,
});
const serverRuntimeConfigSchema = envSchema.pick({
diff --git a/apps/web/config/schema/values.ts b/apps/web/config/schema/values.ts
index d924ccd..e1bd311 100644
--- a/apps/web/config/schema/values.ts
+++ b/apps/web/config/schema/values.ts
@@ -123,6 +123,7 @@ const ValuesSchema = z.object({
vehicleTaxInYear: z.number(),
withTrailer: z.boolean(),
vin: z.string().nullable(),
+ user: z.string().nullable(),
/**
* Link Values
diff --git a/apps/web/config/users.js b/apps/web/config/users.js
new file mode 100644
index 0000000..59b581b
--- /dev/null
+++ b/apps/web/config/users.js
@@ -0,0 +1,3 @@
+export const unlimitedRoles = ['Калькулятор без ограничений'];
+export const defaultRoles = ['МПЛ'];
+export const usersSuper = ['akalinina', 'vchikalkin'];
diff --git a/apps/web/graphql/crm.query.graphql b/apps/web/graphql/crm.query.graphql
index e89768c..6847f24 100644
--- a/apps/web/graphql/crm.query.graphql
+++ b/apps/web/graphql/crm.query.graphql
@@ -639,3 +639,12 @@ query GetInsuranceCompanies {
label: name
}
}
+
+query GetRoles($roleName: String) {
+ roles(name: $roleName) {
+ systemusers {
+ label: fullname
+ value: domainname
+ }
+ }
+}
diff --git a/apps/web/graphql/crm.types.ts b/apps/web/graphql/crm.types.ts
index 361d813..4ea012a 100644
--- a/apps/web/graphql/crm.types.ts
+++ b/apps/web/graphql/crm.types.ts
@@ -470,6 +470,13 @@ export type GetInsuranceCompaniesQueryVariables = Exact<{ [key: string]: never;
export type GetInsuranceCompaniesQuery = { __typename?: 'Query', accounts: Array<{ __typename?: 'account', evo_type_ins_policy: Array | null, evo_evokasko_access: boolean | null, evo_inn: string | null, value: string | null, label: string | null } | null> | null };
+export type GetRolesQueryVariables = Exact<{
+ roleName: InputMaybe;
+}>;
+
+
+export type GetRolesQuery = { __typename?: 'Query', roles: Array<{ __typename?: 'role', systemusers: Array<{ __typename?: 'systemuser', label: string | null, value: string | null } | null> | null } | null> | null };
+
export type GetQuoteAddProductDataQueryVariables = Exact<{
quoteId: Scalars['Uuid'];
}>;
@@ -642,6 +649,7 @@ export const GetInsNsibTypesDocument = {"kind":"Document","definitions":[{"kind"
export const GetLeasingWithoutKaskoTypesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetLeasingWithoutKaskoTypes"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"currentDate"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"DateTime"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_addproduct_types"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"statecode"},"value":{"kind":"IntValue","value":"0"}},{"kind":"Argument","name":{"kind":"Name","value":"evo_product_type"},"value":{"kind":"IntValue","value":"100000007"}},{"kind":"Argument","name":{"kind":"Name","value":"evo_datefrom_param"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"lte"},"value":{"kind":"Variable","name":{"kind":"Name","value":"currentDate"}}}]}},{"kind":"Argument","name":{"kind":"Name","value":"evo_dateto_param"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"gte"},"value":{"kind":"Variable","name":{"kind":"Name","value":"currentDate"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoreAddProductTypesFields"}},{"kind":"Field","name":{"kind":"Name","value":"evo_product_type"}},{"kind":"Field","name":{"kind":"Name","value":"evo_min_period"}},{"kind":"Field","name":{"kind":"Name","value":"evo_max_period"}},{"kind":"Field","name":{"kind":"Name","value":"evo_min_price"}},{"kind":"Field","name":{"kind":"Name","value":"evo_max_price"}},{"kind":"Field","name":{"kind":"Name","value":"evo_leasingobject_types"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_leasingobject_typeid"}}]}},{"kind":"Field","name":{"kind":"Name","value":"evo_visible_calc"}},{"kind":"Field","name":{"kind":"Name","value":"evo_min_first_payment_perc"}},{"kind":"Field","name":{"kind":"Name","value":"evo_max_first_payment_perc"}},{"kind":"Field","name":{"kind":"Name","value":"evo_models"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_modelid"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoreAddProductTypesFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"evo_addproduct_type"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_graph_price"}},{"kind":"Field","alias":{"kind":"Name","value":"label"},"name":{"kind":"Name","value":"evo_name"}},{"kind":"Field","alias":{"kind":"Name","value":"value"},"name":{"kind":"Name","value":"evo_addproduct_typeid"}}]}}]} as unknown as DocumentNode;
export const GetInsuranceCompanyDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetInsuranceCompany"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"accountId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Uuid"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"account"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"accountid"},"value":{"kind":"Variable","name":{"kind":"Name","value":"accountId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_osago_with_kasko"}}]}}]}}]} as unknown as DocumentNode;
export const GetInsuranceCompaniesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetInsuranceCompanies"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"accounts"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"evo_account_type"},"value":{"kind":"ListValue","values":[{"kind":"IntValue","value":"100000002"}]}},{"kind":"Argument","name":{"kind":"Name","value":"statecode"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_type_ins_policy"}},{"kind":"Field","name":{"kind":"Name","value":"evo_evokasko_access"}},{"kind":"Field","name":{"kind":"Name","value":"evo_inn"}},{"kind":"Field","alias":{"kind":"Name","value":"value"},"name":{"kind":"Name","value":"accountid"}},{"kind":"Field","alias":{"kind":"Name","value":"label"},"name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode;
+export const GetRolesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetRoles"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"roleName"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"roles"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"roleName"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"systemusers"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"label"},"name":{"kind":"Name","value":"fullname"}},{"kind":"Field","alias":{"kind":"Name","value":"value"},"name":{"kind":"Name","value":"domainname"}}]}}]}}]}}]} as unknown as DocumentNode;
export const GetQuoteAddProductDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetQuoteAddProductData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Uuid"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"quote"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"quoteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_addproduct_types"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_product_type"}},{"kind":"Field","name":{"kind":"Name","value":"evo_addproduct_typeid"}}]}}]}}]}}]} as unknown as DocumentNode;
export const GetQuoteBonusDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetQuoteBonusData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Uuid"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"quote"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"quoteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_sale_bonus"}}]}}]}}]} as unknown as DocumentNode;
export const GetQuoteConfiguratorDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetQuoteConfiguratorData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Uuid"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"quote"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"quoteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_baseproductid"}},{"kind":"Field","name":{"kind":"Name","value":"evo_client_typeid"}},{"kind":"Field","name":{"kind":"Name","value":"evo_msfo_irr"}}]}}]}}]} as unknown as DocumentNode;
diff --git a/apps/web/pages/_document.jsx b/apps/web/pages/_document.jsx
index 48f85de..9a4eda7 100644
--- a/apps/web/pages/_document.jsx
+++ b/apps/web/pages/_document.jsx
@@ -36,7 +36,7 @@ export default class MyDocument extends Document {
-
+
{metaFavicon}
diff --git a/apps/web/pages/index.jsx b/apps/web/pages/index.jsx
index 5c44751..b6d9a47 100644
--- a/apps/web/pages/index.jsx
+++ b/apps/web/pages/index.jsx
@@ -2,44 +2,19 @@ import { getUser } from '@/api/user/query';
import initializeApollo from '@/apollo/client';
import * as Calculation from '@/Components/Calculation';
import { Error } from '@/Components/Common/Error';
+import { Grid } from '@/Components/Layout/Page';
import Output from '@/Components/Output';
-import { useDefaultReactions } from '@/config/process';
+import { defaultRoles } from '@/config/users';
import * as CRMTypes from '@/graphql/crm.types';
-import * as init from '@/process/init';
-import { min } from '@/styles/mq';
+import { useInsuranceData, useMainData, useReactions } from '@/process/hooks';
+import { getInitialData } from '@/process/hooks/init';
import { dehydrate, QueryClient } from '@tanstack/react-query';
import Head from 'next/head';
-import styled from 'styled-components';
-import { Box } from 'ui/grid';
-const Grid = styled(Box)`
- display: flex;
- flex-direction: column;
- gap: 10px;
-
- ${min('laptop')} {
- display: grid;
- align-items: flex-start;
- grid-template-columns: 2fr 1fr;
- }
-
- ${min('laptop-hd')} {
- grid-template-columns: 2fr 1fr 1.5fr;
- }
-
- ${min('desktop')} {
- margin: 8px 5%;
- }
-
- ${min('desktop-xl')} {
- margin: 8px 10%;
- }
-`;
-
-function Home(props) {
- init.useMainData();
- init.useInsuranceData();
- useDefaultReactions();
+export default function Home(props) {
+ useMainData();
+ useInsuranceData();
+ useReactions();
if (props.statusCode !== 200) return ;
@@ -48,65 +23,69 @@ function Home(props) {
Лизинговый калькулятор - Эволюция
-
+
);
}
-/** @type {import('next').GetServerSideProps} */
-export const getServerSideProps = async ({ req }) => {
- const { cookie = '' } = req.headers;
+export const makeGetServerSideProps = ({ roles }) =>
+ /** @type {import('next').GetServerSideProps} */
+ (
+ async function ({ req }) {
+ const { cookie = '' } = req.headers;
- const queryClient = new QueryClient();
+ const queryClient = new QueryClient();
- const user = await queryClient.fetchQuery(['user'], ({ signal }) =>
- getUser({
- headers: {
- cookie,
- },
- signal,
- })
+ const user = await queryClient.fetchQuery(['user'], ({ signal }) =>
+ getUser({
+ headers: {
+ cookie,
+ },
+ signal,
+ })
+ );
+
+ const apolloClient = initializeApollo();
+
+ try {
+ const {
+ data: { systemuser },
+ } = await apolloClient.query({
+ fetchPolicy: 'network-only',
+ query: CRMTypes.GetSystemUserDocument,
+ variables: {
+ domainname: user.domainName,
+ },
+ });
+
+ if (!systemuser?.roles?.some((x) => x?.name && roles.includes(x.name))) {
+ return {
+ props: { statusCode: 403 },
+ };
+ }
+ const { values, options } = await getInitialData(apolloClient, user);
+
+ return {
+ props: {
+ calculation: {
+ options,
+ values,
+ },
+ initialApolloState: apolloClient.cache.extract(),
+ initialQueryState: dehydrate(queryClient),
+ statusCode: 200,
+ },
+ };
+ } catch (error) {
+ return {
+ props: {
+ error: JSON.stringify(error),
+ statusCode: 500,
+ },
+ };
+ }
+ }
);
- const apolloClient = initializeApollo();
-
- try {
- const {
- data: { systemuser },
- } = await apolloClient.query({
- query: CRMTypes.GetSystemUserDocument,
- variables: {
- domainname: user.domainName,
- },
- });
-
- if (!systemuser.roles.some((x) => x.name === 'МПЛ')) {
- return {
- props: { statusCode: 403 },
- };
- }
- const { values, options } = await init.getInitialData(apolloClient, user);
-
- return {
- props: {
- calculation: {
- options,
- values,
- },
- initialApolloState: apolloClient.cache.extract(),
- initialQueryState: dehydrate(queryClient),
- statusCode: 200,
- },
- };
- } catch (error) {
- return {
- props: {
- error: JSON.stringify(error),
- statusCode: 500,
- },
- };
- }
-};
-
-export default Home;
+export const getServerSideProps = makeGetServerSideProps({ roles: defaultRoles });
diff --git a/apps/web/pages/unlimited.jsx b/apps/web/pages/unlimited.jsx
new file mode 100644
index 0000000..d5d8c4f
--- /dev/null
+++ b/apps/web/pages/unlimited.jsx
@@ -0,0 +1,37 @@
+import { makeGetServerSideProps } from '.';
+import * as Calculation from '@/Components/Calculation';
+import { Error } from '@/Components/Common/Error';
+import { Grid } from '@/Components/Layout/Page';
+import Output from '@/Components/Output';
+import { unlimitedRoles } from '@/config/users';
+import { useGetUsers, useInsuranceData, useMainData, useReactions } from '@/process/hooks';
+import { useStore } from '@/stores/hooks';
+import Head from 'next/head';
+
+export default function Unlimited(props) {
+ const store = useStore();
+ store.$process.add('Unlimited');
+
+ useMainData();
+ useGetUsers();
+ useInsuranceData();
+ useReactions();
+
+ if (props.statusCode !== 200) return ;
+
+ return (
+
+
+ Лизинговый калькулятор без ограничений - Эволюция
+
+
+
+
+
+
+ );
+}
+
+export const getServerSideProps = makeGetServerSideProps({
+ roles: unlimitedRoles,
+});
diff --git a/apps/web/process/calculate/reactions/validation.ts b/apps/web/process/calculate/reactions/validation.ts
index 3a8430b..36c042e 100644
--- a/apps/web/process/calculate/reactions/validation.ts
+++ b/apps/web/process/calculate/reactions/validation.ts
@@ -5,6 +5,7 @@ import type { ProcessContext } from '@/process/types';
import ValidationHelper from '@/stores/validation/helper';
import { reaction } from 'mobx';
import { uid } from 'radash';
+import { makeDisposable } from 'tools';
import type { BaseOption } from 'ui/elements/types';
function hasInvalidValueOrOptions(value: unknown, options: Array>) {
@@ -16,34 +17,38 @@ function hasInvalidValueOrOptions(value: unknown, options: Array {
- const hasElementsErrors = Object.values($calculation.$validation).some(
- (validation) => validation.hasErrors
- );
+ makeDisposable(
+ () =>
+ reaction(
+ () => {
+ 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;
+ const hasPaymentsErrors = $tables.payments.validation.hasErrors;
+ const hasInsuranceErrors = $tables.insurance.validation.hasErrors;
+ const hasFingapErrors = $tables.fingap.validation.hasErrors;
- return hasElementsErrors || hasPaymentsErrors || hasInsuranceErrors || hasFingapErrors;
- },
- (hasErrors) => {
- if (hasErrors) {
- $calculation.$status.setStatus('btnCalculate', 'Disabled');
- $calculation.$status.setStatus('btnCreateKP', 'Disabled');
- $calculation.$status.setStatus('btnCreateKPMini', 'Disabled');
- } else {
- $calculation.$status.setStatus('btnCalculate', 'Default');
- $calculation.$status.setStatus('btnCreateKP', 'Default');
- $calculation.$status.setStatus('btnCreateKPMini', 'Default');
- }
- },
- {
- fireImmediately: true,
- }
+ return hasElementsErrors || hasPaymentsErrors || hasInsuranceErrors || hasFingapErrors;
+ },
+ (hasErrors) => {
+ if (hasErrors) {
+ $calculation.$status.setStatus('btnCalculate', 'Disabled');
+ $calculation.$status.setStatus('btnCreateKP', 'Disabled');
+ $calculation.$status.setStatus('btnCreateKPMini', 'Disabled');
+ } else {
+ $calculation.$status.setStatus('btnCalculate', 'Default');
+ $calculation.$status.setStatus('btnCreateKP', 'Default');
+ $calculation.$status.setStatus('btnCreateKPMini', 'Default');
+ }
+ },
+ {
+ fireImmediately: true,
+ }
+ ),
+ () => $process.has('Unlimited')
);
/**
diff --git a/apps/web/process/configurator/reactions/index.ts b/apps/web/process/configurator/reactions/index.ts
index e294884..1b87c74 100644
--- a/apps/web/process/configurator/reactions/index.ts
+++ b/apps/web/process/configurator/reactions/index.ts
@@ -1,3 +1,4 @@
export { default as filters } from './filters';
+export { default as unlimited } from './unlimited';
export { default as validation } from './validation';
export { default as values } from './values';
diff --git a/apps/web/process/configurator/reactions/unlimited.ts b/apps/web/process/configurator/reactions/unlimited.ts
new file mode 100644
index 0000000..a6ac905
--- /dev/null
+++ b/apps/web/process/configurator/reactions/unlimited.ts
@@ -0,0 +1,41 @@
+import * as CRMTypes from '@/graphql/crm.types';
+import type { ProcessContext } from '@/process/types';
+import { reaction } from 'mobx';
+import { makeDisposable, normalizeOptions } from 'tools';
+
+export default function unlimitedReactions({ store, apolloClient }: ProcessContext) {
+ const { $calculation, $process } = store;
+
+ makeDisposable(
+ () =>
+ reaction(
+ () => $calculation.element('selectUser').getValue(),
+ async (domainname) => {
+ if (!domainname) {
+ $calculation.element('selectLead').reset();
+ $calculation.element('selectOpportunity').reset();
+
+ return;
+ }
+ const {
+ data: { leads },
+ } = await apolloClient.query({
+ query: CRMTypes.GetLeadsDocument,
+ variables: { domainname },
+ });
+
+ $calculation.element('selectLead').setOptions(normalizeOptions(leads));
+
+ const {
+ data: { opportunities },
+ } = await apolloClient.query({
+ query: CRMTypes.GetOpportunitiesDocument,
+ variables: { domainname },
+ });
+
+ $calculation.element('selectOpportunity').setOptions(normalizeOptions(opportunities));
+ }
+ ),
+ () => !$process.has('Unlimited')
+ );
+}
diff --git a/apps/web/process/hooks.ts b/apps/web/process/hooks/common.ts
similarity index 71%
rename from apps/web/process/hooks.ts
rename to apps/web/process/hooks/common.ts
index 8537421..8315456 100644
--- a/apps/web/process/hooks.ts
+++ b/apps/web/process/hooks/common.ts
@@ -1,20 +1,11 @@
import { getUser } from '@/api/user/query';
import { STALE_TIME } from '@/constants/request';
-import type { Process, ProcessContext } from '@/process/types';
+import type { ProcessContext } from '@/process/types';
import { useStore } from '@/stores/hooks';
import { trpcPureClient } from '@/trpc/client';
import { useApolloClient } from '@apollo/client';
import { useQuery, useQueryClient } from '@tanstack/react-query';
-export function useProcess({ reactions }: Process) {
- const context = useProcessContext();
-
- Object.keys(reactions).forEach((name) => {
- const injector = reactions[name];
- injector(context);
- });
-}
-
export function useProcessContext(): ProcessContext {
const store = useStore();
const apolloClient = useApolloClient();
diff --git a/apps/web/process/hooks/index.ts b/apps/web/process/hooks/index.ts
new file mode 100644
index 0000000..07c491c
--- /dev/null
+++ b/apps/web/process/hooks/index.ts
@@ -0,0 +1,3 @@
+export * from './common';
+export * from './init';
+export * from './reactions';
diff --git a/apps/web/process/init/get-initial-data.ts b/apps/web/process/hooks/init/get-initial-data.ts
similarity index 100%
rename from apps/web/process/init/get-initial-data.ts
rename to apps/web/process/hooks/init/get-initial-data.ts
diff --git a/apps/web/process/init/get-insurance-data.js b/apps/web/process/hooks/init/get-insurance-data.js
similarity index 100%
rename from apps/web/process/init/get-insurance-data.js
rename to apps/web/process/hooks/init/get-insurance-data.js
diff --git a/apps/web/process/init/get-main-data.js b/apps/web/process/hooks/init/get-main-data.js
similarity index 100%
rename from apps/web/process/init/get-main-data.js
rename to apps/web/process/hooks/init/get-main-data.js
diff --git a/apps/web/process/hooks/init/get-users.js b/apps/web/process/hooks/init/get-users.js
new file mode 100644
index 0000000..bd70a21
--- /dev/null
+++ b/apps/web/process/hooks/init/get-users.js
@@ -0,0 +1,37 @@
+import * as CRMTypes from '@/graphql/crm.types';
+import { useStore } from '@/stores/hooks';
+import { useApolloClient } from '@apollo/client';
+import { useEffect } from 'react';
+import { normalizeOptions } from 'tools';
+
+/**
+ * @param {import('@apollo/client').ApolloClient} apolloClient
+ * @param {*} onCompleted
+ */
+export function getUsers({ query }, onCompleted) {
+ query({
+ query: CRMTypes.GetRolesDocument,
+ variables: { roleName: 'МПЛ' },
+ }).then(({ data }) => {
+ const users = data.roles?.flatMap((x) => x?.systemusers);
+ onCompleted({
+ selectUser: users,
+ });
+ });
+}
+
+export function useGetUsers() {
+ const { $calculation } = useStore();
+ const apolloClient = useApolloClient();
+
+ function handleOnCompleted(options) {
+ Object.keys(options).forEach((elementName) => {
+ const elementOptions = options[elementName];
+ $calculation.element(elementName).setOptions(normalizeOptions(elementOptions));
+ });
+ }
+
+ useEffect(() => {
+ getUsers(apolloClient, handleOnCompleted);
+ }, []);
+}
diff --git a/apps/web/process/init/index.js b/apps/web/process/hooks/init/index.js
similarity index 78%
rename from apps/web/process/init/index.js
rename to apps/web/process/hooks/init/index.js
index eee9f13..2cf7203 100644
--- a/apps/web/process/init/index.js
+++ b/apps/web/process/hooks/init/index.js
@@ -1,3 +1,4 @@
export * from './get-initial-data';
export * from './get-insurance-data';
export * from './get-main-data';
+export * from './get-users';
diff --git a/apps/web/process/hooks/reactions.ts b/apps/web/process/hooks/reactions.ts
new file mode 100644
index 0000000..1ab2e73
--- /dev/null
+++ b/apps/web/process/hooks/reactions.ts
@@ -0,0 +1,58 @@
+import type { Process } from '../types';
+import { useProcessContext } from './common';
+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 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 recalc from '@/process/recalc';
+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';
+
+type Config = {
+ prune: string[];
+};
+
+function useProcess({ reactions }: Process, config?: Config) {
+ const context = useProcessContext();
+
+ Object.keys(reactions).forEach((name) => {
+ if (!config?.prune.includes(name)) {
+ const injector = reactions[name];
+ injector(context);
+ }
+ });
+}
+
+export function useReactions(config: Config) {
+ useProcess(leadOpportunity, config);
+ useProcess(loadKP, config);
+ useProcess(calculate, config);
+ useProcess(supplierAgent, config);
+ useProcess(price, config);
+ useProcess(fingap, config);
+ useProcess(leasingWithoutKasko, config);
+ useProcess(subsidy, config);
+ useProcess(leasingObject, config);
+ useProcess(configurator, config);
+ useProcess(createKP, config);
+ useProcess(bonuses, config);
+ useProcess(usedPl, config);
+ useProcess(subsidyImportProgram, config);
+ useProcess(payments, config);
+ useProcess(gibdd, config);
+ useProcess(addProduct, config);
+ useProcess(insurance, config);
+ useProcess(recalc, config);
+}
diff --git a/apps/web/process/types.ts b/apps/web/process/types.ts
index b13166d..98cc755 100644
--- a/apps/web/process/types.ts
+++ b/apps/web/process/types.ts
@@ -9,7 +9,7 @@ export type ProcessContext = {
queryClient: QueryClient;
store: RootStore;
trpcClient: TRPCPureClient;
- user: User | undefined;
+ user: Pick | undefined;
};
export type Process = {
diff --git a/apps/web/server/middleware.ts b/apps/web/server/middleware.ts
index 553e146..fedce85 100644
--- a/apps/web/server/middleware.ts
+++ b/apps/web/server/middleware.ts
@@ -1,19 +1,33 @@
import { t } from './trpc';
+import initializeApollo from '@/apollo/client';
+import { unlimitedRoles } from '@/config/users';
+import * as CRMTypes from '@/graphql/crm.types';
import { TRPCError } from '@trpc/server';
/**
* @see https://trpc.io/docs/v10/middlewares
*/
-export const userMiddleware = t.middleware(({ ctx, next }) => {
+export const userMiddleware = t.middleware(async ({ ctx, next }) => {
if (process.env.NODE_ENV !== 'development' && !ctx.user) {
throw new TRPCError({
code: 'UNAUTHORIZED',
});
}
+ const apolloClient = initializeApollo();
+
+ const {
+ data: { systemuser },
+ } = await apolloClient.query({
+ query: CRMTypes.GetSystemUserDocument,
+ variables: {
+ domainname: ctx.user.domainName,
+ },
+ });
+
return next({
ctx: {
- isAdmin: false,
+ unlimited: systemuser?.roles?.some((x) => x?.name && unlimitedRoles.includes(x.name)),
},
});
});
diff --git a/apps/web/server/routers/calculate/index.ts b/apps/web/server/routers/calculate/index.ts
index f4c7a6c..50aceb9 100644
--- a/apps/web/server/routers/calculate/index.ts
+++ b/apps/web/server/routers/calculate/index.ts
@@ -4,6 +4,7 @@ import { transformCalculateResults } from './lib/transform';
import { validate } from './lib/validation';
import { CalculateInputSchema, CalculateOutputSchema } from './types';
import { calculate } from '@/api/core/query';
+import type { User } from '@/api/user/types';
import initializeApollo from '@/apollo/client';
import { protectedProcedure } from '@/server/procedure';
import { QueryClient } from '@tanstack/react-query';
@@ -16,30 +17,37 @@ export const calculateRouter = router({
const apolloClient = initializeApollo();
const queryClient = new QueryClient();
- const validationResult = await validate({
- context: {
- apolloClient,
- queryClient,
- user: ctx.user,
- },
- input,
- });
+ if (ctx.unlimited === false) {
+ const validationResult = await validate({
+ context: {
+ apolloClient,
+ queryClient,
+ user: ctx.user,
+ },
+ input,
+ });
- if (validationResult.success === false) {
- return {
- error: validationResult.error,
- success: false,
- };
+ if (validationResult.success === false) {
+ return {
+ error: validationResult.error,
+ success: false,
+ };
+ }
+ }
+
+ let user: Pick = { domainName: ctx.user.domainName };
+ if (ctx.unlimited && input.values.user) {
+ user = { domainName: input.values.user };
}
const requestData = await createRequestData({
context: {
apolloClient,
queryClient,
- user: ctx.user,
+ ...ctx,
+ user,
},
input,
- user: ctx.user,
});
const calculateResult = await calculate(requestData);
diff --git a/apps/web/server/routers/calculate/lib/request.ts b/apps/web/server/routers/calculate/lib/request.ts
index e1b3b1f..4c50c66 100644
--- a/apps/web/server/routers/calculate/lib/request.ts
+++ b/apps/web/server/routers/calculate/lib/request.ts
@@ -1,7 +1,6 @@
/* eslint-disable sonarjs/cognitive-complexity */
import type { CalculateInput, Context } from '../types';
import type * as CoreTypes from '@/api/core/types';
-import type { User } from '@/api/user/types';
import { ESN, NSIB_MAX, VAT } from '@/constants/values';
import * as CRMTypes from '@/graphql/crm.types';
import helper from '@/process/calculate/lib/helper';
@@ -13,9 +12,8 @@ import { max, sum } from 'radash';
dayjs.extend(utc);
type Input = {
- context: Context;
+ context: Context & { unlimited?: boolean };
input: CalculateInput;
- user: User;
};
type PreparedValuesGetters = {
@@ -29,9 +27,8 @@ type AdditionalDataGetters = {
export async function createRequestData({
context,
input,
- user,
}: Input): Promise {
- const { apolloClient } = context;
+ const { apolloClient, user, unlimited } = context;
const { values, insurance, payments } = input;
const { RUB } = createCurrencyUtility({ apolloClient });
@@ -59,14 +56,17 @@ export async function createRequestData({
).data.transactioncurrency
: null;
- const {
- data: { systemuser },
- } = await apolloClient.query({
- query: CRMTypes.GetSystemUserDocument,
- variables: {
- domainname: user.domainName,
- },
- });
+ let systemuser: CRMTypes.GetSystemUserQuery['systemuser'] = null;
+
+ if (user?.domainName) {
+ const { data } = await apolloClient.query({
+ query: CRMTypes.GetSystemUserDocument,
+ variables: {
+ domainname: user.domainName,
+ },
+ });
+ if (data.systemuser) systemuser = data.systemuser;
+ }
async function getDeprecation() {
if (values.leaseObjectType) {
@@ -1232,6 +1232,9 @@ export async function createRequestData({
return {
additionalData,
+ flags: {
+ DISABLE_CHECKS_RESULTS: unlimited === true,
+ },
preparedPayments,
preparedValues,
};
diff --git a/apps/web/server/routers/quote/index.ts b/apps/web/server/routers/quote/index.ts
index 100c765..3f29522 100644
--- a/apps/web/server/routers/quote/index.ts
+++ b/apps/web/server/routers/quote/index.ts
@@ -13,6 +13,7 @@ import {
} from './types';
import { calculate } from '@/api/core/query';
import { createKP } from '@/api/crm/query';
+import type { User } from '@/api/user/types';
import initializeApollo from '@/apollo/client';
import defaultValues from '@/config/default-values';
import * as insuranceTable from '@/config/tables/insurance-table';
@@ -88,30 +89,37 @@ export const quoteRouter = router({
const apolloClient = initializeApollo();
const queryClient = new QueryClient();
- const validationResult = await validate({
- context: {
- apolloClient,
- queryClient,
- user: ctx.user,
- },
- input,
- });
+ if (ctx.unlimited === false) {
+ const validationResult = await validate({
+ context: {
+ apolloClient,
+ queryClient,
+ user: ctx.user,
+ },
+ input,
+ });
- if (validationResult.success === false) {
- return {
- error: validationResult.error,
- success: false,
- };
+ if (validationResult.success === false) {
+ return {
+ error: validationResult.error,
+ success: false,
+ };
+ }
+ }
+
+ let user: Pick = { domainName: ctx.user.domainName };
+ if (ctx.unlimited && input.values.user) {
+ user = { domainName: input.values.user };
}
const requestData = await createRequestData({
context: {
apolloClient,
queryClient,
- user: ctx.user,
+ ...ctx,
+ user,
},
input,
- user: ctx.user,
});
const calculateResult = await calculate(requestData);
@@ -124,7 +132,7 @@ export const quoteRouter = router({
}
const createKPResult = await createKP({
- domainName: ctx.user.domainName,
+ domainName: user.domainName,
finGAP: input.fingap,
insurance: Object.values(input.insurance.values),
calculation: {
diff --git a/apps/web/stores/calculation/index.ts b/apps/web/stores/calculation/index.ts
index ab662c5..5170830 100644
--- a/apps/web/stores/calculation/index.ts
+++ b/apps/web/stores/calculation/index.ts
@@ -1,3 +1,4 @@
+import Validation from '../validation';
import type { ValidationParams } from '../validation/types';
import OptionsStore from './options';
import StatusStore from './statuses';
@@ -6,17 +7,24 @@ import titles from '@/Components/Calculation/config/elements-titles';
import type * as Values from '@/Components/Calculation/config/map/values';
import { getValueName } from '@/Components/Calculation/config/map/values';
import type RootStore from '@/stores/root';
-import Validation from '@/stores/validation';
import { observable } from 'mobx';
import type { BaseOption } from 'ui/elements/types';
export default class CalculationStore {
+ private root: RootStore;
public $values: ValuesStore;
public $status: StatusStore;
public $options: OptionsStore;
public $validation: Partial>;
+ public get hasErrors() {
+ return (Object.keys(this.$validation) as Values.Elements[]).some(
+ (elementName) => this.$validation[elementName]?.hasErrors
+ );
+ }
+
constructor(rootStore: RootStore) {
+ this.root = rootStore;
this.$values = new ValuesStore(rootStore);
this.$status = new StatusStore(rootStore);
this.$options = new OptionsStore(rootStore);
@@ -24,10 +32,13 @@ export default class CalculationStore {
}
private createElementValidation = (elementName: E) => {
- this.$validation[elementName] = new Validation({
- err_key: elementName,
- err_title: titles[elementName],
- });
+ this.$validation[elementName] = new Validation(
+ {
+ err_key: elementName,
+ err_title: titles[elementName],
+ },
+ this.root
+ );
};
public element = (elementName: E) => ({
diff --git a/apps/web/stores/calculation/statuses/index.ts b/apps/web/stores/calculation/statuses/index.ts
index faf77f8..084897b 100644
--- a/apps/web/stores/calculation/statuses/index.ts
+++ b/apps/web/stores/calculation/statuses/index.ts
@@ -21,7 +21,13 @@ export default class StatusStore {
};
public getStatus(elementName: ElementsActions | ElementsValues) {
- return this.overrided[elementName] || this.statuses[elementName];
+ const status = this.overrided[elementName] || this.statuses[elementName];
+
+ if (this.root.$process.has('Unlimited') && status === 'Disabled') {
+ return 'Default';
+ }
+
+ return status;
}
public setStatus = (elementName: ElementsActions | ElementsValues, status: Status) => {
diff --git a/apps/web/stores/calculation/validation/hooks.js b/apps/web/stores/calculation/validation/hooks.js
index 7a8a06e..8065ed2 100644
--- a/apps/web/stores/calculation/validation/hooks.js
+++ b/apps/web/stores/calculation/validation/hooks.js
@@ -1,16 +1,16 @@
import { useStore } from '@/stores/hooks';
export function useValidation(elementName) {
- const { $calculation } = useStore();
+ const { $calculation, $process } = useStore();
const hasErrors = $calculation.$validation?.[elementName]?.hasErrors;
if (hasErrors) {
return {
help: 'Некорректные данные',
- isValid: false,
+ validateStatus: $process.has('Unlimited') ? 'warning' : 'error',
};
}
return {
- isValid: true,
+ validateStatus: '',
};
}
diff --git a/apps/web/stores/process/index.ts b/apps/web/stores/process/index.ts
index e18ef85..3a97210 100644
--- a/apps/web/stores/process/index.ts
+++ b/apps/web/stores/process/index.ts
@@ -1,7 +1,7 @@
import type { ObservableSet } from 'mobx';
import { observable } from 'mobx';
-export type Process = 'ELT' | 'LoadKP';
+export type Process = 'ELT' | 'LoadKP' | 'Unlimited';
export type ProcessStore = ObservableSet;
export default function createProcessStore() {
diff --git a/apps/web/stores/tables/fingap/index.ts b/apps/web/stores/tables/fingap/index.ts
index 4aeebbf..4b7fe50 100644
--- a/apps/web/stores/tables/fingap/index.ts
+++ b/apps/web/stores/tables/fingap/index.ts
@@ -15,15 +15,22 @@ export default class FinGAPTable {
this.selectedKeys = new Set();
this.risks = observable([]);
- this.validation = new Validation({
- err_key: 'ERR_FINGAP_TABLE',
- err_title: 'Таблица рисков Safe Finance',
- });
+ this.validation = new Validation(
+ {
+ err_key: 'ERR_FINGAP_TABLE',
+ err_title: 'Таблица рисков Safe Finance',
+ },
+ rootStore
+ );
makeAutoObservable(this);
this.root = rootStore;
}
+ public get hasErrors() {
+ return this.validation.hasErrors;
+ }
+
public getSelectedRisks() {
return toJS(this.risks.filter((x) => this.selectedKeys.has(x.key)));
}
diff --git a/apps/web/stores/tables/insurance/index.ts b/apps/web/stores/tables/insurance/index.ts
index 8d70370..461225b 100644
--- a/apps/web/stores/tables/insurance/index.ts
+++ b/apps/web/stores/tables/insurance/index.ts
@@ -21,15 +21,22 @@ export default class InsuranceTable {
insuranceTableConfig.defaultStatuses;
constructor(rootStore: RootStore) {
- this.validation = new Validation({
- err_key: 'ERR_INSURANCE_TABLE',
- err_title: 'Таблица страхования',
- });
+ this.validation = new Validation(
+ {
+ err_key: 'ERR_INSURANCE_TABLE',
+ err_title: 'Таблица страхования',
+ },
+ rootStore
+ );
makeAutoObservable(this);
this.root = rootStore;
}
+ public get hasErrors() {
+ return this.validation.hasErrors;
+ }
+
public hydrate = ({
values: initialValues,
options: initialOptions,
@@ -95,7 +102,11 @@ export default class InsuranceTable {
getOptions: (valueName: V) => this.options[key][valueName],
- getStatus: (valueName: Insurance.Values) => this.statuses[key][valueName],
+ getStatus: (valueName: Insurance.Values) => {
+ if (this.root.$process.has('Unlimited')) return 'Default';
+
+ return this.statuses[key][valueName];
+ },
getValue: (valueName: V) => {
const rowIndex = this.values.findIndex((x) => x.key === key);
diff --git a/apps/web/stores/tables/payments/index.ts b/apps/web/stores/tables/payments/index.ts
index bddc221..5688f33 100644
--- a/apps/web/stores/tables/payments/index.ts
+++ b/apps/web/stores/tables/payments/index.ts
@@ -14,10 +14,13 @@ export default class PaymentsTable {
private overridedStatus: IObservableValue;
constructor(rootStore: RootStore) {
- this.validation = new Validation({
- err_key: 'ERR_PAYMENTS_TABLE',
- err_title: 'Таблица платежей',
- });
+ this.validation = new Validation(
+ {
+ err_key: 'ERR_PAYMENTS_TABLE',
+ err_title: 'Таблица платежей',
+ },
+ rootStore
+ );
this.values = observable([]);
this.statuses = observable([]);
@@ -37,6 +40,10 @@ export default class PaymentsTable {
);
}
+ public get hasErrors() {
+ return this.validation.hasErrors;
+ }
+
public getValue(index: number) {
return this.values[index];
}
@@ -50,6 +57,8 @@ export default class PaymentsTable {
};
public getStatus(index: number) {
+ if (this.root.$process.has('Unlimited')) return 'Default';
+
return this.overridedStatus.get() ?? this.statuses[index];
}
diff --git a/apps/web/stores/validation/index.ts b/apps/web/stores/validation/index.ts
index 5b9ca5a..0154033 100644
--- a/apps/web/stores/validation/index.ts
+++ b/apps/web/stores/validation/index.ts
@@ -1,14 +1,17 @@
+import type RootStore from '../root';
import type { RemoveError, ValidationConfig, ValidationError, ValidationParams } from './types';
import { makeAutoObservable } from 'mobx';
import notification from 'ui/elements/notification';
export default class Validation {
+ private root: RootStore;
private params: ValidationConfig;
private errors: Set;
- constructor(config: ValidationConfig) {
+ constructor(config: ValidationConfig, rootStore: RootStore) {
this.params = config;
this.errors = new Set();
+ this.root = rootStore;
makeAutoObservable(this);
}
@@ -33,10 +36,11 @@ export default class Validation {
this.errors.add({ key, message });
if (!silent) {
- notification.error({
+ notification.open({
description: message,
key: this.params.err_key,
message: this.params.err_title,
+ type: this.root.$process.has('Unlimited') ? 'warning' : 'error',
});
}
diff --git a/packages/ui/elements/Checkbox.tsx b/packages/ui/elements/Checkbox.tsx
index 97a9622..e83ce2a 100644
--- a/packages/ui/elements/Checkbox.tsx
+++ b/packages/ui/elements/Checkbox.tsx
@@ -16,7 +16,7 @@ function Checkbox({
value,
setValue,
status,
- isValid,
+ validateStatus,
help,
text,
...props
@@ -26,7 +26,7 @@ function Checkbox({
}
return (
-
+
) {
+function Input({
+ value,
+ setValue,
+ status,
+ validateStatus,
+ help,
+ ...props
+}: BaseElementProps) {
function handleChange(event: ChangeEvent) {
setValue(event.target.value);
}
return (
-
+
);
diff --git a/packages/ui/elements/InputNumber.tsx b/packages/ui/elements/InputNumber.tsx
index 8164678..583f8da 100644
--- a/packages/ui/elements/InputNumber.tsx
+++ b/packages/ui/elements/InputNumber.tsx
@@ -7,7 +7,13 @@ const { Item: FormItem } = Form;
type InputNumberProps = AntInputNumberProps;
-function InputNumber({ setValue, status, isValid, help, ...props }: BaseElementProps) {
+function InputNumber({
+ setValue,
+ status,
+ validateStatus,
+ help,
+ ...props
+}: BaseElementProps) {
function handleChange(value: number | null) {
if (value) {
setValue(value);
@@ -17,7 +23,7 @@ function InputNumber({ setValue, status, isValid, help, ...props }: BaseElementP
}
return (
-
+
+
& {
options: BaseOption[];
};
-function Segmented({ value, setValue, options, status, isValid, help, ...props }: ElementProps) {
+function Segmented({
+ value,
+ setValue,
+ options,
+ status,
+ validateStatus,
+ help,
+ ...props
+}: ElementProps) {
return (
-
+
& ElementProps) {
@@ -31,7 +31,7 @@ function Select({
);
return (
-
+
) {
+function Switch({
+ value,
+ setValue,
+ status,
+ validateStatus,
+ help,
+ ...props
+}: BaseElementProps) {
return (
-
+
);
diff --git a/packages/ui/elements/badge.js b/packages/ui/elements/badge.js
new file mode 100644
index 0000000..d4ecff9
--- /dev/null
+++ b/packages/ui/elements/badge.js
@@ -0,0 +1 @@
+export { Badge } from 'antd';
diff --git a/packages/ui/elements/index.ts b/packages/ui/elements/index.ts
index ae1c1d3..7ba3afd 100644
--- a/packages/ui/elements/index.ts
+++ b/packages/ui/elements/index.ts
@@ -1,3 +1,4 @@
+export * from './badge';
export { default as Button } from './Button';
export { default as Checkbox } from './Checkbox';
export { default as AntdConfig } from './Config';
@@ -13,5 +14,6 @@ export { default as Segmented } from './Segmented';
export { default as Select } from './Select';
export { default as Switch } from './Switch';
export { default as Table } from './Table';
+export * from './tag';
export { default as Text } from './Text';
export { default as Tooltip } from './Tooltip';
diff --git a/packages/ui/elements/tag.js b/packages/ui/elements/tag.js
new file mode 100644
index 0000000..2bfffd1
--- /dev/null
+++ b/packages/ui/elements/tag.js
@@ -0,0 +1 @@
+export { Tag } from 'antd';
diff --git a/packages/ui/elements/types.ts b/packages/ui/elements/types.ts
index dc065d8..ab86129 100644
--- a/packages/ui/elements/types.ts
+++ b/packages/ui/elements/types.ts
@@ -1,10 +1,12 @@
+import type { ValidateStatus } from 'antd/es/form/FormItem';
+
export type Status = 'Default' | 'Disabled' | 'Hidden' | 'Loading';
export type BaseElementProps = {
help?: string;
- isValid?: boolean;
setValue: (value: Value) => void;
status?: Status;
+ validateStatus?: ValidateStatus;
value: Value;
};