Merge branch 'development' into master

This commit is contained in:
vchikalkin 2021-06-21 15:32:31 +03:00
commit ec4ad39341
64 changed files with 1147 additions and 345 deletions

View File

@ -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 (

View File

@ -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 (

View File

@ -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,
});

View File

@ -34,11 +34,16 @@ const mapCategory = {
100000004: 'E1',
};
const mapInfuranceToLesseSubjectType = {
100000000: 1,
100000001: 2,
};
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;
@ -111,6 +116,9 @@ export default function (this: ICalculationStore) {
const INN = `${this.getValue('INNForCalc')}`;
const infuranceOPF = this.getValue('infuranceOPF');
const lesseSubjectType = get(mapInfuranceToLesseSubjectType, infuranceOPF, 0);
return {
preparams: {
kladr,
@ -172,7 +180,7 @@ export default function (this: ICalculationStore) {
SubjectTypeSpecified: true,
},
Lessee: {
SubjectType: 1,
SubjectType: lesseSubjectType,
SubjectTypeSpecified: true,
INN,
},

View File

@ -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;

View File

@ -1,3 +1,8 @@
import {
MAX_FRANCHISE,
MAX_INSURANCE,
MIN_INSURANCE,
} from 'core/constants/stores/Calculation/limits';
import { ICalculationStore } from 'core/types/Calculation/Store';
export default function (
@ -5,11 +10,27 @@ 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})`,
};
}
if (kaskoSum < MIN_INSURANCE) {
return {
message: `Сумма по страховке не должна быть меньше ${MIN_INSURANCE}`,
};
}
this.setValue('insFranchise', totalFranchise);
this.setTableRows(
@ -22,17 +43,5 @@ export default function (
},
insCost: { value: kaskoSum },
},
// {
// insuranceCompany: {
// value: accountid,
// },
// insCost: { value: goSum },
// },
// {
// insuranceCompany: {
// value: accountid,
// },
// insCost: { value: nsSum },
// },
]);
}

View File

@ -1,19 +1,118 @@
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',
'tbxLeaseObjectYear',
'tbxLeaseObjectMotorPower',
'selectEngineType',
'tbxLeasingPeriod',
'tbxLeaseObjectPrice',
'tbxSupplierDiscountRub',
'tbxInsFranchise',
'selectLeaseObjectCategory',
'selectLeaseObjectUseFor',
'tbxINNForCalc',
'radioInfuranceOPF',
];
export const conditions: TElements<ValidationCondition> = {
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,
};
},
selectLeaseObjectCategory: calculationStore => {
const leaseObjectCategory = calculationStore.getValue(
'leaseObjectCategory',
);
const leaseObjectType = calculationStore.getOption('selectLeaseObjectType');
if (!leaseObjectCategory) {
if (['6', '10'].includes(leaseObjectType?.evo_id || '')) {
return {
isValid: true,
};
} else
return {
isValid: false,
message: 'Не указана категория ТС',
};
}
return {
isValid: true,
};
},
selectEngineType: calculationStore => {
const engineType = calculationStore.getValue('engineType');
if (!engineType) {
if (['8'].includes(engineType?.evo_id || ''))
return {
isValid: true,
};
else
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,
};

View File

@ -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,
});

View File

@ -11,7 +11,7 @@ const mapCategory = {
};
const mapSubCategoryBuilder = (leaseObjectUseFor, maxMass, countSeats) => ({
100000000: '0',
100000000: () => '0',
100000001: () => {
if (leaseObjectUseFor === 100000001) {
return '11';
@ -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;
@ -68,7 +70,8 @@ export default function (this: ICalculationStore) {
maxMass,
countSeats,
);
const subCategory = mapSubCategory[leaseObjectCategory]();
const subCategory = get(mapSubCategory, leaseObjectCategory, () => '0')();
let seatingCapacity = 0;
if (leaseObjectCategory === 100000003) {

View File

@ -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;

View File

@ -1,3 +1,7 @@
import {
MAX_INSURANCE,
MIN_INSURANCE,
} from 'core/constants/stores/Calculation/limits';
import { ICalculationStore } from 'core/types/Calculation/Store';
export default function (
@ -5,10 +9,22 @@ 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})`,
};
}
if (premiumSum < MIN_INSURANCE) {
return {
message: `Сумма по страховке не должна быть меньше ${MIN_INSURANCE}`,
};
}
this.setTableRow(
'tableInsurance',
0,

View File

@ -1,8 +1,12 @@
import { ElementsNames } from 'core/types/Calculation/Store/elements';
import {
ElementsNames,
TElements,
} from 'core/types/Calculation/Store/elements';
import { ValidationCondition } from 'core/validation/validate';
import { omit } from 'lodash';
import { conditions as kaskoConditions } from '../../Kasko/lib/validation';
export const requiredFields: ElementsNames[] = [
'selectRegionRegistration',
'selectTownRegistration',
'selectBrand',
'selectModel',
'tbxLeaseObjectYear',
@ -13,6 +17,42 @@ export const requiredFields: ElementsNames[] = [
'tbxMaxMass',
'tbxCountSeats',
'cbxWithTrailer',
'selectLeaseObjectCategory',
'tbxINNForCalc',
'radioObjectRegistration',
'radioInfuranceOPF',
];
const conditions: TElements<ValidationCondition> = {
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,
omit(kaskoConditions, ['selectEngineType']),
),
};

View File

@ -14,3 +14,9 @@ export default {
pagination: false,
size: 'small',
} as TableProps<any>;
export type InsTableColumn = {
title?: string;
dataIndex: string;
[key: string]: any;
};

View File

@ -3,6 +3,7 @@ import ELTService from 'core/services/ELTService';
import { ICalculationStore } from 'core/types/Calculation/Store';
import { IAccount } from 'core/types/Entities/crmEntities';
import { toJS } from 'mobx';
import { map_evo_id_elt_FieldName } from '../lib/resetIns';
const CancelToken = axios.CancelToken;
export let sources = {};
@ -18,23 +19,30 @@ export const fetchData = (insType: string, composeRequest, convertEltResult) =>
const { ELTStore } = this.stores;
const request = composeRequest.call(this);
const evo_id_elt_fieldName = map_evo_id_elt_FieldName[insType];
const requests = ELTStore[insType].list.map(
(company: IAccount, i: number) =>
new Promise<void>((resolve, reject) => {
(company: IAccount, i: number) => {
//@ts-ignore
company.isFetching = true;
return new Promise<void>((resolve, reject) => {
ELTService[insType]
.getCalculation(
{
companyIds: [company.evo_id_elt],
companyIds: [company[evo_id_elt_fieldName]],
...request,
},
sources[insType].token,
)
.then(res => {
if (!company.evo_id_elt || !res[company.evo_id_elt]) {
if (
!company[evo_id_elt_fieldName] ||
!res[company[evo_id_elt_fieldName]]
) {
return;
}
const converted = convertEltResult(
res[company.evo_id_elt],
res[company[evo_id_elt_fieldName]],
company.accountid,
toJS(this.getValues(['leasingPeriod'])),
);
@ -47,8 +55,13 @@ export const fetchData = (insType: string, composeRequest, convertEltResult) =>
})
.catch(err => {
reject(err);
})
.finally(() => {
//@ts-ignore
company.isFetching = false;
});
}),
});
},
);
return Promise.race(requests);

View File

@ -8,7 +8,17 @@ const mapInsType = {
osago: 100000001,
};
export const initFields = ['evo_id_elt', 'name', 'accountid'];
export const map_evo_id_elt_FieldName = {
kasko: 'evo_id_elt',
osago: 'evo_id_elt_osago',
};
export const initFields = [
'evo_id_elt_osago',
'evo_id_elt',
'name',
'accountid',
];
export function initIns(this: ICalculationStore, insType) {
const insuranceCompanies = this.getTableOptions(
@ -20,10 +30,11 @@ export function initIns(this: ICalculationStore, insType) {
}
const { ELTStore } = this.stores;
const list: TCRMEntity[] = [];
const evo_id_elt_fieldName = map_evo_id_elt_FieldName[insType];
insuranceCompanies.forEach(company => {
if (
company &&
company.evo_id_elt &&
company[evo_id_elt_fieldName] &&
company.evo_type_ins_policy &&
company.evo_type_ins_policy.includes(mapInsType[insType])
) {

View File

@ -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<ValidationCondition>;
};
export default function (this: ICalculationStore, validation: ELTValidation) {
const { requiredFields, conditions: customConditions } = validation;
const requiredFieldsConditions = requiredFields.reduce(
(ac: TElements<ValidationCondition>, 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;
}

View File

@ -4,4 +4,4 @@ import { Spin } from 'antd';
export default Spin;
const loadingOutlined = <LoadingOutlined style={{ fontSize: 24 }} spin />;
export const Outlined = () => <Spin indicator={loadingOutlined} />;
export const Outlined = <Spin indicator={loadingOutlined} />;

View File

@ -273,9 +273,10 @@ const sections: ISection[] = [
{
elements: [
'cbxInsDecentral',
'radioInsKaskoType',
// 'radioInsKaskoType',
'tbxInsFranchise',
'tbxMileage',
'radioInfuranceOPF',
// 'selectInsPeriod',
// 'btnFranschise',
],
@ -286,7 +287,7 @@ const sections: ISection[] = [
'tbxInsAgeDrivers',
'tbxInsExpDrivers',
'cbxWithTrailer',
// 'tbxINNForCalc',
'tbxINNForCalc',
// 'btnDriversApplication',
],
},
@ -294,9 +295,8 @@ const sections: ISection[] = [
elements: [
'selectGPSBrand',
'selectGPSModel',
'selectRegionRegistration',
'selectTownRegistration',
// 'selectInfuranceOPF',
'selectLegalClientRegion',
'selectLegalClientTown',
'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: [

View File

@ -105,7 +105,7 @@ const elementsComponents: TElements<Component> = {
selectGPSModel: Select,
selectRegionRegistration: Select,
selectTownRegistration: Select,
selectInfuranceOPF: Select,
radioInfuranceOPF: Radio,
tbxInsKaskoPriceLeasePeriod: InputNumber,
selectRegistration: Select,
selectInsNSIB: Select,
@ -169,6 +169,8 @@ const elementsComponents: TElements<Component> = {
selectObjectTypeTax: Select,
radioTypePTS: Radio,
labelRegistrationDescription: Label,
selectLegalClientRegion: Select,
selectLegalClientTown: Select,
};
const tablesComponents: StoreTables<Component> = {

View File

@ -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<ElementProps> = {
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<ElementProps> = {
},
tbxInsFranchise: {
min: '0',
max: '75000',
max: MAX_FRANCHISE,
step: '10000.00',
precision: 2,
formatter: formatNumber,
@ -409,7 +410,15 @@ const elementsProps: TElements<ElementProps> = {
precision: 2,
formatter: formatNumber,
},
selectLegalClientRegion: {
showSearch: true,
},
selectLegalClientTown: {
showSearch: true,
},
radioInfuranceOPF: {
style: 'button',
},
};
const resultElementsProps: TElements<ElementProps> = Object.assign(
@ -430,7 +439,8 @@ const resultElementsProps: TElements<ElementProps> = 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 +452,7 @@ const resultElementsProps: TElements<ElementProps> = Object.assign(
].reduce(
(ac, a) => ({
...ac,
[a]: { middleware: value => round(value || 0) },
[a]: { middleware: value => round(value) },
}),
{},
),

View File

@ -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: '1500000.00',
max: MAX_INSURANCE,
step: '1000.00',
precision: 2,
formatter: formatNumber,

View File

@ -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),
},
},
];

View File

@ -86,7 +86,7 @@ export const elementsTitles: TElements<string> = {
selectGPSModel: 'Модель GPS',
selectRegionRegistration: 'Регион регистрации',
selectTownRegistration: 'Город регистрации',
selectInfuranceOPF: 'ОПФ для расчета страховки',
radioInfuranceOPF: 'ОПФ для расчета страховки',
radioInsKaskoType: 'Тип страхования КАСКО',
tbxInsKaskoPriceLeasePeriod: 'Стоимость страховки КАСКО на весь срок',
cbxInsDecentral: 'Децентрализованное страхование',
@ -134,6 +134,8 @@ export const elementsTitles: TElements<string> = {
radioTypePTS: 'Тип ПТС',
labelRegistrationDescription: 'Описание регистрации',
tbxINNForCalc: 'ИНН контрагента',
selectLegalClientRegion: 'Регион по юр.адресу клиента',
selectLegalClientTown: 'Город по юр.адресу клиента',
};
const resultsTitles: TElements<string> = {

View File

@ -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];
}

View File

@ -89,7 +89,7 @@ export const elementsValues: TElements<ValuesNames> = {
selectGPSModel: 'GPSModel',
selectRegionRegistration: 'regionRegistration',
selectTownRegistration: 'townRegistration',
selectInfuranceOPF: 'infuranceOPF',
radioInfuranceOPF: 'infuranceOPF',
radioInsKaskoType: 'insKaskoType',
cbxInsDecentral: 'insDecentral',
selectInsPeriod: 'insPeriod',
@ -133,6 +133,8 @@ export const elementsValues: TElements<ValuesNames> = {
selectObjectCategoryTax: 'objectCategoryTax',
selectObjectTypeTax: 'objectTypeTax',
radioTypePTS: 'typePTS',
selectLegalClientRegion: 'legalClientRegion',
selectLegalClientTown: 'legalClientTown',
};
const resultElementsValues: TElements<ResultValuesNames> = {

View File

@ -11,6 +11,7 @@ const query = gql`
name
evo_type_ins_policy
evo_id_elt
evo_id_elt_osago
}
}
`;

View File

@ -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
@ -242,8 +250,10 @@ const query = gql`
}
}
selectRate: evo_rates(
statecode: $statecode # evo_datefrom_param: { lte: $currentDate } # evo_dateto_param: { gte: $currentDate }
) {
statecode: $statecode
) # evo_datefrom_param: { lte: $currentDate }
# evo_dateto_param: { gte: $currentDate }
{
evo_id
evo_rateid
evo_name
@ -321,6 +331,7 @@ const toOptions = [
'selectRate',
'selectLeaseObjectType',
'selectObjectRegionRegistration',
'selectLegalClientRegion',
];
export default {

View File

@ -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 (
<AntButton
{...props}
disabled={status === ElementStatus.Disabled}
loading={status === ElementStatus.Loading}
onClick={() => {
if (action) action();
if (throttledAction) throttledAction();
}}
>
{text}

View File

@ -51,7 +51,7 @@ const InputNumber = ({
onChange={value => setCurrentValue(value)}
value={value}
/>
{status === ElementStatus.Loading && <Outlined />}
{status === ElementStatus.Loading && Outlined}
</FormWrapper>
);
};

View File

@ -2,7 +2,7 @@ import { Form, Select as AntSelect } from 'antd';
import { ElementStatus } from 'core/types/statuses';
const Select = ({
value,
value = null,
setCurrentValue,
status,
validateStatus,

View File

@ -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;

View File

@ -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<ValidationCondition> = {
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<any> = {
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<any> = {
// 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<ValidationCondition>, 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);
});
}

View File

@ -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`

View File

@ -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 '-';

View File

@ -15,4 +15,6 @@ evo_seats
evo_year
offerprintformapi
evo_regionid
evo_legal_regionid
evo_legal_townid
`;

View File

@ -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: () => {

View File

@ -390,7 +390,7 @@ const gibddReactions: IReactionEffect[] = [
},
}),
calculationStore => ({
(calculationStore, calculationProcess) => ({
expression: () => {
return {
lead: calculationStore.getOption('selectLead'),
@ -405,8 +405,7 @@ const gibddReactions: IReactionEffect[] = [
ElementStatus.Default,
);
let evo_regionid = calculationStore.getOption('selectQuote')
?.evo_regionid;
let evo_regionid;
if (objectRegistration === 100000001) {
calculationStore.setFilter('selectRegionRegistration', options =>
@ -434,7 +433,155 @@ const gibddReactions: IReactionEffect[] = [
}
}
}
calculationStore.setValue('regionRegistration', evo_regionid);
if (!calculationProcess.hasProcess(Process.LoadKp)) {
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 {
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);
},
}),
(calculationStore, calculationProcess) => ({
expression: () => {
return {
...calculationStore.getValues([
'regionRegistration',
'objectRegistration',
'legalClientTown',
]),
townRegistrationOptions: calculationStore.getOption(
'selectTownRegistration',
),
};
},
effect: ({ objectRegistration, legalClientTown }) => {
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);
if (!calculationProcess.hasProcess(Process.LoadKp)) {
calculationStore.setValue('townRegistration', legalClientTown);
}
}
},
}),
];

View File

@ -1,5 +1,6 @@
import eltReactions from './eltReactions';
import gibddReactions from './gibddReactions';
import insuranceReactions from './insuranceReactions';
import loadKpReaction from './loadKpReaction';
import otherReactions from './otherReactions';
import priceReactions from './priceReactions';
@ -17,5 +18,6 @@ export default [
...recalcWoRevisionReactions,
...gibddReactions,
...eltReactions,
...insuranceReactions,
loadKpReaction,
];

View File

@ -0,0 +1,86 @@
import { IReactionEffect } from 'core/types/Calculation/Store/effect';
import { Process } from 'core/types/Calculation/Store/process';
import { get } from 'lodash';
const mapObjectCategoryToUseFor = {
100000000: [100000000, 100000002],
100000001: [
100000000,
100000001,
100000002,
100000003,
100000004,
100000005,
100000006,
100000007,
100000008,
100000009,
100000010,
100000011,
100000012,
100000013,
],
100000002: [100000002, 100000004, 100000005, 100000006, 100000009, 100000010],
100000003: [
100000002,
100000004,
100000006,
100000007,
100000008,
100000011,
100000012,
100000013,
],
100000004: [100000002, 100000009],
};
const insuranceReactions: IReactionEffect[] = [
calculationStore => ({
expression: () => {
return calculationStore.getValue('leaseObjectCategory');
},
effect: leaseObjectCategory => {
if (leaseObjectCategory) {
const allowedObjectUseFor: number[] =
mapObjectCategoryToUseFor[leaseObjectCategory];
calculationStore.setFilter('selectLeaseObjectUseFor', options =>
options.filter(
option =>
option.value &&
typeof option.value === 'number' &&
allowedObjectUseFor &&
allowedObjectUseFor.includes(option.value),
),
);
} else {
calculationStore.setFilter('selectLeaseObjectUseFor', undefined);
}
},
}),
(calculationStore, calculationProcess) => ({
expression: () => {
return calculationStore.getValue('INNForCalc');
},
effect: INNForCalc => {
if (calculationProcess.hasProcess(Process.LoadKp)) {
return;
}
const mapINNForCalcToInfuranceOPF = {
10: 100000000,
12: 100000001,
};
const OPFValue = get(
mapINNForCalcToInfuranceOPF,
INNForCalc ? INNForCalc.toString().length : 0,
null,
);
calculationStore.setValue('infuranceOPF', OPFValue);
},
}),
];
export default insuranceReactions;

View File

@ -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';
@ -59,7 +61,9 @@ const loadKpReaction: IReactionEffect = calculationStore => ({
calcType,
indAgent,
INNForCalc,
regionRegistration,
creditRate,
rate,
infuranceOPF,
} = calculationStore.values;
calculationStore.setStatus('selectQuote', ElementStatus.Disabled);
@ -112,6 +116,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 +131,7 @@ const loadKpReaction: IReactionEffect = calculationStore => ({
'selectFinDepartmentRewardCondtion',
'selectGPSModel',
'selectTownRegistration',
'selectLegalClientTown',
],
});
@ -231,10 +237,6 @@ const loadKpReaction: IReactionEffect = calculationStore => ({
}),
);
const rate = calculationStore.getOption('selectRate', {
evo_rateid: quote.evo_rateid,
});
let clientRisk = quote.evo_client_riskid;
if (opportunity) {
const current_opportunity = calculationStore.getOption(
@ -285,7 +287,7 @@ const loadKpReaction: IReactionEffect = calculationStore => ({
...newValues,
product: base_product?.evo_id,
...addProducts,
rate: rate?.evo_id,
rate,
lead,
opportunity,
quote: quoteId,
@ -298,12 +300,77 @@ const loadKpReaction: IReactionEffect = calculationStore => ({
requirementTelematic,
vehicleTaxInYear,
INNForCalc,
regionRegistration,
creditRate,
infuranceOPF,
});
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 => {

View File

@ -22,7 +22,7 @@ const mapKPtoValues: TValues<string> = {
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,9 @@ const mapKPtoValues: TValues<string> = {
objectTypeTax: 'evo_vehicle_type_tax',
typePTS: 'evo_pts_type',
townRegistration: 'evo_townid',
regionRegistration: 'evo_regionid',
legalClientRegion: 'evo_legal_regionid',
legalClientTown: 'evo_legal_townid',
};
export function getKpPropName(valueName: ValuesNames) {

View File

@ -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
@ -133,6 +134,18 @@ export default gql`
evo_name
evo_townid
evo_fias_id
evo_kladr_id
evo_businessunit_evolution
}
selectLegalClientTown: evo_towns(
statecode: $statecode
evo_regionid: $evo_legal_regionid
) {
evo_name
evo_townid
evo_fias_id
evo_kladr_id
evo_businessunit_evolution
}
}
`;

View File

@ -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
}
}
`;

View File

@ -1,5 +1,6 @@
import { openNotification } from 'client/Elements/Notification';
import { compose } from 'core/tools/func';
import valuesConstants from 'core/constants/values';
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 +1689,7 @@ const reactionEffects: IReactionEffect[] = [
calculationStore.setFilter('selectBrand', options =>
options.filter(
compose(
pipe(
option => {
if (
product &&
@ -1754,6 +1755,18 @@ const reactionEffects: IReactionEffect[] = [
calculationStore.setValue('INNForCalc', inn);
},
}),
calculationStore => ({
expression: () => {
return calculationStore.getOption('selectRate');
},
effect: ({ evo_base_rate }) => {
calculationStore.setValue(
'creditRate',
evo_base_rate || valuesConstants.RATE,
);
},
}),
];
export default reactionEffects;

View File

@ -1074,30 +1074,43 @@ 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.getValues([
regionValueName,
'objectRegistration',
]);
},
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 +1122,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 +1137,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[];

View File

@ -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',
];

View File

@ -1,5 +1,6 @@
import { TElements } from 'core/types/Calculation/Store/elements';
import { IBaseOption } from 'core/types/Calculation/Store/options';
import { orderBy } from 'lodash';
const initialOptions: TElements<IBaseOption[]> = {
selectChannel: [
@ -213,67 +214,71 @@ const initialOptions: TElements<IBaseOption[]> = {
},
],
selectLeaseObjectUseFor: [
{
name: 'Для представительских целей',
value: 100000000,
},
{
name: 'Для использования в качестве «такси»',
value: 100000001,
},
{
name: 'Для передачи третьим лицам (прокат; аренда)',
value: 100000002,
},
{
name: 'Каршеринг',
value: 100000003,
},
{
name: 'Тест-драйв',
value: 100000004,
},
{
name: 'Для доставки продуктов конечному потребителю',
value: 100000005,
},
{
name: 'Для обучения вождению',
value: 100000006,
},
{
name: 'Маршрутные такси / Рейсовые автобусы',
value: 100000007,
},
{
name: 'Междугородние перевозки',
value: 100000008,
},
{
name: 'Для перевозки крупногабаритных грузов',
value: 100000009,
},
{
name: 'Для перевозки малогабаритных грузов',
value: 100000010,
},
{
name: 'Для перевозки сотрудников других организаций (водитель ЛП)',
value: 100000011,
},
{
name: 'Для перевозки сотрудников ЛП',
value: 100000012,
},
{
name:
'Для экскурсионных перевозок в т.ч. на торжества; трансфер в аэропорт и пр.',
value: 100000013,
},
],
selectLeaseObjectUseFor: orderBy(
[
{
name: 'Для представительских целей',
value: 100000000,
},
{
name: 'Для использования в качестве «такси»',
value: 100000001,
},
{
name: 'Для передачи третьим лицам (прокат; аренда)',
value: 100000002,
},
{
name: 'Каршеринг',
value: 100000003,
},
{
name: 'Тест-драйв',
value: 100000004,
},
{
name: 'Для доставки продуктов конечному потребителю',
value: 100000005,
},
{
name: 'Для обучения вождению',
value: 100000006,
},
{
name: 'Маршрутные такси / Рейсовые автобусы',
value: 100000007,
},
{
name: 'Междугородние перевозки',
value: 100000008,
},
{
name: 'Для перевозки крупногабаритных грузов',
value: 100000009,
},
{
name: 'Для перевозки малогабаритных грузов',
value: 100000010,
},
{
name: 'Для перевозки сотрудников других организаций (водитель ЛП)',
value: 100000011,
},
{
name: 'Для перевозки сотрудников ЛП',
value: 100000012,
},
{
name:
'Для экскурсионных перевозок в т.ч. на торжества; трансфер в аэропорт и пр.',
value: 100000013,
},
],
objectUseFor => objectUseFor.name.toLowerCase(),
['asc'],
),
radioInsuranceOPF: [
radioInfuranceOPF: [
{
name: 'ЮЛ',
value: 100000000,

View File

@ -40,6 +40,7 @@ const initialStatuses: TElements<ElementStatus> = {
selectObjectTypeTax: ElementStatus.Disabled,
selectLeaseObjectCategory: ElementStatus.Disabled,
tbxINNForCalc: ElementStatus.Disabled,
radioInfuranceOPF: ElementStatus.Disabled,
};
export default initialStatuses;

View File

@ -1,3 +1,4 @@
import valuesConstants from 'core/constants/values';
import { currentYear } from 'core/tools/date';
import { TValue, TValues } from 'core/types/Calculation/Store/values';
@ -71,7 +72,7 @@ const initialValues: TValues<TValue> = {
NSIB: true,
quoteContactGender: 100000000,
quoteRedemptionGraph: true,
creditRate: 7,
creditRate: valuesConstants.RATE,
requirementTelematic: 100000000,
maxPriceChange: 0,
importerRewardPerc: 0,
@ -86,5 +87,9 @@ const initialValues: TValues<TValue> = {
objectRegistration: 100000000,
typePTS: 100000001,
insNSIB: null,
regionRegistration: null,
legalClientRegion: null,
legalClientTown: null,
infuranceOPF: null,
};
export default initialValues;

View File

@ -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 };
},
},
),
);

View File

@ -1,2 +1,3 @@
export const DEFAULT_DEBOUNCE_DELAY = 350;
export const NOTIFICATION_DEBOUNCE = 750;
export const ACTION_DELAY = 1200;

View File

@ -0,0 +1,3 @@
export const MAX_FRANCHISE = 75000;
export const MAX_INSURANCE = 2500000;
export const MIN_INSURANCE = 3000;

View File

@ -8,4 +8,5 @@ export default {
MAX_VEHICLE_MASS: 3500,
MAX_VEHICLE_SEATS: 20,
PERIODS_NUMBER: 12,
RATE: 7.75,
};

View File

@ -102,6 +102,7 @@ export default class {
static createKp = (data: ICreateKpRequest): Promise<IQuote> =>
new Promise((resolve, reject) => {
console.log('createKp data: ', data);
axios
.post<IQuote>(
String.prototype.concat(

View File

@ -1,2 +0,0 @@
export const compose = (...functions) => args =>
functions.reduce((arg, fn) => fn(arg), args);

13
src/core/tools/func.ts Normal file
View File

@ -0,0 +1,13 @@
export const compose = <R>(fn1: (a: R) => R, ...fns: Array<(a: R) => R>) =>
fns.reduce((prevFn, nextFn) => value => prevFn(nextFn(value)), fn1);
export const pipe = <T extends any[], R>(
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));
};

View File

@ -1,3 +0,0 @@
import { round as _round } from 'lodash';
export const round = (value, n) => _round(value, n || 2).toFixed(n || 2);

3
src/core/tools/num.ts Normal file
View File

@ -0,0 +1,3 @@
import { round as _round } from 'lodash';
export const round = (value = 0, n = 2) => _round(value, n).toFixed(n);

View File

@ -37,6 +37,9 @@ export interface ICreateKpRequest {
calculationValues: TValues<any>;
columns: { [column in ColumnsNames]?: IColumn };
};
elt: {
[insType: string]: any;
};
}
export interface IGetTransTaxRequest {

View File

@ -87,7 +87,7 @@ export type ElementsNames =
| 'selectGPSModel'
| 'selectRegionRegistration'
| 'selectTownRegistration'
| 'selectInfuranceOPF'
| 'radioInfuranceOPF'
| 'radioInsKaskoType'
| 'tbxInsKaskoPriceLeasePeriod'
| 'cbxInsDecentral'
@ -124,7 +124,6 @@ export type ElementsNames =
| 'tbxBusinessUnit'
| 'tbxLeadNumber'
| 'tbxOpportunityNumber'
| 'radioInsuranceOPF'
| 'lblLead'
| 'lblOpportunity'
| 'btnCalculate'
@ -144,7 +143,9 @@ export type ElementsNames =
| 'selectObjectCategoryTax'
| 'selectObjectTypeTax'
| 'radioTypePTS'
| 'labelRegistrationDescription';
| 'labelRegistrationDescription'
| 'selectLegalClientRegion'
| 'selectLegalClientTown';
export type LinkElementsNames = 'linkDownloadKp';

View File

@ -129,7 +129,9 @@ export type ValuesNames =
| 'vehicleTaxInLeasingPeriod'
| 'objectCategoryTax'
| 'objectTypeTax'
| 'typePTS';
| 'typePTS'
| 'legalClientRegion'
| 'legalClientTown';
export type ComputedValuesNames =
| 'leadName'

View File

@ -17,6 +17,7 @@ export interface IAccount {
evo_kpp?: string;
evo_address_legalidData?: IEvoAddress;
evo_id_elt?: string;
evo_id_elt_osago?: string;
}
export interface IEvoAddress {
@ -86,6 +87,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 +224,7 @@ export interface IEvoTown {
statecode?: number;
evo_fias_id?: string;
evo_kladr_id?: string;
evo_businessunit_evolution?: boolean;
}
export interface IEvoContact {
parentcustomerid?: string;

View File

@ -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,
};

View File

@ -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<ValidationCondition>,
) => {
const validationResult: TElements<ValidationResult> = (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 });