MANY: types & get entity options
This commit is contained in:
parent
ba964beaaa
commit
b34bbeb3c4
@ -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;
|
||||
|
||||
@ -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);
|
||||
});
|
||||
});
|
||||
48
src/client/services/CalculationService/Components.ts
Normal file
48
src/client/services/CalculationService/Components.ts
Normal file
@ -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<IGetInitialDataResponse> =>
|
||||
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<IGetEntityOptionsResponse> =>
|
||||
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;
|
||||
35
src/client/services/CalculationService/Entity.ts
Normal file
35
src/client/services/CalculationService/Entity.ts
Normal file
@ -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<IGetEntityOptionsResponse> =>
|
||||
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;
|
||||
4
src/client/services/CalculationService/index.ts
Normal file
4
src/client/services/CalculationService/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import ComponentsService from './Components';
|
||||
import EntityService from './Entity';
|
||||
|
||||
export { ComponentsService, EntityService };
|
||||
@ -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 };
|
||||
|
||||
@ -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 => {
|
||||
|
||||
12
src/core/Data/propsMap.js
Normal file
12
src/core/Data/propsMap.js
Normal file
@ -0,0 +1,12 @@
|
||||
const propsMap = {
|
||||
account: {
|
||||
name: 'name',
|
||||
value: ' accountid',
|
||||
},
|
||||
lead: {
|
||||
name: 'fullname',
|
||||
value: 'leadid',
|
||||
},
|
||||
};
|
||||
|
||||
export default propsMap;
|
||||
@ -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<TElementOption[]> = {
|
||||
const initialOptions: TElements<IBaseOption[]> = {
|
||||
selectChannel: [
|
||||
{
|
||||
name: 'От агента-ФЛ-сотрудника поставщика',
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import { TElementOption } from 'core/types/Calculation/options';
|
||||
import { TElements } from 'core/types/elements';
|
||||
import faker from 'faker';
|
||||
|
||||
const calculationFakeData: TElements<TElementOption[]> = {
|
||||
const calculationFakeData = {
|
||||
selectSupplier: [
|
||||
{
|
||||
name: 'RENAULT (Престиж)',
|
||||
69
src/core/fakeData/entity.ts
Normal file
69
src/core/fakeData/entity.ts
Normal file
@ -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;
|
||||
10
src/core/tools/data.js
Normal file
10
src/core/tools/data.js
Normal file
@ -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;
|
||||
}
|
||||
@ -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[];
|
||||
|
||||
@ -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;
|
||||
|
||||
1
src/core/types/Entities/entityNames.ts
Normal file
1
src/core/types/Entities/entityNames.ts
Normal file
@ -0,0 +1 @@
|
||||
export type EntityNames = 'account' | 'lead' | 'opportunity' | 'quote';
|
||||
24
src/core/types/Entities/index.ts
Normal file
24
src/core/types/Entities/index.ts
Normal file
@ -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;
|
||||
22
src/core/types/Requests/Calculation.ts
Normal file
22
src/core/types/Requests/Calculation.ts
Normal file
@ -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[];
|
||||
}
|
||||
@ -1,12 +1,6 @@
|
||||
import { ElementsNames } from './elements';
|
||||
|
||||
export enum Status {
|
||||
Default,
|
||||
Disabled,
|
||||
Hidden,
|
||||
Readonly,
|
||||
}
|
||||
|
||||
export type TStatuses = {
|
||||
[elementName in ElementsNames]?: any;
|
||||
};
|
||||
|
||||
@ -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<TElementOption[]>;
|
||||
getOptions: (elementName: ElementsNames) => any;
|
||||
setOptions: (elementName: ElementsNames, options: TElementOption[]) => void;
|
||||
applyOptions: (options: TElements<any>) => void;
|
||||
options: TElements<IOption[]>;
|
||||
getOptions: (elementName: ElementsNames) => IOption[];
|
||||
setOptions: (elementName: ElementsNames, options: IOption[]) => void;
|
||||
applyOptions: (options: TElements<IOption[]>) => void;
|
||||
|
||||
filters: TElements<TElementFilter>;
|
||||
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<TValue>;
|
||||
getValue: (sourceValueName: ValuesNames) => TValue;
|
||||
setValue: (sourceValueName: ValuesNames, newValue: TValue) => void;
|
||||
|
||||
statuses: TStatuses;
|
||||
statuses: TElements<Status>;
|
||||
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;
|
||||
|
||||
@ -6,7 +6,6 @@ export type TableValuesNames =
|
||||
| 'insured'
|
||||
| 'cost'
|
||||
| 'insuranceTerm';
|
||||
export type TableTargets = 'values' | 'options' | 'statuses' | 'filters';
|
||||
|
||||
export type TTableValues<T> = {
|
||||
[propName in TableValuesNames]?: T;
|
||||
|
||||
@ -147,6 +147,8 @@ export type ValuesNames =
|
||||
| 'insuranceTermNS'
|
||||
| 'insuranceTermAddEquipment';
|
||||
|
||||
export type TValues = {
|
||||
[valueName in ValuesNames]?: any;
|
||||
export type TValues<T> = {
|
||||
[valueName in ValuesNames]?: T;
|
||||
};
|
||||
|
||||
export type TValue = string | number | boolean | undefined | null;
|
||||
|
||||
@ -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<void> => {
|
||||
// request to Core
|
||||
static getInitialData = async (
|
||||
req: Request,
|
||||
res: Response<IGetInitialDataResponse>,
|
||||
): Promise<any> => {
|
||||
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<any> => {
|
||||
// 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,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user