From 12f0bf2d8d30efc57d6925bcd99c32bbfce08dda Mon Sep 17 00:00:00 2001 From: vchikalkin Date: Tue, 18 May 2021 10:32:52 +0300 Subject: [PATCH] merge elt-connect --- .storybook/main.js | 16 ++ .storybook/preview.js | 10 + .vscode/settings.json | 3 +- package.json | 55 ++++- src/client/{App.tsx => App.jsx} | 4 +- .../ELT/Content/Components/InsContent.jsx | 74 +++++++ .../ELT/Content/Components/InsTable.tsx | 39 ++++ .../ELT/Content/Components/TableControls.jsx | 34 +++ .../ELT/Content/Kasko/Kasko.stories.jsx | 43 ++++ .../Calculation/ELT/Content/Kasko/index.jsx | 18 ++ .../Content/Kasko/lib/composeRequest.test.js | 145 +++++++++++++ .../ELT/Content/Kasko/lib/composeRequest.ts | 200 ++++++++++++++++++ .../ELT/Content/Kasko/lib/convertEltResult.js | 47 ++++ .../Kasko/lib/convertEltResult.test.js | 79 +++++++ .../ELT/Content/Kasko/lib/onSelectRow.ts | 35 +++ .../ELT/Content/Kasko/lib/validation.ts | 13 ++ .../Calculation/ELT/Content/Osago/index.jsx | 18 ++ .../ELT/Content/Osago/lib/composeRequest.ts | 149 +++++++++++++ .../ELT/Content/Osago/lib/convertEltResult.js | 20 ++ .../ELT/Content/Osago/lib/onSelectRow.ts | 21 ++ .../ELT/Content/Osago/lib/validation.ts | 13 ++ .../Calculation/ELT/Content/index.jsx | 20 ++ .../ELT/Content/lib/config/columns.ts | 21 ++ .../ELT/Content/lib/config/index.ts | 18 ++ .../Calculation/ELT/Content/lib/getData.ts | 40 ++++ .../Calculation/ELT/Content/lib/validation.ts | 19 ++ .../Components/Calculation/ELT/index.jsx | 44 ++++ src/client/Components/Spinner.jsx | 25 ++- .../Containers/Calculation/Results/index.jsx | 6 - .../Calculation/Sections/sectionsList.ts | 2 +- .../Calculation/lib/buildElement.js | 3 + .../Calculation/lib/elements/components.ts | 2 + .../Calculation/lib/elements/elementsProps.ts | 3 + .../Calculation/lib/elements/titles.ts | 2 +- .../Calculation/lib/elements/types.ts | 3 +- .../Calculation/lib/fetchData/index.js | 6 +- .../lib/fetchData/queries/insuranceQuery.ts | 3 +- .../lib/fetchData/queries/optionsQuery.ts | 1 + .../Calculation/lib/renderSections.js | 34 ++- src/client/Elements/Alert.jsx | 5 + src/client/Elements/Divider.jsx | 3 + src/client/Elements/Text.jsx | 5 + src/client/hooks/Calculation/useUrl.js | 3 +- src/client/hooks/Calculation/useValue.js | 3 +- .../stores/CalculationStore/Data/tables.js | 4 + .../Effects/actions/calculate/prepareData.ts | 2 +- .../Effects/actions/createKP.js | 3 +- .../Effects/reactions/loadKpReaction/index.ts | 5 +- .../Effects/reactions/requestReactions.ts | 1 + .../stores/CalculationStore/Effects/when.ts | 49 +++++ src/client/stores/CalculationStore/index.ts | 52 +---- .../subStores/calculationProcess.ts | 35 +++ .../subStores/calculationUrls.ts | 13 ++ .../CalculationStore/subStores/eltStore.ts | 32 +++ .../CalculationStore/subStores/index.js | 9 + src/client/stores/index.js | 7 +- src/core/constants/urls.js | 1 + src/core/services/ELTService/Kasko.js | 23 ++ src/core/services/ELTService/Osago.js | 24 +++ src/core/services/ELTService/index.js | 4 + src/core/types/Calculation/Store/effect.ts | 4 +- src/core/types/Calculation/Store/elements.ts | 11 +- src/core/types/Calculation/Store/index.ts | 23 +- src/core/types/Calculation/Store/tables.ts | 5 +- src/core/types/Calculation/components.ts | 16 +- src/core/types/Entities/crmEntities.ts | 1 + src/{index.tsx => index.jsx} | 0 67 files changed, 1504 insertions(+), 127 deletions(-) create mode 100644 .storybook/main.js create mode 100644 .storybook/preview.js rename src/client/{App.tsx => App.jsx} (100%) create mode 100644 src/client/Components/Calculation/ELT/Content/Components/InsContent.jsx create mode 100644 src/client/Components/Calculation/ELT/Content/Components/InsTable.tsx create mode 100644 src/client/Components/Calculation/ELT/Content/Components/TableControls.jsx create mode 100644 src/client/Components/Calculation/ELT/Content/Kasko/Kasko.stories.jsx create mode 100644 src/client/Components/Calculation/ELT/Content/Kasko/index.jsx create mode 100644 src/client/Components/Calculation/ELT/Content/Kasko/lib/composeRequest.test.js create mode 100644 src/client/Components/Calculation/ELT/Content/Kasko/lib/composeRequest.ts create mode 100644 src/client/Components/Calculation/ELT/Content/Kasko/lib/convertEltResult.js create mode 100644 src/client/Components/Calculation/ELT/Content/Kasko/lib/convertEltResult.test.js create mode 100644 src/client/Components/Calculation/ELT/Content/Kasko/lib/onSelectRow.ts create mode 100644 src/client/Components/Calculation/ELT/Content/Kasko/lib/validation.ts create mode 100644 src/client/Components/Calculation/ELT/Content/Osago/index.jsx create mode 100644 src/client/Components/Calculation/ELT/Content/Osago/lib/composeRequest.ts create mode 100644 src/client/Components/Calculation/ELT/Content/Osago/lib/convertEltResult.js create mode 100644 src/client/Components/Calculation/ELT/Content/Osago/lib/onSelectRow.ts create mode 100644 src/client/Components/Calculation/ELT/Content/Osago/lib/validation.ts create mode 100644 src/client/Components/Calculation/ELT/Content/index.jsx create mode 100644 src/client/Components/Calculation/ELT/Content/lib/config/columns.ts create mode 100644 src/client/Components/Calculation/ELT/Content/lib/config/index.ts create mode 100644 src/client/Components/Calculation/ELT/Content/lib/getData.ts create mode 100644 src/client/Components/Calculation/ELT/Content/lib/validation.ts create mode 100644 src/client/Components/Calculation/ELT/index.jsx create mode 100644 src/client/Elements/Alert.jsx create mode 100644 src/client/Elements/Divider.jsx create mode 100644 src/client/stores/CalculationStore/Effects/when.ts create mode 100644 src/client/stores/CalculationStore/subStores/calculationProcess.ts create mode 100644 src/client/stores/CalculationStore/subStores/calculationUrls.ts create mode 100644 src/client/stores/CalculationStore/subStores/eltStore.ts create mode 100644 src/client/stores/CalculationStore/subStores/index.js create mode 100644 src/core/services/ELTService/Kasko.js create mode 100644 src/core/services/ELTService/Osago.js create mode 100644 src/core/services/ELTService/index.js rename src/{index.tsx => index.jsx} (100%) diff --git a/.storybook/main.js b/.storybook/main.js new file mode 100644 index 0000000..6283b05 --- /dev/null +++ b/.storybook/main.js @@ -0,0 +1,16 @@ +module.exports = { + stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + { + name: '@storybook/preset-create-react-app', + options: { + craOverrides: { + fileLoaderExcludes: ['less'], + }, + }, + }, + '@storybook/preset-ant-design', + ], +}; diff --git a/.storybook/preview.js b/.storybook/preview.js new file mode 100644 index 0000000..645f52d --- /dev/null +++ b/.storybook/preview.js @@ -0,0 +1,10 @@ + +export const parameters = { + actions: { argTypesRegex: "^on[A-Z].*" }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 8507475..37e4fb0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -20,5 +20,6 @@ "source.organizeImports": true, "source.fixAll": true }, - "editor.formatOnSave": true + "editor.formatOnSave": true, + "workbench.editor.labelFormat": "short" } diff --git a/package.json b/package.json index 50428f8..fabb102 100644 --- a/package.json +++ b/package.json @@ -4,13 +4,11 @@ "dependencies": { "@ant-design/icons": "^4.6.2", "@apollo/client": "^3.3.13", - "@babel/code-frame": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", "@craco/craco": "^6.1.1", - "@testing-library/jest-dom": "^4.2.4", - "@testing-library/react": "^9.3.2", - "@testing-library/user-event": "^7.1.2", - "antd": "^4.15.0", + "@testing-library/jest-dom": "^5.11.4", + "@testing-library/react": "^11.1.0", + "@testing-library/user-event": "^12.1.10", + "antd": "^4.15.5", "axios": "^0.21.1", "babel-plugin-transform-imports": "^2.0.0", "craco-antd": "^1.19.0", @@ -33,30 +31,65 @@ "validator": "^13.5.2" }, "devDependencies": { + "@storybook/addon-actions": "^6.2.9", + "@storybook/addon-essentials": "^6.2.9", + "@storybook/addon-links": "^6.2.9", + "@storybook/node-logger": "^6.2.9", + "@storybook/preset-ant-design": "^0.0.2", + "@storybook/preset-create-react-app": "^3.1.7", + "@storybook/react": "^6.2.9", "@types/jest": "^26.0.15", "@types/lodash": "^4.14.168", + "@types/node": "^12.0.0", "@types/pluralize": "^0.0.29", - "@types/react": "^17.0.3", - "@types/react-dom": "^17.0.3", + "@types/react": "^17.0.0", + "@types/react-dom": "^17.0.0", "@types/react-router-dom": "^5.1.7", "@types/rebass": "^4.0.8", "@types/styled-components": "^5.1.9", + "@types/uuid": "^8.3.0", "commitizen": "^4.2.3", "cz-conventional-changelog": "^3.3.0", "source-map-explorer": "^2.5.2" }, + "resolutions": { + "babel-loader": "8.1.0" + }, "scripts": { - "test": "craco test", + "test": "react-scripts test", "eject": "react-scripts eject", "start": "craco start", "build": "craco build", "eslint": "eslint ./src", "eslint:fix": "eslint ./src --fix", "commit": "git-cz", - "analyze": "source-map-explorer 'build/static/js/*.js'" + "analyze": "source-map-explorer 'build/static/js/*.js'", + "storybook": "start-storybook -p 6006 -s public", + "build-storybook": "build-storybook -s public" }, "eslintConfig": { - "extends": "react-app" + "extends": [ + "react-app", + "react-app/jest" + ], + "overrides": [ + { + "files": [ + "**/*.stories.*" + ], + "rules": { + "import/no-anonymous-default-export": "off" + } + }, + { + "files": [ + "**/*.stories.*" + ], + "rules": { + "import/no-anonymous-default-export": "off" + } + } + ] }, "browserslist": { "production": [ diff --git a/src/client/App.tsx b/src/client/App.jsx similarity index 100% rename from src/client/App.tsx rename to src/client/App.jsx index eb79d3b..ffd15b9 100644 --- a/src/client/App.tsx +++ b/src/client/App.jsx @@ -1,11 +1,11 @@ +import { ConfigProvider, message } from 'antd'; +import ruRu from 'antd/es/locale/ru_RU'; import { StoreProvider } from 'client/contexts/storeContext'; import theme from 'client/UIKit/theme'; import { BrowserRouter } from 'react-router-dom'; import { ThemeProvider } from 'styled-components'; import './App.less'; import Layout from './Layout'; -import { ConfigProvider, message } from 'antd'; -import ruRu from 'antd/es/locale/ru_RU'; message.config({ top: 70, diff --git a/src/client/Components/Calculation/ELT/Content/Components/InsContent.jsx b/src/client/Components/Calculation/ELT/Content/Components/InsContent.jsx new file mode 100644 index 0000000..d18cb6a --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Components/InsContent.jsx @@ -0,0 +1,74 @@ +import Alert from 'client/Elements/Alert'; +import { useStores } from 'client/hooks/useStores'; +import { useEffect, useState } from 'react'; +import { getFieldsNames, validate } from '../lib/validation'; +import InsTable from './InsTable'; +import Controls from './TableControls'; + +export default ({ + title, + insType, + getData, + onSelectRow, + requiredFields, + ...tableProps +}) => props => { + const { calculationStore } = useStores(); + const { ELTStore } = calculationStore.stores; + const [selectedKey, selectKey] = useState(''); + const [alert, setAlert] = useState({ + message: undefined, + type: undefined, + }); + const [isPending, setIsPending] = useState(false); + + useEffect(() => { + selectKey(ELTStore[insType].selectedKey); + }, []); + + const handleGetData = () => { + const missingFields = validate.call(calculationStore, requiredFields); + if (missingFields && missingFields.length > 0) { + const fieldsNames = getFieldsNames(missingFields); + const msgText = String.prototype.concat( + 'Не заполнены поля: ', + fieldsNames.join(', '), + ); + setAlert({ message: msgText, type: 'error' }); + return; + } else { + setAlert({ message: undefined, type: undefined }); + } + + setIsPending(true); + const resetPending = () => setIsPending(false); + getData.call(calculationStore, resetPending); + }; + + const handleSelectRow = () => { + ELTStore[insType].setKey(selectedKey); + onSelectRow.call(calculationStore, insType, selectedKey); + setAlert({ message: 'Выбранные параметры сохранены', type: 'success' }); + setTimeout(() => { + setAlert({ message: undefined, type: undefined }); + }, 2500); + }; + + return ( + + {alert.message && } + + + ); +}; diff --git a/src/client/Components/Calculation/ELT/Content/Components/InsTable.tsx b/src/client/Components/Calculation/ELT/Content/Components/InsTable.tsx new file mode 100644 index 0000000..0621b60 --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Components/InsTable.tsx @@ -0,0 +1,39 @@ +import { Table as AntTable, TableProps } from 'antd'; +import { Box } from 'client/UIKit/grid'; +import { toJS } from 'mobx'; +import { observer } from 'mobx-react-lite'; +import React from 'react'; +import styled from 'styled-components'; + +const TableWrapper = styled(Box)` + .ant-table-row-level-1 .ant-table-selection-column { + visibility: hidden; + } +`; + +interface ITableProps { + selectKey: (key: string) => void; + selectedKey: string; + tableConfig: TableProps; + dataSource: any[]; +} + +export default observer( + ({ selectKey, selectedKey, tableConfig, dataSource, ...props }) => { + return ( + + { + selectKey(record.key); + }, + })} + dataSource={toJS(dataSource)} + {...props} + > + + ); + }, +) as React.FC; diff --git a/src/client/Components/Calculation/ELT/Content/Components/TableControls.jsx b/src/client/Components/Calculation/ELT/Content/Components/TableControls.jsx new file mode 100644 index 0000000..656583a --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Components/TableControls.jsx @@ -0,0 +1,34 @@ +import ReloadOutlined from '@ant-design/icons/lib/icons/ReloadOutlined'; +import Button from 'client/Elements/Button'; +import { PrimaryText } from 'client/Elements/Text'; +import { Flex } from 'client/UIKit/grid'; +import { ElementStatus } from 'core/types/statuses'; +import styled from 'styled-components'; + +const TopControls = ({ title, getData, isLoading }) => ( + + {title} + +); + +const ContentWrapper = styled(Flex)` + width: 550px !important; +`; + +export default ({ children, ...props }) => ( + + + {children} + + +); diff --git a/src/client/Components/Calculation/ELT/Content/Kasko/Kasko.stories.jsx b/src/client/Components/Calculation/ELT/Content/Kasko/Kasko.stories.jsx new file mode 100644 index 0000000..d6650b3 --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Kasko/Kasko.stories.jsx @@ -0,0 +1,43 @@ +import InsTable from '../InsTable'; +import tableConfig from '../lib/config'; + +export default { + title: 'Components/Calculation/ELT/Kasko', + component: InsTable, +}; + +const Template = args => ; + +const dataSource = [ + { + key: '1', + evo_id_elt: 'Alfa', + name: 'Альфа', + sumTitle: 'Премия по договору', + premiumSum: 55555, + message: 'Комментарий альфы', + children: [ + { + key: '1', + sumTitle: 'КАСКО', + premiumSum: 1111, + }, + { + key: '1', + sumTitle: 'ДГО', + premiumSum: 4444, + }, + { + key: '1', + sumTitle: 'НС', + premiumSum: 8888, + }, + ], + }, +]; + +export const WithData = Template.bind({}); +WithData.args = { + tableConfig, + dataSource, +}; diff --git a/src/client/Components/Calculation/ELT/Content/Kasko/index.jsx b/src/client/Components/Calculation/ELT/Content/Kasko/index.jsx new file mode 100644 index 0000000..5d26e12 --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Kasko/index.jsx @@ -0,0 +1,18 @@ +import InsContent from '../Components/InsContent'; +import tableConfig from '../lib/config'; +import getData from '../lib/getData'; +import composeRequest from './lib/composeRequest'; +import convertEltResult from './lib/convertEltResult'; +import onSelectRow from './lib/onSelectRow'; +import { requiredFields } from './lib/validation'; + +const insType = 'kasko'; + +export default InsContent({ + title: 'КАСКО', + insType, + getData: getData(insType, composeRequest, convertEltResult), + onSelectRow, + tableConfig, + requiredFields, +}); diff --git a/src/client/Components/Calculation/ELT/Content/Kasko/lib/composeRequest.test.js b/src/client/Components/Calculation/ELT/Content/Kasko/lib/composeRequest.test.js new file mode 100644 index 0000000..aeb135f --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Kasko/lib/composeRequest.test.js @@ -0,0 +1,145 @@ +import CalculationStore from 'client/stores/CalculationStore'; +import { currentDate } from 'core/tools/date'; +import composeRequest from './composeRequest'; + +CalculationStore.options = { + selectRegionRegistration: [ + { + evo_name: 'Рязанская область', + value: 'rznregion', + }, + ], + selectTownRegistration: [ + { + evo_name: 'Рязань', + value: 'rzntown', + }, + ], + selectGPSBrand: [ + { + evo_id: 'gps_brand_evo_id', + value: 'gpsbrand', + }, + ], + selectGPSModel: [ + { + evo_id: 'gps_model_evo_id', + value: 'gpsmodel', + }, + ], + selectBrand: [ + { + evo_id: 'AUDI', + value: 'brandid', + }, + ], + selectModel: [ + { + evo_id: 'A5', + value: 'modelid', + }, + ], +}; + +CalculationStore.values = { + regionRegistration: 'rznregion', + townRegistration: 'rzntown', + brand: 'brandid', + model: 'modelid', + leaseObjectUsed: false, + leaseObjectYear: 2021, + leaseObjectMotorPower: 5.5, + engineType: undefined, + leasingPeriod: 12, + leaseObjectPrice: 2000, + supplierDiscountRub: 1000, + insFranchise: 5, + GPSBrand: 'gpsbrand', + GPSModel: 'gpsmodel', + insUnlimitDrivers: true, + leaseObjectCategory: 100000002, + maxMass: 1000, + leaseObjectUseFor: 100000001, + INNForCalc: 1010, +}; + +CalculationStore.tables = { + tableInsurance: { + rows: [{}, {}, { insCost: 10000 }], + }, +}; + +const expected = { + preparams: { + regionName: 'Рязанская область', + cityName: 'Рязань', + brandId: 'AUDI', + modelId: 'A5', + }, + ELTParams: { + currency: 'RUR', + isNew: false, + usageStart: currentDate, + vehicleYear: 2021, + modification: { + power: 5.5, + engineType: '5', + engineVolume: 0, + KPPTypeId: '1', + BodyType: '9', + }, + duration: 12, + bankId: '245', + cost: 1000, + franchise: '5', + ssType: '1', + STOA: '0', + OfficialDealer: true, + PUUs: [ + { + mark: 'gps_brand_evo_id', + model: 'gps_model_evo_id', + }, + ], + driversCount: 1, + risk: 0, + payType: 0, + vehicle: { + maxAllowedMass: 1000, + mileage: 0, + vehicleUsage: 1, + seatingCapacity: 0, + category: 'C2', + classification: '11635', + }, + drivers: [{ age: 18, experience: 0, sex: '0' }], + GO: { limitSumId: '1000000', globalLimitSum: 1000000 }, + NS: { LimitSum: 1000000 }, + Insurer: { + SubjectType: 1, + SubjectTypeSpecified: true, + }, + Owner: { + SubjectType: 1, + SubjectTypeSpecified: true, + }, + Lessee: { + SubjectType: 1, + SubjectTypeSpecified: true, + INN: '1010', + }, + FullDriversInfo: [ + { + surname: 'Иванов', + name: 'Иван', + patronymic: 'Иванович', + sex: '0', + expertienceStart: new Date('2000-01-01'), + }, + ], + }, +}; + +it('ELT/Kasko/composeRequest', () => { + expect(composeRequest.call(CalculationStore)).toEqual(expected); +}); diff --git a/src/client/Components/Calculation/ELT/Content/Kasko/lib/composeRequest.ts b/src/client/Components/Calculation/ELT/Content/Kasko/lib/composeRequest.ts new file mode 100644 index 0000000..2ab8f07 --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Kasko/lib/composeRequest.ts @@ -0,0 +1,200 @@ +import { currentDate } from 'core/tools/date'; +import { ICalculationStore } from 'core/types/Calculation/Store/index'; +import { isNull } from 'lodash'; + +const mapEngineType = { + 100000000: '0', + 100000001: '1', + 100000003: '2', + 100000004: '3', +}; + +const mapVehicleUsage = { + 100000000: 0, + 100000001: 1, + 100000002: 5, + 100000003: 5, + 100000004: 2, + 100000005: 6, + 100000006: 5, + 100000007: 4, + 100000008: 4, + 100000009: 0, + 100000010: 0, + 100000011: 3, + 100000012: 3, + 100000013: 9, +}; + +const mapCategory = { + 100000000: 'A', + 100000001: 'B', + 100000002: 'C2', + 100000003: 'D', + 100000004: 'E1', +}; + +const getSpecified = value => !isNull(value); + +export default function (this: ICalculationStore) { + const regionName = this.getOption('selectRegionRegistration')?.evo_name; + const cityName = this.getOption('selectTownRegistration')?.evo_name; + const brandId = this.getOption('selectBrand')?.evo_id; + const modelId = this.getOption('selectModel')?.evo_id; + + const isNew = !this.getValue('leaseObjectUsed'); + const vehicleYear = this.getValue('leaseObjectYear'); + const power = this.getValue('leaseObjectMotorPower'); + const powerSpecified = getSpecified(power); + + let engineType = '5'; + const engineTypeValue = this.getValue('engineType'); + if (engineTypeValue) { + engineType = mapEngineType[engineTypeValue]; + } + + const duration = this.getValue('leasingPeriod'); + const cost = + this.getValue('leaseObjectPrice') - this.getValue('supplierDiscountRub'); + + const franchise = this.getValue('insFranchise'); + const franchiseSpecified = getSpecified(franchise); + const puuMark = this.getOption('selectGPSBrand')?.evo_id; + const puuModel = this.getOption('selectGPSModel')?.evo_id; + const puuModelSpecified = getSpecified(puuModel); + + let age = this.getValue('insAgeDrivers'), + experience = this.getValue('insExpDrivers'), + sex = '0', + driversCount = 1; + + if (this.getValue('insUnlimitDrivers')) { + age = 18; + experience = 0; + driversCount = 0; + } + const sexSpecified = getSpecified(sex); + + let maxAllowedMass = 0; + if (this.getValue('leaseObjectCategory') === 100000002) { + maxAllowedMass = this.getValue('maxMass'); + } + const maxAllowedMassSpecified = getSpecified(maxAllowedMass); + + let mileage = 0; + if (this.getValue('leaseObjectUsed')) { + mileage = this.getValue('mileage'); + } + const mileageSpecified = getSpecified(mileage); + + let vehicleUsage = 0; + const leaseObjectUseForValue = this.getValue('leaseObjectUseFor'); + if (leaseObjectUseForValue) { + vehicleUsage = mapVehicleUsage[leaseObjectUseForValue] || 0; + } + const vehicleUsageSpecified = getSpecified(vehicleUsage); + + let seatingCapacity = 0; + if (this.getValue('leaseObjectCategory') === 100000003) { + seatingCapacity = this.getValue('countSeats'); + } + const seatingCapacitySpecified = getSpecified(seatingCapacity); + + const category = mapCategory[this.getValue('leaseObjectCategory')]; + + const classification = [100000002, 100000003, 100000004].includes( + this.getValue('leaseObjectCategory'), + ) + ? '11635' + : '0'; + + const globalLimitSum = this.getTableRowValues('tableInsurance', 2, 'value') + .insCost + ? 1000000 + : 0; + const globalLimitSumSpecified = getSpecified(globalLimitSum); + const limitSumId = globalLimitSum + ''; + + const INN = this.getValue('INNForCalc') || '' + ''; + + return { + preparams: { + regionName, + cityName, + brandId, + modelId, + }, + ELTParams: { + currency: 'RUR', + isNew, + usageStart: currentDate, + vehicleYear, + modification: { + power, + powerSpecified, + engineType, + engineVolume: 0, + engineVolumeSpecified: true, + KPPTypeId: 1, + BodyType: 9, + }, + duration, + bankId: '245', + cost, + franchise, + franchiseSpecified, + ssType: '1', + STOA: '0', + OfficialDealerSpecified: true, + OfficialDealer: true, + PUUs: puuMark && [ + { + mark: puuMark, + model: puuModel, + modelSpecified: puuModelSpecified, + }, + ], + driversCount, + risk: 0, + payType: '0', + vehicle: { + maxAllowedMass, + maxAllowedMassSpecified, + mileage, + mileageSpecified, + vehicleUsage, + vehicleUsageSpecified, + seatingCapacity, + seatingCapacitySpecified, + category, + classification, + }, + drivers: [{ age, experience, sex, sexSpecified }], + GO: { limitSumId, globalLimitSum, globalLimitSumSpecified }, + NS: { LimitSum: '1000000' }, + Insurer: { + SubjectType: 1, + SubjectTypeSpecified: true, + }, + Owner: { + SubjectType: 1, + SubjectTypeSpecified: true, + }, + Lessee: { + SubjectType: 1, + SubjectTypeSpecified: true, + INN, + }, + // FullDriversInfo: [ + // { + // surname, + // name, + // patronymic, + // sex, + // sexSpecified, + // expertienceStart, + // }, + // ], + }, + }; +} diff --git a/src/client/Components/Calculation/ELT/Content/Kasko/lib/convertEltResult.js b/src/client/Components/Calculation/ELT/Content/Kasko/lib/convertEltResult.js new file mode 100644 index 0000000..8e73af2 --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Kasko/lib/convertEltResult.js @@ -0,0 +1,47 @@ +import { get, pick } from 'lodash'; + +const mapKaskoSums = [ + { + sumTitle: 'КАСКО', + sumPath: 'paymentPeriods[0].kaskoSum', + }, + { + sumTitle: 'ДГО', + sumPath: 'paymentPeriods[0].goSum', + }, + { + sumTitle: 'НС', + sumPath: 'paymentPeriods[0].nsSum', + }, +]; + +export default function (resultCompany, key) { + if (!resultCompany || Object.keys(resultCompany).length === 0) { + return; + } + + const dataFromResult = pick( + resultCompany, + ['message', 'requestId', 'skCalcId'], + '', + ); + const sumsFromResult = Object.fromEntries( + ['kaskoSum', 'goSum', 'nsSum', 'premiumSum'].map(x => [ + x, + get(resultCompany, 'paymentPeriods[0].' + x, 0), + ]), + ); + + return { + key, + sumType: 'premiumSum', + sumTitle: 'Премия по договору', + ...dataFromResult, + ...sumsFromResult, + children: mapKaskoSums.map(({ sumPath, ...x }) => ({ + key, + ...x, + premiumSum: get(resultCompany, sumPath, 0), + })), + }; +} diff --git a/src/client/Components/Calculation/ELT/Content/Kasko/lib/convertEltResult.test.js b/src/client/Components/Calculation/ELT/Content/Kasko/lib/convertEltResult.test.js new file mode 100644 index 0000000..622597e --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Kasko/lib/convertEltResult.test.js @@ -0,0 +1,79 @@ +import convertEltResult from './convertEltResult'; + +export const resultCompany = { + requestId: '1364968', + skCalcId: '66758382', + product: '', + program: '', + productId: '', + programId: '1', + comment: null, + message: 'Комментарий альфы', + error: '', + errorType: null, + premiumSum: 0, + kaskoSum: 0, + doSum: 0, + goSum: 0, + nsSum: 0, + gapSum: 0, + paymentPeriods: [ + { + num: 1, + PremiumSum: 55555, + KASKOSum: 1111, + GOSum: 4444, + NSSum: 8888, + }, + ], + kbmOsago: null, + totalFranchise: 0, + totalFranchiseSpecified: false, + insuranceCompanyFranchise: null, + insuranceCompanyGo: null, + policyNumber: null, + programCode: null, + calcInfo: null, + options: null, + unicusGUID: null, +}; + +const entityCompany = { + accountid: '0df9ccfb-1407-eb11-af50-00155d088a01', + name: 'Альфа', + evo_id_elt: 'Alfa', +}; + +it('ELT/Kasko/convertKaskoResultToRow', () => { + expect(convertEltResult(resultCompany, entityCompany, '0')).toEqual({ + key: '0', + evo_id_elt: 'Alfa', + name: 'Альфа', + sumType: 'premiumSum', + sumTitle: 'Премия по договору', + PremiumSum: 55555, + KASKOSum: 1111, + GOSum: 4444, + NSSum: 8888, + message: 'Комментарий альфы', + requestId: '1364968', + skCalcId: '66758382', + children: [ + { + key: '0', + sumTitle: 'КАСКО', + premiumSum: 1111, + }, + { + key: '0', + sumTitle: 'ДГО', + premiumSum: 4444, + }, + { + key: '0', + sumTitle: 'НС', + premiumSum: 8888, + }, + ], + }); +}); diff --git a/src/client/Components/Calculation/ELT/Content/Kasko/lib/onSelectRow.ts b/src/client/Components/Calculation/ELT/Content/Kasko/lib/onSelectRow.ts new file mode 100644 index 0000000..df7c96f --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Kasko/lib/onSelectRow.ts @@ -0,0 +1,35 @@ +import { ICalculationStore } from 'core/types/Calculation/Store'; + +export default function ( + this: ICalculationStore, + insType, + selectedKey: string, +) { + const selectedRow = this.stores.ELTStore[insType].list.find( + x => x.key === selectedKey, + ); + const { accountid, kaskoSum, goSum, nsSum } = selectedRow; + this.setTableRows( + 'tableInsurance', + 1, + )([ + { + insuranceCompany: { + value: accountid, + }, + 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 new file mode 100644 index 0000000..223ed45 --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Kasko/lib/validation.ts @@ -0,0 +1,13 @@ +import { ElementsNames } from 'core/types/Calculation/Store/elements'; + +export const requiredFields: ElementsNames[] = [ + 'selectRegionRegistration', + 'selectTownRegistration', + 'selectBrand', + 'selectModel', + 'tbxLeaseObjectYear', + 'tbxLeaseObjectMotorPower', + 'tbxLeasingPeriod', + 'tbxLeaseObjectPrice', + 'selectLeaseObjectCategory', +]; diff --git a/src/client/Components/Calculation/ELT/Content/Osago/index.jsx b/src/client/Components/Calculation/ELT/Content/Osago/index.jsx new file mode 100644 index 0000000..8d384cd --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Osago/index.jsx @@ -0,0 +1,18 @@ +import InsContent from '../Components/InsContent'; +import tableConfig from '../lib/config'; +import getData from '../lib/getData'; +import composeRequest from './lib/composeRequest'; +import convertEltResult from './lib/convertEltResult'; +import onSelectRow from './lib/onSelectRow'; +import { requiredFields } from './lib/validation'; + +const insType = 'osago'; + +export default InsContent({ + title: 'ОСАГО', + insType, + getData: getData(insType, composeRequest, convertEltResult), + onSelectRow, + tableConfig, + requiredFields, +}); diff --git a/src/client/Components/Calculation/ELT/Content/Osago/lib/composeRequest.ts b/src/client/Components/Calculation/ELT/Content/Osago/lib/composeRequest.ts new file mode 100644 index 0000000..988b755 --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Osago/lib/composeRequest.ts @@ -0,0 +1,149 @@ +import { currentDate } from 'core/tools/date'; +import { ICalculationStore } from 'core/types/Calculation/Store'; +import { isNull } from 'lodash'; + +const mapCategory = { + 100000000: 'A', + 100000001: 'B', + 100000002: 'C', + 100000003: 'D', + 100000004: 'ПРОЧИЕ ТС', +}; + +const mapSubCategoryBuilder = (leaseObjectUseFor, maxMass, countSeats) => ({ + 100000000: () => '0', + 100000001: () => { + if (leaseObjectUseFor === 100000001) { + return '11'; + } + return '10'; + }, + 100000002: () => { + if (maxMass <= 16000) { + return '20'; + } + return '21'; + }, + 100000003: () => { + if (leaseObjectUseFor === 100000001) { + return '32'; + } + if (countSeats <= 20) { + return 30; + } + return '31'; + }, + 100000004: () => '22', +}); + +const getSpecified = value => !isNull(value); + +export default function (this: ICalculationStore) { + const regionName = this.getOption('selectRegionRegistration')?.evo_name; + const cityName = this.getOption('selectTownRegistration')?.evo_name; + const brandId = this.getOption('selectBrand')?.evo_id; + const modelId = this.getOption('selectModel')?.evo_id; + + const mark = this.getOption('selectGPSBrand')?.evo_id; + const model = this.getOption('selectGPSModel')?.evo_id; + const vehicleYear = this.getValue('leaseObjectYear') + ''; + const leaseObjectCategory = this.getValue('leaseObjectCategory'); + const vehiclePower = + leaseObjectCategory === 100000001 + ? parseFloat(this.getValue('leaseObjectMotorPower') || '0') + : '0'; + + let category = '0'; + if (Object.keys(mapCategory).includes(leaseObjectCategory)) { + category = mapCategory[leaseObjectCategory]; + } + + const leaseObjectUseFor = this.getValue('leaseObjectUseFor'); + const maxMass = this.getValue('maxMass'); + const countSeats = this.getValue('countSeats'); + const mapSubCategory = mapSubCategoryBuilder( + leaseObjectUseFor, + maxMass, + countSeats, + ); + const subCategory = mapSubCategory[leaseObjectCategory]; + + let seatingCapacity = 0; + if (leaseObjectCategory === 100000003) { + seatingCapacity = countSeats; + } + const seatingCapacitySpecified = getSpecified(seatingCapacity); + + let maxAllowedMass = 0; + if (leaseObjectCategory === 100000002) { + maxAllowedMass = maxMass; + } + const maxAllowedMassSpecified = getSpecified(maxAllowedMass); + + const useWithTrailer = this.getValue('withTrailer'); + const useWithTrailerSpecified = true; + + const address = { + resident: 1, + country: 'Российская Федерация', + region: 'Москва', + district: '0', + city: 'Москва', + cityKladr: '7700000000000', + street: 'ул. Котляковская', + streetKladr: '0', + house: '8', + korpus: '0', + flat: '337', + }; + + const owner = { + JuridicalName: 'ООО "ЛК "ЭВОЛЮЦИЯ"', + inn: '9724016636', + kpp: '772401001', + ogrn: '1207700245037', + registrationAddress: address, + factAddress: address, + phone: '8 (800) 333-75-75', + email: 'client@evoleasing.ru', + }; + + return { + preparams: { + regionName, + cityName, + brandId, + modelId, + }, + ELTParams: { + tsToRegistrationPlace: 0, + contractBeginDate: currentDate, + duration: 12, + carInfo: { + mark, + model, + vehicleYear, + vehiclePower, + tsType: { category, subCategory }, + vehicle: { + regNumber: '0', + bodyNumber: '0', + chassisNumber: '0', + VIN: '0', + seatingCapacity, + seatingCapacitySpecified, + maxAllowedMass, + maxAllowedMassSpecified, + }, + useWithTrailer, + useWithTrailerSpecified, + }, + owner, + FullDriversInfo: [ + { + kbm: '3', + }, + ], + }, + }; +} diff --git a/src/client/Components/Calculation/ELT/Content/Osago/lib/convertEltResult.js b/src/client/Components/Calculation/ELT/Content/Osago/lib/convertEltResult.js new file mode 100644 index 0000000..b746fa0 --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Osago/lib/convertEltResult.js @@ -0,0 +1,20 @@ +import { pick } from 'lodash'; + +export default function (resultCompany, key) { + if (!resultCompany || Object.keys(resultCompany).length === 0) { + return; + } + + const dataFromResult = pick( + resultCompany, + ['numCalc', 'premiumSum', 'message'], + '', + ); + + return { + key, + sumType: 'premiumSum', + sumTitle: 'Премия по договору', + ...dataFromResult, + }; +} diff --git a/src/client/Components/Calculation/ELT/Content/Osago/lib/onSelectRow.ts b/src/client/Components/Calculation/ELT/Content/Osago/lib/onSelectRow.ts new file mode 100644 index 0000000..92050f9 --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Osago/lib/onSelectRow.ts @@ -0,0 +1,21 @@ +import { ICalculationStore } from 'core/types/Calculation/Store'; + +export default function ( + this: ICalculationStore, + insType, + selectedKey: string, +) { + const selectedRow = this.stores.ELTStore[insType].list.find( + x => x.key === selectedKey, + ); + const { accountid, premiumSum } = selectedRow; + this.setTableRow( + 'tableInsurance', + 0, + )({ + insuranceCompany: { + value: accountid, + }, + insCost: { value: premiumSum }, + }); +} diff --git a/src/client/Components/Calculation/ELT/Content/Osago/lib/validation.ts b/src/client/Components/Calculation/ELT/Content/Osago/lib/validation.ts new file mode 100644 index 0000000..223ed45 --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/Osago/lib/validation.ts @@ -0,0 +1,13 @@ +import { ElementsNames } from 'core/types/Calculation/Store/elements'; + +export const requiredFields: ElementsNames[] = [ + 'selectRegionRegistration', + 'selectTownRegistration', + 'selectBrand', + 'selectModel', + 'tbxLeaseObjectYear', + 'tbxLeaseObjectMotorPower', + 'tbxLeasingPeriod', + 'tbxLeaseObjectPrice', + 'selectLeaseObjectCategory', +]; diff --git a/src/client/Components/Calculation/ELT/Content/index.jsx b/src/client/Components/Calculation/ELT/Content/index.jsx new file mode 100644 index 0000000..38e1cea --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/index.jsx @@ -0,0 +1,20 @@ +import { Flex } from 'client/UIKit/grid'; +import mq from 'client/UIKit/mq'; +import styled from 'styled-components'; +import Kasko from './Kasko'; +import Osago from './Osago'; + +const ContentDivider = styled.div` + margin: 16px 0; + ${mq.laptopHD` + margin: 0 16px; + `} +`; + +export default () => ( + + + + + +); diff --git a/src/client/Components/Calculation/ELT/Content/lib/config/columns.ts b/src/client/Components/Calculation/ELT/Content/lib/config/columns.ts new file mode 100644 index 0000000..2450641 --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/lib/config/columns.ts @@ -0,0 +1,21 @@ +export type KaskoDataNames = 'name' | 'sumTitle' | 'premiumSum'; + +const columns: { title: string; dataIndex: KaskoDataNames }[] = [ + { + title: 'Страховая компания', + dataIndex: 'name', + }, + { + title: '', + dataIndex: 'sumTitle', + }, + { + title: 'Сумма', + dataIndex: 'premiumSum', + //@ts-ignore + sorter: (a, b) => a.premiumSum - b.premiumSum, + sortDirections: ['descend', 'ascend'], + }, +]; + +export default columns; diff --git a/src/client/Components/Calculation/ELT/Content/lib/config/index.ts b/src/client/Components/Calculation/ELT/Content/lib/config/index.ts new file mode 100644 index 0000000..f6add11 --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/lib/config/index.ts @@ -0,0 +1,18 @@ +import { TableProps } from 'antd'; +import columns from './columns'; + +export default { + columns, + rowSelection: { + hideSelectAll: true, + type: 'radio', + }, + expandable: { + // rowExpandable: record => record.message || record.children, + // expandedRowRender: record => record.message, + // expandRowByClick: true, + // expandIconColumnIndex: -1, + }, + pagination: false, + size: 'small', +} as TableProps; diff --git a/src/client/Components/Calculation/ELT/Content/lib/getData.ts b/src/client/Components/Calculation/ELT/Content/lib/getData.ts new file mode 100644 index 0000000..45deb9a --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/lib/getData.ts @@ -0,0 +1,40 @@ +import ELTService from 'core/services/ELTService'; +import { ICalculationStore } from 'core/types/Calculation/Store'; +import { IAccount } from 'core/types/Entities/crmEntities'; + +export default (insType: string, composeRequest, convertEltResult) => + function (this: ICalculationStore, callback: () => any) { + const { ELTStore } = this.stores; + const request = composeRequest.call(this); + + const requests = ELTStore[insType].list.map( + (company: IAccount, i: number) => + new Promise((resolve, reject) => { + ELTService[insType] + .getCalculation({ + companyIds: [company.evo_id_elt], + ...request, + }) + .then(res => { + if (!company.evo_id_elt || !res[company.evo_id_elt]) { + return; + } + const converted = convertEltResult( + res[company.evo_id_elt], + company.accountid, + ); + ELTStore.setCompanyRes( + insType, + i, + Object.assign(company, converted), + ); + resolve(); + }) + .catch(err => { + reject(err); + }); + }), + ); + + Promise.allSettled(requests).then(() => callback()); + }; diff --git a/src/client/Components/Calculation/ELT/Content/lib/validation.ts b/src/client/Components/Calculation/ELT/Content/lib/validation.ts new file mode 100644 index 0000000..0f93f7e --- /dev/null +++ b/src/client/Components/Calculation/ELT/Content/lib/validation.ts @@ -0,0 +1,19 @@ +import { elementsTitles } from 'client/Containers/Calculation/lib/elements/titles'; +import { elementsValues } from 'client/Containers/Calculation/lib/elements/values'; +import { ICalculationStore } from 'core/types/Calculation/Store'; +import { ElementsNames } from 'core/types/Calculation/Store/elements'; + +export function validate(this: ICalculationStore, requiredValues) { + const missingValues = requiredValues.filter(x => { + const valueName = elementsValues[x] || ''; + + return ( + this.values[valueName] === undefined || this.values[valueName] === null + ); + }); + return missingValues; +} + +export function getFieldsNames(elementsNames: ElementsNames[]): string[] { + return elementsNames.map(x => elementsTitles[x] || ''); +} diff --git a/src/client/Components/Calculation/ELT/index.jsx b/src/client/Components/Calculation/ELT/index.jsx new file mode 100644 index 0000000..37f6b02 --- /dev/null +++ b/src/client/Components/Calculation/ELT/index.jsx @@ -0,0 +1,44 @@ +import { Modal } from 'antd'; +import { Outlined as SpinnerOutlined } from 'client/Components/Spinner'; +import Button from 'client/Elements/Button'; +import { Box } from 'client/UIKit/grid'; +import { lazy, Suspense, useState } from 'react'; + +const Content = lazy(() => import('./Content')); + +const ELT = ({ title }) => { + const [isOpenModal, setIsOpenModal] = useState(false); + function closeModal() { + setIsOpenModal(false); + } + return ( + <> + +