diff --git a/src/client/Containers/Calculation/index.jsx b/src/client/Containers/Calculation/index.jsx index e4020c0..575b835 100644 --- a/src/client/Containers/Calculation/index.jsx +++ b/src/client/Containers/Calculation/index.jsx @@ -1,5 +1,5 @@ import { useStores } from 'client/hooks/useStores'; -import { getOptions } from 'client/services/CalculationService'; +import { ComponentsService } from 'client/services/CalculationService'; import { Box, Flex } from 'client/UIKit/grid'; import React, { useEffect } from 'react'; import Results from './Results'; @@ -8,9 +8,13 @@ import Sections from './Sections'; const Calculation = () => { const { calculationStore } = useStores(); useEffect(() => { - getOptions() + ComponentsService.getEntityOptions({ + entityName: 'lead', + fields: undefined, + where: undefined, + }) .then(options => { - calculationStore.applyOptions(options); + calculationStore.applyOptions({ selectLead: options }); }) .catch(err => { throw err; diff --git a/src/client/services/CalculationService.ts b/src/client/services/CalculationService.ts deleted file mode 100644 index fd34ef7..0000000 --- a/src/client/services/CalculationService.ts +++ /dev/null @@ -1,16 +0,0 @@ -import axios from 'axios'; - -export const getOptions = () => - new Promise((resolve, reject) => { - axios - .get('/api/calculation/getOptions') - //@ts-ignore - .then(res => { - console.log(res); - const { options } = res.data; - resolve(options); - }) - .catch(err => { - reject(err); - }); - }); diff --git a/src/client/services/CalculationService/Components.ts b/src/client/services/CalculationService/Components.ts new file mode 100644 index 0000000..bdf44b0 --- /dev/null +++ b/src/client/services/CalculationService/Components.ts @@ -0,0 +1,48 @@ +import axios from 'axios'; +import { + IGetEntity, + IGetEntityOptionsResponse, + IGetInitialData, + IGetInitialDataResponse, +} from 'core/types/Requests/Calculation'; + +class ComponentsService { + static _getInitialData = ({ + username, + }: IGetInitialData): Promise => + new Promise((resolve, reject) => { + axios + .post('/api/calculation/getInitialData', { + username, + }) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + + static getEntityOptions = ({ + entityName, + fields, + where, + }: IGetEntity): Promise => + new Promise((resolve, reject) => { + axios + .post('/api/calculation/getEntityOptions', { + entityName, + fields, + where, + }) + .then(res => { + const { entityOptions } = res.data; + resolve(entityOptions); + }) + .catch(err => { + reject(err); + }); + }); +} + +export default ComponentsService; diff --git a/src/client/services/CalculationService/Entity.ts b/src/client/services/CalculationService/Entity.ts new file mode 100644 index 0000000..58afe71 --- /dev/null +++ b/src/client/services/CalculationService/Entity.ts @@ -0,0 +1,35 @@ +import axios from 'axios'; +import { + IGetEntity, + IGetEntityOptionsResponse, +} from 'core/types/Requests/Calculation'; + +class EntityService { + static getEntityOptions = ({ + entityName, + fields, + where, + ...props + }: IGetEntity): Promise => + new Promise((resolve, reject) => { + axios({ + url: '/api/calculation/getEntityOptions', + method: 'POST', + data: { + entityName, + fields, + where, + ...props, + }, + }) + .then(res => { + const { entityOptions }: IGetEntityOptionsResponse = res.data; + resolve({ entityOptions }); + }) + .catch(err => { + reject(err); + }); + }); +} + +export default EntityService; diff --git a/src/client/services/CalculationService/index.ts b/src/client/services/CalculationService/index.ts new file mode 100644 index 0000000..bbf07dc --- /dev/null +++ b/src/client/services/CalculationService/index.ts @@ -0,0 +1,4 @@ +import ComponentsService from './Components'; +import EntityService from './Entity'; + +export { ComponentsService, EntityService }; diff --git a/src/client/stores/CalculationStore/Data/values.js b/src/client/stores/CalculationStore/Data/values.js index fcce4b9..bcf68dd 100644 --- a/src/client/stores/CalculationStore/Data/values.js +++ b/src/client/stores/CalculationStore/Data/values.js @@ -49,9 +49,9 @@ const valuesActions = { setFilter(elementName, filters) { this.filters[elementName] = filters; }, - applyFilters(filters) { - this.filters = { ...this.filters, ...filters }; - }, + // applyFilters(filters) { + // this.filters = { ...this.filters, ...filters }; + // }, }; export { valuesData, valuesActions }; diff --git a/src/client/stores/CalculationStore/Effects/reaction.ts b/src/client/stores/CalculationStore/Effects/reaction.ts index 15ef08e..82417b2 100644 --- a/src/client/stores/CalculationStore/Effects/reaction.ts +++ b/src/client/stores/CalculationStore/Effects/reaction.ts @@ -1,6 +1,5 @@ import { IReactionEffect } from 'core/types/effect'; import { Status } from 'core/types/statuses'; -import { filter } from 'lodash'; const reactionEffects: IReactionEffect[] = [ calculationStore => ({ @@ -43,8 +42,8 @@ const reactionEffects: IReactionEffect[] = [ expression: () => { const { options, filters } = calculationStore; if (filters.selectQuote && options.selectQuote) { - const res = filters.selectQuote(options.selectQuote); - return res; + const filteredQuotes = filters.selectQuote(options.selectQuote); + return filteredQuotes; } }, effect: quotes => { diff --git a/src/core/Data/propsMap.js b/src/core/Data/propsMap.js new file mode 100644 index 0000000..e39ab66 --- /dev/null +++ b/src/core/Data/propsMap.js @@ -0,0 +1,12 @@ +const propsMap = { + account: { + name: 'name', + value: ' accountid', + }, + lead: { + name: 'fullname', + value: 'leadid', + }, +}; + +export default propsMap; diff --git a/src/core/config/initialOptions.ts b/src/core/config/initialOptions.ts index 09885d7..f86573f 100644 --- a/src/core/config/initialOptions.ts +++ b/src/core/config/initialOptions.ts @@ -1,7 +1,7 @@ import { TElements } from 'core/types/elements'; -import { TElementOption } from 'core/types/Calculation/options'; +import { IBaseOption } from 'core/types/Calculation/options'; -const initialOptions: TElements = { +const initialOptions: TElements = { selectChannel: [ { name: 'От агента-ФЛ-сотрудника поставщика', diff --git a/src/core/fakeData/calculation.ts b/src/core/fakeData/calculation.js similarity index 97% rename from src/core/fakeData/calculation.ts rename to src/core/fakeData/calculation.js index 9eddba5..dad20b2 100644 --- a/src/core/fakeData/calculation.ts +++ b/src/core/fakeData/calculation.js @@ -1,8 +1,6 @@ -import { TElementOption } from 'core/types/Calculation/options'; -import { TElements } from 'core/types/elements'; import faker from 'faker'; -const calculationFakeData: TElements = { +const calculationFakeData = { selectSupplier: [ { name: 'RENAULT (Престиж)', diff --git a/src/core/fakeData/entity.ts b/src/core/fakeData/entity.ts new file mode 100644 index 0000000..8d07c77 --- /dev/null +++ b/src/core/fakeData/entity.ts @@ -0,0 +1,69 @@ +import { IOption } from 'core/types/Calculation/options'; +import { EntityNames } from 'core/types/Entities/entityNames'; + +import faker from 'faker'; + +/** + * Fake Consts + */ +const ACCOUNT_1_ID = faker.random.uuid(); +const ACCOUNT_2_ID = faker.random.uuid(); + +const LEAD_1_ID = faker.random.uuid(); +const LEAD_2_ID = faker.random.uuid(); + +const OPPORTUNITY_1_ID = faker.random.uuid(); +const OPPORTUNITY_2_ID = faker.random.uuid(); + +const QUOTE_1_ID = faker.random.uuid(); +const QUOTE_2_ID = faker.random.uuid(); +/** + * Fake Consts + */ + +const entityFakeData: { + [entity in EntityNames]?: IOption[]; +} = { + account: [ + { + accountid: ACCOUNT_1_ID, + name: 'Account10101010', + }, + ], + lead: [ + { + fullname: '100_ООО "Архимаг', + leadid: LEAD_1_ID, + evo_opportunityid: OPPORTUNITY_1_ID, + }, + { + fullname: '150_ООО "Некромант', + leadid: LEAD_2_ID, + evo_opportunityid: OPPORTUNITY_2_ID, + }, + ], + opportunity: [ + { + name: '112345_ООО "Архимаг', + opportunityid: OPPORTUNITY_1_ID, + }, + { + name: '145678_ООО "Некромант', + opportunityid: OPPORTUNITY_2_ID, + }, + ], + quote: [ + { + name: '2345_ООО "Архимаг"', + quoteid: QUOTE_1_ID, + evo_leadid: LEAD_1_ID, + }, + { + name: '6789_ООО "Некромант"', + quoteid: QUOTE_2_ID, + evo_leadid: LEAD_2_ID, + }, + ], +}; + +export default entityFakeData; diff --git a/src/core/tools/data.js b/src/core/tools/data.js new file mode 100644 index 0000000..ac1c5c0 --- /dev/null +++ b/src/core/tools/data.js @@ -0,0 +1,10 @@ +import propsMap from '../../core/Data/propsMap'; + +export function objectToOption(obj, entityName) { + const optionatedObject = { + ...obj, + name: obj[propsMap[entityName]['name']] || `Unknown ${entityName}`, + value: obj[propsMap[entityName]['value']], + }; + return optionatedObject; +} diff --git a/src/core/types/Calculation/filters.ts b/src/core/types/Calculation/filters.ts index 2c378d3..245fac9 100644 --- a/src/core/types/Calculation/filters.ts +++ b/src/core/types/Calculation/filters.ts @@ -1,3 +1,3 @@ -import { TElementOption } from 'core/types/Calculation/options'; +import { IOption } from 'core/types/Calculation/options'; -export type TElementFilter = (options: TElementOption[]) => TElementOption[]; +export type TElementFilter = (options: IOption[]) => IOption[]; diff --git a/src/core/types/Calculation/options.ts b/src/core/types/Calculation/options.ts index 2d6439f..a1dbdf9 100644 --- a/src/core/types/Calculation/options.ts +++ b/src/core/types/Calculation/options.ts @@ -1,5 +1,11 @@ -export type TElementOption = { - name: string; - value: any; - [key: string]: any; +import { TEntity } from 'core/types/Entities'; + +export type IBaseOption = { + /** + * TODO: Remove optional mark when remove fakes + */ + name?: string; + value?: string | number | boolean; }; + +export type IOption = IBaseOption & TEntity; diff --git a/src/core/types/Entities/entityNames.ts b/src/core/types/Entities/entityNames.ts new file mode 100644 index 0000000..4557f37 --- /dev/null +++ b/src/core/types/Entities/entityNames.ts @@ -0,0 +1 @@ +export type EntityNames = 'account' | 'lead' | 'opportunity' | 'quote'; diff --git a/src/core/types/Entities/index.ts b/src/core/types/Entities/index.ts new file mode 100644 index 0000000..1aa8b2c --- /dev/null +++ b/src/core/types/Entities/index.ts @@ -0,0 +1,24 @@ +import { IBaseOption } from 'core/types/Calculation/options'; + +export interface IAccount extends IBaseOption { + accountid?: string; + evo_inn?: string; +} + +export interface ILead extends IBaseOption { + leadid?: string; + fullname?: string; + evo_opportunityid?: string; +} + +export interface IOpportunity extends IBaseOption { + opportunityid?: string; +} + +export interface IQuote extends IBaseOption { + quoteid?: string; + quotenumber?: string; + evo_leadid?: string; +} + +export type TEntity = IAccount & ILead & IOpportunity & IQuote; diff --git a/src/core/types/Requests/Calculation.ts b/src/core/types/Requests/Calculation.ts new file mode 100644 index 0000000..56d03d5 --- /dev/null +++ b/src/core/types/Requests/Calculation.ts @@ -0,0 +1,22 @@ +import { IOption } from 'core/types/Calculation/options'; +import { EntityNames } from 'core/types/Entities/entityNames'; + +export interface IGetInitialData { + username: string; +} + +export interface IGetInitialDataResponse { + leads: IOption[]; +} + +export interface IGetEntity { + // TODO enitity names list + entityName: EntityNames; + fields: string[]; + where: { [prop: string]: any }; + [prop: string]: any; +} + +export interface IGetEntityOptionsResponse { + entityOptions: IOption[]; +} diff --git a/src/core/types/statuses.ts b/src/core/types/statuses.ts index 8ffeeb9..3aac50d 100644 --- a/src/core/types/statuses.ts +++ b/src/core/types/statuses.ts @@ -1,12 +1,6 @@ -import { ElementsNames } from './elements'; - export enum Status { Default, Disabled, Hidden, Readonly, } - -export type TStatuses = { - [elementName in ElementsNames]?: any; -}; diff --git a/src/core/types/stores.ts b/src/core/types/stores.ts index 1b1d268..2449cf0 100644 --- a/src/core/types/stores.ts +++ b/src/core/types/stores.ts @@ -1,31 +1,26 @@ -import { - IStoreTable, - TableNames, - TableValuesNames, - TableTargets, -} from './tables'; -import { TValues, ValuesNames } from './values'; -import { TElements, ElementsNames } from './elements'; -import { TStatuses, Status } from './statuses'; -import { TElementOption } from 'core/types/Calculation/options'; import { TElementFilter } from 'core/types/Calculation/filters'; +import { IBaseOption, IOption } from 'core/types/Calculation/options'; +import { ElementsNames, TElements } from './elements'; +import { Status } from './statuses'; +import { IStoreTable, TableNames, TableValuesNames } from './tables'; +import { TValue, TValues, ValuesNames } from './values'; export interface ICalculationStore { - options: TElements; - getOptions: (elementName: ElementsNames) => any; - setOptions: (elementName: ElementsNames, options: TElementOption[]) => void; - applyOptions: (options: TElements) => void; + options: TElements; + getOptions: (elementName: ElementsNames) => IOption[]; + setOptions: (elementName: ElementsNames, options: IOption[]) => void; + applyOptions: (options: TElements) => void; filters: TElements; - getFilter: (elementName: ElementsNames) => any; - setFilter: (elementName: ElementsNames, filter: TElementFilter) => any; - applyFilters: (filters: TElementFilter[]) => void; + getFilter: (elementName: ElementsNames) => TElementFilter; + setFilter: (elementName: ElementsNames, filter: TElementFilter) => void; + // applyFilters: (filters: TElementFilter[]) => void; - values: TValues; - getValue: (sourceValueName: ValuesNames) => any; - setValue: (sourceValueName: ValuesNames, newValue: any) => void; + values: TValues; + getValue: (sourceValueName: ValuesNames) => TValue; + setValue: (sourceValueName: ValuesNames, newValue: TValue) => void; - statuses: TStatuses; + statuses: TElements; getStatus: (elementName: ElementsNames) => Status; setStatus: (elementName: ElementsNames, status: Status) => void; @@ -41,18 +36,18 @@ export interface ICalculationStore { statuses, filters, }: { - values?: { [prop in TableValuesNames]?: any }; - statuses?: { [prop in TableValuesNames]?: any }; - filters?: { [prop in TableValuesNames]?: any }; + values?: { [prop in TableValuesNames]?: TValue }; + statuses?: { [prop in TableValuesNames]?: Status }; + filters?: { [prop in TableValuesNames]?: TElementFilter }; }, ) => void; setRowOptions: ( { tableName }: { tableName: TableNames }, - options: { [prop in TableValuesNames]?: any }, + options: { [prop in TableValuesNames]?: IBaseOption[] }, ) => void; setTable: ( { tableName }: { tableName: TableNames }, - values: { [prop in TableValuesNames]?: any }[], + values: { [prop in TableValuesNames]?: TValue }[], ) => void; deleteTableRow: (tableName: TableNames, rowIndex: number) => void; diff --git a/src/core/types/tables.ts b/src/core/types/tables.ts index a88ee5e..6410eb8 100644 --- a/src/core/types/tables.ts +++ b/src/core/types/tables.ts @@ -6,7 +6,6 @@ export type TableValuesNames = | 'insured' | 'cost' | 'insuranceTerm'; -export type TableTargets = 'values' | 'options' | 'statuses' | 'filters'; export type TTableValues = { [propName in TableValuesNames]?: T; diff --git a/src/core/types/values.ts b/src/core/types/values.ts index b8e9643..9bae135 100644 --- a/src/core/types/values.ts +++ b/src/core/types/values.ts @@ -147,6 +147,8 @@ export type ValuesNames = | 'insuranceTermNS' | 'insuranceTermAddEquipment'; -export type TValues = { - [valueName in ValuesNames]?: any; +export type TValues = { + [valueName in ValuesNames]?: T; }; + +export type TValue = string | number | boolean | undefined | null; diff --git a/src/server/controllers/CalculationController.ts b/src/server/controllers/CalculationController.ts index 449eb26..875cf5b 100644 --- a/src/server/controllers/CalculationController.ts +++ b/src/server/controllers/CalculationController.ts @@ -1,12 +1,60 @@ +import { objectToOption } from '../../core/tools/data'; +import { + IGetEntity, + IGetInitialData, + IGetInitialDataResponse, +} from 'core/types/Requests/Calculation'; import { Request, Response } from 'express'; -import calculationFakeData from '../../core/fakeData/calculation'; +import entityFakeData from '../../core/fakeData/entity'; +import { EntityNames } from 'core/types/Entities/entityNames'; +function _getFakeEntities(entityName, fields, where) { + let entities = entityFakeData[entityName]; + + if (entities) + if (where) + entities = entities.filter(entity => { + for (let w in where) { + return entity[w] === where[w]; + } + return true; + }); + return entities; +} + +//TODO: move logic from controller to service class CalculationController { - static getOptions = async (req: Request, res: Response): Promise => { - // request to Core + static getInitialData = async ( + req: Request, + res: Response, + ): Promise => { + const { username }: IGetInitialData = req.body; + // TODO: get session: options, values, filters - const options = calculationFakeData; - res.send({ options }); + let leads = _getFakeEntities('lead', undefined, undefined); + console.log('CalculationController -> leads', leads); + // TODO: check leads exist + leads = leads.map(lead => objectToOption(lead, 'lead')); + res.send({ + leads, + }); + }; + + static getEntityOptions = async ( + req: Request, + res: Response, + ): Promise => { + // TODO request to Core + const { entityName, fields, where }: IGetEntity = req.body; + + let entityOptions = _getFakeEntities(entityName, fields, where); + entityOptions = entityOptions.map(entityOption => + objectToOption(entityOption, entityName), + ); + + res.send({ + entityOptions, + }); }; } diff --git a/src/server/routes/calculation.ts b/src/server/routes/calculation.ts index e58d563..1040e09 100644 --- a/src/server/routes/calculation.ts +++ b/src/server/routes/calculation.ts @@ -3,6 +3,7 @@ import { Router } from 'express'; const router = Router(); -router.get('/getOptions', CalculationController.getOptions); +router.post('/getInitialData', CalculationController.getInitialData); +router.post('/getEntityOptions', CalculationController.getEntityOptions); export default router;