diff --git a/package.json b/package.json index 42d3989..6dafe01 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,8 @@ "helmet": "^4.1.0", "http-errors": "^1.8.0", "lodash": "^4.17.20", - "mobx": "^5.15.6", - "mobx-react": "^6.3.0", - "mobx-react-lite": "^2.2.2", + "mobx": "^6.0.0", + "mobx-react-lite": "^3.0.0", "morgan": "^1.10.0", "mssql": "^6.2.1", "nodemon": "^2.0.4", diff --git a/src/client/App.tsx b/src/client/App.tsx index 137d4b3..dbe21cb 100644 --- a/src/client/App.tsx +++ b/src/client/App.tsx @@ -1,4 +1,3 @@ -import 'mobx-react/batchingForReactDom'; import { StoreProvider } from 'client/contexts/storeContext'; import theme from 'client/UIKit/theme'; import React from 'react'; diff --git a/src/client/Containers/Calculation/Sections/sectionsList.ts b/src/client/Containers/Calculation/Sections/sectionsList.ts index 8da5cc4..049375a 100644 --- a/src/client/Containers/Calculation/Sections/sectionsList.ts +++ b/src/client/Containers/Calculation/Sections/sectionsList.ts @@ -1294,23 +1294,22 @@ const sections: ISections[] = [ }, { elements: [ - // { - // title: 'Марка GPS', - // Component: Select, - // props: { - // name: 'selectGPSBrand', - // valueName: 'GPSBrand', - // }, - // }, - // { - // title: 'Модель GPS', - // Component: Select, - // props: { - // name: 'selectGPSModel', - // valueName: 'GPSModel', - // }, - // }, - + { + title: 'Марка GPS', + Component: Select, + props: { + name: 'selectGPSBrand', + valueName: 'GPSBrand', + }, + }, + { + title: 'Модель GPS', + Component: Select, + props: { + name: 'selectGPSModel', + valueName: 'GPSModel', + }, + }, { title: 'Регион регистрации', Component: Select, @@ -1348,6 +1347,47 @@ const sections: ISections[] = [ }, ], }, + { + elements: [ + { + type: ElementType.Table, + Component: Table, + props: { + name: 'tableInsurance', + features: { + // canDeleteRow: true, + }, + columns: [ + { + name: 'policyType', + title: 'Тип полиса', + Component: Label, + }, + { + name: 'insuranceCompany', + title: 'Страховая компания', + Component: Select, + }, + { + name: 'insured', + title: 'Плательщик', + Component: Select, + }, + { + name: 'insCost', + title: 'Стоимость полиса', + Component: InputNumber, + }, + { + name: 'insTerm', + title: 'Срок страхования', + Component: Select, + }, + ], + }, + }, + ], + }, ], }, ], @@ -1358,45 +1398,7 @@ const sections: ISections[] = [ { blocks: [ { - elements: [ - { - type: ElementType.Table, - Component: Table, - props: { - name: 'tableInsurance', - features: { - canDeleteRow: true, - }, - columns: [ - { - name: 'policyType', - title: 'Тип полиса', - Component: Select, - }, - { - name: 'insuranceCompany', - title: 'Страховщик', - Component: Select, - }, - { - name: 'insured', - title: 'Страхователь', - Component: Select, - }, - { - name: 'cost', - title: 'Стоимость полиса', - Component: InputNumber, - }, - { - name: 'insuranceTerm', - title: 'Срок страхования', - Component: InputNumber, - }, - ], - }, - }, - ], + elements: [], }, ], }, diff --git a/src/client/Containers/Calculation/index.jsx b/src/client/Containers/Calculation/index.jsx index a54da2c..3039813 100644 --- a/src/client/Containers/Calculation/index.jsx +++ b/src/client/Containers/Calculation/index.jsx @@ -31,14 +31,36 @@ const Calculation = () => { CalculationService.getEntityOptions({ entityName: 'opportunity', }), + CalculationService.getEntityOptions({ + entityName: 'account', + where: { evo_account_type: 100000002, statecode: 0 }, + }), ]) - .then(([initialOptions, staticEntities, leadOptions, opportunities]) => { - calculationStore.applyOptions({ ...initialOptions }); - calculationStore.setStaticData(staticEntities); - calculationStore.applyOptions({ selectLead: leadOptions }); - calculationStore.applyOptions({ selectOpportunity: opportunities }); - setReady(true); - }) + .then( + ([ + initialOptions, + staticEntities, + leadOptions, + opportunities, + insuranceCompanies, + ]) => { + calculationStore.applyOptions({ ...initialOptions }); + calculationStore.setStaticData(staticEntities); + calculationStore.applyOptions({ selectLead: leadOptions }); + calculationStore.applyOptions({ selectOpportunity: opportunities }); + calculationStore.setTableColumn( + { + tableName: 'tableInsurance', + }, + { + options: { + insuranceCompany: insuranceCompanies, + }, + }, + ); + setReady(true); + }, + ) .catch(err => { setError(err); throw err; diff --git a/src/client/hooks/useOptions.js b/src/client/hooks/useOptions.js index ecd1e71..8d69d27 100644 --- a/src/client/hooks/useOptions.js +++ b/src/client/hooks/useOptions.js @@ -18,7 +18,8 @@ export const useTableOptions = ({ tableName, rowIndex, propName }) => { []; const filter = calculationStore.tables[tableName].filters && - calculationStore.tables[tableName].filters[propName]; + calculationStore.tables[tableName].filters[rowIndex] && + calculationStore.tables[tableName].filters[rowIndex][propName]; return { options: filter ? filter(options) : options, }; diff --git a/src/client/stores/CalculationStore/Data/tables.js b/src/client/stores/CalculationStore/Data/tables.js index 923163e..8851175 100644 --- a/src/client/stores/CalculationStore/Data/tables.js +++ b/src/client/stores/CalculationStore/Data/tables.js @@ -4,38 +4,71 @@ const tablesData = { tables: initialTables, }; +const checkIsTableExist = function (tableName) { + if (!this.tables[tableName]) { + throw new Error(`Table ${tableName} doesn't exist in store!`); + } +}; + +const addRowParams = function (tableName, rowIndex, targetName, params) { + if (!this.tables[tableName][targetName]) { + this.tables[tableName][targetName] = []; + } + + this.tables[tableName][targetName].splice(rowIndex, 0, params || {}); +}; + +const setRowParams = function (tableName, rowIndex, targetName, params) { + if ( + params && + Object.keys(params).length > 0 && + !Object.values(params).every(x => x === undefined) + ) + this.tables[tableName][targetName][rowIndex] = Object.assign( + this.tables[tableName][targetName][rowIndex] ?? {}, + params, + ); +}; + const tablesActions = { - setTableRow({ tableName, rowIndex }, { values, statuses }) { - if (!this.tables[tableName]) { - throw new Error(`Table ${tableName} doesn't exist in store`); - } + addTableRow({ tableName, rowIndex }, params) { + checkIsTableExist.call(this, tableName); if (rowIndex === undefined) { rowIndex = this.tables[tableName].values.length; } - const applyRowParams = (targetName, values) => { - if (!this.tables[tableName][targetName]) { - this.tables[tableName][targetName] = []; - } - this.tables[tableName][targetName][rowIndex] = Object.assign( - this.tables[tableName][targetName][rowIndex] ?? {}, - values, + for (let paramsName in params) { + addRowParams.call( + this, + tableName, + rowIndex, + paramsName, + params[paramsName], ); - }; - - if (values && Object.keys(values).length > 0) { - applyRowParams('values', values); - } - if (statuses && Object.keys(statuses).length > 0) { - applyRowParams('statuses', statuses); } }, - setTableColumn({ tableName }, { filters, options, callbacks }) { - if (!this.tables[tableName]) { - throw new Error(`Table ${tableName} doesn't exist in store`); + setTableRow({ tableName, rowIndex }, params) { + checkIsTableExist.call(this, tableName); + + if (!this.tables[tableName].values[rowIndex]) { + throw new Error(`Missing row#${rowIndex} in table ${tableName}!`); } + for (let paramsName in params) { + setRowParams.call( + this, + tableName, + rowIndex, + paramsName, + params[paramsName], + ); + } + }, + + setTableColumn({ tableName }, { options, callbacks }) { + checkIsTableExist.call(this, tableName); + const applyColumnParams = (targetName, values) => { if (!this.tables[tableName][targetName]) { this.tables[tableName][targetName] = {}; @@ -47,9 +80,6 @@ const tablesActions = { ); }; - if (filters && Object.keys(filters).length > 0) { - applyColumnParams('filters', filters); - } if (options && Object.keys(options).length > 0) { applyColumnParams('options', options); } @@ -58,16 +88,6 @@ const tablesActions = { } }, - setRowOptions({ tableName }, options) { - if (!this.tables[tableName]) { - throw new Error(`Table ${tableName} doesn't exist in store`); - } - if (!this.tables[tableName].options) { - this.tables[tableName].options = []; - } - this.tables[tableName].options = options; - }, - setTable({ tableName }, values) { if (!this.tables[tableName]) { this.tables[tableName] = {}; @@ -76,13 +96,11 @@ const tablesActions = { }, deleteTableRow(tableName, rowIndex) { + checkIsTableExist.call(this, tableName); const targetTable = this.tables[tableName]; - if (!targetTable) { - throw new Error(`Table ${tableName} doesn't exist in store`); - } if (targetTable.values) targetTable.values.splice(rowIndex, 1); - if (targetTable.filters) targetTable.filters.splice(rowIndex, 1); if (targetTable.statuses) targetTable.statuses.splice(rowIndex, 1); + if (targetTable.filters) targetTable.filters.splice(rowIndex, 1); }, cleanTable(tableName) { diff --git a/src/client/stores/CalculationStore/Effects/reaction.ts b/src/client/stores/CalculationStore/Effects/reaction.ts index 47afeb3..934f5c2 100644 --- a/src/client/stores/CalculationStore/Effects/reaction.ts +++ b/src/client/stores/CalculationStore/Effects/reaction.ts @@ -2023,6 +2023,149 @@ const reactionEffects: IReactionEffect[] = [ calculationStore.setValue('importerRewardRub', 0); }, }), + + calculationStore => ({ + expression: () => { + const { values: tableValues } = calculationStore.tables.tableInsurance; + const kaskoRowIndex = tableValues.findIndex( + x => x.policyType === 'КАСКО', + ); + const kaskoRow = tableValues[kaskoRowIndex]; + if (kaskoRow) { + return kaskoRow.insTerm; + } + }, + effect: insTerm => { + if (insTerm) { + const { values: tableValues } = calculationStore.tables.tableInsurance; + const dgoRowIndex = tableValues.findIndex(x => x.policyType === 'ДГО'); + if (dgoRowIndex && dgoRowIndex >= 0) + calculationStore.setTableRow( + { + tableName: 'tableInsurance', + rowIndex: dgoRowIndex, + }, + { + values: { + insTerm, + }, + }, + ); + const nsRowIndex = tableValues.findIndex(x => x.policyType === 'НС'); + if (nsRowIndex && nsRowIndex >= 0) + calculationStore.setTableRow( + { + tableName: 'tableInsurance', + rowIndex: nsRowIndex, + }, + { + values: { + insTerm, + }, + }, + ); + } + + const { values: tableValues } = calculationStore.tables.tableInsurance; + const kaskoRowIndex = tableValues.findIndex( + x => x.policyType === 'КАСКО', + ); + + if (insTerm === 'dl_period' && kaskoRowIndex) { + if (kaskoRowIndex >= 0) + calculationStore.setTableRow( + { + tableName: 'tableInsurance', + rowIndex: kaskoRowIndex, + }, + { + values: { + insured: 'evo', + }, + statuses: { + insured: Status.Disabled, + }, + }, + ); + } else { + if (kaskoRowIndex >= 0) + calculationStore.setTableRow( + { + tableName: 'tableInsurance', + rowIndex: kaskoRowIndex, + }, + { + statuses: { + insured: Status.Default, + }, + }, + ); + } + }, + }), + + calculationStore => ({ + expression: () => { + const { leasingPeriod } = calculationStore.values; + return leasingPeriod; + }, + effect: leasingPeriod => { + const { values: tableValues } = calculationStore.tables.tableInsurance; + const kaskoRowIndex = tableValues.findIndex( + x => x.policyType === 'КАСКО', + ); + if (leasingPeriod) + if (leasingPeriod < 13) { + if (kaskoRowIndex >= 0) + calculationStore.setTableRow( + { + tableName: 'tableInsurance', + rowIndex: kaskoRowIndex, + }, + { + values: { + insTerm: 'year_period', + }, + statuses: { + insTerm: Status.Disabled, + }, + }, + ); + } else if (leasingPeriod > 12 && leasingPeriod < 16) { + if (kaskoRowIndex >= 0) + calculationStore.setTableRow( + { + tableName: 'tableInsurance', + rowIndex: kaskoRowIndex, + }, + { + values: { + insTerm: 'dl_period', + }, + statuses: { + insTerm: Status.Disabled, + }, + }, + ); + } else { + if (kaskoRowIndex >= 0) + calculationStore.setTableRow( + { + tableName: 'tableInsurance', + rowIndex: kaskoRowIndex, + }, + { + statuses: { + insTerm: Status.Default, + }, + }, + ); + } + }, + options: { + fireImmediately: true, + }, + }), ]; export default reactionEffects; diff --git a/src/client/stores/CalculationStore/index.ts b/src/client/stores/CalculationStore/index.ts index 02ef7a7..8f05521 100644 --- a/src/client/stores/CalculationStore/index.ts +++ b/src/client/stores/CalculationStore/index.ts @@ -5,7 +5,7 @@ import { import actionsEffects from 'client/stores/CalculationStore/Effects/action'; import assignProperties from 'client/tools/assignProps'; import { ICalculationStore } from 'core/types/stores'; -import { autorun, observable, reaction, when } from 'mobx'; +import { autorun, makeAutoObservable, reaction, when } from 'mobx'; import CommonStore from '../CommonStore'; import { tablesActions, @@ -19,7 +19,7 @@ import computedEffects from './Effects/computed'; import reactionEffects from './Effects/reaction'; import whenEffects from './Effects/when'; -const CalculationStore: ICalculationStore = observable( +const CalculationStore: ICalculationStore = makeAutoObservable( assignProperties( {}, staticData, @@ -41,7 +41,11 @@ autorunEffects.map(autorunEffect => reactionEffects.map(reactionEffectBuilder => { const reactionEffect = reactionEffectBuilder(CalculationStore); - return reaction(reactionEffect.expression, reactionEffect.effect); + return reaction( + reactionEffect.expression, + reactionEffect.effect, + reactionEffect.options, + ); }); whenEffects.map(whenEffectBuilder => { diff --git a/src/core/config/initialTables.ts b/src/core/config/initialTables.ts index 90f9418..ab7bd16 100644 --- a/src/core/config/initialTables.ts +++ b/src/core/config/initialTables.ts @@ -4,45 +4,80 @@ const initialTables: IStoreTable = { tableInsurance: { values: [ { - policyType: 'osago', - insuranceCompany: 'РЕСО', - insured: 'МЫ', - cost: 5555, - insuranceTerm: 12, + policyType: 'ОСАГО', + insuranceCompany: null, + insured: null, + insCost: 0, + insTerm: null, }, { - policyType: 'kasko', - insuranceCompany: 'ВСК', - insured: 'ОНИ', - cost: 151515, - insuranceTerm: 36, + policyType: 'КАСКО', + insuranceCompany: null, + insured: null, + insCost: 0, + insTerm: null, + }, + { + policyType: 'ДГО', + insuranceCompany: null, + insured: null, + insCost: 0, + insTerm: null, + }, + { + policyType: 'НС', + insuranceCompany: null, + insured: null, + insCost: 0, + insTerm: null, }, ], statuses: [ { - policyType: Status.Disabled, - insuranceCompany: Status.Default, + insTerm: Status.Disabled, + }, + { + insTerm: Status.Disabled, + }, + { + insured: Status.Disabled, + insuranceCompany: Status.Disabled, + insTerm: Status.Disabled, + }, + { + insured: Status.Disabled, + insuranceCompany: Status.Disabled, + insTerm: Status.Disabled, }, ], options: { - policyType: [ - { name: 'ОСАГО', value: 'osago' }, - { name: 'КАСКО', value: 'kasko' }, - { name: 'ДГО', value: 'dgo' }, - { name: 'НС', value: 'nc' }, + insured: [ + { + name: 'Лизингополучатель', + value: 'client', + }, + { + name: 'Лизингодатель', + value: 'evo', + }, + ], + insTerm: [ + { + name: '12 месяцев', + value: 'year_period', + }, + { + name: 'Срок ДЛ', + value: 'dl_period', + }, ], }, - filters: { - policyType: options => options, - insuranceCompany: options => options, - }, + filters: [], callbacks: { policyType: (calculationStore, rowIndex, propName) => { - console.log('policyType Callback', rowIndex, propName); //action }, insuranceCompany: (calculationStore, rowIndex, propName) => { - console.log('insuranceCompany Callback', rowIndex, propName); //action }, }, diff --git a/src/core/fakeData/entityFakes.ts b/src/core/fakeData/entityFakes.ts index 71aa588..8c19481 100644 --- a/src/core/fakeData/entityFakes.ts +++ b/src/core/fakeData/entityFakes.ts @@ -19,6 +19,9 @@ const ACCOUNT_10_ID = faker.random.uuid(); const ACCOUNT_11_ID = faker.random.uuid(); const ACCOUNT_12_ID = faker.random.uuid(); const ACCOUNT_13_ID = faker.random.uuid(); +const ACCOUNT_14_ID = faker.random.uuid(); +const ACCOUNT_15_ID = faker.random.uuid(); +const ACCOUNT_16_ID = faker.random.uuid(); const LEAD_1_ID = faker.random.uuid(); const LEAD_2_ID = faker.random.uuid(); @@ -198,6 +201,24 @@ const entityFakeData: { evo_supplier_type: 100000001, statecode: 0, }, + { + name: 'ВСК', + accountid: ACCOUNT_14_ID, + evo_account_type: 100000002, + statecode: 0, + }, + { + name: 'РЕСО', + accountid: ACCOUNT_15_ID, + evo_account_type: 100000002, + statecode: 0, + }, + { + name: 'Ингосстрах', + accountid: ACCOUNT_16_ID, + evo_account_type: 100000002, + statecode: 0, + }, ], transactioncurrency: [ { diff --git a/src/core/types/effect.ts b/src/core/types/effect.ts index 9435f98..96094d3 100644 --- a/src/core/types/effect.ts +++ b/src/core/types/effect.ts @@ -1,5 +1,5 @@ import CommonStore from 'client/stores/CommonStore'; -import { IReactionPublic, Lambda } from 'mobx'; +import { IReactionOptions, IReactionPublic, Lambda, reaction } from 'mobx'; import { ICalculationStore } from './stores'; type TCommonStore = typeof CommonStore; @@ -17,7 +17,8 @@ export interface IAutorunEffect { export interface IReactionEffect { (CalculationStore: ICalculationStore, CommonStore?: TCommonStore): { expression: (r: IReactionPublic) => any; - effect: (arg: any, r: IReactionPublic) => void; + effect: (arg: any, prev: any, r: IReactionPublic) => void; + options?: IReactionOptions; }; } diff --git a/src/core/types/stores.ts b/src/core/types/stores.ts index 11518c6..4087a02 100644 --- a/src/core/types/stores.ts +++ b/src/core/types/stores.ts @@ -47,7 +47,7 @@ export interface ICalculationStore { ) => void; tables: IStoreTable; - setTableRow: ( + addTableRow: ( { tableName, rowIndex }: { tableName: TableNames; rowIndex?: number }, { values, @@ -55,6 +55,18 @@ export interface ICalculationStore { }: { values?: TTableValues; statuses?: TTableValues; + filters?: TTableValues[]; + }, + ) => void; + setTableRow: ( + { tableName, rowIndex }: { tableName: TableNames; rowIndex: number }, + { + values, + statuses, + }: { + values?: TTableValues; + statuses?: TTableValues; + filters?: TTableValues[]; }, ) => void; setTableColumn: ( diff --git a/src/core/types/tables.ts b/src/core/types/tables.ts index 4324bb5..f533509 100644 --- a/src/core/types/tables.ts +++ b/src/core/types/tables.ts @@ -7,8 +7,8 @@ export type TableValuesNames = | 'policyType' | 'insuranceCompany' | 'insured' - | 'cost' - | 'insuranceTerm'; + | 'insCost' + | 'insTerm'; export type TTableValues = { [propName in TableValuesNames]?: T; @@ -21,11 +21,11 @@ export type TCellCallback = ( ) => void; export type IStoreTable = { - [tableName in TableNames]?: { - values?: TTableValues[]; - statuses?: TTableValues[]; + [tableName in TableNames]: { + values: TTableValues[]; + statuses: TTableValues[]; options?: TTableValues; - filters?: TTableValues; + filters?: TTableValues[]; callbacks?: TTableValues; }; };