diff --git a/src/client/Components/Calculation/ELT/Content/Components/Controls/BottomControls.jsx b/src/client/Components/Calculation/ELT/Content/Components/Controls/BottomControls.jsx index e486652..7525746 100644 --- a/src/client/Components/Calculation/ELT/Content/Components/Controls/BottomControls.jsx +++ b/src/client/Components/Calculation/ELT/Content/Components/Controls/BottomControls.jsx @@ -1,5 +1,6 @@ import { message } from 'antd'; import Button from 'client/Elements/Button'; +import { openNotification } from 'client/Elements/Notification'; import { useStores } from 'client/hooks/useStores'; import { Process } from 'core/types/Calculation/Store/process'; import { ElementStatus } from 'core/types/statuses'; @@ -10,11 +11,19 @@ const BottomControls = ({ insType, onSelectRow, selectedKey }) => { const handleSelectRow = () => { const { calculationProcess } = calculationStore.stores; calculationProcess.addProcess(Process.ELT); - ELTStore[insType].setKey(selectedKey); - onSelectRow.call(calculationStore, insType, selectedKey); - calculationProcess.deleteProcess(Process.ELT); + const selectRes = onSelectRow.call(calculationStore, insType, selectedKey); - message.success({ content: 'Выбранный расчет ЭЛТ применен' }); + if (selectRes && selectRes.message) { + openNotification({ + type: 'warning', + title: 'Внимание', + description: selectRes.message, + })(); + } else { + ELTStore[insType].setKey(selectedKey); + message.success({ content: 'Выбранный расчет ЭЛТ применен' }); + } + calculationProcess.deleteProcess(Process.ELT); }; return ( diff --git a/src/client/Components/Calculation/ELT/Content/Components/Controls/TopControls.jsx b/src/client/Components/Calculation/ELT/Content/Components/Controls/TopControls.jsx index bd32e19..710394b 100644 --- a/src/client/Components/Calculation/ELT/Content/Components/Controls/TopControls.jsx +++ b/src/client/Components/Calculation/ELT/Content/Components/Controls/TopControls.jsx @@ -1,49 +1,26 @@ import ReloadOutlined from '@ant-design/icons/lib/icons/ReloadOutlined'; -import { getTitle } from 'client/Containers/Calculation/lib/elements/tools'; import Button from 'client/Elements/Button'; -import { openNotification } from 'client/Elements/Notification'; import { PrimaryText } from 'client/Elements/Text'; import { useStores } from 'client/hooks/useStores'; import { Flex } from 'client/UIKit/grid'; import { ElementStatus } from 'core/types/statuses'; import { useState } from 'react'; import { resetIns } from '../../lib/resetIns'; -import { validate } from '../../lib/validation'; +import validate from '../../lib/validation'; -const TopControls = ({ title, insType, fetchData, requiredFields }) => { +const TopControls = ({ title, insType, fetchData, validation }) => { const [isPending, setIsPending] = useState(false); const { calculationStore } = useStores(); - function getMissingFields() { - const missingFields = validate.call(calculationStore, requiredFields); - if (missingFields && missingFields.length > 0) { - const elementsNames = missingFields.map(fieldName => getTitle(fieldName)); - return elementsNames; - } - } - const handleGetData = () => { - const missingFieldsTitles = getMissingFields(); - if (missingFieldsTitles && missingFieldsTitles.length > 0) { - const message = String.prototype.concat( - 'Не заполнены поля: ', - missingFieldsTitles.join(', '), - ); - openNotification({ - type: 'error', - title: 'Ошибка во время расчета ЭЛТ', - description: message, - })(); - return; - } + const validationRes = validate.call(calculationStore, validation); + if (!validationRes) return; resetIns.call(calculationStore, insType); setIsPending(true); - fetchData.call(calculationStore).finally( - setTimeout(() => { - setIsPending(false); - }, 1500), - ); + fetchData.call(calculationStore).finally(() => { + setIsPending(false); + }); }; return ( diff --git a/src/client/Components/Calculation/ELT/Content/Kasko/index.jsx b/src/client/Components/Calculation/ELT/Content/Kasko/index.jsx index 7b9a425..4eccfc5 100644 --- a/src/client/Components/Calculation/ELT/Content/Kasko/index.jsx +++ b/src/client/Components/Calculation/ELT/Content/Kasko/index.jsx @@ -4,7 +4,7 @@ import composeRequest from './lib/composeRequest'; import tableConfig from './lib/config'; import convertEltResult from './lib/convertEltResult'; import onSelectRow from './lib/onSelectRow'; -import { requiredFields } from './lib/validation'; +import validation from './lib/validation'; const insType = 'kasko'; @@ -14,5 +14,5 @@ export default buildELTContent({ fetchData: fetchData(insType, composeRequest, convertEltResult), onSelectRow, tableConfig, - requiredFields, + validation, }); diff --git a/src/client/Components/Calculation/ELT/Content/Kasko/lib/composeRequest.ts b/src/client/Components/Calculation/ELT/Content/Kasko/lib/composeRequest.ts index d14ff8c..5cabef9 100644 --- a/src/client/Components/Calculation/ELT/Content/Kasko/lib/composeRequest.ts +++ b/src/client/Components/Calculation/ELT/Content/Kasko/lib/composeRequest.ts @@ -37,8 +37,8 @@ const mapCategory = { const getSpecified = value => !isNull(value); export default function (this: ICalculationStore) { - const region = this.getOption('selectRegionRegistration'); - const city = this.getOption('selectTownRegistration'); + const region = this.getOption('selectLegalClientRegion'); + const city = this.getOption('selectLegalClientTown'); const kladr = get(city, 'evo_kladr_id') || get(region, 'evo_kladr_id'); const brandId = this.getOption('selectBrand')?.evo_id; const modelId = this.getOption('selectModel')?.evo_id; diff --git a/src/client/Components/Calculation/ELT/Content/Kasko/lib/config/columns.ts b/src/client/Components/Calculation/ELT/Content/Kasko/lib/config/columns.ts index 7485c9a..0450501 100644 --- a/src/client/Components/Calculation/ELT/Content/Kasko/lib/config/columns.ts +++ b/src/client/Components/Calculation/ELT/Content/Kasko/lib/config/columns.ts @@ -1,6 +1,8 @@ +import { InsTableColumn } from 'client/Components/Calculation/ELT/Content/lib/config/table'; +import { Outlined } from 'client/Components/Spinner'; import { formatMoney } from 'core/tools/format'; -const columns: { title: string; dataIndex: string; [key: string]: any }[] = [ +const columns: InsTableColumn[] = [ { title: 'Страховая компания', dataIndex: 'name', @@ -18,6 +20,11 @@ const columns: { title: string; dataIndex: string; [key: string]: any }[] = [ dataIndex: 'totalFranchise', render: value => formatMoney(value, 'RUB'), }, + { + title: undefined, + dataIndex: 'isFetching', + render: isFetching => (isFetching ? Outlined : null), + }, ]; export default columns; diff --git a/src/client/Components/Calculation/ELT/Content/Kasko/lib/onSelectRow.ts b/src/client/Components/Calculation/ELT/Content/Kasko/lib/onSelectRow.ts index 62428c9..d1a8b1a 100644 --- a/src/client/Components/Calculation/ELT/Content/Kasko/lib/onSelectRow.ts +++ b/src/client/Components/Calculation/ELT/Content/Kasko/lib/onSelectRow.ts @@ -1,3 +1,7 @@ +import { + MAX_FRANCHISE, + MAX_INSURANCE, +} from 'core/constants/stores/Calculation/limits'; import { ICalculationStore } from 'core/types/Calculation/Store'; export default function ( @@ -5,11 +9,21 @@ export default function ( insType, selectedKey: string, ) { - const selectedRow = this.stores.ELTStore[insType].list.find( - x => x.key === selectedKey, - ); + const selectedRow = this.stores.ELTStore[insType].getCompany(selectedKey); const { accountid, kaskoSum, totalFranchise } = selectedRow; + if (totalFranchise > MAX_FRANCHISE) { + return { + message: `Выбранный расчет ЭЛТ превышает максимально допустимое значение по франшизе (${MAX_FRANCHISE})`, + }; + } + + if (kaskoSum > MAX_INSURANCE) { + return { + message: `Выбранный расчет ЭЛТ превышает максимально допустимое значение по стоимости КАСКО (${MAX_INSURANCE})`, + }; + } + this.setValue('insFranchise', totalFranchise); this.setTableRows( @@ -22,17 +36,5 @@ export default function ( }, insCost: { value: kaskoSum }, }, - // { - // insuranceCompany: { - // value: accountid, - // }, - // insCost: { value: goSum }, - // }, - // { - // insuranceCompany: { - // value: accountid, - // }, - // insCost: { value: nsSum }, - // }, ]); } diff --git a/src/client/Components/Calculation/ELT/Content/Kasko/lib/validation.ts b/src/client/Components/Calculation/ELT/Content/Kasko/lib/validation.ts index b9561d6..f16bf9b 100644 --- a/src/client/Components/Calculation/ELT/Content/Kasko/lib/validation.ts +++ b/src/client/Components/Calculation/ELT/Content/Kasko/lib/validation.ts @@ -1,8 +1,10 @@ -import { ElementsNames } from 'core/types/Calculation/Store/elements'; +import { + ElementsNames, + TElements, +} from 'core/types/Calculation/Store/elements'; +import { ValidationCondition } from 'core/validation/validate'; export const requiredFields: ElementsNames[] = [ - 'selectRegionRegistration', - 'selectTownRegistration', 'selectBrand', 'selectModel', 'cbxLeaseObjectUsed', @@ -17,3 +19,61 @@ export const requiredFields: ElementsNames[] = [ 'selectLeaseObjectUseFor', 'tbxINNForCalc', ]; + +export const conditions: TElements = { + selectLeaseObjectType: calculationStore => { + const leaseObjectType = calculationStore.getOption('selectLeaseObjectType'); + if (['9', '11'].includes(leaseObjectType?.evo_id || '')) { + return { + isValid: false, + message: `По данному Типу предмета лизинга возможен только индивидуальный запрос тарифов КАСКО и ОСАГО. Просьба обратиться на адрес strakhovka@evoleasing.ru`, + }; + } + return { + isValid: true, + }; + }, + selectLeaseObjectUseFor: calculationStore => { + const leaseObjectUseFor = calculationStore.getValue('leaseObjectUseFor'); + if ( + [100000001, 100000002, 100000003, 100000004, 100000006].includes( + leaseObjectUseFor, + ) + ) { + return { + isValid: false, + message: `По данной цели использования возможен только индивидуальный запрос тарифов КАСКО и ОСАГО. Просьба обратиться на адрес strakhovka@evoleasing.ru`, + }; + } + return { isValid: true }; + }, + selectLegalClientRegion: calculationStore => { + const objectRegistration = calculationStore.getValue('objectRegistration'); + if (objectRegistration === 100000000) { + const legalClientRegion = calculationStore.getValue('legalClientRegion'); + if (!legalClientRegion) { + return { + isValid: false, + message: 'Не указан Регион по юр.адресу клиента', + }; + } + } + return { + isValid: true, + }; + }, +}; + +export const resetFields: ElementsNames[] = [ + ...requiredFields, + ...(Object.keys(conditions) as ElementsNames[]), + 'tbxInsAgeDrivers', + 'tbxInsExpDrivers', + 'selectLegalClientTown', + 'selectLegalClientRegion', +]; + +export default { + requiredFields, + conditions, +}; diff --git a/src/client/Components/Calculation/ELT/Content/Osago/index.jsx b/src/client/Components/Calculation/ELT/Content/Osago/index.jsx index aca7123..27bbb2e 100644 --- a/src/client/Components/Calculation/ELT/Content/Osago/index.jsx +++ b/src/client/Components/Calculation/ELT/Content/Osago/index.jsx @@ -4,7 +4,7 @@ import composeRequest from './lib/composeRequest'; import tableConfig from './lib/config'; import convertEltResult from './lib/convertEltResult'; import onSelectRow from './lib/onSelectRow'; -import { requiredFields } from './lib/validation'; +import validation from './lib/validation'; const insType = 'osago'; @@ -14,5 +14,5 @@ export default buildELTContent({ fetchData: fetchData(insType, composeRequest, convertEltResult), onSelectRow, tableConfig, - requiredFields, + validation, }); diff --git a/src/client/Components/Calculation/ELT/Content/Osago/lib/composeRequest.ts b/src/client/Components/Calculation/ELT/Content/Osago/lib/composeRequest.ts index cde4973..4bb10d7 100644 --- a/src/client/Components/Calculation/ELT/Content/Osago/lib/composeRequest.ts +++ b/src/client/Components/Calculation/ELT/Content/Osago/lib/composeRequest.ts @@ -39,9 +39,11 @@ const mapSubCategoryBuilder = (leaseObjectUseFor, maxMass, countSeats) => ({ const getSpecified = value => !isNull(value); export default function (this: ICalculationStore) { - const region = this.getOption('selectRegionRegistration'); const city = this.getOption('selectTownRegistration'); - const kladr = get(city, 'evo_kladr_id') || get(region, 'evo_kladr_id'); + let kladr = '7700000000000'; + if (this.getValue('objectRegistration') === 100000001) { + kladr = get(city, 'evo_kladr_id', kladr); + } const brandId = this.getOption('selectBrand')?.evo_id; const modelId = this.getOption('selectModel')?.evo_id; diff --git a/src/client/Components/Calculation/ELT/Content/Osago/lib/config/columns.ts b/src/client/Components/Calculation/ELT/Content/Osago/lib/config/columns.ts index d4c2901..d5a4db0 100644 --- a/src/client/Components/Calculation/ELT/Content/Osago/lib/config/columns.ts +++ b/src/client/Components/Calculation/ELT/Content/Osago/lib/config/columns.ts @@ -1,6 +1,8 @@ +import { InsTableColumn } from 'client/Components/Calculation/ELT/Content/lib/config/table'; +import { Outlined } from 'client/Components/Spinner'; import { formatMoney } from 'core/tools/format'; -const columns: { title: string; dataIndex: string; [key: string]: any }[] = [ +const columns: InsTableColumn[] = [ { title: 'Страховая компания', dataIndex: 'name', @@ -13,6 +15,11 @@ const columns: { title: string; dataIndex: string; [key: string]: any }[] = [ sortDirections: ['descend', 'ascend'], render: value => formatMoney(value), }, + { + title: undefined, + dataIndex: 'isFetching', + render: isFetching => (isFetching ? Outlined : null), + }, ]; export default columns; diff --git a/src/client/Components/Calculation/ELT/Content/Osago/lib/onSelectRow.ts b/src/client/Components/Calculation/ELT/Content/Osago/lib/onSelectRow.ts index 92050f9..0f25b6c 100644 --- a/src/client/Components/Calculation/ELT/Content/Osago/lib/onSelectRow.ts +++ b/src/client/Components/Calculation/ELT/Content/Osago/lib/onSelectRow.ts @@ -1,3 +1,4 @@ +import { MAX_INSURANCE } from 'core/constants/stores/Calculation/limits'; import { ICalculationStore } from 'core/types/Calculation/Store'; export default function ( @@ -5,10 +6,16 @@ export default function ( insType, selectedKey: string, ) { - const selectedRow = this.stores.ELTStore[insType].list.find( - x => x.key === selectedKey, - ); + const selectedRow = this.stores.ELTStore[insType].getCompany(selectedKey); + const { accountid, premiumSum } = selectedRow; + + if (premiumSum > MAX_INSURANCE) { + return { + message: `Выбранный расчет ЭЛТ превышает максимально допустимое значение по стоимости ОСАГО (${MAX_INSURANCE})`, + }; + } + this.setTableRow( 'tableInsurance', 0, diff --git a/src/client/Components/Calculation/ELT/Content/Osago/lib/validation.ts b/src/client/Components/Calculation/ELT/Content/Osago/lib/validation.ts index fc43ff6..d31a3de 100644 --- a/src/client/Components/Calculation/ELT/Content/Osago/lib/validation.ts +++ b/src/client/Components/Calculation/ELT/Content/Osago/lib/validation.ts @@ -1,8 +1,11 @@ -import { ElementsNames } from 'core/types/Calculation/Store/elements'; +import { + ElementsNames, + TElements, +} from 'core/types/Calculation/Store/elements'; +import { ValidationCondition } from 'core/validation/validate'; +import { conditions as kaskoConditions } from '../../Kasko/lib/validation'; export const requiredFields: ElementsNames[] = [ - 'selectRegionRegistration', - 'selectTownRegistration', 'selectBrand', 'selectModel', 'tbxLeaseObjectYear', @@ -15,4 +18,37 @@ export const requiredFields: ElementsNames[] = [ 'cbxWithTrailer', 'selectLeaseObjectCategory', 'tbxINNForCalc', + 'radioObjectRegistration', ]; + +const conditions: TElements = { + selectTownRegistration: calculationStore => { + const objectRegistration = calculationStore.getValue('objectRegistration'); + if (objectRegistration === 100000001) { + const townRegistration = calculationStore.getValue('townRegistration'); + if (!townRegistration) { + return { + isValid: false, + message: 'Не указан Город регистрации', + }; + } + } + return { + isValid: true, + }; + }, +}; + +export const resetFields: ElementsNames[] = [ + ...requiredFields, + ...(Object.keys(conditions) as ElementsNames[]), + 'selectLegalClientTown', + 'selectLegalClientRegion', + 'radioObjectRegistration', + 'selectTownRegistration', +]; + +export default { + requiredFields, + conditions: Object.assign(conditions, kaskoConditions), +}; diff --git a/src/client/Components/Calculation/ELT/Content/lib/config/table.ts b/src/client/Components/Calculation/ELT/Content/lib/config/table.ts index b399cec..17f6a35 100644 --- a/src/client/Components/Calculation/ELT/Content/lib/config/table.ts +++ b/src/client/Components/Calculation/ELT/Content/lib/config/table.ts @@ -14,3 +14,9 @@ export default { pagination: false, size: 'small', } as TableProps; + +export type InsTableColumn = { + title?: string; + dataIndex: string; + [key: string]: any; +}; diff --git a/src/client/Components/Calculation/ELT/Content/lib/requests.ts b/src/client/Components/Calculation/ELT/Content/lib/requests.ts index c5e3fd9..f00e9aa 100644 --- a/src/client/Components/Calculation/ELT/Content/lib/requests.ts +++ b/src/client/Components/Calculation/ELT/Content/lib/requests.ts @@ -19,8 +19,10 @@ export const fetchData = (insType: string, composeRequest, convertEltResult) => const request = composeRequest.call(this); const requests = ELTStore[insType].list.map( - (company: IAccount, i: number) => - new Promise((resolve, reject) => { + (company: IAccount, i: number) => { + //@ts-ignore + company.isFetching = true; + return new Promise((resolve, reject) => { ELTService[insType] .getCalculation( { @@ -47,8 +49,13 @@ export const fetchData = (insType: string, composeRequest, convertEltResult) => }) .catch(err => { reject(err); + }) + .finally(() => { + //@ts-ignore + company.isFetching = false; }); - }), + }); + }, ); return Promise.race(requests); diff --git a/src/client/Components/Calculation/ELT/Content/lib/validation.ts b/src/client/Components/Calculation/ELT/Content/lib/validation.ts index d89b766..fcebf32 100644 --- a/src/client/Components/Calculation/ELT/Content/lib/validation.ts +++ b/src/client/Components/Calculation/ELT/Content/lib/validation.ts @@ -1,16 +1,85 @@ -import { getValueName } from 'client/Containers/Calculation/lib/elements/tools'; +import { getTitle } from 'client/Containers/Calculation/lib/elements/tools'; +import { openNotification } from 'client/Elements/Notification'; +import { pipe } from 'core/tools/func'; import { ICalculationStore } from 'core/types/Calculation/Store'; -import { ElementsNames } from 'core/types/Calculation/Store/elements'; -import { isNil } from 'lodash'; +import { + ElementsNames, + TElements, +} from 'core/types/Calculation/Store/elements'; +import CONDITIONS from 'core/validation/conditions'; +import { + convertToValidationResult, + getValue, + validate, + ValidationCondition, +} from 'core/validation/validate'; -export function validate( - this: ICalculationStore, - requiredFields: ElementsNames[], -) { - const missingValues = requiredFields.filter(fieldName => { - const valueName = getValueName(fieldName); - const value = this.getValue(valueName); - return isNil(value); - }); - return missingValues; +type ELTValidation = { + requiredFields: ElementsNames[]; + conditions?: TElements; +}; + +export default function (this: ICalculationStore, validation: ELTValidation) { + const { requiredFields, conditions: customConditions } = validation; + + const requiredFieldsConditions = requiredFields.reduce( + (ac: TElements, elementName) => { + ac[elementName] = pipe( + getValue, + CONDITIONS.IS_NULL, + convertToValidationResult, + ); + return ac; + }, + {}, + ); + + const requiredFieldsResult = validate(this, requiredFieldsConditions); + let missingElementsNames: string[] = []; + (Object.keys(requiredFieldsResult) as ElementsNames[]).forEach( + elementName => { + if (requiredFieldsResult[elementName]?.isValid === false) { + const elementTitle = getTitle(elementName); + missingElementsNames.push(elementTitle); + } + }, + ); + + if (missingElementsNames.length > 0) { + openNotification({ + type: 'error', + title: 'Ошибка во время расчета ЭЛТ', + description: String.prototype.concat( + 'Не заполнены поля: ', + missingElementsNames.join(', '), + ), + })(); + return false; + } + + if (customConditions) { + const customConditionsResult = validate(this, customConditions); + let messages: string[] = []; + (Object.keys(customConditionsResult) as ElementsNames[]).forEach( + elementName => { + const validationResult = customConditionsResult[elementName]; + if (validationResult?.isValid === false && validationResult.message) { + messages.push(validationResult.message); + } + }, + ); + if (messages && messages.length > 0) { + messages.forEach(message => { + if (message) + openNotification({ + type: 'error', + title: 'Ошибка во время расчета ЭЛТ', + description: message, + })(); + }); + return false; + } + } + + return true; } diff --git a/src/client/Components/Spinner.jsx b/src/client/Components/Spinner.jsx index cf4acd9..f7ab91f 100644 --- a/src/client/Components/Spinner.jsx +++ b/src/client/Components/Spinner.jsx @@ -4,4 +4,4 @@ import { Spin } from 'antd'; export default Spin; const loadingOutlined = ; -export const Outlined = () => ; +export const Outlined = ; diff --git a/src/client/Containers/Calculation/Sections/sectionsList.ts b/src/client/Containers/Calculation/Sections/sectionsList.ts index 21da004..8b5c069 100644 --- a/src/client/Containers/Calculation/Sections/sectionsList.ts +++ b/src/client/Containers/Calculation/Sections/sectionsList.ts @@ -286,7 +286,7 @@ const sections: ISection[] = [ 'tbxInsAgeDrivers', 'tbxInsExpDrivers', 'cbxWithTrailer', - // 'tbxINNForCalc', + 'tbxINNForCalc', // 'btnDriversApplication', ], }, @@ -294,8 +294,8 @@ const sections: ISection[] = [ elements: [ 'selectGPSBrand', 'selectGPSModel', - 'selectRegionRegistration', - 'selectTownRegistration', + 'selectLegalClientRegion', + 'selectLegalClientTown', // 'selectInfuranceOPF', 'tbxInsKaskoPriceLeasePeriod', ], @@ -312,20 +312,20 @@ const sections: ISection[] = [ }, ], }, - // { - // title: 'ЭЛТ', - // groups: [ - // { - // title: 'Расчет страховки ЭЛТ', - // style: { columnsNumber: 1 }, - // blocks: [ - // { - // elements: ['componentElt'], - // }, - // ], - // }, - // ], - // }, + { + title: 'ЭЛТ', + groups: [ + { + title: 'Расчет страховки ЭЛТ', + style: { columnsNumber: 1 }, + blocks: [ + { + elements: ['componentElt'], + }, + ], + }, + ], + }, { title: 'Доп. продукты', groups: [ diff --git a/src/client/Containers/Calculation/lib/elements/components.ts b/src/client/Containers/Calculation/lib/elements/components.ts index cdc2c62..042505a 100644 --- a/src/client/Containers/Calculation/lib/elements/components.ts +++ b/src/client/Containers/Calculation/lib/elements/components.ts @@ -169,6 +169,8 @@ const elementsComponents: TElements = { selectObjectTypeTax: Select, radioTypePTS: Radio, labelRegistrationDescription: Label, + selectLegalClientRegion: Select, + selectLegalClientTown: Select, }; const tablesComponents: StoreTables = { diff --git a/src/client/Containers/Calculation/lib/elements/elementsProps.ts b/src/client/Containers/Calculation/lib/elements/elementsProps.ts index ef8f25d..4b148aa 100644 --- a/src/client/Containers/Calculation/lib/elements/elementsProps.ts +++ b/src/client/Containers/Calculation/lib/elements/elementsProps.ts @@ -1,14 +1,15 @@ import DownloadOutlined from '@ant-design/icons/lib/icons/DownloadOutlined'; import InsuranceTag from 'client/Components/Calculation/InsuranceTag'; +import { MAX_FRANCHISE } from 'core/constants/stores/Calculation/limits'; import { currentYear } from 'core/tools/date'; import { formatMoney, formatNumber } from 'core/tools/format'; -import { compose } from 'core/tools/func'; +import { pipe } from 'core/tools/func'; import { round } from 'core/tools/num'; import { validateEmail, validateInn, validateKpp, - validatePhone + validatePhone, } from 'core/tools/validate'; import { ElementProps } from 'core/types/Calculation/components'; import { TElements } from 'core/types/Calculation/Store/elements'; @@ -192,10 +193,10 @@ const elementsProps: TElements = { formatter: formatNumber, }, tbxEngineVolume: { - min: '0.00', - max: '99.99', - step: '0.50', - precision: 2, + min: '0.0000', + max: '99.9999', + step: '0.5', + precision: 4, formatter: formatNumber, }, tbxMaxMass: { @@ -262,7 +263,7 @@ const elementsProps: TElements = { }, tbxInsFranchise: { min: '0', - max: '75000', + max: MAX_FRANCHISE, step: '10000.00', precision: 2, formatter: formatNumber, @@ -409,7 +410,12 @@ const elementsProps: TElements = { precision: 2, formatter: formatNumber, }, - + selectLegalClientRegion: { + showSearch: true, + }, + selectLegalClientTown: { + showSearch: true, + }, }; const resultElementsProps: TElements = Object.assign( @@ -430,7 +436,8 @@ const resultElementsProps: TElements = Object.assign( ].reduce( (ac, a) => ({ ...ac, - [a]: { middleware: value => compose(round, formatMoney)(value || 0) }, + //@ts-ignore + [a]: { middleware: value => pipe(round, formatMoney)(value) }, }), {}, ), @@ -442,7 +449,7 @@ const resultElementsProps: TElements = Object.assign( ].reduce( (ac, a) => ({ ...ac, - [a]: { middleware: value => round(value || 0) }, + [a]: { middleware: value => round(value) }, }), {}, ), diff --git a/src/client/Containers/Calculation/lib/elements/tables/insurance.ts b/src/client/Containers/Calculation/lib/elements/tables/insurance.ts index b6967ca..e911ac6 100644 --- a/src/client/Containers/Calculation/lib/elements/tables/insurance.ts +++ b/src/client/Containers/Calculation/lib/elements/tables/insurance.ts @@ -6,6 +6,7 @@ import { insuranceKaskoDefaultFilter, insuranceOsagoDefaultFilter, } from 'core/constants/stores/Calculation/filters'; +import { MAX_INSURANCE } from 'core/constants/stores/Calculation/limits'; import { formatNumber } from 'core/tools/format'; import { ITable, @@ -47,7 +48,7 @@ const columns: TableColumn[] = [ Component: InputNumber, props: { min: '0.00', - max: '2500000.00', + max: MAX_INSURANCE, step: '1000.00', precision: 2, formatter: formatNumber, diff --git a/src/client/Containers/Calculation/lib/elements/tables/results.ts b/src/client/Containers/Calculation/lib/elements/tables/results.ts index 001a35f..2a55ced 100644 --- a/src/client/Containers/Calculation/lib/elements/tables/results.ts +++ b/src/client/Containers/Calculation/lib/elements/tables/results.ts @@ -1,6 +1,7 @@ +//@ts-nocheck import Label from 'client/Elements/Label'; import { formatMoney } from 'core/tools/format'; -import { compose } from 'core/tools/func'; +import { pipe } from 'core/tools/func'; import { round } from 'core/tools/num'; import { ITable, @@ -14,7 +15,7 @@ const columns: TableColumn[] = [ title: 'Сумма платежа', Component: Label, props: { - middleware: value => compose(round, formatMoney)(value || 0), + middleware: value => pipe(round, formatMoney)(value), }, }, { @@ -22,7 +23,7 @@ const columns: TableColumn[] = [ title: 'НДС к возмещению', Component: Label, props: { - middleware: value => compose(round, formatMoney)(value || 0), + middleware: value => pipe(round, formatMoney)(value), }, }, { @@ -30,7 +31,7 @@ const columns: TableColumn[] = [ title: 'Сумма досрочного выкупа', Component: Label, props: { - middleware: value => compose(round, formatMoney)(value || 0), + middleware: value => pipe(round, formatMoney)(value), }, }, ]; diff --git a/src/client/Containers/Calculation/lib/elements/titles.ts b/src/client/Containers/Calculation/lib/elements/titles.ts index 01bdcac..12335f8 100644 --- a/src/client/Containers/Calculation/lib/elements/titles.ts +++ b/src/client/Containers/Calculation/lib/elements/titles.ts @@ -134,6 +134,8 @@ export const elementsTitles: TElements = { radioTypePTS: 'Тип ПТС', labelRegistrationDescription: 'Описание регистрации', tbxINNForCalc: 'ИНН контрагента', + selectLegalClientRegion: 'Регион по юр.адресу клиента', + selectLegalClientTown: 'Город по юр.адресу клиента', }; const resultsTitles: TElements = { diff --git a/src/client/Containers/Calculation/lib/elements/tools.ts b/src/client/Containers/Calculation/lib/elements/tools.ts index da5862a..f119469 100644 --- a/src/client/Containers/Calculation/lib/elements/tools.ts +++ b/src/client/Containers/Calculation/lib/elements/tools.ts @@ -4,8 +4,8 @@ import { ValuesNames } from 'core/types/Calculation/Store/values'; import { elementsTitles } from './titles'; import { elementsValues } from './values'; -export function getValueName(fieldName: ElementsNames): ValuesNames { - return elementsValues[fieldName]; +export function getValueName(elementName: ElementsNames): ValuesNames { + return elementsValues[elementName]; } export function getFieldName(valueName: ValuesNames): ElementsNames { @@ -14,6 +14,6 @@ export function getFieldName(valueName: ValuesNames): ElementsNames { ); } -export function getTitle(fieldName: ElementsNames): string { - return elementsTitles[fieldName]; +export function getTitle(elementName: ElementsNames): string { + return elementsTitles[elementName]; } diff --git a/src/client/Containers/Calculation/lib/elements/values.ts b/src/client/Containers/Calculation/lib/elements/values.ts index 8a12aec..69b920b 100644 --- a/src/client/Containers/Calculation/lib/elements/values.ts +++ b/src/client/Containers/Calculation/lib/elements/values.ts @@ -133,6 +133,8 @@ export const elementsValues: TElements = { selectObjectCategoryTax: 'objectCategoryTax', selectObjectTypeTax: 'objectTypeTax', radioTypePTS: 'typePTS', + selectLegalClientRegion: 'legalClientRegion', + selectLegalClientTown: 'legalClientTown', }; const resultElementsValues: TElements = { diff --git a/src/client/Containers/Calculation/lib/fetchData/queries/optionsQuery.ts b/src/client/Containers/Calculation/lib/fetchData/queries/optionsQuery.ts index ac6ec17..de78d5c 100644 --- a/src/client/Containers/Calculation/lib/fetchData/queries/optionsQuery.ts +++ b/src/client/Containers/Calculation/lib/fetchData/queries/optionsQuery.ts @@ -60,6 +60,14 @@ const query = gql` evo_oktmo evo_kladr_id } + selectLegalClientRegion: evo_regions(statecode: $statecode) { + evo_name + evo_regionid + evo_fias_id + evo_businessunit_evolution + evo_oktmo + evo_kladr_id + } selectAccount: accounts( evo_account_type: $account_account_type statecode: $statecode @@ -321,6 +329,7 @@ const toOptions = [ 'selectRate', 'selectLeaseObjectType', 'selectObjectRegionRegistration', + 'selectLegalClientRegion', ]; export default { diff --git a/src/client/Elements/Button.jsx b/src/client/Elements/Button.jsx index 13b8913..eb2c2c1 100644 --- a/src/client/Elements/Button.jsx +++ b/src/client/Elements/Button.jsx @@ -1,14 +1,19 @@ import { Button as AntButton } from 'antd'; +import { ACTION_DELAY } from 'core/constants/debounce'; import { ElementStatus } from 'core/types/statuses'; +import { throttle } from 'lodash'; const Button = ({ status, action, text, ...props }) => { + const throttledAction = action + ? throttle(action, ACTION_DELAY, { trailing: false }) + : undefined; return ( { - if (action) action(); + if (throttledAction) throttledAction(); }} > {text} diff --git a/src/client/Elements/InputNumber.jsx b/src/client/Elements/InputNumber.jsx index 640fdd9..d5b21e8 100644 --- a/src/client/Elements/InputNumber.jsx +++ b/src/client/Elements/InputNumber.jsx @@ -51,7 +51,7 @@ const InputNumber = ({ onChange={value => setCurrentValue(value)} value={value} /> - {status === ElementStatus.Loading && } + {status === ElementStatus.Loading && Outlined} ); }; diff --git a/src/client/stores/CalculationStore/Effects/actions/calculate/prepareData.ts b/src/client/stores/CalculationStore/Effects/actions/calculate/prepareData.ts index 65a4d48..5435402 100644 --- a/src/client/stores/CalculationStore/Effects/actions/calculate/prepareData.ts +++ b/src/client/stores/CalculationStore/Effects/actions/calculate/prepareData.ts @@ -96,7 +96,7 @@ export default function (this: ICalculationStore): IPreparedData { ? ((preparedValues.nmper as number) - 2) * (0.0234 / ((1 - 1 / 1.0234) ^ ((preparedValues.nmper as number) - 2))) : 1; - preparedValues.loanRate = (values.creditRate as number) / 100; + preparedValues.loanRate = parseFloat(values.creditRate) / 100; preparedValues.balanceHolder = values.balanceHolder; preparedValues.dogDate = preparedValues.calcDate; preparedValues.paymentDateNew = undefined; diff --git a/src/client/stores/CalculationStore/Effects/actions/calculate/validate/elements.ts b/src/client/stores/CalculationStore/Effects/actions/calculate/validate/elements.ts index ef6abb2..eaaf6ce 100644 --- a/src/client/stores/CalculationStore/Effects/actions/calculate/validate/elements.ts +++ b/src/client/stores/CalculationStore/Effects/actions/calculate/validate/elements.ts @@ -1,49 +1,95 @@ -import { getValueName } from 'client/Containers/Calculation/lib/elements/tools'; +import { pipe } from 'core/tools/func'; import { ICalculationStore } from 'core/types/Calculation/Store'; import { ElementsNames, TElements, } from 'core/types/Calculation/Store/elements'; +import CONDITIONS from 'core/validation/conditions'; +import { + convertToValidationResult, + getValue, + validate, + ValidationCondition, +} from 'core/validation/validate'; -const CONDITIONS = { - IS_NULL: value => value === undefined || value === null, - LESS_ZERO: value => value < 0, - LESS_OR_EQUALS_ZERO: value => value <= 0, -}; - -const CUSTOM_CONDITIONS: TElements< - (calculationStore: ICalculationStore) => boolean -> = { +const customConditions: TElements = { selectLeaseObjectCategory: calculationStore => { - return ( - calculationStore.values['selectLeaseObjectCategory'] && - ['6', '9', '10'].includes( - calculationStore.getOption('selectLeaseObjectType')?.evo_id || '', - ) + const leaseObjectType = calculationStore.getOption('selectLeaseObjectType'); + const leaseObjectCategory = calculationStore.getValue( + 'leaseObjectCategory', ); + if ( + CONDITIONS.IS_NULL(leaseObjectCategory) && + !['6', '9', '10'].includes(leaseObjectType?.evo_id || '') + ) { + return { + isValid: false, + }; + } + return { isValid: true }; }, selectQuote: calculationStore => { const quote = calculationStore.getValue('quote'); - return ( + if ( calculationStore.getValue('recalcWithRevision') === true && CONDITIONS.IS_NULL(quote) - ); + ) { + return { + isValid: false, + }; + } + return { isValid: true }; }, tbxVehicleTaxInYear: calculationStore => { const objectRegistration = calculationStore.getValue('objectRegistration'); - if (objectRegistration === 100000001) { - const vehicleTaxInYear = calculationStore.getValue('vehicleTaxInYear'); - return CONDITIONS.LESS_OR_EQUALS_ZERO(vehicleTaxInYear); + const vehicleTaxInYear = calculationStore.getValue('vehicleTaxInYear'); + if ( + objectRegistration === 100000001 && + CONDITIONS.LESS_OR_EQUALS_ZERO(vehicleTaxInYear) + ) { + return { + isValid: false, + }; } - return false; + return { isValid: true }; }, radioTypePTS: calculationStore => { const objectRegistration = calculationStore.getValue('objectRegistration'); - if (objectRegistration === 100000001) { - const typePTS = calculationStore.getValue('typePTS'); - return CONDITIONS.IS_NULL(typePTS); + const typePTS = calculationStore.getValue('typePTS'); + if (objectRegistration === 100000001 && CONDITIONS.IS_NULL(typePTS)) { + return { + isValid: false, + }; } - return false; + return { isValid: true }; + }, + selectTownRegistration: calculationStore => { + const objectRegistration = calculationStore.getValue('objectRegistration'); + const townRegistration = calculationStore.getValue('townRegistration'); + if ( + objectRegistration === 100000001 && + CONDITIONS.IS_NULL(townRegistration) + ) { + return { + isValid: false, + }; + } + return { isValid: true }; + }, + selectObjectRegionRegistration: calculationStore => { + const objectRegistration = calculationStore.getValue('objectRegistration'); + const objectRegionRegistration = calculationStore.getValue( + 'objectRegionRegistration', + ); + if ( + objectRegistration === 100000001 && + CONDITIONS.IS_NULL(objectRegionRegistration) + ) { + return { + isValid: false, + }; + } + return { isValid: true }; }, }; @@ -58,11 +104,10 @@ const elementsValidations: TElements = { selectDealer: CONDITIONS.IS_NULL, selectDealerPerson: CONDITIONS.IS_NULL, selectRegionRegistration: CONDITIONS.IS_NULL, - selectTownRegistration: CONDITIONS.IS_NULL, + // selectTownRegistration: CONDITIONS.IS_NULL, selectTarif: CONDITIONS.IS_NULL, // selectRate: VALIDATIONS.IS_NULL, selectRegistration: CONDITIONS.IS_NULL, - selectLeaseObjectCategory: CUSTOM_CONDITIONS.selectLeaseObjectCategory, // selectSeasonType: valueName => // CalculationStore.getValue('graphType') === 100000003 && // VALIDATIONS.IS_NULL(valueName), @@ -75,24 +120,29 @@ const elementsValidations: TElements = { // tbxFirstPaymentPerc: VALIDATIONS.IS_NULL, // tbxFirstPaymentRub: VALIDATIONS.IS_NULL, tbxLeaseObjectCount: CONDITIONS.LESS_OR_EQUALS_ZERO, - selectQuote: CUSTOM_CONDITIONS.selectQuote, - tbxVehicleTaxInYear: CUSTOM_CONDITIONS.tbxVehicleTaxInYear, - radioTypePTS: CUSTOM_CONDITIONS.radioTypePTS, - selectObjectRegionRegistration: CONDITIONS.IS_NULL, + selectLegalClientRegion: CONDITIONS.IS_NULL, }; +const elementsConditions = (Object.keys( + elementsValidations, +) as ElementsNames[]).reduce( + (ac: TElements, elementName) => { + ac[elementName] = pipe( + getValue, + elementsValidations[elementName], + convertToValidationResult, + ); + return ac; + }, + {}, +); + +const conditions = Object.assign({}, customConditions, elementsConditions); + export default function (this: ICalculationStore) { - (Object.keys(elementsValidations) as ElementsNames[]).forEach(elementName => { - const valueName = getValueName(elementName); - const value = this.getValue(valueName); - const condition = elementsValidations[elementName]; - let conditionRes; - if (Object.keys(CUSTOM_CONDITIONS).includes(elementName)) { - conditionRes = condition(this); - } else { - conditionRes = condition(value); - } - //@ts-ignore - this.setValidation(elementName, !conditionRes); + const validationResult = validate(this, conditions); + (Object.keys(validationResult) as ElementsNames[]).forEach(elementName => { + const isValid = validationResult[elementName]?.isValid; + if (isValid !== undefined) this.setValidation(elementName, isValid); }); } diff --git a/src/client/stores/CalculationStore/Effects/actions/createKP.ts b/src/client/stores/CalculationStore/Effects/actions/createKP.ts index d6f376b..ffd9b48 100644 --- a/src/client/stores/CalculationStore/Effects/actions/createKP.ts +++ b/src/client/stores/CalculationStore/Effects/actions/createKP.ts @@ -12,7 +12,7 @@ import calculate from './calculate'; export default async function (this: ICalculationStore) { const { values, tables } = this; - const { calculationUrls } = this.stores; + const { calculationUrls, ELTStore } = this.stores; const calculationRes = await calculate.call(this); if (!calculationRes) { @@ -29,7 +29,6 @@ export default async function (this: ICalculationStore) { return resObj; }); - console.log('insurances', insurances); const { columns, postValues, @@ -38,27 +37,33 @@ export default async function (this: ICalculationStore) { } = calculationRes; const domainname = UserStore.getDomainName(); - console.log('domainname', domainname); - console.log('values', values); - //@ts-ignore - console.log('insKaskoPriceLeasePeriod', this.insKaskoPriceLeasePeriod()); - CrmService.createKp({ - domainName: domainname, - calculation: { - insurances, - preparedValues, - preparedPayments, - columns, - postValues, - calculationValues: { - ...values, - insKaskoPriceLeasePeriod: customValues.insKaskoPriceLeasePeriod.call( - this, - ), + const elt = Object.assign( + {}, + ...['osago', 'kasko'].map(insType => ({ + [insType]: toJS(ELTStore[insType].getCompany()), + })), + ); + + CrmService.createKp( + toJS({ + domainName: domainname, + calculation: { + insurances, + preparedValues, + preparedPayments, + columns, + postValues, + calculationValues: { + ...values, + insKaskoPriceLeasePeriod: customValues.insKaskoPriceLeasePeriod.call( + this, + ), + }, }, - }, - }) + elt, + }), + ) .then(({ quoteid }) => { CrmService.crmgqlquery({ query: gql` diff --git a/src/client/stores/CalculationStore/Effects/computed.js b/src/client/stores/CalculationStore/Effects/computed.js index f8cfe17..b87e7ea 100644 --- a/src/client/stores/CalculationStore/Effects/computed.js +++ b/src/client/stores/CalculationStore/Effects/computed.js @@ -50,7 +50,7 @@ const computedEffects = { }, irrInfo() { const tarif = this.getOption('selectTarif'); - if (tarif) { + if (tarif && tarif.evo_min_irr && tarif.evo_max_irr) { return `Min: ${tarif.evo_min_irr}% - Max: ${tarif.evo_max_irr}%`; } return '-'; diff --git a/src/client/stores/CalculationStore/Effects/lib/queries.js b/src/client/stores/CalculationStore/Effects/lib/queries.js index 5b8c6c0..1ce4d99 100644 --- a/src/client/stores/CalculationStore/Effects/lib/queries.js +++ b/src/client/stores/CalculationStore/Effects/lib/queries.js @@ -15,4 +15,6 @@ evo_seats evo_year offerprintformapi evo_regionid +evo_legal_regionid +evo_legal_townid `; diff --git a/src/client/stores/CalculationStore/Effects/reactions/eltReactions.ts b/src/client/stores/CalculationStore/Effects/reactions/eltReactions.ts index 4d05d98..88428d6 100644 --- a/src/client/stores/CalculationStore/Effects/reactions/eltReactions.ts +++ b/src/client/stores/CalculationStore/Effects/reactions/eltReactions.ts @@ -1,8 +1,8 @@ import { message } from 'antd'; -import { requiredFields as kaskoRequiredFields } from 'client/Components/Calculation/ELT/Content/Kasko/lib/validation'; +import { resetFields as kaskoResetFields } from 'client/Components/Calculation/ELT/Content/Kasko/lib/validation'; import { cancelRequests } from 'client/Components/Calculation/ELT/Content/lib/requests'; import { resetIns } from 'client/Components/Calculation/ELT/Content/lib/resetIns'; -import { requiredFields as osagoRequiredFields } from 'client/Components/Calculation/ELT/Content/Osago/lib/validation'; +import { resetFields as osagoResetFields } from 'client/Components/Calculation/ELT/Content/Osago/lib/validation'; import { getValueName } from 'client/Containers/Calculation/lib/elements/tools'; import { TCalculationProcess } from 'client/stores/CalculationStore/subStores/calculationProcess'; import { IReactionEffect } from 'core/types/Calculation/Store/effect'; @@ -13,16 +13,12 @@ import { Process } from 'core/types/Calculation/Store/process'; const resetConf = [ { insType: 'osago', - requiredFields: osagoRequiredFields, + resetFields: osagoResetFields, tableRowNumber: 0, }, { insType: 'kasko', - requiredFields: [ - ...kaskoRequiredFields, - 'tbxInsAgeDrivers', - 'tbxInsExpDrivers', - ], + resetFields: kaskoResetFields, tableRowNumber: 1, }, ]; @@ -34,14 +30,14 @@ const RESET_MESSAGES = { const eltReactions: IReactionEffect[] = [ ...resetConf.map( - ({ insType, requiredFields }) => ( + ({ insType, resetFields }) => ( calculationStore: ICalculationStore, calculationProcess: TCalculationProcess, ) => ({ expression: () => { return calculationStore.getValues( //@ts-ignore - (requiredFields as ElementsNames[]).map(getValueName), + (resetFields as ElementsNames[]).map(getValueName), ); }, effect: () => { diff --git a/src/client/stores/CalculationStore/Effects/reactions/gibddReactions.ts b/src/client/stores/CalculationStore/Effects/reactions/gibddReactions.ts index ef1cf7a..f77e1b0 100644 --- a/src/client/stores/CalculationStore/Effects/reactions/gibddReactions.ts +++ b/src/client/stores/CalculationStore/Effects/reactions/gibddReactions.ts @@ -390,7 +390,7 @@ const gibddReactions: IReactionEffect[] = [ }, }), - calculationStore => ({ + (calculationStore, calculationProcess) => ({ expression: () => { return { lead: calculationStore.getOption('selectLead'), @@ -399,6 +399,9 @@ const gibddReactions: IReactionEffect[] = [ }; }, effect: ({ lead, opportunity, objectRegistration }) => { + if (calculationProcess.hasProcess(Process.LoadKp)) { + return; + } calculationStore.setFilter('selectRegionRegistration', undefined); calculationStore.setStatus( 'selectRegionRegistration', @@ -437,6 +440,147 @@ const gibddReactions: IReactionEffect[] = [ calculationStore.setValue('regionRegistration', evo_regionid); }, }), + + (calculationStore, calculationProcess) => ({ + expression: () => { + return { + lead: calculationStore.getOption('selectLead'), + opportunity: calculationStore.getOption('selectOpportunity'), + objectRegistration: calculationStore.getValue('objectRegistration'), + regionRegistration: calculationStore.getValue('regionRegistration'), + }; + }, + effect: ({ lead, opportunity, objectRegistration, regionRegistration }) => { + if (calculationProcess.hasProcess(Process.LoadKp)) { + return; + } + calculationStore.setStatus( + 'selectLegalClientRegion', + ElementStatus.Default, + ); + + let evo_legal_regionid = calculationStore.getOption('selectQuote') + ?.evo_legal_regionid; + if (objectRegistration === 100000000) { + evo_legal_regionid = regionRegistration; + calculationStore.setStatus( + 'selectLegalClientRegion', + ElementStatus.Disabled, + ); + } else { + const evo_region_fias_id = get( + lead.accountidData || opportunity.accountidData, + 'evo_address_legalidData.evo_region_fias_id', + undefined, + ); + if (evo_region_fias_id) { + calculationStore.setValue('legalClientRegion', evo_region_fias_id); + calculationStore.setStatus( + 'selectLegalClientRegion', + ElementStatus.Disabled, + ); + + const targetLegalClientRegion = calculationStore.getOption( + 'selectLegalClientRegion', + { + evo_fias_id: evo_region_fias_id, + }, + ); + if (targetLegalClientRegion) { + evo_legal_regionid = targetLegalClientRegion.evo_regionid; + } + } + } + calculationStore.setValue('legalClientRegion', evo_legal_regionid); + }, + options: { + fireImmediately: true, + }, + }), + + (calculationStore, calculationProcess) => ({ + expression: () => { + return calculationStore.getValues([ + 'regionRegistration', + 'objectRegistration', + 'legalClientTown', + ]); + }, + effect: ({ objectRegistration, legalClientTown }) => { + if (calculationProcess.hasProcess(Process.LoadKp)) { + return; + } + if (objectRegistration === 100000001) { + calculationStore.setStatus( + 'selectTownRegistration', + ElementStatus.Default, + ); + calculationStore.setFilter('selectTownRegistration', towns => + towns.filter(town => town.evo_businessunit_evolution === true), + ); + } else { + calculationStore.setStatus( + 'selectTownRegistration', + ElementStatus.Disabled, + ); + calculationStore.setFilter('selectTownRegistration', undefined); + calculationStore.setValue('townRegistration', legalClientTown); + } + }, + }), + + (calculationStore, calculationProcess) => ({ + expression: () => { + return { + lead: calculationStore.getOption('selectLead'), + opportunity: calculationStore.getOption('selectOpportunity'), + townOptions: calculationStore.getOptions('selectLegalClientTown'), + }; + }, + effect: ({ lead, opportunity, townOptions }) => { + if ( + calculationProcess.hasProcess(Process.LoadKp) || + !townOptions || + townOptions.length === 0 + ) { + return; + } + calculationStore.setStatus( + 'selectLegalClientTown', + ElementStatus.Default, + ); + + let evo_legal_townid = calculationStore.getOption('selectQuote') + ?.evo_legal_townid; + + const evo_city_fias_id = get( + lead.accountidData || opportunity.accountidData, + 'evo_address_legalidData.evo_city_fias_id', + undefined, + ); + if (evo_city_fias_id) { + calculationStore.setStatus( + 'selectLegalClientTown', + ElementStatus.Disabled, + ); + + const targetLegalClientTown = calculationStore.getOption( + 'selectLegalClientTown', + { + evo_fias_id: evo_city_fias_id, + }, + ); + if (targetLegalClientTown) { + evo_legal_townid = targetLegalClientTown.evo_townid; + calculationStore.setValue( + 'legalClientTown', + targetLegalClientTown.evo_townid, + ); + } + } + calculationStore.setValue('legalClientTown', evo_legal_townid); + }, + }), ]; export default gibddReactions; diff --git a/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/index.ts b/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/index.ts index edebfe4..9d0814f 100644 --- a/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/index.ts +++ b/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/index.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ import { message } from 'antd'; +import { resetIns } from 'client/Components/Calculation/ELT/Content/lib/resetIns'; import { elementsValues } from 'client/Containers/Calculation/lib/elements/values'; import { openNotification } from 'client/Elements/Notification'; import initialValues from 'client/stores/CalculationStore/config/initialValues'; @@ -12,6 +13,7 @@ import { Process } from 'core/types/Calculation/Store/process'; import { ValuesNames } from 'core/types/Calculation/Store/values'; import { IEvoGraph } from 'core/types/Entities/crmEntities'; import { ElementStatus } from 'core/types/statuses'; +import { get, isNil } from 'lodash'; import NIL from 'uuid/dist/nil'; import { getKpPropName } from './mapKpToValues'; import optionsQuery from './optionsQuery'; @@ -60,6 +62,7 @@ const loadKpReaction: IReactionEffect = calculationStore => ({ indAgent, INNForCalc, regionRegistration, + creditRate, } = calculationStore.values; calculationStore.setStatus('selectQuote', ElementStatus.Disabled); @@ -112,6 +115,7 @@ const loadKpReaction: IReactionEffect = calculationStore => ({ quote.evo_fin_department_accountid || NIL, evo_gps_brandid: quote.evo_gps_brandid || NIL, evo_regionid: quote.evo_regionid || NIL, + evo_legal_regionid: quote.evo_legal_regionid || NIL, }, toOptions: [ 'selectModel', @@ -126,6 +130,7 @@ const loadKpReaction: IReactionEffect = calculationStore => ({ 'selectFinDepartmentRewardCondtion', 'selectGPSModel', 'selectTownRegistration', + 'selectLegalClientTown', ], }); @@ -299,11 +304,76 @@ const loadKpReaction: IReactionEffect = calculationStore => ({ vehicleTaxInYear, INNForCalc, regionRegistration, + creditRate, }); message.success({ content: `КП ${quote?.evo_quotename || ''} загружено!`, }); + + const { ELTStore } = calculationStore.stores; + // ELT KASKO + { + resetIns.call(calculationStore, 'kasko'); + const kaskoIndex = ELTStore.kasko.list.findIndex( + x => x.accountid === quote.evo_kasko_accountid, + ); + + if (kaskoIndex !== undefined) { + const mapQuoteToELTKasko = { + key: 'evo_kasko_accountid', + accountid: 'evo_kasko_accountid', + kaskoSum: 'evo_kasko_price', + requestId: 'evo_id_elt_kasko', + skCalcId: 'evo_id_kasko_calc', + totalFranchise: 'evo_franchise', + }; + + let row = {}; + Object.keys(mapQuoteToELTKasko).forEach(rowFieldName => { + const quoteFieldName = mapQuoteToELTKasko[rowFieldName]; + const quoteValue = get(quote, quoteFieldName); + if (!isNil(quoteValue)) row[rowFieldName] = quoteValue; + }); + if ( + Object.keys(mapQuoteToELTKasko).length === + Object.keys(row).length + ) { + ELTStore.addToCompanyRes('kasko', kaskoIndex, row); + ELTStore.kasko.setKey(quote.evo_kasko_accountid); + } + } + } + + // ELT OSAGO + { + resetIns.call(calculationStore, 'osago'); + const osagoIndex = ELTStore.osago.list.findIndex( + x => x.accountid === quote.evo_osago_accountid, + ); + if (osagoIndex !== undefined) { + const mapQuoteToELTOsago = { + key: 'evo_osago_accountid', + accountid: 'evo_osago_accountid', + numCalc: 'evo_id_elt_osago', + premiumSum: 'evo_osago_price', + }; + + let row = {}; + Object.keys(mapQuoteToELTOsago).forEach(rowFieldName => { + const quoteFieldName = mapQuoteToELTOsago[rowFieldName]; + const quoteValue = get(quote, quoteFieldName); + if (!isNil(quoteValue)) row[rowFieldName] = quoteValue; + }); + if ( + Object.keys(mapQuoteToELTOsago).length === + Object.keys(row).length + ) { + ELTStore.addToCompanyRes('osago', osagoIndex, row); + ELTStore.osago.setKey(quote.evo_osago_accountid); + } + } + } } }) .catch(err => { diff --git a/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/mapKpToValues.ts b/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/mapKpToValues.ts index 9169519..71113ec 100644 --- a/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/mapKpToValues.ts +++ b/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/mapKpToValues.ts @@ -22,7 +22,7 @@ const mapKPtoValues: TValues = { saleBonus: 'evo_sale_bonus', leasingPeriod: 'evo_period', tarif: 'evo_tarifid', - creditRate: 'evo_rate', + // creditRate: 'evo_rate', IRR_Perc: 'evo_msfo_irr', leaseObjectType: 'evo_leasingobject_typeid', deliveryTime: 'evo_delivery_time', @@ -93,6 +93,8 @@ const mapKPtoValues: TValues = { objectTypeTax: 'evo_vehicle_type_tax', typePTS: 'evo_pts_type', townRegistration: 'evo_townid', + legalClientRegion: 'evo_legal_regionid', + legalClientTown: 'evo_legal_townid', }; export function getKpPropName(valueName: ValuesNames) { diff --git a/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/optionsQuery.js b/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/optionsQuery.js index a478e69..e0ab7c4 100644 --- a/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/optionsQuery.js +++ b/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/optionsQuery.js @@ -16,6 +16,7 @@ export default gql` $findepartment_accountid: Uuid! $evo_gps_brandid: Uuid! $evo_regionid: Uuid! + $evo_legal_regionid: Uuid! ) { selectModel: evo_models(statecode: $statecode, evo_brandid: $evo_brandid) { evo_id @@ -134,5 +135,15 @@ export default gql` evo_townid evo_fias_id } + selectLegalClientTown: evo_towns( + statecode: $statecode + evo_regionid: $evo_legal_regionid + ) { + evo_name + evo_townid + evo_fias_id + evo_kladr_id + evo_businessunit_evolution + } } `; diff --git a/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/quoteQuery.js b/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/quoteQuery.js index 757ea25..ec1f581 100644 --- a/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/quoteQuery.js +++ b/src/client/stores/CalculationStore/Effects/reactions/loadKpReaction/quoteQuery.js @@ -46,6 +46,14 @@ export default gql` evo_double_agent_accountid evo_broker_accountid evo_fin_department_accountid + + evo_kasko_accountid + evo_kasko_price + evo_id_elt_kasko + evo_id_kasko_calc + evo_franchise + evo_id_elt_osago + evo_osago_price } } `; diff --git a/src/client/stores/CalculationStore/Effects/reactions/otherReactions.ts b/src/client/stores/CalculationStore/Effects/reactions/otherReactions.ts index 7312710..4260933 100644 --- a/src/client/stores/CalculationStore/Effects/reactions/otherReactions.ts +++ b/src/client/stores/CalculationStore/Effects/reactions/otherReactions.ts @@ -1,5 +1,5 @@ import { openNotification } from 'client/Elements/Notification'; -import { compose } from 'core/tools/func'; +import { pipe } from 'core/tools/func'; import { IReactionEffect } from 'core/types/Calculation/Store/effect'; import { Process } from 'core/types/Calculation/Store/process'; import { ElementStatus } from 'core/types/statuses'; @@ -1688,7 +1688,7 @@ const reactionEffects: IReactionEffect[] = [ calculationStore.setFilter('selectBrand', options => options.filter( - compose( + pipe( option => { if ( product && diff --git a/src/client/stores/CalculationStore/Effects/reactions/requestReactions.ts b/src/client/stores/CalculationStore/Effects/reactions/requestReactions.ts index 819c99d..d65ea83 100644 --- a/src/client/stores/CalculationStore/Effects/reactions/requestReactions.ts +++ b/src/client/stores/CalculationStore/Effects/reactions/requestReactions.ts @@ -1074,30 +1074,40 @@ export default [ options: { fireImmediately: true }, }), - (calculationStore, calculationProcess) => ({ - expression: () => { - const { regionRegistration } = calculationStore.values; - return regionRegistration; + ...[ + { + regionElementName: 'selectRegionRegistration', + regionValueName: 'regionRegistration', + townElementName: 'selectTownRegistration', + townValueName: 'townRegistration', }, - effect: regionRegistrationId => { - if (calculationProcess.hasProcess(Process.LoadKp)) { - return; - } - calculationStore.setStatus( - 'selectTownRegistration', - ElementStatus.Disabled, - ); - calculationStore.setOptions('selectTownRegistration', []); - calculationStore.setValue('townRegistration', null); + { + regionElementName: 'selectLegalClientRegion', + regionValueName: 'legalClientRegion', + townElementName: 'selectLegalClientTown', + townValueName: 'legalClientTown', + }, + ].map( + ({ + regionElementName, + regionValueName, + townElementName, + townValueName, + }) => (calculationStore, calculationProcess) => ({ + expression: () => { + return calculationStore.getValue(regionValueName); + }, + effect: regionId => { + if (calculationProcess.hasProcess(Process.LoadKp)) { + return; + } + // calculationStore.setStatus(townElementName, ElementStatus.Disabled); + calculationStore.setOptions(townElementName, []); + calculationStore.setValue(townValueName, null); - if (regionRegistrationId) { - const regionRegistration = calculationStore.getOption( - 'selectRegionRegistration', - { - evo_regionid: regionRegistrationId, - }, - ); - if (regionRegistration) { + const { evo_regionid } = calculationStore.getOption(regionElementName); + + if (evo_regionid) { CrmService.crmgqlquery({ query: gql` query($statecode: Int, $evo_regionid: Uuid) { @@ -1109,12 +1119,13 @@ export default [ evo_townid evo_fias_id evo_kladr_id + evo_businessunit_evolution } } `, variables: { statecode: 0, - evo_regionid: regionRegistrationId, + evo_regionid: evo_regionid, }, toOptions: ['evo_town'], }).then(({ entities }) => { @@ -1123,20 +1134,16 @@ export default [ Array.isArray(entities.evo_town) && entities.evo_town.length > 0 ) { - calculationStore.setStatus( - 'selectTownRegistration', - ElementStatus.Default, - ); - calculationStore.setOptions( - 'selectTownRegistration', - entities.evo_town, - ); - calculationStore.setValue('townRegistration', null); + // calculationStore.setStatus( + // townElementName, + // ElementStatus.Default, + // ); + calculationStore.setOptions(townElementName, entities.evo_town); } }); } - } - }, - options: { fireImmediately: true }, - }), + }, + options: { fireImmediately: true }, + }), + ), ] as IReactionEffect[]; diff --git a/src/client/stores/CalculationStore/Effects/reactions/statusReactions.ts b/src/client/stores/CalculationStore/Effects/reactions/statusReactions.ts index bc14d72..f1e76be 100644 --- a/src/client/stores/CalculationStore/Effects/reactions/statusReactions.ts +++ b/src/client/stores/CalculationStore/Effects/reactions/statusReactions.ts @@ -1,12 +1,12 @@ -import { ElementsNames } from 'core/types/Calculation/Store/elements'; import { IReactionEffect } from 'core/types/Calculation/Store/effect'; +import { ElementsNames } from 'core/types/Calculation/Store/elements'; import { ElementStatus } from 'core/types/statuses'; const elementsNames: ElementsNames[] = [ 'selectModel', 'selectConfiguration', 'selectGPSModel', - 'selectTownRegistration', + // 'selectTownRegistration', 'selectDealerPerson', ]; diff --git a/src/client/stores/CalculationStore/config/initialValues.ts b/src/client/stores/CalculationStore/config/initialValues.ts index 342479d..ae07a32 100644 --- a/src/client/stores/CalculationStore/config/initialValues.ts +++ b/src/client/stores/CalculationStore/config/initialValues.ts @@ -71,7 +71,7 @@ const initialValues: TValues = { NSIB: true, quoteContactGender: 100000000, quoteRedemptionGraph: true, - creditRate: 7, + creditRate: 7.75, requirementTelematic: 100000000, maxPriceChange: 0, importerRewardPerc: 0, @@ -86,5 +86,8 @@ const initialValues: TValues = { objectRegistration: 100000000, typePTS: 100000001, insNSIB: null, + regionRegistration: null, + legalClientRegion: null, + legalClientTown: null, }; export default initialValues; diff --git a/src/client/stores/CalculationStore/subStores/eltStore.ts b/src/client/stores/CalculationStore/subStores/eltStore.ts index 5ff43e5..883fab5 100644 --- a/src/client/stores/CalculationStore/subStores/eltStore.ts +++ b/src/client/stores/CalculationStore/subStores/eltStore.ts @@ -21,11 +21,10 @@ const ELTStore = makeAutoObservable( setKey(key) { this.selectedKey = key; }, - getSelectedCompany() { - const selectedItem = this.list.find( - x => x.evo_id_elt === this.selectedKey, - ); - return selectedItem; + + getCompany(selectedKey) { + if (selectedKey) return this.list.find(x => x.key === selectedKey); + return this.list.find(x => x.key === this.selectedKey); }, }, })), @@ -33,6 +32,10 @@ const ELTStore = makeAutoObservable( setCompanyRes(insType, index, res) { this[insType].list[index] = res; }, + addToCompanyRes(insType, index, res) { + const companyData = this[insType].list[index]; + this[insType].list[index] = { ...companyData, ...res }; + }, }, ), ); diff --git a/src/core/constants/debounce.js b/src/core/constants/debounce.js index 4873980..fd7ab33 100644 --- a/src/core/constants/debounce.js +++ b/src/core/constants/debounce.js @@ -1,2 +1,3 @@ export const DEFAULT_DEBOUNCE_DELAY = 350; export const NOTIFICATION_DEBOUNCE = 750; +export const ACTION_DELAY = 1200; diff --git a/src/core/constants/stores/Calculation/limits.js b/src/core/constants/stores/Calculation/limits.js new file mode 100644 index 0000000..a8f072f --- /dev/null +++ b/src/core/constants/stores/Calculation/limits.js @@ -0,0 +1,2 @@ +export const MAX_FRANCHISE = 75000; +export const MAX_INSURANCE = 2500000; diff --git a/src/core/services/CrmService/index.ts b/src/core/services/CrmService/index.ts index 3efd825..787e9b5 100644 --- a/src/core/services/CrmService/index.ts +++ b/src/core/services/CrmService/index.ts @@ -102,6 +102,7 @@ export default class { static createKp = (data: ICreateKpRequest): Promise => new Promise((resolve, reject) => { + console.log('createKp data: ', data); axios .post( String.prototype.concat( diff --git a/src/core/tools/func.js b/src/core/tools/func.js deleted file mode 100644 index 0530eb2..0000000 --- a/src/core/tools/func.js +++ /dev/null @@ -1,2 +0,0 @@ -export const compose = (...functions) => args => - functions.reduce((arg, fn) => fn(arg), args); diff --git a/src/core/tools/func.ts b/src/core/tools/func.ts new file mode 100644 index 0000000..1bf2a06 --- /dev/null +++ b/src/core/tools/func.ts @@ -0,0 +1,13 @@ +export const compose = (fn1: (a: R) => R, ...fns: Array<(a: R) => R>) => + fns.reduce((prevFn, nextFn) => value => prevFn(nextFn(value)), fn1); + +export const pipe = ( + fn1: (...args: T) => R, + ...fns: Array<(a: R) => R> +) => { + const piped = fns.reduce( + (prevFn, nextFn) => (value: R) => nextFn(prevFn(value)), + value => value, + ); + return (...args: T) => piped(fn1(...args)); +}; diff --git a/src/core/tools/num.js b/src/core/tools/num.js deleted file mode 100644 index 94f8552..0000000 --- a/src/core/tools/num.js +++ /dev/null @@ -1,3 +0,0 @@ -import { round as _round } from 'lodash'; - -export const round = (value, n) => _round(value, n || 2).toFixed(n || 2); diff --git a/src/core/tools/num.ts b/src/core/tools/num.ts new file mode 100644 index 0000000..be0139c --- /dev/null +++ b/src/core/tools/num.ts @@ -0,0 +1,3 @@ +import { round as _round } from 'lodash'; + +export const round = (value = 0, n = 2) => _round(value, n).toFixed(n); diff --git a/src/core/types/Calculation/Requests.ts b/src/core/types/Calculation/Requests.ts index 8957c33..1cb884a 100644 --- a/src/core/types/Calculation/Requests.ts +++ b/src/core/types/Calculation/Requests.ts @@ -37,6 +37,9 @@ export interface ICreateKpRequest { calculationValues: TValues; columns: { [column in ColumnsNames]?: IColumn }; }; + elt: { + [insType: string]: any; + }; } export interface IGetTransTaxRequest { diff --git a/src/core/types/Calculation/Store/elements.ts b/src/core/types/Calculation/Store/elements.ts index 9424d06..fbf3eb7 100644 --- a/src/core/types/Calculation/Store/elements.ts +++ b/src/core/types/Calculation/Store/elements.ts @@ -144,7 +144,9 @@ export type ElementsNames = | 'selectObjectCategoryTax' | 'selectObjectTypeTax' | 'radioTypePTS' - | 'labelRegistrationDescription'; + | 'labelRegistrationDescription' + | 'selectLegalClientRegion' + | 'selectLegalClientTown'; export type LinkElementsNames = 'linkDownloadKp'; diff --git a/src/core/types/Calculation/Store/values.ts b/src/core/types/Calculation/Store/values.ts index b496c39..a30b7b3 100644 --- a/src/core/types/Calculation/Store/values.ts +++ b/src/core/types/Calculation/Store/values.ts @@ -129,7 +129,9 @@ export type ValuesNames = | 'vehicleTaxInLeasingPeriod' | 'objectCategoryTax' | 'objectTypeTax' - | 'typePTS'; + | 'typePTS' + | 'legalClientRegion' + | 'legalClientTown'; export type ComputedValuesNames = | 'leadName' diff --git a/src/core/types/Entities/crmEntities.ts b/src/core/types/Entities/crmEntities.ts index fc3aaf7..8ffca1c 100644 --- a/src/core/types/Entities/crmEntities.ts +++ b/src/core/types/Entities/crmEntities.ts @@ -86,6 +86,12 @@ export interface IQuote { evo_year?: number; evo_regionid?: string; evo_townid?: string; + evo_legal_regionid?: string; + evo_legal_townid?: string; + evo_id_elt_kasko?: string; + evo_id_kasko_calc?: string; + evo_franchise?: string; + evo_id_elt_osago?: string; } export interface IEvoGraph { @@ -217,6 +223,7 @@ export interface IEvoTown { statecode?: number; evo_fias_id?: string; evo_kladr_id?: string; + evo_businessunit_evolution?: boolean; } export interface IEvoContact { parentcustomerid?: string; diff --git a/src/core/validation/conditions.js b/src/core/validation/conditions.js new file mode 100644 index 0000000..9ad4bd2 --- /dev/null +++ b/src/core/validation/conditions.js @@ -0,0 +1,5 @@ +export default { + IS_NULL: value => value === undefined || value === null, + LESS_ZERO: value => value < 0, + LESS_OR_EQUALS_ZERO: value => value <= 0, +}; diff --git a/src/core/validation/validate.ts b/src/core/validation/validate.ts new file mode 100644 index 0000000..549c120 --- /dev/null +++ b/src/core/validation/validate.ts @@ -0,0 +1,41 @@ +import { getValueName } from 'client/Containers/Calculation/lib/elements/tools'; +import { + ElementsNames, + TElements, +} from './../types/Calculation/Store/elements'; +import { ICalculationStore } from './../types/Calculation/Store/index'; + +export type ValidationResult = { + isValid: boolean; + message?: string; +}; + +export type ValidationCondition = ( + calculationStore: ICalculationStore, + elementName: ElementsNames, +) => ValidationResult; + +export const validate = ( + calculationStore: ICalculationStore, + conditions: TElements, +) => { + const validationResult: TElements = (Object.keys( + conditions, + ) as ElementsNames[]).reduce((ac, elementName) => { + const condition = conditions[elementName]; + ac[elementName] = condition && condition(calculationStore, elementName); + return ac; + }, {}); + return validationResult; +}; + +export const getValue = ( + calculationStore: ICalculationStore, + elementName: ElementsNames, +) => { + const valueName = getValueName(elementName); + const value = calculationStore.getValue(valueName); + return value; +}; + +export const convertToValidationResult = result => ({ isValid: !result });