diff --git a/.eslintrc.json b/.eslintrc.json index 052062c..f320aec 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -74,7 +74,10 @@ "ignore": ["^.*.(jsx|tsx)$"] } ], - "import/no-unresolved": "warn" + "import/no-unresolved": "warn", + "implicit-arrow-linebreak": "warn", + "operator-linebreak": "warn", + "function-paren-newline": "warn" }, "overrides": [ // Only uses Testing Library lint rules in test files diff --git a/Components/Calculation/Form/Payments/PaymentsParams.jsx b/Components/Calculation/Form/Payments/PaymentsParams.jsx index 4f3174f..97fd0d3 100644 --- a/Components/Calculation/Form/Payments/PaymentsParams.jsx +++ b/Components/Calculation/Form/Payments/PaymentsParams.jsx @@ -14,7 +14,7 @@ function PaymentsParams() { const [selectSeasonType, tbxParmentsDecreasePercent, selectHighSeasonStart] = renderedElements; const { $calculation } = useStore(); - const graphType = $calculation.getElementValue('radioGraphType'); + const graphType = $calculation.element('radioGraphType').getValue(); switch (graphType) { case 100_000_000: diff --git a/Components/Calculation/addons/currency-addon.tsx b/Components/Calculation/addons/currency-addon.tsx index b2499b7..368f804 100644 --- a/Components/Calculation/addons/currency-addon.tsx +++ b/Components/Calculation/addons/currency-addon.tsx @@ -14,7 +14,7 @@ const QUERY_GET_CURRENCY_SYMBOL = gql` const CurrencyAddon = observer(() => { const { $calculation } = useStore(); - const currencyid = $calculation.$values.getValue('supplierCurrency'); + const currencyid = $calculation.element('selectSupplierCurrency').getValue(); const { data } = useQuery< CRMTypes.GetCurrencySymbolQuery, diff --git a/Components/Calculation/config/elements-render/override.tsx b/Components/Calculation/config/elements-render/override.tsx index 2e08e79..cd9b208 100644 --- a/Components/Calculation/config/elements-render/override.tsx +++ b/Components/Calculation/config/elements-render/override.tsx @@ -180,7 +180,7 @@ const overrideRender: Partial> = { const Title = observer(() => { const { $calculation } = useStore(); - const graphType = $calculation.getElementValue('radioGraphType'); + const graphType = $calculation.element('radioGraphType').getValue(); switch (graphType) { case 100_000_001: diff --git a/Components/Output/Validation.jsx b/Components/Output/Validation.jsx index 43db968..c17c446 100644 --- a/Components/Output/Validation.jsx +++ b/Components/Output/Validation.jsx @@ -3,7 +3,6 @@ import { observer } from 'mobx-react-lite'; import { useStore } from 'stores/hooks'; import styled from 'styled-components'; import { Box, Flex } from 'UIKit/grid'; -import titles from '../Calculation/config/elements-titles'; const Bold = styled.span` font-weight: bold; @@ -19,14 +18,19 @@ function Message(title, text) { ); } +const AlertWrapper = styled(Box)` + margin: 0 0 5px 0; +`; + function getElementsErrors($calculation) { - const { elementsErrors } = $calculation.$validation; - const errors = Object.keys(elementsErrors).map((elementName) => { - const elementErrors = elementsErrors[elementName]; - const elementTitle = titles[elementName]; + const errors = Object.values($calculation.$validation).map((validation) => { + const elementErrors = validation.getMessages(); + const elementTitle = validation.params.err_title; return elementErrors.map((error) => ( - + + + )); }); @@ -51,14 +55,22 @@ function getInsuranceTableErrors($tables) { const Errors = observer(() => { const { $calculation, $tables } = useStore(); + const hasElementsErrors = Object.values($calculation.$validation).some( + (validation) => validation.hasErrors + ); + const hasPaymentsErrors = $tables.payments.validation.hasErrors; + const hasInsuranceErrors = $tables.insurance.validation.hasErrors; + + if (!hasElementsErrors && !hasPaymentsErrors && !hasInsuranceErrors) { + return ; + } + const elementsErrors = getElementsErrors($calculation); const paymentsErrors = getPaymentsTableErrors($tables); const insuranceErrors = getInsuranceTableErrors($tables); const errors = [...elementsErrors, ...paymentsErrors, ...insuranceErrors]; - if (errors.length === 0) return ; - return {errors}; }); diff --git a/Elements/message.js b/Elements/message.js new file mode 100644 index 0000000..16cca37 --- /dev/null +++ b/Elements/message.js @@ -0,0 +1,2 @@ +/* eslint-disable no-restricted-exports */ +export { message as default } from 'antd'; diff --git a/config/default-statuses.ts b/config/default-statuses.ts index e9c9e13..8a94c59 100644 --- a/config/default-statuses.ts +++ b/config/default-statuses.ts @@ -1,10 +1,10 @@ import type { CalculationStatuses } from 'stores/calculation/statuses/types'; const defaultStatuses: CalculationStatuses = { - selectIndAgent: 'Disabled', - selectCalcBroker: 'Disabled', - selectCalcFinDepartment: 'Disabled', - selectCalcDoubleAgent: 'Disabled', + selectIndAgent: 'Default', + selectCalcBroker: 'Default', + selectCalcFinDepartment: 'Default', + selectCalcDoubleAgent: 'Default', selectClientType: 'Disabled', tbxImporterRewardRub: 'Disabled', tbxImporterRewardPerc: 'Disabled', @@ -71,13 +71,13 @@ const defaultStatuses: CalculationStatuses = { selectDealerBrokerRewardCondition: 'Default', tbxDealerBrokerRewardSumm: 'Disabled', selectIndAgentRewardCondition: 'Default', - tbxIndAgentRewardSumm: 'Default', + tbxIndAgentRewardSumm: 'Disabled', selectCalcDoubleAgentRewardCondition: 'Default', - tbxCalcDoubleAgentRewardSumm: 'Default', + tbxCalcDoubleAgentRewardSumm: 'Disabled', selectCalcBrokerRewardCondition: 'Default', - tbxCalcBrokerRewardSum: 'Default', + tbxCalcBrokerRewardSum: 'Disabled', selectFinDepartmentRewardCondtion: 'Default', - tbxFinDepartmentRewardSumm: 'Default', + tbxFinDepartmentRewardSumm: 'Disabled', selectGPSBrand: 'Default', selectGPSModel: 'Default', selectRegionRegistration: 'Default', diff --git a/config/schema/values.ts b/config/schema/values.ts new file mode 100644 index 0000000..691d28c --- /dev/null +++ b/config/schema/values.ts @@ -0,0 +1,144 @@ +import { z } from 'zod'; + +const ValuesSchema = z.object({ + lead: z.string().nullable(), + opportunity: z.string().nullable(), + quote: z.string().nullable(), + recalcWithRevision: z.boolean(), + product: z.string().nullable(), + clientRisk: z.string().nullable(), + clientType: z.string().nullable(), + leaseObjectPrice: z.number(), + supplierCurrency: z.string().nullable(), + supplierDiscountRub: z.number(), + supplierDiscountPerc: z.number(), + leasingPeriod: z.number(), + firstPaymentPerc: z.number(), + firstPaymentRub: z.number(), + lastPaymentPerc: z.number(), + lastPaymentRub: z.number(), + lastPaymentRule: z.number().nullable(), + importProgram: z.string().nullable(), + importProgramSum: z.number(), + addEquipmentPrice: z.number(), + redemptionPaymentSum: z.number(), + balanceHolder: z.number().nullable(), + graphType: z.number().nullable(), + parmentsDecreasePercent: z.number(), + seasonType: z.number().nullable(), + highSeasonStart: z.number().nullable(), + comissionPerc: z.number(), + comissionRub: z.number(), + saleBonus: z.number(), + IRR_Perc: z.number(), + leaseObjectType: z.string().nullable(), + deliveryTime: z.number().nullable(), + leaseObjectCount: z.number(), + withTrailer: z.boolean(), + leaseObjectUsed: z.boolean(), + maxMass: z.number(), + countSeats: z.number(), + maxSpeed: z.number(), + brand: z.string().nullable(), + model: z.string().nullable(), + configuration: z.string().nullable(), + leaseObjectYear: z.number(), + engineType: z.number().nullable(), + leaseObjectCategory: z.number().nullable(), + leaseObjectMotorPower: z.number(), + engineVolume: z.number(), + leaseObjectUseFor: z.number().nullable(), + dealer: z.string().nullable(), + dealerPerson: z.string().nullable(), + dealerRewardCondition: z.string().nullable(), + dealerRewardSumm: z.number(), + dealerBroker: z.string().nullable(), + dealerBrokerRewardCondition: z.string().nullable(), + dealerBrokerRewardSumm: z.number(), + indAgent: z.string().nullable(), + indAgentRewardCondition: z.string().nullable(), + indAgentRewardSumm: z.number(), + calcDoubleAgent: z.string().nullable(), + calcDoubleAgentRewardCondition: z.string().nullable(), + calcDoubleAgentRewardSumm: z.number(), + calcBroker: z.string().nullable(), + calcBrokerRewardCondition: z.string().nullable(), + calcBrokerRewardSum: z.number(), + calcFinDepartment: z.string().nullable(), + finDepartmentRewardCondtion: z.string().nullable(), + finDepartmentRewardSumm: z.number(), + GPSBrand: z.string().nullable(), + GPSModel: z.string().nullable(), + regionRegistration: z.string().nullable(), + townRegistration: z.string().nullable(), + infuranceOPF: z.number().nullable(), + insKaskoType: z.number().nullable(), + insDecentral: z.boolean(), + insFranchise: z.number(), + insUnlimitDrivers: z.boolean(), + insAgeDrivers: z.number(), + insExpDrivers: z.number(), + INNForCalc: z.number(), + lastPaymentRedemption: z.boolean(), + priceWithDiscount: z.boolean(), + fullPriceWithDiscount: z.boolean(), + costIncrease: z.boolean(), + insurance: z.boolean(), + registrationQuote: z.boolean(), + technicalCardQuote: z.boolean(), + NSIB: z.boolean(), + quoteName: z.string().nullable(), + quoteContactGender: z.number().nullable(), + quoteRedemptionGraph: z.boolean(), + showFinGAP: z.boolean(), + tarif: z.string().nullable(), + creditRate: z.number(), + rate: z.string().nullable(), + requirementTelematic: z.number().nullable(), + minPriceChange: z.number(), + maxPriceChange: z.number(), + importerRewardPerc: z.number(), + importerRewardRub: z.number(), + disableChecks: z.boolean(), + registration: z.string().nullable(), + insNSIB: z.string().nullable(), + technicalCard: z.string().nullable(), + telematic: z.string().nullable(), + tracker: z.string().nullable(), + mileage: z.number(), + calcType: z.number().nullable(), + totalPayments: z.number(), + objectRegistration: z.number().nullable(), + objectRegionRegistration: z.string().nullable(), + vehicleTaxInYear: z.number(), + vehicleTaxInLeasingPeriod: z.number(), + objectCategoryTax: z.number().nullable(), + objectTypeTax: z.number().nullable(), + typePTS: z.number().nullable(), + legalClientRegion: z.string().nullable(), + legalClientTown: z.string().nullable(), + subsidy: z.string().nullable(), + fuelCard: z.string().nullable(), + leaseObjectPriceWthtVAT: z.number(), + VATInLeaseObjectPrice: z.number(), + engineHours: z.number(), + bonusCoefficient: z.number(), + + /** Link Values */ + kpUrl: z.string().nullable(), + leadUrl: z.string().nullable(), + opportunityUrl: z.string().nullable(), + quoteUrl: z.string().nullable(), + + /** Readonly Values */ + leaseObjectRiskName: z.string().nullable(), + insKaskoPriceLeasePeriod: z.number(), + irrInfo: z.string().nullable(), + registrationDescription: z.string().nullable(), + depreciationGroup: z.string().nullable(), + subsidySum: z.number(), + plPriceRub: z.number(), + discountRub: z.number(), +}); + +export default ValuesSchema; diff --git a/graphql/crm.types.ts b/graphql/crm.types.ts index 29c545b..fb48cda 100644 --- a/graphql/crm.types.ts +++ b/graphql/crm.types.ts @@ -122,70 +122,6 @@ export type GetCurrencySymbolQueryVariables = Exact<{ export type GetCurrencySymbolQuery = { __typename?: 'Query', transactioncurrency?: { __typename?: 'transactioncurrency', currencysymbol?: string | null } | null }; -export type GetAgentQueryVariables = Exact<{ - agentid: Scalars['Uuid']; -}>; - - -export type GetAgentQuery = { __typename?: 'Query', agent?: { __typename?: 'account', label?: string | null, value?: any | null } | null }; - -export type GetAgentAccountIdFromLeadQueryVariables = Exact<{ - leadid: Scalars['Uuid']; -}>; - - -export type GetAgentAccountIdFromLeadQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null }; - -export type GetDoubleAgentAccountIdQueryVariables = Exact<{ - leadid: Scalars['Uuid']; -}>; - - -export type GetDoubleAgentAccountIdQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null }; - -export type GetBrokerAccountIdQueryVariables = Exact<{ - leadid: Scalars['Uuid']; -}>; - - -export type GetBrokerAccountIdQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null }; - -export type GetFinDepartmentAccountIdQueryVariables = Exact<{ - leadid: Scalars['Uuid']; -}>; - - -export type GetFinDepartmentAccountIdQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null }; - -export type GetDealerPersonQueryVariables = Exact<{ - dealerId: Scalars['Uuid']; -}>; - - -export type GetDealerPersonQuery = { __typename?: 'Query', salon_providers?: Array<{ __typename?: 'account', label?: string | null, value?: any | null } | null> | null }; - -export type GetBrokerAccountIdFromDealerQueryVariables = Exact<{ - dealerId: Scalars['Uuid']; -}>; - - -export type GetBrokerAccountIdFromDealerQuery = { __typename?: 'Query', dealer?: { __typename?: 'account', evo_broker_accountid?: any | null } | null }; - -export type GetRewardConditionsQueryVariables = Exact<{ - agentid: Scalars['Uuid']; - currentDate?: InputMaybe; -}>; - - -export type GetRewardConditionsQuery = { __typename?: 'Query', evo_reward_conditions?: Array<{ __typename?: 'evo_reward_condition', evo_reward_summ?: any | null, label?: string | null, value?: any | null } | null> | null }; - -export type GetRewardSummQueryVariables = Exact<{ - conditionId: Scalars['Uuid']; -}>; - - -export type GetRewardSummQuery = { __typename?: 'Query', evo_reward_condition?: { __typename?: 'evo_reward_condition', evo_reward_summ?: any | null } | null }; - export type GetFinGapAddProductTypesQueryVariables = Exact<{ currentDate?: InputMaybe; }>; @@ -301,3 +237,102 @@ export type GetCurrencyIsoCodeQueryVariables = Exact<{ export type GetCurrencyIsoCodeQuery = { __typename?: 'Query', transactioncurrency?: { __typename?: 'transactioncurrency', isocurrencycode?: string | null } | null }; + +export type GetRewardRulesQueryVariables = Exact<{ + conditionId: Scalars['Uuid']; +}>; + + +export type GetRewardRulesQuery = { __typename?: 'Query', evo_reward_condition?: { __typename?: 'evo_reward_condition', evo_calc_reward_rules?: number | null } | null }; + +export type GetAgentsDataFromQuoteQueryVariables = Exact<{ + quoteId: Scalars['Uuid']; +}>; + + +export type GetAgentsDataFromQuoteQuery = { __typename?: 'Query', quote?: { __typename?: 'quote', evo_supplier_accountid?: any | null, evo_dealer_person_accountid?: any | null, evo_dealer_reward_conditionid?: any | null, evo_dealer_reward_total?: any | null, evo_dealer_reward_summ?: any | null, evo_dealer_broker_accountid?: any | null, evo_dealer_broker_reward_conditionid?: any | null, evo_dealer_broker_reward_total?: any | null, evo_dealer_broker_reward_summ?: any | null, evo_agent_accountid?: any | null, evo_agent_reward_conditionid?: any | null, evo_agent_reward_total?: any | null, evo_agent_reward_summ?: any | null, evo_double_agent_accountid?: any | null, evo_double_agent_reward_conditionid?: any | null, evo_double_agent_reward_total?: any | null, evo_double_agent_reward_summ?: any | null, evo_broker_accountid?: any | null, evo_broker_reward_conditionid?: any | null, evo_broker_reward_total?: any | null, evo_broker_reward_summ?: any | null, evo_fin_department_accountid?: any | null, evo_fin_department_reward_conditionid?: any | null, evo_fin_department_reward_total?: any | null, evo_fin_department_reward_summ?: any | null } | null }; + +export type GetRewardConditionsQueryVariables = Exact<{ + agentid: Scalars['Uuid']; + currentDate?: InputMaybe; +}>; + + +export type GetRewardConditionsQuery = { __typename?: 'Query', evo_reward_conditions?: Array<{ __typename?: 'evo_reward_condition', evo_reward_summ?: any | null, label?: string | null, value?: any | null } | null> | null }; + +export type GetRewardSummQueryVariables = Exact<{ + conditionId: Scalars['Uuid']; +}>; + + +export type GetRewardSummQuery = { __typename?: 'Query', evo_reward_condition?: { __typename?: 'evo_reward_condition', evo_reward_summ?: any | null } | null }; + +export type GetRewardConditionQueryVariables = Exact<{ + conditionId: Scalars['Uuid']; +}>; + + +export type GetRewardConditionQuery = { __typename?: 'Query', evo_reward_condition?: { __typename?: 'evo_reward_condition', evo_reward_summ?: any | null, evo_reduce_reward?: boolean | null, evo_min_reward_summ?: any | null } | null }; + +export type GetAgentAccountIdFromLeadQueryVariables = Exact<{ + leadid: Scalars['Uuid']; +}>; + + +export type GetAgentAccountIdFromLeadQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null }; + +export type GetDoubleAgentAccountIdQueryVariables = Exact<{ + leadid: Scalars['Uuid']; +}>; + + +export type GetDoubleAgentAccountIdQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null }; + +export type GetBrokerAccountIdQueryVariables = Exact<{ + leadid: Scalars['Uuid']; +}>; + + +export type GetBrokerAccountIdQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null }; + +export type GetFinDepartmentAccountIdQueryVariables = Exact<{ + leadid: Scalars['Uuid']; +}>; + + +export type GetFinDepartmentAccountIdQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null }; + +export type GetAgentQueryVariables = Exact<{ + agentid: Scalars['Uuid']; +}>; + + +export type GetAgentQuery = { __typename?: 'Query', agent?: { __typename?: 'account', label?: string | null, value?: any | null } | null }; + +export type GetRewardWithoutOtherAgentQueryVariables = Exact<{ + conditionId: Scalars['Uuid']; +}>; + + +export type GetRewardWithoutOtherAgentQuery = { __typename?: 'Query', evo_reward_condition?: { __typename?: 'evo_reward_condition', evo_agency_agreementidData?: { __typename?: 'evo_agency_agreement', evo_reward_without_other_agent?: boolean | null } | null } | null }; + +export type GetDealerReturnLeasingQueryVariables = Exact<{ + dealerId: Scalars['Uuid']; +}>; + + +export type GetDealerReturnLeasingQuery = { __typename?: 'Query', dealer?: { __typename?: 'account', evo_return_leasing_dealer?: boolean | null } | null }; + +export type GetDealerPersonQueryVariables = Exact<{ + dealerId: Scalars['Uuid']; +}>; + + +export type GetDealerPersonQuery = { __typename?: 'Query', salon_providers?: Array<{ __typename?: 'account', evo_inn?: string | null, evo_kpp?: string | null, label?: string | null, value?: any | null } | null> | null }; + +export type GetBrokerAccountIdFromDealerQueryVariables = Exact<{ + dealerId: Scalars['Uuid']; +}>; + + +export type GetBrokerAccountIdFromDealerQuery = { __typename?: 'Query', dealer?: { __typename?: 'account', evo_broker_accountid?: any | null } | null }; diff --git a/next.config.js b/next.config.js index af96319..45a8a9c 100644 --- a/next.config.js +++ b/next.config.js @@ -16,7 +16,6 @@ const nextConfig = { compiler: { styledComponents: true, }, - pageExtensions: ['tsx', 'jsx'], rewrites: process.env.NODE_ENV === 'development' && async function rewrites() { diff --git a/package.json b/package.json index 18e03df..ef2fd00 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,11 @@ "@ant-design/icons": "^4.7.0", "@apollo/client": "^3.7.0", "@fontsource/montserrat": "^4.5.12", - "@tanstack/react-query": "^4.13.0", + "@tanstack/react-query": "^4.14.1", + "@trpc/client": "^10.0.0-rc.3", + "@trpc/next": "^10.0.0-rc.3", + "@trpc/react-query": "^10.0.0-rc.3", + "@trpc/server": "^10.0.0-rc.3", "antd": "^4.21.3", "axios": "^1.1.3", "dayjs": "^1.11.2", @@ -40,7 +44,9 @@ "rebass": "^4.0.7", "sharp": "^0.30.4", "styled-components": "^5.3.5", - "use-debounce": "^8.0.1" + "superjson": "^1.11.0", + "use-debounce": "^8.0.1", + "zod": "^3.19.1" }, "devDependencies": { "@graphql-codegen/cli": "2.12.0", diff --git a/pages/_app.jsx b/pages/_app.jsx index 554cab5..6535411 100644 --- a/pages/_app.jsx +++ b/pages/_app.jsx @@ -9,6 +9,7 @@ import 'normalize.css'; import { useMemo } from 'react'; import StoreProvider from 'stores/Provider'; import { ThemeProvider } from 'styled-components'; +import { trpcClient } from 'trpc/client'; import { GlobalStyle } from 'UIKit/colors'; import theme from 'UIKit/theme'; import '../styles/fonts.css'; @@ -51,4 +52,4 @@ function App({ Component, pageProps }) { ); } -export default App; +export default trpcClient.withTRPC(App); diff --git a/pages/api/trpc/[trpc].ts b/pages/api/trpc/[trpc].ts new file mode 100644 index 0000000..47e091a --- /dev/null +++ b/pages/api/trpc/[trpc].ts @@ -0,0 +1,8 @@ +import * as trpcNext from '@trpc/server/adapters/next'; +import appRouter from 'trpc/routers'; + +export default trpcNext.createNextApiHandler({ + router: appRouter, + // eslint-disable-next-line object-curly-newline + createContext: () => ({}), +}); diff --git a/pages/index.jsx b/pages/index.jsx index fc5ad4a..7101151 100644 --- a/pages/index.jsx +++ b/pages/index.jsx @@ -11,6 +11,7 @@ import injectDefaultReactions from 'process/init/inject-reactions/default'; import { useEffect } from 'react'; import { useStore } from 'stores/hooks'; import styled from 'styled-components'; +import { trpcPureClient } from 'trpc/client'; import { Box } from 'UIKit/grid'; import { min } from 'UIKit/mq'; @@ -45,7 +46,7 @@ function Home() { useEffect(() => { getData(apolloClient, store); - injectDefaultReactions(store, apolloClient, queryClient); + injectDefaultReactions(store, apolloClient, queryClient, trpcPureClient); }, []); return ( diff --git a/process/agents/reactions/common.ts b/process/agents/reactions/common.ts deleted file mode 100644 index 5fbbc16..0000000 --- a/process/agents/reactions/common.ts +++ /dev/null @@ -1,292 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import type { ApolloClient } from '@apollo/client'; -import { gql } from '@apollo/client'; -import dayjs from 'dayjs'; -import utc from 'dayjs/plugin/utc'; -import type * as CRMTypes from 'graphql/crm.types'; -import { reaction } from 'mobx'; -import type RootStore from 'stores/root'; -import { normalizeOptions } from 'tools/entity'; -import * as fillAgentsFromLead from '../lib/fill-agents-from-lead'; -import { QUERY_GET_AGENT } from '../lib/query'; - -dayjs.extend(utc); - -export default function commonReactions(store: RootStore, apolloClient: ApolloClient) { - const { $calculation } = store; - - /** - * Заполняем агентов из Интереса - */ - reaction( - () => $calculation.getElementValue('selectLead'), - (leadid) => { - fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid); - fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid); - fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid); - fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid); - } - ); - - /** - * Заполняем selectDealerPerson - * На изменение Салон приобретения формируем список в поле ЮЛ поставщика - записи Контрагент, - * у которых статус = активный И Поставщик = Да И Тип поставщика = Юридическое лицо - * И связаны с карточкой Контрагент из поля "Салон приобретения" по связи Салон-ЮЛ - */ - - const QUERY_GET_DEALER_PERSON = gql` - query GetDealerPerson($dealerId: Uuid!) { - salon_providers(statecode: 0, salonaccountid: $dealerId) { - label: name - value: accountid - } - } - `; - - reaction( - () => $calculation.getElementValue('selectDealer'), - async (dealerId) => { - if (!dealerId) { - $calculation.resetElement('selectDealerPerson'); - $calculation.resetElement('selectDealerBroker'); - - return; - } - - const { - data: { salon_providers }, - } = await apolloClient.query< - CRMTypes.GetDealerPersonQuery, - CRMTypes.GetDealerPersonQueryVariables - >({ - query: QUERY_GET_DEALER_PERSON, - variables: { - dealerId, - }, - }); - - if (salon_providers?.length) { - $calculation.setElementOptions('selectDealerPerson', normalizeOptions(salon_providers)); - $calculation.setElementValue('selectDealerPerson', salon_providers[0]?.value); - } - } - ); - - /** - * Заполняем selectDealerBroker - */ - - const QUERY_GET_BROKER_ACCOUNTID_FROM_DEALER = gql` - query GetBrokerAccountIdFromDealer($dealerId: Uuid!) { - dealer: account(accountid: $dealerId) { - evo_broker_accountid - } - } - `; - - reaction( - () => $calculation.getElementValue('selectDealerPerson'), - async (dealerPersonId) => { - if (!dealerPersonId) { - return; - } - - const { - data: { dealer }, - } = await apolloClient.query< - CRMTypes.GetBrokerAccountIdFromDealerQuery, - CRMTypes.GetBrokerAccountIdFromDealerQueryVariables - >({ - query: QUERY_GET_BROKER_ACCOUNTID_FROM_DEALER, - variables: { - dealerId: dealerPersonId, - }, - }); - - if (dealer?.evo_broker_accountid) { - const { - data: { agent: dealerBroker }, - } = await apolloClient.query({ - query: QUERY_GET_AGENT, - variables: { - agentid: dealer?.evo_broker_accountid, - }, - }); - - if (dealerBroker) { - $calculation.setElementOptions('selectDealerBroker', normalizeOptions([dealerBroker])); - $calculation.setElementValue('selectDealerBroker', dealerBroker.value); - } - } else { - $calculation.resetElement('selectDealerBroker'); - } - } - ); - - /** - * Заполняем selectDealerRewardCondition - */ - - const QUERY_GET_REWARD_CONDITIONS = gql` - query GetRewardConditions($agentid: Uuid!, $currentDate: DateTime) { - evo_reward_conditions( - evo_agent_accountid: $agentid - evo_datefrom_param: { lte: $currentDate } - evo_dateto_param: { gte: $currentDate } - statecode: 0 - evo_agency_agreementid_param: { has: true } - ) { - label: evo_name - value: evo_reward_conditionid - evo_reward_summ - } - } - `; - - reaction( - () => $calculation.getElementValue('selectDealerPerson'), - async (dealerPersonId) => { - if (!dealerPersonId) { - $calculation.resetElement('selectDealerRewardCondition'); - - return; - } - const { - data: { evo_reward_conditions }, - } = await apolloClient.query< - CRMTypes.GetRewardConditionsQuery, - CRMTypes.GetRewardConditionsQueryVariables - >({ - query: QUERY_GET_REWARD_CONDITIONS, - variables: { - agentid: dealerPersonId, - currentDate: dayjs().toISOString(), - }, - }); - - if (evo_reward_conditions?.length) { - $calculation.setElementOptions( - 'selectDealerRewardCondition', - normalizeOptions(evo_reward_conditions) - ); - } - } - ); - - const QUERY_GET_REWARD_SUMM = gql` - query GetRewardSumm($conditionId: Uuid!) { - evo_reward_condition(evo_reward_conditionid: $conditionId) { - evo_reward_summ - } - } - `; - - reaction( - () => $calculation.getElementValue('selectDealerRewardCondition'), - async (rewardConditionId) => { - if (!rewardConditionId) { - $calculation.resetElement('tbxDealerRewardSumm'); - - return; - } - - const { - data: { evo_reward_condition }, - } = await apolloClient.query< - CRMTypes.GetRewardSummQuery, - CRMTypes.GetRewardSummQueryVariables - >({ - query: QUERY_GET_REWARD_SUMM, - variables: { - conditionId: rewardConditionId, - }, - }); - - $calculation.setElementValue('tbxDealerRewardSumm', evo_reward_condition?.evo_reward_summ); - $calculation.unblockElement('tbxDealerRewardSumm'); - } - ); - - /** - * Заполняем selectDealerBrokerRewardCondition - */ - - reaction( - () => $calculation.getElementValue('selectDealerBroker'), - async (dealerBrokerId) => { - if (!dealerBrokerId) { - $calculation.resetElement('selectDealerBrokerRewardCondition'); - - return; - } - const { - data: { evo_reward_conditions }, - } = await apolloClient.query< - CRMTypes.GetRewardConditionsQuery, - CRMTypes.GetRewardConditionsQueryVariables - >({ - query: QUERY_GET_REWARD_CONDITIONS, - variables: { - agentid: dealerBrokerId, - currentDate: dayjs().toISOString(), - }, - }); - - if (evo_reward_conditions?.length) { - $calculation.setElementOptions( - 'selectDealerBrokerRewardCondition', - normalizeOptions(evo_reward_conditions) - ); - } - } - ); - - reaction( - () => $calculation.getElementValue('selectDealerBrokerRewardCondition'), - async (rewardConditionId) => { - if (!rewardConditionId) { - $calculation.resetElement('tbxDealerBrokerRewardSumm'); - - return; - } - - const { - data: { evo_reward_condition }, - } = await apolloClient.query< - CRMTypes.GetRewardSummQuery, - CRMTypes.GetRewardSummQueryVariables - >({ - query: QUERY_GET_REWARD_SUMM, - variables: { - conditionId: rewardConditionId, - }, - }); - - $calculation.setElementValue( - 'tbxDealerBrokerRewardSumm', - evo_reward_condition?.evo_reward_summ - ); - - $calculation.unblockElement('tbxDealerBrokerRewardSumm'); - } - ); - - reaction( - () => $calculation.getElementValue('selectDealerRewardCondition'), - (dealerRewardConditionId) => { - if (dealerRewardConditionId) { - $calculation.resetElementValue('selectDealerBroker'); - } - } - ); - - reaction( - () => $calculation.getElementValue('selectDealerBrokerRewardCondition'), - (dealerBrokerRewardConditionId) => { - if (dealerBrokerRewardConditionId) { - $calculation.resetElementValue('selectDealerPerson'); - } - } - ); -} diff --git a/process/agents/reactions/index.js b/process/agents/reactions/index.js deleted file mode 100644 index 1e2e8e6..0000000 --- a/process/agents/reactions/index.js +++ /dev/null @@ -1,2 +0,0 @@ -/* eslint-disable import/prefer-default-export */ -export { default as common } from './common'; diff --git a/process/calculate/reactions/validation.ts b/process/calculate/reactions/validation.ts index e6ed9f7..76c55f3 100644 --- a/process/calculate/reactions/validation.ts +++ b/process/calculate/reactions/validation.ts @@ -6,7 +6,9 @@ export default function validationReactions(store: RootStore, apolloClient: Apol const { $calculation, $tables } = store; reaction( () => { - const hasElementsErrors = $calculation.$validation.hasErrors; + 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; @@ -15,11 +17,11 @@ export default function validationReactions(store: RootStore, apolloClient: Apol }, (hasErrors) => { if (hasErrors) { - $calculation.blockElement('btnCalculate'); - $calculation.blockElement('btnCreateKP'); + $calculation.$status.setStatus('btnCalculate', 'Disabled'); + $calculation.$status.setStatus('btnCreateKP', 'Disabled'); } else { - $calculation.unblockElement('btnCalculate'); - $calculation.unblockElement('btnCreateKP'); + $calculation.$status.setStatus('btnCalculate', 'Default'); + $calculation.$status.setStatus('btnCreateKP', 'Default'); } }, { diff --git a/process/fingap/reactions/common.ts b/process/fingap/reactions/common.ts index d63e2d6..dffc3b1 100644 --- a/process/fingap/reactions/common.ts +++ b/process/fingap/reactions/common.ts @@ -53,7 +53,7 @@ export default function commonReactions( reaction( () => { const finGAPInsuranceCompany = $tables.insurance.getRowValue('fingap', 'insuranceCompany'); - const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); + const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); return { finGAPInsuranceCompany, @@ -127,8 +127,8 @@ export default function commonReactions( const paymentsValues = toJS($tables.payments.values); const plPriceRub = $calculation.$values.getValue('plPriceRub'); const discountRub = $calculation.$values.getValue('discountRub'); - const firstPaymentRub = $calculation.getElementValue('tbxFirstPaymentRub'); - const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); + const firstPaymentRub = $calculation.element('tbxFirstPaymentRub').getValue(); + const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); return { finGAPInsuranceCompany, @@ -147,8 +147,7 @@ export default function commonReactions( firstPaymentRub, leasingPeriod, }) => { - if ($tables.fingap.validation.hasErrors) return; - if (!finGAPInsuranceCompany) return; + if (!finGAPInsuranceCompany || $tables.payments.validation.hasErrors) return; const { data: { evo_addproduct_types }, diff --git a/process/fingap/reactions/validation.ts b/process/fingap/reactions/validation.ts index 1a2778d..6060397 100644 --- a/process/fingap/reactions/validation.ts +++ b/process/fingap/reactions/validation.ts @@ -10,9 +10,6 @@ export default function validationReactions( ) { const { $tables } = store; - const errorText = 'Неверно заполнены платежи'; - let removeError: () => void; - reaction( () => { const hasPaymentsErrors = $tables.payments.validation.hasErrors; @@ -24,9 +21,10 @@ export default function validationReactions( }; }, ({ hasPaymentsErrors, finGAPInsuranceCompany }) => { - if (finGAPInsuranceCompany && hasPaymentsErrors) { - removeError = $tables.fingap.validation.addError(errorText); - } else if (removeError) removeError(); + $tables.fingap.validate({ + invalid: finGAPInsuranceCompany !== null && hasPaymentsErrors, + message: 'Неверно заполнены платежи', + }); }, { fireImmediately: true, diff --git a/process/init/get-data/index.js b/process/init/get-data/index.js index a967552..ec6fcfd 100644 --- a/process/init/get-data/index.js +++ b/process/init/get-data/index.js @@ -10,7 +10,7 @@ export default function getData(apolloClient, store) { function setManyOptions(options) { Object.keys(options).forEach((elementName) => { const elementOptions = options[elementName]; - $calculation.$options.setOptions(elementName, elementOptions); + $calculation.element(elementName).setOptions(elementOptions); }); } diff --git a/process/init/inject-reactions/default.js b/process/init/inject-reactions/default.js index 40b4245..5de44a9 100644 --- a/process/init/inject-reactions/default.js +++ b/process/init/inject-reactions/default.js @@ -1,19 +1,28 @@ -import * as agentsReactions from '../../agents/reactions'; +import loadKpReactions from 'process/load-kp/reactions'; import * as calculateReactions from '../../calculate/reactions'; import * as fingapReactions from '../../fingap/reactions'; import * as leadOpportunityReactions from '../../lead-opportunity/reactions'; import paymentsReactions from '../../payments/reactions'; import * as priceReactions from '../../price/reactions'; +import * as agentsReactions from '../../supplier-agent/reactions/agents'; +import leasebackReactions from '../../supplier-agent/reactions/leaseback'; +import * as supplierReactions from '../../supplier-agent/reactions/supplier'; import setInitialValuesReactions from '../set-values/reactions'; -export default function injectDefaultReactions(store, apolloClient, queryClient) { +export default function injectDefaultReactions(store, apolloClient, queryClient, trpcClient) { leadOpportunityReactions.common(store, apolloClient, queryClient); leadOpportunityReactions.urls(store, apolloClient, queryClient); paymentsReactions(store, apolloClient, queryClient); calculateReactions.validation(store, apolloClient, queryClient); - agentsReactions.common(store, apolloClient, queryClient); + supplierReactions.commonReactions(store, apolloClient, queryClient); + supplierReactions.validationReactions(store, apolloClient, queryClient); + agentsReactions.fillReactions(store, apolloClient, queryClient); + agentsReactions.commonReactions(store, apolloClient, queryClient); + agentsReactions.validationReactions(store, apolloClient, queryClient); + leasebackReactions(store, apolloClient, queryClient); priceReactions.computed(store, apolloClient, queryClient); fingapReactions.common(store, apolloClient, queryClient); fingapReactions.validation(store, apolloClient, queryClient); setInitialValuesReactions(store, apolloClient, queryClient); + loadKpReactions(store, apolloClient, queryClient, trpcClient); } diff --git a/process/init/set-values/reactions.ts b/process/init/set-values/reactions.ts index 83d04de..11c25c7 100644 --- a/process/init/set-values/reactions.ts +++ b/process/init/set-values/reactions.ts @@ -35,10 +35,9 @@ export default function setInitialValuesReactions( (x) => x?.isocurrencycode === 'RUB' ); - $calculation.setElementValue( - 'selectSupplierCurrency', - transactioncurrency_rub?.transactioncurrencyid - ); + $calculation + .element('selectSupplierCurrency') + .setValue(transactioncurrency_rub?.transactioncurrencyid); } ); } diff --git a/process/lead-opportunity/reactions/common.ts b/process/lead-opportunity/reactions/common.ts index 55b8d43..ab8df2d 100644 --- a/process/lead-opportunity/reactions/common.ts +++ b/process/lead-opportunity/reactions/common.ts @@ -1,12 +1,14 @@ +/* eslint-disable implicit-arrow-linebreak */ import type { ApolloClient } from '@apollo/client'; import { gql } from '@apollo/client'; import type * as CRMTypes from 'graphql/crm.types'; import { reaction } from 'mobx'; import type RootStore from 'stores/root'; import { normalizeOptions } from 'tools/entity'; +import { makeDisposable } from 'tools/mobx'; export default function commonReactions(store: RootStore, apolloClient: ApolloClient) { - const { $calculation } = store; + const { $calculation, $process } = store; /** * Если lead содержит данные, то в opportunity подгружается значение из поля Интереса @@ -26,33 +28,37 @@ export default function commonReactions(store: RootStore, apolloClient: ApolloCl } `; - reaction( - () => $calculation.getElementValue('selectLead'), - async (leadid) => { - if (!leadid) { - $calculation.resetElementValue('selectOpportunity'); + makeDisposable( + () => + reaction( + () => $calculation.element('selectLead').getValue(), + async (leadid) => { + if (!leadid) { + $calculation.element('selectOpportunity').resetValue(); - return; - } + return; + } - const { - data: { lead }, - } = await apolloClient.query< - CRMTypes.GetOpportunityByLeadQuery, - CRMTypes.GetOpportunityByLeadQueryVariables - >({ - query: QUERY_GET_OPPORTUNITY_BY_LEAD, - variables: { - leadid, - }, - }); + const { + data: { lead }, + } = await apolloClient.query< + CRMTypes.GetOpportunityByLeadQuery, + CRMTypes.GetOpportunityByLeadQueryVariables + >({ + query: QUERY_GET_OPPORTUNITY_BY_LEAD, + variables: { + leadid, + }, + }); - if (lead?.evo_opportunityidData?.value) { - $calculation.setElementValue('selectOpportunity', lead?.evo_opportunityidData?.value); - } else { - $calculation.resetElementValue('selectOpportunity'); - } - } + if (lead?.evo_opportunityidData?.value) { + $calculation.element('selectOpportunity').setValue(lead?.evo_opportunityidData?.value); + } else { + $calculation.element('selectOpportunity').resetValue(); + } + } + ), + () => $process.has('LoadKP') ); /** @@ -70,9 +76,9 @@ export default function commonReactions(store: RootStore, apolloClient: ApolloCl `; reaction( - () => $calculation.getElementValue('selectOpportunity'), + () => $calculation.element('selectOpportunity').getValue(), async (opportunityid) => { - const leadid = $calculation.getElementValue('selectLead'); + const leadid = $calculation.element('selectLead').getValue(); if (leadid) { const { @@ -88,7 +94,7 @@ export default function commonReactions(store: RootStore, apolloClient: ApolloCl }); if (!opportunityid && lead?.evo_opportunityidData?.value) { - $calculation.resetElementValue('selectLead'); + $calculation.element('selectLead').resetValue(); } } @@ -103,7 +109,7 @@ export default function commonReactions(store: RootStore, apolloClient: ApolloCl }, }); - $calculation.setElementValue('selectLead', data.opportunity?.evo_leadid); + $calculation.element('selectLead').setValue(data.opportunity?.evo_leadid); } } ); @@ -125,7 +131,7 @@ export default function commonReactions(store: RootStore, apolloClient: ApolloCl `; reaction( - () => $calculation.getElementValue('selectLead'), + () => $calculation.element('selectLead').getValue(), async (leadid) => { if (leadid) { const { @@ -140,9 +146,9 @@ export default function commonReactions(store: RootStore, apolloClient: ApolloCl }, }); - $calculation.setElementOptions('selectQuote', normalizeOptions(quotes)); + $calculation.element('selectQuote').setOptions(normalizeOptions(quotes)); } else { - $calculation.resetElement('selectQuote'); + $calculation.element('selectQuote').reset(); } } ); diff --git a/process/lead-opportunity/reactions/urls.ts b/process/lead-opportunity/reactions/urls.ts index cef94c6..477f719 100644 --- a/process/lead-opportunity/reactions/urls.ts +++ b/process/lead-opportunity/reactions/urls.ts @@ -12,10 +12,10 @@ export default function urlsReactions(store: RootStore, apolloClient: ApolloClie */ function makeLinkReaction(elementName: Elements, linkElementName: Elements, query: DocumentNode) { reaction( - () => $calculation.getElementValue(elementName), + () => $calculation.element(elementName).getValue(), (id) => { if (!id) { - $calculation.resetElementValue(linkElementName); + $calculation.element(linkElementName).resetValue(); return; } @@ -34,22 +34,22 @@ export default function urlsReactions(store: RootStore, apolloClient: ApolloClie .then(({ data }) => { clearTimeout(timeoutId); if (data.entity?.link) { - $calculation.setElementValue(linkElementName, data.entity?.link); + $calculation.element(linkElementName).setValue(data.entity?.link); } }) .catch(() => { clearTimeout(timeoutId); - $calculation.resetElementValue(linkElementName); + $calculation.element(linkElementName).resetValue(); }); } ); reaction( - () => $calculation.getElementValue(linkElementName), + () => $calculation.element(linkElementName).getValue(), (url) => { if (!url) { - $calculation.blockElement(linkElementName); + $calculation.element(linkElementName).block(); } else { - $calculation.unblockElement(linkElementName); + $calculation.element(linkElementName).unblock(); } } ); diff --git a/process/load-kp/reactions.ts b/process/load-kp/reactions.ts new file mode 100644 index 0000000..2f64454 --- /dev/null +++ b/process/load-kp/reactions.ts @@ -0,0 +1,51 @@ +import type { ApolloClient } from '@apollo/client'; +import type { QueryClient } from '@tanstack/react-query'; +import message from 'Elements/message'; +import { reaction, toJS } from 'mobx'; +import type RootStore from 'stores/root'; +import type { TRPCPureClient } from 'trpc/types'; + +export default function loadKpReactions( + store: RootStore, + apolloClient: ApolloClient, + queryClient: QueryClient, + trpcClient: TRPCPureClient +) { + const { $calculation, $process } = store; + + reaction( + () => $calculation.element('selectQuote').getValue(), + (quoteId) => { + if (!quoteId) return; + + $process.add('LoadKP'); + + const quoteName = $calculation.element('selectQuote').getOption()?.label; + const { quote } = toJS($calculation.$values.values); + + trpcClient.quote.getValues + .query({ + values: { + quote, + }, + }) + .then(({ values }) => { + $calculation.$values.setValues({ + values, + exclude: ['lead', 'opportunity', 'quote', 'leadUrl', 'opportunityUrl', 'quoteUrl'], + }); + message.success({ + content: `КП ${quoteName} загружено`, + }); + }) + .catch(() => { + message.error({ + content: `Ошибка во время загрузки КП ${quoteName}`, + }); + }) + .finally(() => { + $process.delete('LoadKP'); + }); + } + ); +} diff --git a/process/payments/reactions.ts b/process/payments/reactions.ts index 4bf4937..e5dca45 100644 --- a/process/payments/reactions.ts +++ b/process/payments/reactions.ts @@ -8,7 +8,9 @@ import { shift } from 'radash'; import type { CalculationOptions } from 'stores/calculation/options/types'; import type RootStore from 'stores/root'; import type { Row } from 'stores/tables/payments/types'; +import ValidationHelper from 'stores/validation/helper'; import { difference } from 'tools/array'; +import { makeDisposable } from 'tools/mobx'; import * as seasonsConstants from './lib/seasons-constants'; import * as seasonsTools from './lib/seasons-tools'; import validatePaymentsTable from './validation'; @@ -18,17 +20,17 @@ export default function paymentsReactions( apolloClient: ApolloClient, queryClient: QueryClient ) { - const { $calculation, $tables } = store; + const { $calculation, $tables, $process } = store; reaction( - () => $calculation.getElementValue('tbxFirstPaymentPerc'), + () => $calculation.element('tbxFirstPaymentPerc').getValue(), (firstPaymentPerc) => { $tables.payments.setValue(0, firstPaymentPerc); } ); reaction( - () => $calculation.getElementValue('tbxLastPaymentPerc'), + () => $calculation.element('tbxLastPaymentPerc').getValue(), (lastPaymentPerc) => { const paymentsLength = $tables.payments.values.length; $tables.payments.setValue(paymentsLength - 1, lastPaymentPerc); @@ -38,155 +40,169 @@ export default function paymentsReactions( /** * Аннуитет */ - reaction( - () => { - const graphType = $calculation.getElementValue('radioGraphType'); - const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); + makeDisposable( + () => + reaction( + () => { + const graphType = $calculation.element('radioGraphType').getValue(); + const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); - return { - graphType, - leasingPeriod, - }; - }, - ({ graphType, leasingPeriod }) => { - if (graphType === 100_000_000) { - const middlePayments: Row[] = Array.from( - { - length: leasingPeriod - 2, - }, - () => ({ - value: 100, - status: 'Disabled', - }) - ); + return { + graphType, + leasingPeriod, + }; + }, + ({ graphType, leasingPeriod }) => { + if (graphType === 100_000_000) { + const middlePayments: Row[] = Array.from( + { + length: leasingPeriod - 2, + }, + () => ({ + value: 100, + status: 'Disabled', + }) + ); - const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc'); - const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc'); + const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue(); + const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue(); - $tables.payments.setRows([ - { - value: firstPaymentPerc, - status: 'Disabled', - }, - ...middlePayments, - { - value: lastPaymentPerc, - status: 'Disabled', - }, - ]); - } - }, - { - fireImmediately: true, - } + $tables.payments.setRows([ + { + value: firstPaymentPerc, + status: 'Disabled', + }, + ...middlePayments, + { + value: lastPaymentPerc, + status: 'Disabled', + }, + ]); + } + }, + { + fireImmediately: true, + } + ), + () => $process.has('LoadKP') ); /** * Равноубывающий */ - reaction( - () => { - const graphType = $calculation.getElementValue('radioGraphType'); - const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); - const parmentsDecreasePercent = $calculation.getElementValue('tbxParmentsDecreasePercent'); + makeDisposable( + () => + reaction( + () => { + const graphType = $calculation.element('radioGraphType').getValue(); + const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); + const parmentsDecreasePercent = $calculation + .element('tbxParmentsDecreasePercent') + .getValue(); - return { - graphType, - leasingPeriod, - parmentsDecreasePercent, - }; - }, - ({ graphType, leasingPeriod, parmentsDecreasePercent }) => { - if (graphType === 100_000_002) { - const middlePayments: Row[] = Array.from( - { - length: leasingPeriod - 2, - }, - (_, k) => { - const payment = 100 * (parmentsDecreasePercent / 100) ** k; + return { + graphType, + leasingPeriod, + parmentsDecreasePercent, + }; + }, + ({ graphType, leasingPeriod, parmentsDecreasePercent }) => { + if (graphType === 100_000_002) { + const middlePayments: Row[] = Array.from( + { + length: leasingPeriod - 2, + }, + (_, k) => { + const payment = 100 * (parmentsDecreasePercent / 100) ** k; - return { - value: Number(payment.toFixed(2)), - status: 'Disabled', - }; + return { + value: Number(payment.toFixed(2)), + status: 'Disabled', + }; + } + ); + + const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue(); + const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue(); + + $tables.payments.setRows([ + { + value: firstPaymentPerc, + status: 'Disabled', + }, + ...middlePayments, + { + value: lastPaymentPerc, + status: 'Disabled', + }, + ]); } - ); - - const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc'); - const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc'); - - $tables.payments.setRows([ - { - value: firstPaymentPerc, - status: 'Disabled', - }, - ...middlePayments, - { - value: lastPaymentPerc, - status: 'Disabled', - }, - ]); - } - } + } + ), + () => $process.has('LoadKP') ); /** * Легкий старт */ - reaction( - () => { - const graphType = $calculation.getElementValue('radioGraphType'); - const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); + makeDisposable( + () => + reaction( + () => { + const graphType = $calculation.element('radioGraphType').getValue(); + const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); - return { - graphType, - leasingPeriod, - }; - }, - ({ graphType, leasingPeriod }) => { - if (graphType === 100_000_004) { - const editablePayments: Row[] = [ - { - value: 25, - status: 'Default', - }, - { - value: 50, - status: 'Default', - }, - { - value: 75, - status: 'Default', - }, - ]; + return { + graphType, + leasingPeriod, + }; + }, + ({ graphType, leasingPeriod }) => { + if (graphType === 100_000_004) { + const editablePayments: Row[] = [ + { + value: 25, + status: 'Default', + }, + { + value: 50, + status: 'Default', + }, + { + value: 75, + status: 'Default', + }, + ]; - const payments: Row[] = Array.from( - { - length: leasingPeriod - 5, - }, - () => ({ - value: 100, - status: 'Disabled', - }) - ); + const payments: Row[] = Array.from( + { + length: leasingPeriod - 5, + }, + () => ({ + value: 100, + status: 'Disabled', + }) + ); - const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc'); - const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc'); + const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue(); + const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue(); - $tables.payments.setRows([ - { - value: firstPaymentPerc, - status: 'Disabled', - }, - ...editablePayments, - ...payments, - { - value: lastPaymentPerc, - status: 'Disabled', - }, - ]); - } - } + $tables.payments.setRows([ + { + value: firstPaymentPerc, + status: 'Disabled', + }, + ...editablePayments, + ...payments, + { + value: lastPaymentPerc, + status: 'Disabled', + }, + ]); + } + } + ), + () => $process.has('LoadKP') ); /** @@ -200,7 +216,7 @@ export default function paymentsReactions( reaction( () => { - const graphType = $calculation.getElementValue('radioGraphType'); + const graphType = $calculation.element('radioGraphType').getValue(); return graphType; }, @@ -216,7 +232,7 @@ export default function paymentsReactions( seasonSeasonTypes.has(option.value) ); } - $calculation.setElementOptions('selectSeasonType', selectSeasonTypeOptions); + $calculation.element('selectSeasonType').setOptions(selectSeasonTypeOptions); } ); @@ -227,133 +243,141 @@ export default function paymentsReactions( 100_000_006: [100, 7, 3], }; - reaction( - () => { - const degressionType = $calculation.getElementValue('selectSeasonType'); - const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); - const graphType = $calculation.getElementValue('radioGraphType'); + makeDisposable( + () => + reaction( + () => { + const degressionType = $calculation.element('selectSeasonType').getValue(); + const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); + const graphType = $calculation.element('radioGraphType').getValue(); - return { - degressionType, - leasingPeriod, - graphType, - }; - }, - ({ degressionType, leasingPeriod, graphType }) => { - if (graphType === 100_000_001) { - let payments: Row[] = []; + return { + degressionType, + leasingPeriod, + graphType, + }; + }, + ({ degressionType, leasingPeriod, graphType }) => { + if (graphType === 100_000_001) { + let payments: Row[] = []; - switch (degressionType) { - case 100_000_007: { - const editablePayments: Row[] = Array.from( + switch (degressionType) { + case 100_000_007: { + const editablePayments: Row[] = Array.from( + { + length: leasingPeriod - 3, + }, + () => ({ + value: 100, + status: 'Default', + }) + ); + + payments = [ + { + value: 100, + status: 'Disabled', + }, + ...editablePayments, + ]; + + break; + } + case 100_000_003: + case 100_000_004: + case 100_000_005: + case 100_000_006: { + const [step1, step2, step3] = degressionSteps[degressionType]; + const paymentsInStep = Math.ceil((leasingPeriod - 2) / 3); + + payments = Array.from( + { + length: leasingPeriod - 2, + }, + (_v, i) => { + let value = step3; + + if (i <= paymentsInStep * 2 - 1) { + value = step2; + } + + if (i <= paymentsInStep - 1) { + value = step1; + } + + return { + value, + status: 'Disabled', + }; + } + ); + break; + } + default: { + break; + } + } + + const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue(); + const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue(); + + $tables.payments.setRows([ { - length: leasingPeriod - 3, - }, - () => ({ - value: 100, - status: 'Default', - }) - ); - - payments = [ - { - value: 100, + value: firstPaymentPerc, status: 'Disabled', }, - ...editablePayments, - ]; - - break; - } - case 100_000_003: - case 100_000_004: - case 100_000_005: - case 100_000_006: { - const [step1, step2, step3] = degressionSteps[degressionType]; - const paymentsInStep = Math.ceil((leasingPeriod - 2) / 3); - - payments = Array.from( + ...payments, { - length: leasingPeriod - 2, + value: lastPaymentPerc, + status: 'Disabled', }, - (_v, i) => { - let value = step3; - - if (i <= paymentsInStep * 2 - 1) { - value = step2; - } - - if (i <= paymentsInStep - 1) { - value = step1; - } - - return { - value, - status: 'Disabled', - }; - } - ); - break; - } - default: { - break; + ]); } } - - const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc'); - const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc'); - - $tables.payments.setRows([ - { - value: firstPaymentPerc, - status: 'Disabled', - }, - ...payments, - { - value: lastPaymentPerc, - status: 'Disabled', - }, - ]); - } - } + ), + () => $process.has('LoadKP') ); - reaction( - () => { - const graphType = $calculation.getElementValue('radioGraphType'); - const payments = toJS($tables.payments.values); - const degressionType = $calculation.getElementValue('selectSeasonType'); + makeDisposable( + () => + reaction( + () => { + const graphType = $calculation.element('radioGraphType').getValue(); + const payments = toJS($tables.payments.values); + const degressionType = $calculation.element('selectSeasonType').getValue(); - return { - graphType, - payments, - degressionType, - }; - }, - (nextParams, prevParams) => { - if (nextParams.graphType === 100_000_001 && nextParams.degressionType === 100_000_007) { - const changes = difference(nextParams.payments, prevParams.payments); + return { + graphType, + payments, + degressionType, + }; + }, + (nextParams, prevParams) => { + if (nextParams.graphType === 100_000_001 && nextParams.degressionType === 100_000_007) { + const changes = difference(nextParams.payments, prevParams.payments); - if (changes === null || changes.length > 1) return; + if (changes === null || changes.length > 1) return; - const [changeIndex] = changes; - const value = nextParams.payments[changeIndex]; - const payments = nextParams.payments.slice(1, -1).map((payment, i) => { - if (i <= changeIndex - 2) return payment; + const [changeIndex] = changes; + const value = nextParams.payments[changeIndex]; + const payments = nextParams.payments.slice(1, -1).map((payment, i) => { + if (i <= changeIndex - 2) return payment; - return value; - }); + return value; + }); - const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc'); - const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc'); + const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue(); + const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue(); - $tables.payments.setValues([firstPaymentPerc, ...payments, lastPaymentPerc]); - } - }, - { - delay: 50, - equals: comparer.structural, - } + $tables.payments.setValues([firstPaymentPerc, ...payments, lastPaymentPerc]); + } + }, + { + delay: 50, + equals: comparer.structural, + } + ), + () => $process.has('LoadKP') ); /** @@ -362,7 +386,7 @@ export default function paymentsReactions( reaction( () => { - const graphType = $calculation.getElementValue('radioGraphType'); + const graphType = $calculation.element('radioGraphType').getValue(); return { graphType, @@ -371,8 +395,8 @@ export default function paymentsReactions( ({ graphType }) => { if (graphType !== 100_000_003) return; - const seasonType = $calculation.getElementValue('selectSeasonType'); - const highSeasonStart = $calculation.getElementValue('selectHighSeasonStart'); + const seasonType = $calculation.element('selectSeasonType').getValue(); + const highSeasonStart = $calculation.element('selectHighSeasonStart').getValue(); if (!seasonType || !highSeasonStart) { $tables.payments.setValues([]); @@ -382,16 +406,16 @@ export default function paymentsReactions( reaction( () => { - const seasonType = $calculation.getElementValue('selectSeasonType'); + const seasonType = $calculation.element('selectSeasonType').getValue(); return seasonType; }, (seasonType) => { - const graphType = $calculation.getElementValue('radioGraphType'); + const graphType = $calculation.element('radioGraphType').getValue(); if (graphType !== 100_000_003) return; if (!seasonType) { - $calculation.resetElement('selectHighSeasonStart'); + $calculation.element('selectHighSeasonStart').reset(); return; } @@ -400,7 +424,7 @@ export default function paymentsReactions( (option) => !seasonsConstants.FORBIDDEN_HIGH_SEASON_START[seasonType].includes(option.label) ); - $calculation.setElementOptions('selectHighSeasonStart', highSeasonStartOptions); + $calculation.element('selectHighSeasonStart').setOptions(highSeasonStartOptions); } ); @@ -418,123 +442,131 @@ export default function paymentsReactions( return rows; } - reaction( - () => { - const seasonType = $calculation.getElementValue('selectSeasonType'); - const highSeasonStartOption = $calculation.getElementOption('selectHighSeasonStart'); - const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); + makeDisposable( + () => + reaction( + () => { + const seasonType = $calculation.element('selectSeasonType').getValue(); + const highSeasonStartOption = $calculation.element('selectHighSeasonStart').getOption(); + const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); - return { - seasonType, - highSeasonStartOption, - leasingPeriod, - }; - }, - ({ seasonType, highSeasonStartOption, leasingPeriod }) => { - const graphType = $calculation.getElementValue('radioGraphType'); - if (graphType !== 100_000_003) return; - - if (!seasonType || !highSeasonStartOption) { - $tables.payments.setValues([]); - - return; - } - - const seasons = seasonsTools.generateSeasons( - seasonType, - seasonsConstants.DEFAULT_SEASONS_VALUES - ); - const shiftNumber = Number.parseInt(highSeasonStartOption.label, 10) - 2; - const payments = seasonsTools.generateSeasonsPayments( - leasingPeriod, - shift(seasons, shiftNumber) - ); - const rows: Row[] = generateSeasonPaymentsRows(seasonType, shiftNumber, payments); - const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc'); - const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc'); - - $tables.payments.setRows([ - { - value: firstPaymentPerc, - status: 'Disabled', + return { + seasonType, + highSeasonStartOption, + leasingPeriod, + }; }, - ...rows, - { - value: lastPaymentPerc, - status: 'Disabled', - }, - ]); - } + ({ seasonType, highSeasonStartOption, leasingPeriod }) => { + const graphType = $calculation.element('radioGraphType').getValue(); + if (graphType !== 100_000_003) return; + + if (!seasonType || !highSeasonStartOption) { + $tables.payments.setValues([]); + + return; + } + + const seasons = seasonsTools.generateSeasons( + seasonType, + seasonsConstants.DEFAULT_SEASONS_VALUES + ); + const shiftNumber = Number.parseInt(highSeasonStartOption.label, 10) - 2; + const payments = seasonsTools.generateSeasonsPayments( + leasingPeriod, + shift(seasons, shiftNumber) + ); + const rows: Row[] = generateSeasonPaymentsRows(seasonType, shiftNumber, payments); + const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue(); + const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue(); + + $tables.payments.setRows([ + { + value: firstPaymentPerc, + status: 'Disabled', + }, + ...rows, + { + value: lastPaymentPerc, + status: 'Disabled', + }, + ]); + } + ), + () => $process.has('LoadKP') ); - reaction( - () => { - const payments = toJS($tables.payments.values); - const seasons = payments.slice(1, seasonsConstants.SEASONS_PERIOD_NUMBER + 1); + makeDisposable( + () => + reaction( + () => { + const payments = toJS($tables.payments.values); + const seasons = payments.slice(1, seasonsConstants.SEASONS_PERIOD_NUMBER + 1); - return seasons; - }, - (nextSeasons, prevSeasons) => { - const graphType = $calculation.getElementValue('radioGraphType'); - if (graphType !== 100_000_003) return; - - const seasonType = $calculation.getElementValue('selectSeasonType'); - const highSeasonStartOption = $calculation.getElementOption('selectHighSeasonStart'); - if (!seasonType || !highSeasonStartOption) return; - - const shiftNumber = Number.parseInt(highSeasonStartOption.label, 10) - 2; - const unshiftedNextSeasons = shift(nextSeasons, -shiftNumber); - const unshiftedPrevSeasons = shift(prevSeasons, -shiftNumber); - - const changes = difference(unshiftedNextSeasons, unshiftedPrevSeasons); - if (changes === null || changes.length > 1) return; - - const [changeIndex] = changes; - const positionIndex = seasonsTools.getPositionIndex(seasonType, changeIndex); - - const values = seasonsTools.getSeasonsValues(seasonType, unshiftedNextSeasons); - values[positionIndex] = unshiftedNextSeasons[changeIndex]; - - const seasons = seasonsTools.generateSeasons(seasonType, values); - const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); - const payments = seasonsTools.generateSeasonsPayments( - leasingPeriod, - shift(seasons, shiftNumber) - ); - const rows: Row[] = generateSeasonPaymentsRows(seasonType, shiftNumber, payments); - const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc'); - const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc'); - - $tables.payments.setRows([ - { - value: firstPaymentPerc, - status: 'Disabled', + return seasons; }, - ...rows, - { - value: lastPaymentPerc, - status: 'Disabled', + (nextSeasons, prevSeasons) => { + const graphType = $calculation.element('radioGraphType').getValue(); + if (graphType !== 100_000_003) return; + + const seasonType = $calculation.element('selectSeasonType').getValue(); + const highSeasonStartOption = $calculation.element('selectHighSeasonStart').getOption(); + if (!seasonType || !highSeasonStartOption) return; + + const shiftNumber = Number.parseInt(highSeasonStartOption.label, 10) - 2; + const unshiftedNextSeasons = shift(nextSeasons, -shiftNumber); + const unshiftedPrevSeasons = shift(prevSeasons, -shiftNumber); + + const changes = difference(unshiftedNextSeasons, unshiftedPrevSeasons); + if (changes === null || changes.length > 1) return; + + const [changeIndex] = changes; + const positionIndex = seasonsTools.getPositionIndex(seasonType, changeIndex); + + const values = seasonsTools.getSeasonsValues(seasonType, unshiftedNextSeasons); + values[positionIndex] = unshiftedNextSeasons[changeIndex]; + + const seasons = seasonsTools.generateSeasons(seasonType, values); + const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); + const payments = seasonsTools.generateSeasonsPayments( + leasingPeriod, + shift(seasons, shiftNumber) + ); + const rows: Row[] = generateSeasonPaymentsRows(seasonType, shiftNumber, payments); + const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue(); + const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue(); + + $tables.payments.setRows([ + { + value: firstPaymentPerc, + status: 'Disabled', + }, + ...rows, + { + value: lastPaymentPerc, + status: 'Disabled', + }, + ]); }, - ]); - }, - { - delay: 50, - equals: comparer.structural, - } + { + delay: 50, + equals: comparer.structural, + } + ), + () => $process.has('LoadKP') ); /** * Валидация */ - let removeError: () => void; + const validationHelper = new ValidationHelper(); reaction( () => { const payments = toJS($tables.payments.values); - const graphType = $calculation.getElementValue('radioGraphType'); - const seasonType = $calculation.getElementValue('selectSeasonType'); - const highSeasonStart = $calculation.getElementValue('selectHighSeasonStart'); - const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); + const graphType = $calculation.element('radioGraphType').getValue(); + const seasonType = $calculation.element('selectSeasonType').getValue(); + const highSeasonStart = $calculation.element('selectHighSeasonStart').getValue(); + const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); return { payments, @@ -545,11 +577,12 @@ export default function paymentsReactions( }; }, () => { - if (removeError) removeError(); + validationHelper.removeErrors(); const errorText = validatePaymentsTable(store); if (errorText) { - removeError = $tables.payments.validation.addError(errorText); + const removeError = $tables.payments.validation.addError(errorText); + validationHelper.add(removeError); } }, { diff --git a/process/payments/validation.ts b/process/payments/validation.ts index eb75d22..3dd671c 100644 --- a/process/payments/validation.ts +++ b/process/payments/validation.ts @@ -7,10 +7,10 @@ import { areEqual, isSorted } from 'tools/array'; import { SEASONS_PERIODS, SEASONS_PERIOD_NUMBER } from './lib/seasons-constants'; export default function validatePaymentsTable({ $calculation, $tables }: RootStore) { - switch ($calculation.getElementValue('radioGraphType')) { + switch ($calculation.element('radioGraphType').getValue()) { // Дегрессия case 100_000_001: - if (!$calculation.getElementValue('selectSeasonType')) { + if (!$calculation.element('selectSeasonType').getValue()) { return 'Не выбран тип дегрессии'; } /** @@ -18,7 +18,7 @@ export default function validatePaymentsTable({ $calculation, $tables }: RootSto */ { const MIN_PAYMENT = 3; - const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); + const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1); if (!targetPayments.every((payment) => payment >= MIN_PAYMENT)) { @@ -30,7 +30,7 @@ export default function validatePaymentsTable({ $calculation, $tables }: RootSto * при Дегрессии все значения не должны быть равны друг другу + что при Легком старте 2,3 и 4 платежи не должны быть равны 100 */ { - const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); + const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1); if (new Set(targetPayments).size === 1) { @@ -42,7 +42,7 @@ export default function validatePaymentsTable({ $calculation, $tables }: RootSto * Проверка на возрастание */ { - const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); + const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1); for (let i = 2; i < targetPayments.length - 1; i += 1) { @@ -73,7 +73,7 @@ export default function validatePaymentsTable({ $calculation, $tables }: RootSto * иначе не осуществлять Расчет графика и выводить ошибку "Нельзя осуществить расчет - указана очень жетская дегрессия. Не менее чем у 4х платежей "Соотношение платежа" должно не отличаться между самой", */ { - const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); + const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1); const counts = counting(targetPayments, (v) => v); if (Object.values(counts).filter((count) => count > 1).length < 2) { @@ -84,17 +84,17 @@ export default function validatePaymentsTable({ $calculation, $tables }: RootSto break; case 100_000_003: { - const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); + const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); if (leasingPeriod < 14) { return 'При сезонном виде графика срок лизинга должен быть больше 14 месяцев'; } - const seasonType = $calculation.getElementValue('selectSeasonType'); + const seasonType = $calculation.element('selectSeasonType').getValue(); if (!seasonType) { return 'Не выбран тип сезонности'; } - const highSeasonStartOption = $calculation.getElementOption('selectHighSeasonStart'); + const highSeasonStartOption = $calculation.element('selectHighSeasonStart').getOption(); if (!highSeasonStartOption) { return 'Не выбрано смещение сезонности'; } diff --git a/process/price/reactions/computed.ts b/process/price/reactions/computed.ts index d05d088..c2c20be 100644 --- a/process/price/reactions/computed.ts +++ b/process/price/reactions/computed.ts @@ -31,9 +31,9 @@ export default function computedReactions(store: RootStore, apolloClient: Apollo autorun( async () => { - const supplierCurrencyId = $calculation.getElementValue('selectSupplierCurrency'); - const leaseObjectPrice = $calculation.getElementValue('tbxLeaseObjectPrice'); - const supplierDiscountRub = $calculation.getElementValue('tbxSupplierDiscountRub'); + const supplierCurrencyId = $calculation.element('selectSupplierCurrency').getValue(); + const leaseObjectPrice = $calculation.element('tbxLeaseObjectPrice').getValue(); + const supplierDiscountRub = $calculation.element('tbxSupplierDiscountRub').getValue(); if (!supplierCurrencyId) { $calculation.$values.setValue('plPriceRub', leaseObjectPrice); diff --git a/process/supplier-agent/get-kp-values/get-sums.ts b/process/supplier-agent/get-kp-values/get-sums.ts new file mode 100644 index 0000000..929dd8b --- /dev/null +++ b/process/supplier-agent/get-kp-values/get-sums.ts @@ -0,0 +1,97 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import { gql } from '@apollo/client'; +import initializeApollo from 'apollo/client'; +import type * as CRMTypes from 'graphql/crm.types'; +import type { Quote } from './index'; + +const QUERY_GET_REWARD_RULES = gql` + query GetRewardRules($conditionId: Uuid!) { + evo_reward_condition(evo_reward_conditionid: $conditionId) { + evo_calc_reward_rules + } + } +`; + +async function getRewardSum( + conditionId: string | null | undefined, + quote: Quote, + quoteRewardSummField: keyof Quote, + quoteRewardTotalField: keyof Quote +) { + if (!conditionId) return 0; + + const apolloClient = initializeApollo(); + const { + data: { evo_reward_condition }, + } = await apolloClient.query( + { + query: QUERY_GET_REWARD_RULES, + variables: { + conditionId, + }, + } + ); + + if (evo_reward_condition?.evo_calc_reward_rules === 100_000_001) { + return quote[quoteRewardSummField]; + } + + return quote[quoteRewardTotalField]; +} + +export default async function getSums(quote: Quote) { + const [ + dealerRewardSumm, + dealerBrokerRewardSumm, + indAgentRewardSumm, + calcDoubleAgentRewardSumm, + calcBrokerRewardSum, + finDepartmentRewardSumm, + ] = await Promise.all([ + getRewardSum( + quote?.evo_dealer_reward_conditionid, + quote, + 'evo_dealer_reward_summ', + 'evo_dealer_reward_total' + ), + getRewardSum( + quote?.evo_dealer_broker_reward_conditionid, + quote, + 'evo_dealer_broker_reward_summ', + 'evo_dealer_broker_reward_total' + ), + getRewardSum( + quote?.evo_agent_reward_conditionid, + quote, + 'evo_agent_reward_summ', + 'evo_agent_reward_total' + ), + getRewardSum( + quote.evo_double_agent_reward_conditionid, + quote, + 'evo_double_agent_reward_summ', + 'evo_double_agent_reward_total' + ), + getRewardSum( + quote.evo_broker_reward_conditionid, + quote, + 'evo_broker_reward_summ', + 'evo_broker_reward_total' + ), + getRewardSum( + quote.evo_fin_department_reward_conditionid, + quote, + 'evo_fin_department_reward_summ', + 'evo_fin_department_reward_total' + ), + ]); + + return { + dealerRewardSumm, + dealerBrokerRewardSumm, + indAgentRewardSumm, + calcDoubleAgentRewardSumm, + calcBrokerRewardSum, + finDepartmentRewardSumm, + }; +} diff --git a/process/supplier-agent/get-kp-values/index.ts b/process/supplier-agent/get-kp-values/index.ts new file mode 100644 index 0000000..09d2d84 --- /dev/null +++ b/process/supplier-agent/get-kp-values/index.ts @@ -0,0 +1,103 @@ +import { gql } from '@apollo/client'; +import initializeApollo from 'apollo/client'; +import type * as CRMTypes from 'graphql/crm.types'; +import type { CalculationValues } from 'stores/calculation/values/types'; +import getSums from './get-sums'; + +const QUERY_GET_AGENTS_DATA_FROM_QUOTE = gql` + query GetAgentsDataFromQuote($quoteId: Uuid!) { + quote(quoteId: $quoteId) { + evo_supplier_accountid + evo_dealer_person_accountid + evo_dealer_reward_conditionid + evo_dealer_reward_total + evo_dealer_reward_summ + evo_dealer_broker_accountid + evo_dealer_broker_reward_conditionid + evo_dealer_broker_reward_total + evo_dealer_broker_reward_summ + evo_agent_accountid + evo_agent_reward_conditionid + evo_agent_reward_total + evo_agent_reward_summ + evo_double_agent_accountid + evo_double_agent_reward_conditionid + evo_double_agent_reward_total + evo_double_agent_reward_summ + evo_broker_accountid + evo_broker_reward_conditionid + evo_broker_reward_total + evo_broker_reward_summ + evo_fin_department_accountid + evo_fin_department_reward_conditionid + evo_fin_department_reward_total + evo_fin_department_reward_summ + } + } +`; + +export type Quote = NonNullable; + +type InputData = { + quoteId: NonNullable; +}; + +type ResultData = { + values: Partial; +}; + +export default async function getSupplierAgentsDataFromKP({ + quoteId, +}: InputData): Promise { + const apolloClient = initializeApollo(); + + const { + data: { quote }, + } = await apolloClient.query< + CRMTypes.GetAgentsDataFromQuoteQuery, + CRMTypes.GetAgentsDataFromQuoteQueryVariables + >({ + query: QUERY_GET_AGENTS_DATA_FROM_QUOTE, + variables: { + quoteId, + }, + }); + + if (!quote) { + throw new Error('Quote is empty'); + } + + const { + dealerRewardSumm, + dealerBrokerRewardSumm, + indAgentRewardSumm, + calcDoubleAgentRewardSumm, + calcBrokerRewardSum, + finDepartmentRewardSumm, + } = await getSums(quote); + + return { + values: { + dealer: quote?.evo_supplier_accountid, + dealerPerson: quote?.evo_dealer_person_accountid, + dealerRewardCondition: quote?.evo_dealer_reward_conditionid, + dealerRewardSumm, + dealerBroker: quote?.evo_dealer_broker_accountid, + dealerBrokerRewardCondition: quote?.evo_dealer_broker_reward_conditionid, + dealerBrokerRewardSumm, + + indAgent: quote?.evo_agent_accountid, + indAgentRewardCondition: quote?.evo_agent_reward_conditionid, + indAgentRewardSumm, + calcDoubleAgent: quote?.evo_double_agent_accountid, + calcDoubleAgentRewardCondition: quote?.evo_double_agent_reward_conditionid, + calcDoubleAgentRewardSumm, + calcBroker: quote?.evo_broker_accountid, + calcBrokerRewardCondition: quote?.evo_broker_reward_conditionid, + calcBrokerRewardSum, + calcFinDepartment: quote?.evo_fin_department_accountid, + finDepartmentRewardCondtion: quote?.evo_fin_department_reward_conditionid, + finDepartmentRewardSumm, + }, + }; +} diff --git a/process/supplier-agent/lib/create-reactions.ts b/process/supplier-agent/lib/create-reactions.ts new file mode 100644 index 0000000..30bffa0 --- /dev/null +++ b/process/supplier-agent/lib/create-reactions.ts @@ -0,0 +1,216 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import type { ApolloClient } from '@apollo/client'; +import { gql } from '@apollo/client'; +import type * as Values from 'Components/Calculation/config/map/values'; +import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc'; +import type * as CRMTypes from 'graphql/crm.types'; +import { reaction } from 'mobx'; +import type RootStore from 'stores/root'; +import ValidationHelper from 'stores/validation/helper'; +import { normalizeOptions } from 'tools/entity'; +import { makeDisposable } from 'tools/mobx'; + +dayjs.extend(utc); + +const QUERY_GET_REWARD_CONDITIONS = gql` + query GetRewardConditions($agentid: Uuid!, $currentDate: DateTime) { + evo_reward_conditions( + evo_agent_accountid: $agentid + evo_datefrom_param: { lte: $currentDate } + evo_dateto_param: { gte: $currentDate } + statecode: 0 + evo_agency_agreementid_param: { has: true } + ) { + label: evo_name + value: evo_reward_conditionid + evo_reward_summ + } + } +`; + +export function fillAgentRewardReaction( + store: RootStore, + apolloClient: ApolloClient, + agentParams: { + agentField: Values.Elements; + rewardConditionField: Values.Elements; + } +) { + const { $calculation, $process } = store; + const { agentField, rewardConditionField } = agentParams; + + reaction( + () => $calculation.element(agentField).getValue(), + async (agentId) => { + if (!agentId) { + $calculation.element(rewardConditionField).reset(); + + return; + } + const { + data: { evo_reward_conditions }, + } = await apolloClient.query< + CRMTypes.GetRewardConditionsQuery, + CRMTypes.GetRewardConditionsQueryVariables + >({ + query: QUERY_GET_REWARD_CONDITIONS, + variables: { + agentid: agentId, + currentDate: dayjs().toISOString(), + }, + }); + + if (evo_reward_conditions?.length) { + $calculation + .element(rewardConditionField) + .setOptions(normalizeOptions(evo_reward_conditions)); + } + } + ); +} + +const QUERY_GET_REWARD_SUMM = gql` + query GetRewardSumm($conditionId: Uuid!) { + evo_reward_condition(evo_reward_conditionid: $conditionId) { + evo_reward_summ + } + } +`; + +export function fillAgentRewardSummReaction( + store: RootStore, + apolloClient: ApolloClient, + agentParams: { + rewardConditionField: Values.Elements; + rewardSummField: Values.Elements; + } +) { + const { $calculation, $process } = store; + const { rewardConditionField, rewardSummField } = agentParams; + + makeDisposable( + () => + reaction( + () => $calculation.element(rewardConditionField).getValue(), + async (rewardConditionId) => { + if (!rewardConditionId) { + $calculation.element(rewardSummField).reset(); + + return; + } + + const { + data: { evo_reward_condition }, + } = await apolloClient.query< + CRMTypes.GetRewardSummQuery, + CRMTypes.GetRewardSummQueryVariables + >({ + query: QUERY_GET_REWARD_SUMM, + variables: { + conditionId: rewardConditionId, + }, + }); + + $calculation.element(rewardSummField).setValue(evo_reward_condition?.evo_reward_summ); + } + ), + () => $process.has('LoadKP') + ); + + reaction( + () => $calculation.element(rewardConditionField).getValue(), + (rewardConditionId) => { + if (!rewardConditionId) { + $calculation.element(rewardSummField).block(); + } else { + $calculation.element(rewardSummField).unblock(); + } + } + ); +} + +const QUERY_GET_REWARD_CONDITION = gql` + query GetRewardCondition($conditionId: Uuid!) { + evo_reward_condition(evo_reward_conditionid: $conditionId) { + evo_reward_summ + evo_reduce_reward + evo_min_reward_summ + } + } +`; + +export function validateAgentRewardSumm( + store: RootStore, + apolloClient: ApolloClient, + agentParams: { + rewardConditionField: Values.Elements; + rewardSummField: Values.Elements; + } +) { + const { $calculation } = store; + const { rewardConditionField, rewardSummField } = agentParams; + + const validationHelper = new ValidationHelper(); + + reaction( + () => $calculation.element(rewardSummField).getValue() as number, + async (rewardSumm) => { + const conditionId = $calculation.element(rewardConditionField).getValue(); + if (!conditionId) { + validationHelper.removeErrors(); + + return; + } + + const { + data: { evo_reward_condition }, + } = await apolloClient.query< + CRMTypes.GetRewardConditionQuery, + CRMTypes.GetRewardConditionQueryVariables + >({ + query: QUERY_GET_REWARD_CONDITION, + variables: { + conditionId, + }, + }); + + $calculation + .element(rewardSummField) + .validate({ + invalid: + evo_reward_condition?.evo_reward_summ && + rewardSumm > evo_reward_condition.evo_reward_summ, + message: 'Вознаграждение указано больше условия по агентскому договору!', + }) + .err((removeError) => { + validationHelper.add(removeError); + }); + + $calculation + .element(rewardSummField) + .validate({ + invalid: + !evo_reward_condition?.evo_reduce_reward && + evo_reward_condition?.evo_reward_summ && + rewardSumm < evo_reward_condition.evo_reward_summ, + message: 'Вознаграждение указано меньше условия по агентскому договору!', + }) + .err((removeError) => { + validationHelper.add(removeError); + }); + + $calculation + .element(rewardSummField) + .validate({ + invalid: + evo_reward_condition?.evo_min_reward_summ && + rewardSumm < evo_reward_condition?.evo_min_reward_summ, + message: 'Вознаграждение указано меньше условия по агентскому договору!', + }) + .err((removeError) => { + validationHelper.add(removeError); + }); + } + ); +} diff --git a/process/agents/lib/fill-agents-from-lead.ts b/process/supplier-agent/lib/fill-agents-from-lead.ts similarity index 94% rename from process/agents/lib/fill-agents-from-lead.ts rename to process/supplier-agent/lib/fill-agents-from-lead.ts index a308318..d92aebd 100644 --- a/process/agents/lib/fill-agents-from-lead.ts +++ b/process/supplier-agent/lib/fill-agents-from-lead.ts @@ -18,7 +18,7 @@ function makeFillAgentFromLead( leadid: string | null ) { if (!leadid) { - $calculation.resetElement(elementName); + $calculation.element(elementName).reset(); return; } @@ -43,11 +43,13 @@ function makeFillAgentFromLead( }); if (agent) { - $calculation.setElementOptions(elementName, normalizeOptions([agent])); - $calculation.setElementValue(elementName, agent.value); + $calculation + .element(elementName) + .setOptions(normalizeOptions([agent])) + .setValue(agent.value); } } else { - $calculation.resetElement(elementName); + $calculation.element(elementName).reset(); } }; } diff --git a/process/agents/lib/query.ts b/process/supplier-agent/lib/query.ts similarity index 100% rename from process/agents/lib/query.ts rename to process/supplier-agent/lib/query.ts index 3736dfe..79482d8 100644 --- a/process/agents/lib/query.ts +++ b/process/supplier-agent/lib/query.ts @@ -1,6 +1,6 @@ +/* eslint-disable import/prefer-default-export */ import { gql } from '@apollo/client'; -/* eslint-disable import/prefer-default-export */ export const QUERY_GET_AGENT = gql` query GetAgent($agentid: Uuid!) { agent: account(accountid: $agentid) { diff --git a/process/supplier-agent/reactions/agents.ts b/process/supplier-agent/reactions/agents.ts new file mode 100644 index 0000000..abfd843 --- /dev/null +++ b/process/supplier-agent/reactions/agents.ts @@ -0,0 +1,513 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import type { ApolloClient } from '@apollo/client'; +import { gql } from '@apollo/client'; +import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc'; +import type * as CRMTypes from 'graphql/crm.types'; +import { reaction } from 'mobx'; +import type RootStore from 'stores/root'; +import { makeDisposable } from 'tools/mobx'; +import * as createReactions from '../lib/create-reactions'; +import * as fillAgentsFromLead from '../lib/fill-agents-from-lead'; + +dayjs.extend(utc); + +export function fillReactions(store: RootStore, apolloClient: ApolloClient) { + const { $calculation, $process } = store; + + /** + * Заполняем агентов из Интереса + */ + makeDisposable( + () => + reaction( + () => $calculation.element('selectLead').getValue(), + (leadid) => { + fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid); + fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid); + fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid); + fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid); + } + ), + () => $process.has('LoadKP') + ); + + /** + * IndAgent + */ + // Заполняем selectIndAgentRewardCondition + createReactions.fillAgentRewardReaction(store, apolloClient, { + agentField: 'selectIndAgent', + rewardConditionField: 'selectIndAgentRewardCondition', + }); + + // Заполняем tbxIndAgentRewardSumm + createReactions.fillAgentRewardSummReaction(store, apolloClient, { + rewardConditionField: 'selectIndAgentRewardCondition', + rewardSummField: 'tbxIndAgentRewardSumm', + }); + + /** + * CalcDoubleAgent + */ + // Заполняем selectCalcDoubleAgentRewardCondition + createReactions.fillAgentRewardReaction(store, apolloClient, { + agentField: 'selectCalcDoubleAgent', + rewardConditionField: 'selectCalcDoubleAgentRewardCondition', + }); + + // Заполняем tbxCalcDoubleAgentRewardSumm + createReactions.fillAgentRewardSummReaction(store, apolloClient, { + rewardConditionField: 'selectCalcDoubleAgentRewardCondition', + rewardSummField: 'tbxCalcDoubleAgentRewardSumm', + }); + + /** + * CalcBroker + */ + // Заполняем selectCalcBrokerRewardCondition + createReactions.fillAgentRewardReaction(store, apolloClient, { + agentField: 'selectCalcBroker', + rewardConditionField: 'selectCalcBrokerRewardCondition', + }); + + // Заполняем tbxCalcBrokerRewardSum + createReactions.fillAgentRewardSummReaction(store, apolloClient, { + rewardConditionField: 'selectCalcBrokerRewardCondition', + rewardSummField: 'tbxCalcBrokerRewardSum', + }); + + /** + * CalcFinDepartment + */ + // Заполняем selectFinDepartmentRewardCondtion + createReactions.fillAgentRewardReaction(store, apolloClient, { + agentField: 'selectCalcFinDepartment', + rewardConditionField: 'selectFinDepartmentRewardCondtion', + }); + + // Заполняем tbxCalcBrokerRewardSum + createReactions.fillAgentRewardSummReaction(store, apolloClient, { + rewardConditionField: 'selectFinDepartmentRewardCondtion', + rewardSummField: 'tbxFinDepartmentRewardSumm', + }); +} + +export function commonReactions(store: RootStore, apolloClient: ApolloClient) { + const { $calculation } = store; + + const QUERY_GET_REWARD_WITHOUT_OTHER_AGENT = gql` + query GetRewardWithoutOtherAgent($conditionId: Uuid!) { + evo_reward_condition(evo_reward_conditionid: $conditionId) { + evo_agency_agreementidData { + evo_reward_without_other_agent + } + } + } + `; + + /** + * Добавить реакцию на изменение списка в поле selectDealerRewardCondition : + Если в списке selectDealerRewardCondition есть запись, + у которой evo_reward_condition.evo_agency_agreementid. + Выплата без других агентов (evo_reward_without_other_agent) = True, + то сбрасывают значение и закрываются для выбора поля: + + selectDealerBroker + selectIndAgent + selectCalcDoubleAgent + selectCalcBroker + selectFinDepartment + */ + + reaction( + () => $calculation.element('selectDealerRewardCondition').getValue(), + async (rewardConditionId) => { + function fillAgents() { + const leadid = $calculation.element('selectLead').getValue(); + fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid); + fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid); + fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid); + fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid); + } + + if (!rewardConditionId) { + fillAgents(); + + return; + } + + const { + data: { evo_reward_condition }, + } = await apolloClient.query< + CRMTypes.GetRewardWithoutOtherAgentQuery, + CRMTypes.GetRewardWithoutOtherAgentQueryVariables + >({ + query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT, + variables: { + conditionId: rewardConditionId, + }, + }); + + if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) { + $calculation.element('selectDealerBroker').reset(); + $calculation.element('selectIndAgent').reset(); + $calculation.element('selectCalcDoubleAgent').reset(); + $calculation.element('selectCalcBroker').reset(); + $calculation.element('selectCalcFinDepartment').reset(); + } else { + fillAgents(); + } + } + ); + + /** + * Добавить реакцию на изменение списка в поле selectDealerBrokerRewardCondition : + + Если в списке selectDealerBrokerRewardCondition есть запись, + у которой evo_reward_condition.evo_agency_agreementid. + Выплата без других агентов (evo_reward_without_other_agent) = True, + то сбрасывают значение и закрываются для выбора поля: + + selectDealerPerson (не обнуляем) + selectIndAgent + selectCalcDoubleAgent + selectCalcBroker + selectFinDepartment + иначе + + selectDealerPerson открываем для редактирования + selectIndAgent заполняется значением из Интереса + selectCalcDoubleAgent заполняется значением из Интереса + selectCalcBrokerRewardCondition заполняется значением из Интереса + selectFinDepartmentRewardCondtion заполняется значением из Интереса + */ + reaction( + () => $calculation.element('selectDealerBrokerRewardCondition').getValue(), + async (rewardConditionId) => { + function fillAgents() { + const leadid = $calculation.element('selectLead').getValue(); + fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid); + fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid); + fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid); + fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid); + } + + if (!rewardConditionId) { + fillAgents(); + + return; + } + + const { + data: { evo_reward_condition }, + } = await apolloClient.query< + CRMTypes.GetRewardWithoutOtherAgentQuery, + CRMTypes.GetRewardWithoutOtherAgentQueryVariables + >({ + query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT, + variables: { + conditionId: rewardConditionId, + }, + }); + + if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) { + $calculation.element('selectDealerPerson').block(); + $calculation.element('selectIndAgent').reset(); + $calculation.element('selectCalcDoubleAgent').reset(); + $calculation.element('selectCalcBroker').reset(); + $calculation.element('selectCalcFinDepartment').reset(); + } else { + $calculation.element('selectDealerPerson').unblock(); + fillAgents(); + } + } + ); + + /** + * Добавить реакцию на изменение списка в поле selectIndAgentRewardCondition : + + Если в списке selectIndAgentRewardCondition есть запись, + у которой evo_reward_condition.evo_agency_agreementid. + Выплата без других агентов (evo_reward_without_other_agent) = True, + то сбрасывают значение и закрываются для выбора поля: + + selectDealerPerson (не обнуляем) + selectDealerBroker + selectCalcDoubleAgent + selectCalcBroker + selectFinDepartment + иначе + + selectDealerPerson открываем для редактирования + selectDealerBroker открываем для редактирования + selectCalcDoubleAgent заполняется значением из Интереса + selectCalcBroker заполняется значением из Интереса + selectCalcFinDepartment заполняется значением из Интереса + */ + + reaction( + () => $calculation.element('selectIndAgentRewardCondition').getValue(), + async (rewardConditionId) => { + function fillAgents() { + const leadid = $calculation.element('selectLead').getValue(); + fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid); + fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid); + fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid); + } + + if (!rewardConditionId) { + fillAgents(); + + return; + } + + const { + data: { evo_reward_condition }, + } = await apolloClient.query< + CRMTypes.GetRewardWithoutOtherAgentQuery, + CRMTypes.GetRewardWithoutOtherAgentQueryVariables + >({ + query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT, + variables: { + conditionId: rewardConditionId, + }, + }); + + if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) { + $calculation.element('selectDealerPerson').block(); + $calculation.element('selectDealerBroker').reset(); + $calculation.element('selectCalcDoubleAgent').reset(); + $calculation.element('selectCalcBroker').reset(); + $calculation.element('selectCalcFinDepartment').reset(); + } else { + $calculation.element('selectDealerPerson').unblock(); + fillAgents(); + } + } + ); + + /** + * Добавить реакцию на изменение списка в поле selectCalcDoubleAgentRewardCondition : + + Если в списке selectCalcDoubleAgentRewardCondition есть запись, + у которой evo_reward_condition.evo_agency_agreementid. + Выплата без других агентов (evo_reward_without_other_agent) = True, + то сбрасывают значение и закрываются для выбора поля: + + selectDealerPerson (не обнуляем) + selectDealerBroker + selectIndAgent + selectCalcBroker + selectCalcFinDepartment + иначе + + selectDealerPerson открываем для редактирования + selectDealerBroker открываем для редактирования + selectIndAgent заполняется значением из Интереса + selectCalcBroker заполняется значением из Интереса + selectCalcFinDepartment заполняется значением из Интереса + */ + + reaction( + () => $calculation.element('selectCalcDoubleAgentRewardCondition').getValue(), + async (rewardConditionId) => { + function fillAgents() { + const leadid = $calculation.element('selectLead').getValue(); + fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid); + fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid); + fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid); + } + + if (!rewardConditionId) { + fillAgents(); + + return; + } + + const { + data: { evo_reward_condition }, + } = await apolloClient.query< + CRMTypes.GetRewardWithoutOtherAgentQuery, + CRMTypes.GetRewardWithoutOtherAgentQueryVariables + >({ + query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT, + variables: { + conditionId: rewardConditionId, + }, + }); + + if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) { + $calculation.element('selectDealerPerson').block(); + $calculation.element('selectDealerBroker').reset(); + $calculation.element('selectIndAgent').reset(); + $calculation.element('selectCalcBroker').reset(); + $calculation.element('selectCalcFinDepartment').reset(); + } else { + $calculation.element('selectDealerPerson').unblock(); + $calculation.element('selectDealerBroker').unblock(); + fillAgents(); + } + } + ); + + /** + * @description + * Добавить реакцию на изменение списка в поле selectCalcBrokerRewardCondition: + + Если в списке selectCalcBrokerRewardCondition есть запись, + у которой evo_reward_condition.evo_agency_agreementid. + Выплата без других агентов (evo_reward_without_other_agent) = True, + то сбрасывают значение и закрываются для выбора поля: + + selectDealerPerson (не обнуляем) + selectDealerBroker + selectIndAgent + selectCalcDoubleAgent + selectCalcFinDepartment + иначе + + selectDealerPerson открываем для редактирования + selectDealerBroker открываем для редактирования + selectIndAgent заполняется значением из Интереса + selectCalcDoubleAgent заполняется значением из Интереса + selectCalcFinDepartment заполняется значением из Интереса + */ + reaction( + () => $calculation.element('selectCalcBrokerRewardCondition').getValue(), + async (rewardConditionId) => { + function fillAgents() { + const leadid = $calculation.element('selectLead').getValue(); + fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid); + fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid); + fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid); + } + + if (!rewardConditionId) { + fillAgents(); + + return; + } + + const { + data: { evo_reward_condition }, + } = await apolloClient.query< + CRMTypes.GetRewardWithoutOtherAgentQuery, + CRMTypes.GetRewardWithoutOtherAgentQueryVariables + >({ + query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT, + variables: { + conditionId: rewardConditionId, + }, + }); + + if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) { + $calculation.element('selectDealerPerson').block(); + $calculation.element('selectDealerBroker').reset(); + $calculation.element('selectIndAgent').reset(); + $calculation.element('selectCalcDoubleAgent').reset(); + $calculation.element('selectCalcFinDepartment').reset(); + } else { + $calculation.element('selectDealerPerson').unblock(); + $calculation.element('selectDealerBroker').unblock(); + fillAgents(); + } + } + ); + + /** + * Добавить реакцию на изменение списка в поле selectFinDepartmentRewardCondtion: + + Если в списке selectFinDepartmentRewardCondtion есть запись, + у которой evo_reward_condition.evo_agency_agreementid. + Выплата без других агентов (evo_reward_without_other_agent) = True, + то сбрасывают значение и закрываются для выбора поля: + + selectDealerPerson (не обнуляем) + selectDealerBroker + selectIndAgent + selectCalcDoubleAgent + selectCalcBroker + иначе + + selectDealerPerson открываем для редактирования + selectDealerBroker открываем для редактирования + selectIndAgent заполняется значением из Интереса + selectCalcDoubleAgent заполняется значением из Интереса + selectCalcBroker заполняется значением из Интереса + */ + + reaction( + () => $calculation.element('selectFinDepartmentRewardCondtion').getValue(), + async (rewardConditionId) => { + function fillAgents() { + const leadid = $calculation.element('selectLead').getValue(); + fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid); + fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid); + fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid); + } + + if (!rewardConditionId) { + fillAgents(); + + return; + } + + const { + data: { evo_reward_condition }, + } = await apolloClient.query< + CRMTypes.GetRewardWithoutOtherAgentQuery, + CRMTypes.GetRewardWithoutOtherAgentQueryVariables + >({ + query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT, + variables: { + conditionId: rewardConditionId, + }, + }); + + if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) { + $calculation.element('selectDealerPerson').block(); + $calculation.element('selectDealerBroker').reset(); + $calculation.element('selectIndAgent').reset(); + $calculation.element('selectCalcDoubleAgent').reset(); + $calculation.element('selectCalcBroker').reset(); + } else { + $calculation.element('selectDealerPerson').unblock(); + $calculation.element('selectDealerBroker').unblock(); + fillAgents(); + } + } + ); +} + +export function validationReactions(store: RootStore, apolloClient: ApolloClient) { + createReactions.validateAgentRewardSumm(store, apolloClient, { + rewardConditionField: 'selectDealerRewardCondition', + rewardSummField: 'tbxDealerRewardSumm', + }); + + createReactions.validateAgentRewardSumm(store, apolloClient, { + rewardConditionField: 'selectDealerBrokerRewardCondition', + rewardSummField: 'tbxDealerBrokerRewardSumm', + }); + + createReactions.validateAgentRewardSumm(store, apolloClient, { + rewardConditionField: 'selectIndAgentRewardCondition', + rewardSummField: 'tbxIndAgentRewardSumm', + }); + + createReactions.validateAgentRewardSumm(store, apolloClient, { + rewardConditionField: 'selectCalcDoubleAgentRewardCondition', + rewardSummField: 'tbxCalcDoubleAgentRewardSumm', + }); + + createReactions.validateAgentRewardSumm(store, apolloClient, { + rewardConditionField: 'selectCalcBrokerRewardCondition', + rewardSummField: 'tbxCalcBrokerRewardSum', + }); + + createReactions.validateAgentRewardSumm(store, apolloClient, { + rewardConditionField: 'selectFinDepartmentRewardCondtion', + rewardSummField: 'tbxFinDepartmentRewardSumm', + }); +} diff --git a/process/supplier-agent/reactions/leaseback.ts b/process/supplier-agent/reactions/leaseback.ts new file mode 100644 index 0000000..bb9e9e0 --- /dev/null +++ b/process/supplier-agent/reactions/leaseback.ts @@ -0,0 +1,90 @@ +import type { ApolloClient } from '@apollo/client'; +import { gql } from '@apollo/client'; +import type * as CRMTypes from 'graphql/crm.types'; +import { reaction } from 'mobx'; +import type RootStore from 'stores/root'; + +export default function leasebackReactions(store: RootStore, apolloClient: ApolloClient) { + const { $calculation, $tables } = store; + /** + * Дополнить реакцию на изменение поля Салон приобретения selectDealer: + +если в поле selectDealer указан account, у которого evo_return_leasing_dealer = true, то + +1) поле selectDealerPerson обнулять и закрывать для редактирования, +иначе формировать список связанных значений + +2) в таблице страхования в столбце Плательщик +в строках ОСАГО и КАСКО указывать "Лизингополучатель" (100 000 000) и закрывать для редактирования , +иначе открывать данные поля для редактирования + +3) ПЛ БУ cbxLeaseObjectUsed = true + */ + + const QUERY_GET_DEALER_RETURN_LEASING = gql` + query GetDealerReturnLeasing($dealerId: Uuid!) { + dealer: account(accountid: $dealerId) { + evo_return_leasing_dealer + } + } + `; + + reaction( + () => $calculation.element('selectDealer').getValue(), + async (dealerId) => { + if (!dealerId) return; + + const { + data: { dealer }, + } = await apolloClient.query< + CRMTypes.GetDealerReturnLeasingQuery, + CRMTypes.GetDealerReturnLeasingQueryVariables + >({ + query: QUERY_GET_DEALER_RETURN_LEASING, + variables: { + dealerId, + }, + }); + + if (dealer?.evo_return_leasing_dealer === true) { + $tables.insurance.row('kasko').setValue('insured', 100_000_000).block('insured'); + $calculation.element('cbxLeaseObjectUsed').setValue(true); + } else { + $tables.insurance.row('kasko').resetStatus('insured'); + } + } + ); + + // объединили реакцию для прицепа и возвратного лизинга + reaction( + () => ({ + dealerId: $calculation.element('selectDealer').getValue(), + leaseObjectCategory: $calculation.element('selectLeaseObjectCategory').getValue(), + }), + async ({ dealerId, leaseObjectCategory }) => { + const isTrailer = leaseObjectCategory === 100_000_004; + let returnLeasing = false; + + if (dealerId) { + const { + data: { dealer }, + } = await apolloClient.query< + CRMTypes.GetDealerReturnLeasingQuery, + CRMTypes.GetDealerReturnLeasingQueryVariables + >({ + query: QUERY_GET_DEALER_RETURN_LEASING, + variables: { + dealerId, + }, + }); + returnLeasing = dealer?.evo_return_leasing_dealer === true; + } + + if (isTrailer || returnLeasing) { + $tables.insurance.row('osago').setValue('insured', 100_000_000).block('insured'); + } else { + $tables.insurance.row('osago').resetStatus('insured'); + } + } + ); +} diff --git a/process/supplier-agent/reactions/supplier.ts b/process/supplier-agent/reactions/supplier.ts new file mode 100644 index 0000000..8df291c --- /dev/null +++ b/process/supplier-agent/reactions/supplier.ts @@ -0,0 +1,173 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import type { ApolloClient } from '@apollo/client'; +import { gql } from '@apollo/client'; +import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc'; +import type * as CRMTypes from 'graphql/crm.types'; +import { reaction } from 'mobx'; +import { sift } from 'radash'; +import type RootStore from 'stores/root'; +import { normalizeOptions } from 'tools/entity'; +import * as createReactions from '../lib/create-reactions'; +import * as query from '../lib/query'; + +dayjs.extend(utc); + +export function commonReactions(store: RootStore, apolloClient: ApolloClient) { + const { $calculation, $process } = store; + + /** + * Заполняем selectDealerPerson + * На изменение Салон приобретения формируем список в поле ЮЛ поставщика - записи Контрагент, + * у которых статус = активный И Поставщик = Да И Тип поставщика = Юридическое лицо + * И связаны с карточкой Контрагент из поля "Салон приобретения" по связи Салон-ЮЛ + */ + + const QUERY_GET_DEALER_PERSON = gql` + query GetDealerPerson($dealerId: Uuid!) { + salon_providers(statecode: 0, salonaccountid: $dealerId) { + label: name + value: accountid + evo_inn + evo_kpp + } + } + `; + + reaction( + () => $calculation.element('selectDealer').getValue(), + async (dealerId) => { + if (!dealerId) { + $calculation.element('selectDealerPerson').reset(); + $calculation.element('selectDealerBroker').reset(); + + return; + } + + const { + data: { salon_providers }, + } = await apolloClient.query< + CRMTypes.GetDealerPersonQuery, + CRMTypes.GetDealerPersonQueryVariables + >({ + query: QUERY_GET_DEALER_PERSON, + variables: { + dealerId, + }, + }); + + if (salon_providers?.length) { + $calculation.element('selectDealerPerson').setOptions( + normalizeOptions( + salon_providers.map((dp) => ({ + ...dp, + label: `${dp?.label} ${sift([dp?.evo_inn, dp?.evo_kpp]).join(' | ')}`, + })) + ) + ); + + if (!$process.has('LoadKP')) { + $calculation.element('selectDealerPerson').setValue(salon_providers[0]?.value); + } + } + } + ); + + /** + * Заполняем selectDealerBroker + */ + + const QUERY_GET_BROKER_ACCOUNTID_FROM_DEALER = gql` + query GetBrokerAccountIdFromDealer($dealerId: Uuid!) { + dealer: account(accountid: $dealerId) { + evo_broker_accountid + } + } + `; + + reaction( + () => $calculation.element('selectDealerPerson').getValue(), + async (dealerPersonId) => { + if (!dealerPersonId) { + return; + } + + const { + data: { dealer }, + } = await apolloClient.query< + CRMTypes.GetBrokerAccountIdFromDealerQuery, + CRMTypes.GetBrokerAccountIdFromDealerQueryVariables + >({ + query: QUERY_GET_BROKER_ACCOUNTID_FROM_DEALER, + variables: { + dealerId: dealerPersonId, + }, + }); + + if (dealer?.evo_broker_accountid) { + const { + data: { agent: dealerBroker }, + } = await apolloClient.query({ + query: query.QUERY_GET_AGENT, + variables: { + agentid: dealer?.evo_broker_accountid, + }, + }); + + if (dealerBroker) { + $calculation.element('selectDealerBroker').setOptions(normalizeOptions([dealerBroker])); + + if (!$process.has('LoadKP')) { + $calculation.element('selectDealerBroker').setValue(dealerBroker.value); + } + } + } else { + $calculation.element('selectDealerBroker').reset(); + } + } + ); + + // Заполняем selectDealerRewardCondition + createReactions.fillAgentRewardReaction(store, apolloClient, { + agentField: 'selectDealerPerson', + rewardConditionField: 'selectDealerRewardCondition', + }); + + // Заполняем tbxDealerRewardSumm + createReactions.fillAgentRewardSummReaction(store, apolloClient, { + rewardConditionField: 'selectDealerRewardCondition', + rewardSummField: 'tbxDealerRewardSumm', + }); + + // Заполняем selectDealerBrokerRewardCondition + createReactions.fillAgentRewardReaction(store, apolloClient, { + agentField: 'selectDealerBroker', + rewardConditionField: 'selectDealerBrokerRewardCondition', + }); + + // Заполняем tbxDealerBrokerRewardSumm + createReactions.fillAgentRewardSummReaction(store, apolloClient, { + rewardConditionField: 'selectDealerBrokerRewardCondition', + rewardSummField: 'tbxDealerBrokerRewardSumm', + }); + + reaction( + () => $calculation.element('selectDealerRewardCondition').getValue(), + (dealerRewardConditionId) => { + if (dealerRewardConditionId) { + $calculation.element('selectDealerBroker').resetValue(); + } + } + ); + + reaction( + () => $calculation.element('selectDealerBrokerRewardCondition').getValue(), + (dealerBrokerRewardConditionId) => { + if (dealerBrokerRewardConditionId) { + $calculation.element('selectDealerPerson').resetValue(); + } + } + ); +} + +export function validationReactions(store: RootStore, apolloClient: ApolloClient) {} diff --git a/stores/calculation/index.ts b/stores/calculation/index.ts index 101e45e..1a165c3 100644 --- a/stores/calculation/index.ts +++ b/stores/calculation/index.ts @@ -1,72 +1,118 @@ /* eslint-disable import/no-cycle */ -import type { Elements as ElementsActions } from 'Components/Calculation/config/map/actions'; +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 { BaseOption } from 'Elements/types'; +import { observable } from 'mobx'; import type RootStore from 'stores/root'; +import Validation from 'stores/validation'; +import type { RemoveError, ValidationParams } from '../validation/types'; import OptionsStore from './options'; import StatusStore from './statuses'; -import ValidationStore from './validation'; import ValuesStore from './values'; export default class CalculationStore { $values: ValuesStore; $status: StatusStore; $options: OptionsStore; - $validation: ValidationStore; + $validation: Partial>; constructor(rootStore: RootStore) { this.$values = new ValuesStore(rootStore); this.$status = new StatusStore(rootStore); this.$options = new OptionsStore(rootStore); - this.$validation = new ValidationStore(rootStore); + this.$validation = observable.object({}); } - resetElement = (elementName: Values.Elements) => { - this.resetElementValue(elementName); - this.$options.resetOptions(elementName); - this.$status.resetStatus(elementName); - this.$validation.clearErrors(elementName); + private createElementValidation = (elementName: E) => { + this.$validation[elementName] = new Validation({ + err_key: elementName, + err_title: titles[elementName], + }); }; - blockElement = (elementName: Values.Elements | ElementsActions) => { - this.$status.setStatus(elementName, 'Disabled'); - }; + element = (elementName: E) => ({ + reset: () => { + const valueName = getValueName(elementName); + this.$values.resetValue(valueName); - unblockElement = (elementName: Values.Elements | ElementsActions) => { - this.$status.setStatus(elementName, 'Default'); - }; + this.$options.resetOptions(elementName); + this.$status.resetStatus(elementName); + this.$validation[elementName]?.clearErrors(); - getElementValue(elementName: E) { - const valueName = getValueName(elementName); + return this.element(elementName); + }, - return this.$values.getValue(valueName) as Values.ElementsTypes[E]; - } + block: () => { + this.$status.setStatus(elementName, 'Disabled'); - setElementValue = (elementName: E, value: Values.ElementsTypes[E]) => { - const valueName = getValueName(elementName); - this.$values.setValue(valueName, value); - }; + return this.element(elementName); + }, - resetElementValue = (elementName: Values.Elements) => { - const valueName = getValueName(elementName); - this.$values.resetValue(valueName); - }; + unblock: () => { + this.$status.setStatus(elementName, 'Default'); - setElementOptions = ( - elementName: T, - options: BaseOption[] - ) => { - this.$options.setOptions(elementName, options); - }; + return this.element(elementName); + }, - resetElementOptions = (elementName: T) => { - this.$options.resetOptions(elementName); - }; + getValue: () => { + const valueName = getValueName(elementName); - getElementOption(elementName: T) { - const value = this.getElementValue(elementName); + return this.$values.getValue(valueName) as Values.ElementsTypes[E]; + }, - return this.$options.getOptions(elementName)?.find((x) => x.value === value); - } + setValue: (value: Values.ElementsTypes[E]) => { + const valueName = getValueName(elementName); + this.$values.setValue(valueName, value); + + return this.element(elementName); + }, + + resetValue: () => { + const valueName = getValueName(elementName); + this.$values.resetValue(valueName); + + return this.element(elementName); + }, + + getOption: () => { + const valueName = getValueName(elementName); + const value = this.$values.getValue(valueName) as Values.ElementsTypes[E]; + + return this.$options.getOptions(elementName)?.find((x) => x.value === value); + }, + + setOptions: (options: BaseOption[]) => { + this.$options.setOptions(elementName, options); + + return this.element(elementName); + }, + + resetOptions: () => { + this.$options.resetOptions(elementName); + + return this.element(elementName); + }, + + validate: ({ invalid, message }: ValidationParams) => { + if (!this.$validation[elementName]) this.createElementValidation(elementName); + + let removeError: RemoveError | undefined; + if (invalid) { + removeError = this.$validation[elementName]?.addError(message); + } else { + this.$validation[elementName]?.removeError(message); + } + + return { + err(callback: (removeError: RemoveError) => void) { + if (removeError) callback(removeError); + }, + }; + }, + + cleanErrors: () => { + this.$validation[elementName]?.clearErrors(); + }, + }); } diff --git a/stores/calculation/options/index.ts b/stores/calculation/options/index.ts index 3b2811c..cb829a8 100644 --- a/stores/calculation/options/index.ts +++ b/stores/calculation/options/index.ts @@ -30,13 +30,12 @@ export default class OptionsStore { /** * Проверяем, что значение есть в новом списке, иначе сбрасываем значение */ - const value = this.root.$calculation.getElementValue(elementName); + const value = this.root.$calculation.element(elementName).getValue(); if ( - // eslint-disable-next-line operator-linebreak !this.options[elementName]?.length || !this.options[elementName].some((x) => x.value === value) ) { - this.root.$calculation.resetElementValue(elementName); + this.root.$calculation.element(elementName).resetValue(); } }; diff --git a/stores/calculation/validation/hooks.js b/stores/calculation/validation/hooks.js index 61aeea7..fdf8120 100644 --- a/stores/calculation/validation/hooks.js +++ b/stores/calculation/validation/hooks.js @@ -3,10 +3,16 @@ import { useStore } from 'stores/hooks'; export function useValidation(elementName) { const { $calculation } = useStore(); - const validationResult = $calculation.$validation.getValidation(elementName); + const messages = $calculation.$validation[elementName]?.getMessages(); + + if (messages?.length) { + return { + isValid: false, + help: 'Некорректные данные', + }; + } return { - ...validationResult, - help: validationResult?.isValid === false ? 'Некорректные данные' : null, + isValid: true, }; } diff --git a/stores/calculation/validation/index.ts b/stores/calculation/validation/index.ts deleted file mode 100644 index 64fa0c7..0000000 --- a/stores/calculation/validation/index.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* eslint-disable object-curly-newline */ -import titles from 'Components/Calculation/config/elements-titles'; -import type { Elements } from 'Components/Calculation/config/map/values'; -import notification from 'Elements/notification'; -import { makeAutoObservable, observable } from 'mobx'; -import type RootStore from 'stores/root'; -import type { ElementsErrors, Error } from './types'; - -export default class ValidationStore { - root: RootStore; - elementsErrors: Partial = {}; - - constructor(rootStore: RootStore) { - makeAutoObservable(this); - this.root = rootStore; - } - - get hasErrors() { - return (Object.keys(this.elementsErrors) as Elements[]).some( - (elementName) => this.elementsErrors[elementName]?.length - ); - } - - getValidation(elementName: Elements) { - return { - isValid: !this.elementsErrors[elementName]?.length, - errors: this.elementsErrors[elementName]?.map((x) => x.text), - }; - } - - addError = (elementName: Elements, error: Error) => { - if (!this.elementsErrors[elementName]) this.elementsErrors[elementName] = observable([]); - - const errorIndex = this.elementsErrors[elementName]?.findIndex((x) => x.name === error.name); - const hasError = errorIndex !== undefined && errorIndex !== -1; - - if (!hasError) { - this.elementsErrors[elementName]?.push(error); - } else { - this.elementsErrors[elementName]?.splice(errorIndex, 1, error); - } - - notification.error({ - key: error.name, - message: `${titles[elementName]}`, - description: error.text, - }); - - return () => this.#removeError(elementName, error.name); - }; - - #removeError = (elementName: Elements, errorName: Error['name']) => { - const errorIndex = this.elementsErrors[elementName]?.findIndex((x) => x.name === errorName); - if (errorIndex) this.elementsErrors[elementName]?.splice(errorIndex, 1); - }; - - clearErrors = (elementName: Elements) => { - this.elementsErrors[elementName]?.clear(); - }; -} diff --git a/stores/calculation/validation/types.ts b/stores/calculation/validation/types.ts deleted file mode 100644 index 7917c33..0000000 --- a/stores/calculation/validation/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { Elements } from 'Components/Calculation/config/map/values'; -import type { IObservableArray } from 'mobx'; - -export type Error = { name: string; text: string }; -export type ElementsErrors = Record>; diff --git a/stores/calculation/values/index.ts b/stores/calculation/values/index.ts index 2213af8..a1b4112 100644 --- a/stores/calculation/values/index.ts +++ b/stores/calculation/values/index.ts @@ -1,6 +1,7 @@ /* eslint-disable object-curly-newline */ import defaultValues from 'config/default-values'; import { makeAutoObservable } from 'mobx'; +import { pick } from 'radash'; import type RootStore from '../../root'; import type { CalculationValues, Values } from './types'; @@ -17,6 +18,13 @@ export default class ValuesStore { this.values = initialValues; }; + setValues = (params: { values: CalculationValues; exclude: Values[] }) => { + const { values, exclude } = params; + + const savedValues = pick(this.values, exclude); + this.values = { ...values, ...savedValues }; + }; + getValue(valueName: V) { return this.values[valueName]; } diff --git a/stores/calculation/values/types.ts b/stores/calculation/values/types.ts index 1bb332a..74383c8 100644 --- a/stores/calculation/values/types.ts +++ b/stores/calculation/values/types.ts @@ -1,142 +1,5 @@ -export type CalculationValues = { - lead: string | null; - opportunity: string | null; - quote: string | null; - recalcWithRevision: boolean; - product: string | null; - clientRisk: string | null; - clientType: string | null; - leaseObjectPrice: number; - supplierCurrency: string | null; - supplierDiscountRub: number; - supplierDiscountPerc: number; - leasingPeriod: number; - firstPaymentPerc: number; - firstPaymentRub: number; - lastPaymentPerc: number; - lastPaymentRub: number; - lastPaymentRule: number | null; - importProgram: string | null; - importProgramSum: number; - addEquipmentPrice: number; - redemptionPaymentSum: number; - balanceHolder: number | null; - graphType: number | null; - parmentsDecreasePercent: number; - seasonType: number | null; - highSeasonStart: number | null; - comissionPerc: number; - comissionRub: number; - saleBonus: number; - IRR_Perc: number; - leaseObjectType: string | null; - deliveryTime: number | null; - leaseObjectCount: number; - withTrailer: boolean; - leaseObjectUsed: boolean; - maxMass: number; - countSeats: number; - maxSpeed: number; - brand: string | null; - model: string | null; - configuration: string | null; - leaseObjectYear: number; - engineType: number | null; - leaseObjectCategory: number | null; - leaseObjectMotorPower: number; - engineVolume: number; - leaseObjectUseFor: number | null; - dealer: string | null; - dealerPerson: string | null; - dealerRewardCondition: string | null; - dealerRewardSumm: number; - dealerBroker: string | null; - dealerBrokerRewardCondition: string | null; - dealerBrokerRewardSumm: number; - indAgent: string | null; - indAgentRewardCondition: string | null; - indAgentRewardSumm: number; - calcDoubleAgent: string | null; - calcDoubleAgentRewardCondition: string | null; - calcDoubleAgentRewardSumm: number; - calcBroker: string | null; - calcBrokerRewardCondition: string | null; - calcBrokerRewardSum: number; - calcFinDepartment: string | null; - finDepartmentRewardCondtion: string | null; - finDepartmentRewardSumm: number; - GPSBrand: string | null; - GPSModel: string | null; - regionRegistration: string | null; - townRegistration: string | null; - infuranceOPF: number | null; - insKaskoType: number | null; - insDecentral: boolean; - insFranchise: number; - insUnlimitDrivers: boolean; - insAgeDrivers: number; - insExpDrivers: number; - INNForCalc: number; - lastPaymentRedemption: boolean; - priceWithDiscount: boolean; - fullPriceWithDiscount: boolean; - costIncrease: boolean; - insurance: boolean; - registrationQuote: boolean; - technicalCardQuote: boolean; - NSIB: boolean; - quoteName: string | null; - quoteContactGender: number | null; - quoteRedemptionGraph: boolean; - showFinGAP: boolean; - tarif: string | null; - creditRate: number; - rate: string | null; - requirementTelematic: number | null; - minPriceChange: number; - maxPriceChange: number; - importerRewardPerc: number; - importerRewardRub: number; - disableChecks: boolean; - registration: string | null; - insNSIB: string | null; - technicalCard: string | null; - telematic: string | null; - tracker: string | null; - mileage: number; - calcType: number | null; - totalPayments: number; - objectRegistration: number | null; - objectRegionRegistration: string | null; - vehicleTaxInYear: number; - vehicleTaxInLeasingPeriod: number; - objectCategoryTax: number | null; - objectTypeTax: number | null; - typePTS: number | null; - legalClientRegion: string | null; - legalClientTown: string | null; - subsidy: string | null; - fuelCard: string | null; - leaseObjectPriceWthtVAT: number; - VATInLeaseObjectPrice: number; - engineHours: number; - bonusCoefficient: number; - - /** Link Values */ - kpUrl: string | null; - leadUrl: string | null; - opportunityUrl: string | null; - quoteUrl: string | null; - - /** Readonly Values */ - leaseObjectRiskName: string | null; - insKaskoPriceLeasePeriod: number; - irrInfo: string | null; - registrationDescription: string | null; - depreciationGroup: string | null; - subsidySum: number; - plPriceRub: number; - discountRub: number; -}; +import type ValuesSchema from 'config/schema/values'; +import type { z } from 'zod'; +export type CalculationValues = z.infer; export type Values = keyof CalculationValues; diff --git a/stores/process/index.ts b/stores/process/index.ts new file mode 100644 index 0000000..89037e0 --- /dev/null +++ b/stores/process/index.ts @@ -0,0 +1,9 @@ +import type { ObservableSet } from 'mobx'; +import { observable } from 'mobx'; + +export type Process = 'LoadKP' | 'ELT'; +export type ProcessStore = ObservableSet; + +export default function createProcessStore() { + return observable.set(); +} diff --git a/stores/root.ts b/stores/root.ts index 4c1f6eb..a5f372e 100644 --- a/stores/root.ts +++ b/stores/root.ts @@ -1,6 +1,8 @@ /* eslint-disable import/no-cycle */ import { enableStaticRendering } from 'mobx-react-lite'; import CalculationStore from './calculation'; +import type { ProcessStore } from './process'; +import createProcessStore from './process'; import ResultsStore from './results'; import TablesStore from './tables'; @@ -10,10 +12,12 @@ export default class RootStore { $calculation: CalculationStore; $results: ResultsStore; $tables: TablesStore; + $process: ProcessStore; constructor() { this.$calculation = new CalculationStore(this); this.$results = new ResultsStore(this); this.$tables = new TablesStore(this); + this.$process = createProcessStore(); } } diff --git a/stores/tables/fingap/index.ts b/stores/tables/fingap/index.ts index 857adc3..bd10568 100644 --- a/stores/tables/fingap/index.ts +++ b/stores/tables/fingap/index.ts @@ -2,7 +2,8 @@ import type * as FinGAP from 'Components/Calculation/Form/Insurance/FinGAPTable/ import type { IObservableArray } from 'mobx'; import { makeAutoObservable, observable } from 'mobx'; import type RootStore from 'stores/root'; -import Validation from '../validation'; +import Validation from '../../validation'; +import type { ValidationParams } from '../../validation/types'; export default class FinGAPTable { root: RootStore; @@ -13,13 +14,13 @@ export default class FinGAPTable { constructor(rootStore: RootStore) { this.selectedKeys = new Set(); this.risks = observable([]); - makeAutoObservable(this); this.validation = new Validation({ err_key: 'ERR_FINGAP_TABLE', err_title: 'Таблица рисков Safe Finance', }); + makeAutoObservable(this); this.root = rootStore; } @@ -37,6 +38,14 @@ export default class FinGAPTable { .reduce((sum, risk) => sum + risk.premium, 0); } + validate = ({ invalid, message }: ValidationParams) => { + if (invalid) { + this.validation?.addError(message); + } else { + this.validation?.removeError(message); + } + }; + clear = () => { this.risks.clear(); this.selectedKeys.clear(); diff --git a/stores/tables/insurance/index.ts b/stores/tables/insurance/index.ts index 5695445..ca24cca 100644 --- a/stores/tables/insurance/index.ts +++ b/stores/tables/insurance/index.ts @@ -3,7 +3,8 @@ import type * as Insurance from 'Components/Calculation/Form/Insurance/Insurance import * as insuranceTableConfig from 'config/tables/insurance-table'; import { makeAutoObservable } from 'mobx'; import type RootStore from 'stores/root'; -import Validation from '../validation'; +import Validation from '../../validation'; +import type { ValidationParams } from '../../validation/types'; export interface InsuranceTableData { values?: Insurance.RowValues[]; @@ -19,12 +20,13 @@ export default class InsuranceTable { statuses: Record = insuranceTableConfig.defaultStatuses; constructor(rootStore: RootStore) { - this.root = rootStore; this.validation = new Validation({ err_key: 'ERR_INSURANCE_TABLE', err_title: 'Таблица страхования', }); + makeAutoObservable(this); + this.root = rootStore; } hydrate = ({ @@ -49,6 +51,8 @@ export default class InsuranceTable { if (rowIndex >= 0) { this.values[rowIndex] = { ...this.values[rowIndex], ...rowValues }; } + + return this; }; getRowOptions(key: Insurance.Keys) { @@ -65,12 +69,81 @@ export default class InsuranceTable { setRowStatuses = (key: Insurance.Keys, rowStatuses: Partial) => { this.statuses[key] = { ...this.statuses[key], ...rowStatuses }; + + return this; }; - reset = () => { + validate = ({ invalid, message }: ValidationParams) => { + if (invalid) { + this.validation?.addError(message); + } else { + this.validation?.removeError(message); + } + }; + + resetTable = () => { this.values = insuranceTableConfig.defaultValues; this.options = insuranceTableConfig.defaultOptions; this.statuses = insuranceTableConfig.defaultStatuses; this.validation.clearErrors(); }; + + row = (key: K) => ({ + setValue: (valueName: V, value: Insurance.RowValues[V]) => { + const rowIndex = this.values.findIndex((x) => x.key === key); + + if (rowIndex >= 0) { + this.values[rowIndex] = { ...this.values[rowIndex], [valueName]: value }; + } + + return this.row(key); + }, + + block: (valueName: Insurance.Values) => { + this.statuses[key][valueName] = 'Disabled'; + + return this.row(key); + }, + + unblock: (valueName: Insurance.Values) => { + this.statuses[key][valueName] = 'Default'; + + return this.row(key); + }, + + setOptions: (valueName: V, options: Insurance.RowOptions[V]) => { + this.options[key][valueName] = options; + + return this.row(key); + }, + + resetValue: (valueName: Insurance.Values) => { + const rowIndex = this.values.findIndex((x) => x.key === key); + + if (rowIndex >= 0) { + const defaultValue = insuranceTableConfig.defaultValues[rowIndex][valueName]; + this.values[rowIndex] = { ...this.values[rowIndex], [valueName]: defaultValue }; + } + + return this.row(key); + }, + + resetStatus: (valueName: Insurance.Values) => { + this.statuses[key][valueName] = insuranceTableConfig.defaultStatuses[key][valueName]; + + return this.row(key); + }, + + resetOptions: (valueName: V) => { + this.options[key][valueName] = insuranceTableConfig.defaultOptions[key][valueName]; + + return this.row(key); + }, + + reset: (valueName: Insurance.Values) => { + this.row(key).resetValue(valueName).resetStatus(valueName).resetOptions(valueName); + + return this.row(key); + }, + }); } diff --git a/stores/tables/payments/index.ts b/stores/tables/payments/index.ts index d3c0eed..81b1abd 100644 --- a/stores/tables/payments/index.ts +++ b/stores/tables/payments/index.ts @@ -3,7 +3,8 @@ import type { IObservableArray } from 'mobx'; import { makeAutoObservable, observable, reaction } from 'mobx'; import type RootStore from 'stores/root'; -import Validation from '../validation'; +import Validation from '../../validation'; +import type { ValidationParams } from '../../validation/types'; import type { Row } from './types'; export default class PaymentsTable { @@ -13,14 +14,16 @@ export default class PaymentsTable { statuses: IObservableArray; constructor(rootStore: RootStore) { - this.root = rootStore; this.validation = new Validation({ err_key: 'ERR_PAYMENTS_TABLE', err_title: 'Таблица платежей', }); + this.values = observable([]); this.statuses = observable([]); + makeAutoObservable(this); + this.root = rootStore; /** * Синхронизируем длину массива значений и статусов @@ -70,6 +73,14 @@ export default class PaymentsTable { this.setStatuses(statuses); }; + validate = ({ invalid, message }: ValidationParams) => { + if (invalid) { + this.validation?.addError(message); + } else { + this.validation?.removeError(message); + } + }; + reset = () => { this.values.clear(); this.statuses.clear(); diff --git a/stores/validation/helper.ts b/stores/validation/helper.ts new file mode 100644 index 0000000..c31f5d5 --- /dev/null +++ b/stores/validation/helper.ts @@ -0,0 +1,20 @@ +import type { ObservableSet } from 'mobx'; +import { observable } from 'mobx'; +import type { RemoveError } from './types'; + +export default class ValidationHelper { + errors: ObservableSet; + + constructor() { + this.errors = observable.set(); + } + + add = (removeError: RemoveError) => { + this.errors.add(removeError); + }; + + removeErrors = () => { + this.errors.forEach((removeError) => removeError()); + this.errors.clear(); + }; +} diff --git a/stores/tables/validation.ts b/stores/validation/index.ts similarity index 60% rename from stores/tables/validation.ts rename to stores/validation/index.ts index 3b504da..69f6a56 100644 --- a/stores/tables/validation.ts +++ b/stores/validation/index.ts @@ -1,17 +1,13 @@ import notification from 'Elements/notification'; import { makeAutoObservable } from 'mobx'; - -type Params = { - err_key: string; - err_title: string; -}; +import type { ValidationConfig } from './types'; export default class Validation { - params: Params; + params: ValidationConfig; messages: Set; - constructor(params: Params) { - this.params = params; + constructor(config: ValidationConfig) { + this.params = config; this.messages = new Set(); makeAutoObservable(this); } @@ -24,24 +20,25 @@ export default class Validation { return [...this.messages]; } + removeError = (message: string) => { + this.messages.delete(message); + if (this.messages.size === 0) notification.close(this.params.err_key); + }; + addError = (message: string) => { this.messages.add(message); - const removeError = () => { - this.messages.delete(message); - notification.close(this.params.err_key); - }; - notification.error({ key: this.params.err_key, message: this.params.err_title, description: message, }); - return removeError; + return () => this.removeError(message); }; clearErrors = () => { this.messages.clear(); + notification.close(this.params.err_key); }; } diff --git a/stores/validation/types.ts b/stores/validation/types.ts new file mode 100644 index 0000000..21e8bc4 --- /dev/null +++ b/stores/validation/types.ts @@ -0,0 +1,11 @@ +export type ValidationConfig = { + err_key: string; + err_title: string; +}; + +export type ValidationParams = { + invalid: boolean; + message: string; +}; + +export type RemoveError = () => void; diff --git a/tools/mobx.ts b/tools/mobx.ts new file mode 100644 index 0000000..a36643f --- /dev/null +++ b/tools/mobx.ts @@ -0,0 +1,23 @@ +/* eslint-disable import/prefer-default-export */ +import type { IReactionDisposer } from 'mobx'; +import { autorun } from 'mobx'; + +export function makeDisposable( + createReaction: () => IReactionDisposer, + mustBeDisposed: () => boolean +) { + let disposer: IReactionDisposer | undefined; + + function cleanDisposer() { + disposer = undefined; + } + + autorun(() => { + if (mustBeDisposed()) { + if (disposer !== undefined) disposer(); + cleanDisposer(); + } else { + disposer = createReaction(); + } + }); +} diff --git a/trpc/client.ts b/trpc/client.ts new file mode 100644 index 0000000..574d56d --- /dev/null +++ b/trpc/client.ts @@ -0,0 +1,35 @@ +import { createTRPCProxyClient, httpBatchLink } from '@trpc/client'; +import { createTRPCNext } from '@trpc/next'; +import SuperJSON from 'superjson'; +import type { AppRouter } from './routers'; + +function getBaseUrl() { + if (typeof window !== 'undefined') { + return process.env.NEXT_PUBLIC_BASE_PATH ?? ''; + } + + return `http://localhost:${process.env.PORT ?? 3000}${process.env.NEXT_PUBLIC_BASE_PATH ?? ''}`; +} + +export const trpcClient = createTRPCNext({ + config() { + return { + links: [ + httpBatchLink({ + url: `${getBaseUrl()}/api/trpc`, + }), + ], + transformer: SuperJSON, + }; + }, + ssr: true, +}); + +export const trpcPureClient = createTRPCProxyClient({ + links: [ + httpBatchLink({ + url: `${getBaseUrl()}/api/trpc`, + }), + ], + transformer: SuperJSON, +}); diff --git a/trpc/routers/index.ts b/trpc/routers/index.ts new file mode 100644 index 0000000..190e228 --- /dev/null +++ b/trpc/routers/index.ts @@ -0,0 +1,10 @@ +import { t } from '../server'; +import quoteRouter from './quote'; + +const appRouter = t.router({ + quote: quoteRouter, +}); + +export type AppRouter = typeof appRouter; + +export default appRouter; diff --git a/trpc/routers/quote.ts b/trpc/routers/quote.ts new file mode 100644 index 0000000..b85ff3e --- /dev/null +++ b/trpc/routers/quote.ts @@ -0,0 +1,32 @@ +import defaultValues from 'config/default-values'; +import ValuesSchema from 'config/schema/values'; +import getSupplierAgentsDataFromKP from 'process/supplier-agent/get-kp-values'; +import { z } from 'zod'; +import { t } from '../server'; + +const quoteRouter = t.router({ + getValues: t.procedure + .input( + z.object({ + values: ValuesSchema.pick({ + quote: true, + }), + }) + ) + .output( + z.object({ + values: ValuesSchema, + }) + ) + .query(async ({ input }) => { + const { values } = await getSupplierAgentsDataFromKP({ + quoteId: input.values.quote!, + }); + + return { + values: Object.assign(defaultValues, values), + }; + }), +}); + +export default quoteRouter; diff --git a/trpc/server.ts b/trpc/server.ts new file mode 100644 index 0000000..6adacac --- /dev/null +++ b/trpc/server.ts @@ -0,0 +1,7 @@ +/* eslint-disable import/prefer-default-export */ +import { initTRPC } from '@trpc/server'; +import SuperJSON from 'superjson'; + +export const t = initTRPC.create({ + transformer: SuperJSON, +}); diff --git a/trpc/types.ts b/trpc/types.ts new file mode 100644 index 0000000..b52d155 --- /dev/null +++ b/trpc/types.ts @@ -0,0 +1,5 @@ +import type { trpcClient, trpcPureClient } from './client'; + +export type TRPCClient = typeof trpcClient; + +export type TRPCPureClient = typeof trpcPureClient; diff --git a/yarn.lock b/yarn.lock index 839e250..847303c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2078,17 +2078,17 @@ dependencies: tslib "^2.4.0" -"@tanstack/query-core@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.13.0.tgz#89153096d1fce42c0294fa1d1ae4b3e72aa5353b" - integrity sha512-PzmLQcEgC4rl2OzkiPHYPC9O79DFcMGaKsOzDEP+U4PJ+tbkcEP+Z+FQDlfvX8mCwYC7UNH7hXrQ5EdkGlJjVg== +"@tanstack/query-core@4.14.1": + version "4.14.1" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.14.1.tgz#a74c4da03e79a8be07fa5ab2ebc12865146915e2" + integrity sha512-mUejKoFDe4NZB8jQJR1uuAl6IwvkUpOD2m8NcuTVPOu0pcxeeFPdrnHaljwOEFPtlqXoiiIIQGYy6whjCMN+iQ== -"@tanstack/react-query@^4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.13.0.tgz#13797d590a6c0708545881e38aea5eb39b960c28" - integrity sha512-dI/5hJ/pGQ74P5hxBLC9h6K0/Cap2T3k0ZjjjFLBCNnohDYgl7LNmMopzrRzBHk2mMjf2hgXHIzcKNG8GOZ5hg== +"@tanstack/react-query@^4.14.1": + version "4.14.1" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.14.1.tgz#336545119b191e2096c394a3f2df2744cdc5e041" + integrity sha512-cRgNzigw4GSPwGlTEkXi8hi/xgUnSEt9jCkiC8oAT3PEIdsQ50onZcpXd+JNJcZk2RTh8KM1fGyWz6xYLiY8bg== dependencies: - "@tanstack/query-core" "4.13.0" + "@tanstack/query-core" "4.14.1" use-sync-external-store "^1.2.0" "@testing-library/dom@^8.5.0": @@ -2139,6 +2139,28 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== +"@trpc/client@^10.0.0-rc.3": + version "10.0.0-rc.3" + resolved "https://registry.yarnpkg.com/@trpc/client/-/client-10.0.0-rc.3.tgz#22cea038dd5e38ce0e39ff4a339793bb5808ab18" + integrity sha512-gZYVfZra1YB2DluDY+GcIrL7KqPXCI9y0mF4utXYAUAl+jrxfLyG63pCv30USRRYlwwSKaoLJNpjQB9k05aYaw== + +"@trpc/next@^10.0.0-rc.3": + version "10.0.0-rc.3" + resolved "https://registry.yarnpkg.com/@trpc/next/-/next-10.0.0-rc.3.tgz#2585aa271c2916afb2f7291583c9299c324f799d" + integrity sha512-L9sHV93dPA4lZ/I8opfn3BJONnlnnJzJERggv7srt8H3aEhKVlNWIqxciNLHGXSq9q0C9i3Q6ND4F5kpRSQ5YA== + dependencies: + react-ssr-prepass "^1.5.0" + +"@trpc/react-query@^10.0.0-rc.3": + version "10.0.0-rc.3" + resolved "https://registry.yarnpkg.com/@trpc/react-query/-/react-query-10.0.0-rc.3.tgz#34a0449c62544522d1fa0f07844d1f11cf38eb55" + integrity sha512-nEBqkTdKsd+vIE4RuDRX/b8U5ayxENp0G2vnh/fn4hiIszrLiPTGvnhGCZm/fT2GGW5nk7EEBcqf2o0z3r8Ftg== + +"@trpc/server@^10.0.0-rc.3": + version "10.0.0-rc.3" + resolved "https://registry.yarnpkg.com/@trpc/server/-/server-10.0.0-rc.3.tgz#4ddc4410305b17a47248b3bfa881df3b52202e60" + integrity sha512-aSs3uDQ5wumwVjtxj855WLDjlDC+v50QoqHzvuptI33NhJZV7meu0pU2EJkrSZXFt27CSNfP9o2ZPfoReoPUuw== + "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" @@ -3897,6 +3919,13 @@ copy-anything@^2.0.1: dependencies: is-what "^3.14.1" +copy-anything@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-3.0.2.tgz#7189171ff5e1893b2287e8bf574b8cd448ed50b1" + integrity sha512-CzATjGXzUQ0EvuvgOCI6A4BGOo2bcVx8B+eC2nF862iv9fopnPQwlrbACakNCHRIJbCSBj+J/9JeDf60k64MkA== + dependencies: + is-what "^4.1.6" + copy-to-clipboard@^3.2.0: version "3.3.1" resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" @@ -5928,6 +5957,11 @@ is-what@^3.14.1: resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1" integrity sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA== +is-what@^4.1.6: + version "4.1.7" + resolved "https://registry.yarnpkg.com/is-what/-/is-what-4.1.7.tgz#c41dc1d2d2d6a9285c624c2505f61849c8b1f9cc" + integrity sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ== + is-windows@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -8315,6 +8349,11 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +react-ssr-prepass@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/react-ssr-prepass/-/react-ssr-prepass-1.5.0.tgz#bc4ca7fcb52365e6aea11cc254a3d1bdcbd030c5" + integrity sha512-yFNHrlVEReVYKsLI5lF05tZoHveA5pGzjFbFJY/3pOqqjGOmMmqx83N4hIjN2n6E1AOa+eQEUxs3CgRnPmT0RQ== + react@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" @@ -9178,6 +9217,13 @@ styled-system@^5.0.0, styled-system@^5.1.5: "@styled-system/variant" "^5.1.5" object-assign "^4.1.1" +superjson@^1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/superjson/-/superjson-1.11.0.tgz#f6e2ae0d8fbac61c3fca09ab6739ac9678414d1b" + integrity sha512-6PfAg1FKhqkwWvPb2uXhH4MkMttdc17eJ91+Aoz4s1XUEDZFmLfFx/xVA3wgkPxAGy5dpozgGdK6V/n20Wj9yg== + dependencies: + copy-anything "^3.0.2" + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -10028,3 +10074,8 @@ zen-observable@0.8.15, zen-observable@^0.8.0: version "0.8.15" resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== + +zod@^3.19.1: + version "3.19.1" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.19.1.tgz#112f074a97b50bfc4772d4ad1576814bd8ac4473" + integrity sha512-LYjZsEDhCdYET9ikFu6dVPGp2YH9DegXjdJToSzD9rO6fy4qiRYFoyEYwps88OseJlPyl2NOe2iJuhEhL7IpEA==