MANY: types & get entity options

This commit is contained in:
Владислав Чикалкин 2020-09-22 18:46:14 +03:00
parent ba964beaaa
commit b34bbeb3c4
23 changed files with 332 additions and 77 deletions

View File

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

View File

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

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

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

View File

@ -0,0 +1,4 @@
import ComponentsService from './Components';
import EntityService from './Entity';
export { ComponentsService, EntityService };

View File

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

View File

@ -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
View File

@ -0,0 +1,12 @@
const propsMap = {
account: {
name: 'name',
value: ' accountid',
},
lead: {
name: 'fullname',
value: 'leadid',
},
};
export default propsMap;

View File

@ -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: 'От агента-ФЛ-сотрудника поставщика',

View File

@ -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 (Престиж)',

View 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
View 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;
}

View File

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

View File

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

View File

@ -0,0 +1 @@
export type EntityNames = 'account' | 'lead' | 'opportunity' | 'quote';

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

View 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[];
}

View File

@ -1,12 +1,6 @@
import { ElementsNames } from './elements';
export enum Status {
Default,
Disabled,
Hidden,
Readonly,
}
export type TStatuses = {
[elementName in ElementsNames]?: any;
};

View File

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

View File

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

View File

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

View File

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

View File

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