partial: connect to crm service

This commit is contained in:
Chika 2020-11-08 21:12:16 +03:00
parent 6a33d26de0
commit 60f9f7b59e
33 changed files with 554 additions and 462 deletions

View File

@ -3,12 +3,14 @@
"version": "0.0.1",
"private": true,
"dependencies": {
"@apollo/client": "^3.2.5",
"@babel/code-frame": "^7.10.4",
"@babel/helper-split-export-declaration": "^7.11.0",
"@craco/craco": "^5.6.4",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"@types/graphql": "^14.5.0",
"antd": "^4.6.4",
"axios": "^0.20.0",
"body-parser": "^1.19.0",
@ -17,16 +19,20 @@
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"craco-less": "^1.17.0",
"cross-fetch": "^3.0.6",
"express": "^4.17.1",
"graphql": "^15.4.0",
"helmet": "^4.1.0",
"http-errors": "^1.8.0",
"lodash": "^4.17.20",
"luxon": "^1.25.0",
"mobx": "^6.0.0",
"mobx-react-lite": "^3.0.0",
"morgan": "^1.10.0",
"mssql": "^6.2.1",
"nodemon": "^2.0.4",
"normalize.css": "^8.0.1",
"pluralize": "^8.0.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router": "^5.2.0",
@ -38,7 +44,7 @@
"styled-system": "^5.1.5",
"ts-loader": "^8.0.2",
"typeorm": "^0.2.25",
"typescript": "^4.0.3",
"typescript": "3.9.7",
"use-debounce": "^3.4.3",
"validator": "^13.1.1"
},
@ -49,9 +55,12 @@
"@types/cors": "^2.8.7",
"@types/express": "^4.17.7",
"@types/faker": "^5.1.0",
"@types/jest": "^26.0.15",
"@types/lodash": "^4.14.159",
"@types/luxon": "^1.25.0",
"@types/morgan": "^1.9.1",
"@types/node": "^14.6.0",
"@types/pluralize": "^0.0.29",
"@types/react-router-dom": "^5.1.5",
"@types/styled-components": "^5.1.2",
"@types/styled-system": "^5.1.10",

View File

@ -1,9 +0,0 @@
import React from 'react';
import { render } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
const { getByText } = render(<App />);
const linkElement = getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});

View File

@ -4,7 +4,7 @@ import { withStoreModal } from 'client/hocs/withStore';
import { useStores } from 'client/hooks/useStores';
import CalculationService from 'client/services/CalculationService';
import { Box, Flex } from 'client/UIKit/grid';
import initialOptionsMap from 'core/Data/initialOptionsMap';
import initialOptions from 'core/Data/initialOptions';
import staticEntitiesList from 'core/Data/staticEntitiesList';
import React, { useEffect, useState } from 'react';
import Result from 'client/Components/Result';
@ -17,30 +17,35 @@ const Calculation = () => {
const { calculationStore } = useStores();
useEffect(() => {
Promise.all([
CalculationService.getEntitiesOptions({
elementsList: initialOptionsMap,
CalculationService.getEntities({
queries: initialOptions,
toOptions: true,
}),
CalculationService.getStaticData({
staticEntitiesList,
}),
CalculationService.getEntityOptions({
query: {
entityName: 'account',
where: { evo_account_type: 100000002, statecode: 0 },
},
CalculationService.getEntities({
queries: staticEntitiesList,
}),
// CalculationService.getEntities({
// queries: [
// {
// entityName: 'accounts',
// where: { evo_account_type: 100000002, statecode: 0 },
// },
// ],
// toOptions: true,
// }),
])
.then(
([
{ entitiesOptions: initialOptions },
{ staticEntities },
{ entityOptions: insuranceCompanies },
{ entities: initialOptions },
{ entities: staticEntities },
// { entities: insuranceCompanies },
]) => {
calculationStore.applyOptions({ ...initialOptions });
console.log(initialOptions);
calculationStore.applyOptions(initialOptions);
calculationStore.applyStaticData(staticEntities);
calculationStore.setTableColumns('tableInsurance')({
options: { insuranceCompany: insuranceCompanies },
});
// calculationStore.setTableColumns('tableInsurance')({
// options: { insuranceCompany: insuranceCompanies },
// });
setStatus(LoadingStatus.ready);
},
)

View File

@ -1,52 +1,15 @@
import axios from 'axios';
import {
IGetEntitiesOptionsRequest,
IGetEntityOptionsRequest,
} from 'core/types/Calculation/Requests';
import {
IGetEntitiesOptionsResponse,
IGetEntityOptionsResponse,
} from 'core/types/Calculation/Responses';
import { IGetStaticEntitiesRequest } from 'core/types/Calculation/Requests';
import { IGetStaticEntitiesResponse } from 'core/types/Calculation/Responses';
import { IGetEntitiesRequest } from 'core/types/Calculation/Requests';
import { IGetEntitiesResponse } from 'core/types/Calculation/Responses';
class CalculationService {
static getEntitiesOptions = ({
elementsList,
}: IGetEntitiesOptionsRequest): Promise<IGetEntitiesOptionsResponse> =>
static getEntities = ({
queries,
toOptions,
}: IGetEntitiesRequest): Promise<IGetEntitiesResponse> =>
new Promise((resolve, reject) => {
axios
.post('/api/calculation/getEntitiesOptions', { elementsList })
.then(res => {
resolve(res.data);
})
.catch(err => {
reject(err);
});
});
static getEntityOptions = ({
query,
}: IGetEntityOptionsRequest): Promise<IGetEntityOptionsResponse> =>
new Promise((resolve, reject) => {
axios
.post('/api/calculation/getEntityOptions', { query })
.then(res => {
resolve(res.data);
})
.catch(err => {
reject(err);
});
});
static getStaticData = ({
staticEntitiesList,
}: IGetStaticEntitiesRequest): Promise<IGetStaticEntitiesResponse> =>
new Promise((resolve, reject) => {
axios
.post('/api/calculation/getStaticEntities', {
staticEntitiesList,
})
.post('/api/calculation/getCRMEntities', { queries, toOptions })
.then(res => {
resolve(res.data);
})

View File

@ -17,7 +17,7 @@ import {
import { staticData, staticDataAction } from './Data/staticEntities';
import autorunEffects from './Effects/autorun';
import computedEffects from './Effects/computed';
import reactionEffects from './Effects/reaction';
// import reactionEffects from './Effects/reaction';
import whenEffects from './Effects/when';
const CalculationStore: ICalculationStore = makeAutoObservable(
@ -42,15 +42,15 @@ autorunEffects.map(autorunEffect =>
autorun(autorunEffect(CalculationStore, CommonStore)),
);
reactionEffects.map(reactionEffectBuilder => {
const reactionEffect = reactionEffectBuilder(CalculationStore);
return reaction(reactionEffect.expression, reactionEffect.effect, {
...reactionEffect.options,
equals: (nextParams, prevParams) => {
return isEqual(nextParams, prevParams);
},
});
});
// reactionEffects.map(reactionEffectBuilder => {
// const reactionEffect = reactionEffectBuilder(CalculationStore);
// return reaction(reactionEffect.expression, reactionEffect.effect, {
// ...reactionEffect.options,
// equals: (nextParams, prevParams) => {
// return isEqual(nextParams, prevParams);
// },
// });
// });
whenEffects.map(whenEffectBuilder => {
const whenEffect = whenEffectBuilder(CalculationStore);

View File

@ -0,0 +1,95 @@
import { TEntityQuery } from 'core/types/Entities/query';
const initialOptions: TEntityQuery[] = [
{
alias: 'selectLead',
entityName: 'lead',
fields: ['leadid', 'fullname'],
where: { statecode: 0 },
many: true,
},
// {
// alias: 'selectOpportunity',
// entityName: 'opportunities',
// fields: ['opportunityid', 'name'],
// where: { statecode: 0 },
// },
{
alias: 'selectSupplier',
entityName: 'account',
where: {
evo_account_type: 100000001,
statecode: 0,
evo_legal_form: 100000001,
},
fields: ['accountid', 'name'],
many: true,
},
// {
// alias: 'selectSupplierCurrency',
// entityName: 'transactioncurrency',
// where: {
// statecode: 0,
// },
// },
// {
// alias: 'selectClientRisk',
// entityName: 'evo_client_risk',
// where: {
// statecode: 0,
// },
// },
// {
// alias: 'selectClientType',
// entityName: 'evo_client_type',
// where: {
// statecode: 0,
// },
// },
// {
// alias: 'selectDealer',
// entityName: 'account',
// where: {
// evo_account_type: 100000001,
// statecode: 0,
// },
// whereIn: {
// evo_supplier_type: 100000000,
// },
// },
// {
// alias: 'selectGPSBrand',
// entityName: 'evo_gps_brand',
// where: {
// statecode: 0,
// },
// },
// {
// alias: 'selectRegionRegistration',
// entityName: 'evo_region',
// where: {
// statecode: 0,
// },
// },
// {
// alias: 'selectTownRegistration',
// entityName: 'evo_town',
// where: {
// statecode: 0,
// },
// },
// // TODO: remove on prod
// {
// alias: 'selectAccount',
// entityName: 'account',
// },
// {
// alias: 'selectBrand',
// entityName: 'evo_brand',
// where: {
// statecode: 0,
// },
// },
];
export default initialOptions;

View File

@ -1,80 +0,0 @@
import { TElements } from 'core/types/Calculation/Store/elements';
import { TGetEntities } from 'core/types/Entities/query';
const initialOptionMap: TElements<TGetEntities> = {
selectLead: {
entityName: 'lead',
fields: undefined,
where: undefined,
},
selectOpportunity: { entityName: 'opportunity' },
selectSupplier: {
entityName: 'account',
where: {
evo_account_type: 100000001,
statecode: 0,
},
whereIn: {
evo_supplier_type: 100000000,
},
},
selectSupplierCurrency: {
entityName: 'transactioncurrency',
where: {
statecode: 0,
},
},
selectClientRisk: {
entityName: 'evo_client_risk',
where: {
statecode: 0,
},
},
selectClientType: {
entityName: 'evo_client_type',
where: {
statecode: 0,
},
},
selectDealer: {
entityName: 'account',
where: {
evo_account_type: 100000001,
statecode: 0,
},
whereIn: {
evo_supplier_type: 100000000,
},
},
selectGPSBrand: {
entityName: 'evo_gps_brand',
where: {
statecode: 0,
},
},
selectRegionRegistration: {
entityName: 'evo_region',
where: {
statecode: 0,
},
},
selectTownRegistration: {
entityName: 'evo_town',
where: {
statecode: 0,
},
},
// TODO: remove on prod
selectAccount: {
entityName: 'account',
},
selectBrand: {
entityName: 'evo_brand',
where: {
statecode: 0,
},
},
};
export default initialOptionMap;

View File

@ -1,7 +1,10 @@
import { TEntity } from 'core/types/Entities';
import { TEntities } from './../types/Entities/entityNames';
import { TCRMEntity } from 'core/types/Entities/crmEntities';
import { TEntities } from '../types/Entities/crmEntityNames';
const propsMap: TEntities<{ name: keyof TEntity; value: keyof TEntity }> = {
const propsMap: TEntities<{
name: keyof TCRMEntity;
value: keyof TCRMEntity;
}> = {
account: {
name: 'name',
value: 'accountid',

View File

@ -1,11 +1,13 @@
import { TGetEntities } from '../types/Entities/query';
import { TEntityQuery } from '../types/Entities/query';
const staticEntitiesList: TGetEntities[] = [
const staticEntitiesList: TEntityQuery[] = [
{
entityName: 'evo_impairment_group',
where: {
statecode: 0,
},
fields: ['evo_impairment_groupid', 'evo_name'],
many: true,
},
{
entityName: 'evo_currencychange',
@ -14,6 +16,8 @@ const staticEntitiesList: TGetEntities[] = [
// evo_coursedate: new Date(),
statecode: 0,
},
fields: ['evo_currencychange'],
many: true,
},
];

View File

@ -1 +1,2 @@
export const API_PORT = 3001;
export const CRM_SERVICE_URL = 'http://crmgraphql-dev.evoleasing.ru';

View File

@ -1,5 +1,5 @@
import { IOption } from 'core/types/Calculation/Store/options';
import { TEntities } from 'core/types/Entities/entityNames';
import { TEntities } from 'core/types/Entities/crmEntityNames';
import faker from 'faker';

View File

@ -1,17 +0,0 @@
import propsMap from '../../core/Data/propsMap';
export function objectToOption(obj, entityName) {
if (!propsMap[entityName]) {
console.warn(`Warning: ${entityName} not found in propsMap!`);
return obj;
}
const name = obj[propsMap[entityName]['name']] || obj['name'];
const value = obj[propsMap[entityName]['value']];
const optionatedObject = {
...obj,
name,
value,
};
return optionatedObject;
}

View File

@ -0,0 +1,24 @@
import propsMap from '../Data/propsMap';
import { IBaseOption } from '../types/Calculation/Store/options';
import { TCRMEntity } from '../types/Entities/crmEntities';
import { CRMEntityNames } from '../types/Entities/crmEntityNames';
export function convertEntityToOption(
entity: TCRMEntity,
entityName: CRMEntityNames,
): (TCRMEntity & IBaseOption) | undefined {
if (!entity || !propsMap || !propsMap[entityName]) {
throw new Error(`${entityName} not found in propsMap!`);
}
const entityPropsMap = propsMap[entityName];
if (entityPropsMap) {
const { name: propName, value: propValue } = entityPropsMap;
const optionatedObject = {
...entity,
name: entity[propName],
value: entity[propValue],
};
return optionatedObject;
}
}

View File

@ -0,0 +1,20 @@
import { convertJSONToGQL } from './query';
it('query converter works', () => {
const res = convertJSONToGQL([
{
entityName: 'evo_baseproducts',
where: { statecode: 0 },
fields: ['evo_id', 'evo_name'],
relatedEntities: [
{
entityName: 'evo_leasingobject_types',
fields: ['evo_id', 'evo_name'],
},
],
},
]);
console.log(res);
expect(res).not.toBeUndefined();
});

78
src/core/tools/query.ts Normal file
View File

@ -0,0 +1,78 @@
import {
TEntityQuery,
TWhere,
ComparisonOperators,
} from 'core/types/Entities/query';
import { TBaseEntityQuery, TEntitiesKeys } from './../types/Entities/query';
import { stringifyObject } from './string';
import { plural } from 'pluralize';
const convert = {
fields: (fields: TEntitiesKeys[]): string => {
let res_fields: string[] = [];
for (let field of fields) {
res_fields.push(stringifyObject(field).replace(/[^\w\s,:!?]/g, ''));
}
return res_fields.toString().replace(/"/, '').replace(/,/, ' ');
},
relatedEntities: (relatedEntities?: TBaseEntityQuery[]): string => {
if (!relatedEntities) {
return '';
}
let res_related: string[] = [];
if (relatedEntities && relatedEntities.length > 0) {
for (let relatedEntity of relatedEntities) {
res_related.push(convertNestedEntity(relatedEntity));
}
}
return res_related.toString().replace(/"/, '');
},
where: (where: TWhere<any>): string => {
// return JSON.stringify(whereIn || {}).replace(/[^\w\s,[\]:!?]/g, '');
return stringifyObject(where);
},
whereCmp: (whereCmp?: TWhere<ComparisonOperators>) => {
if (!whereCmp) {
return '';
}
return Object.keys(whereCmp).map(
//@ts-ignore
key => `${key}:{${stringifyObject(whereCmp[key])}}`,
);
},
};
function convertNestedEntity(query: TBaseEntityQuery) {
let entityQuery: string = `${query.entityName}{
${convert.fields(query.fields)}
${convert.relatedEntities(query.relatedEntities)}
}`;
if (query.alias) {
return `${query.alias}:${entityQuery}`;
}
return entityQuery;
}
//TODO: WhereCmp
function convertQuery(query: TEntityQuery) {
let entityQuery: string = `${
query.many ? plural(query.entityName) : query.entityName
}(${convert.where(query.where)},${convert.whereCmp(query.whereCmp)}){
${convert.fields(query.fields)}
${convert.relatedEntities(query.relatedEntities)}
}`;
if (query.alias) {
return `${query.alias}:${entityQuery}`;
}
return entityQuery;
}
export const convertJSONToGQLQuery = (queries: TEntityQuery[]) => {
let res = '';
for (let query of queries) {
res += convertQuery(query);
}
return `query {
${res}
}`;
};

9
src/core/tools/string.ts Normal file
View File

@ -0,0 +1,9 @@
export function stringifyObject(obj_from_json: any): string {
if (typeof obj_from_json !== 'object' || Array.isArray(obj_from_json)) {
return JSON.stringify(obj_from_json);
}
let props = Object.keys(obj_from_json)
.map(key => `${key}:${stringifyObject(obj_from_json[key])}`)
.join(',');
return `${props}`;
}

View File

@ -1,4 +1,4 @@
import { EntityNames } from './../Entities/entityNames';
import { CRMEntityNames } from '../Entities/crmEntityNames';
export interface PreparedValues {
calcDate: Date;
calcType: number;
@ -104,13 +104,6 @@ export interface PaymentRow {
export type PreparedPayments = PaymentRow[];
export interface PreparedData {
preparedValues: PreparedValues;
preparedPayments: PreparedPayments;
}
type EntitiesAliases = 'evo_coefficient_season' | 'evo_coefficient_bonus';
export type TPrepareEntities<T> = {
[entityAlias in EntitiesAliases | EntityNames]?: T;
[entityAlias in CRMEntityNames]?: T;
};

View File

@ -1,18 +1,10 @@
import { TGetEntities } from '../Entities/query';
import { TElements } from './../Calculation/Store/elements';
import { TEntityQuery } from '../Entities/query';
import { ValuesTables } from './Store/tables';
import { TValue, TValues } from './Store/values';
export interface IGetEntitiesOptionsRequest {
elementsList: TElements<TGetEntities>;
}
export interface IGetEntityOptionsRequest {
query: TGetEntities;
}
export interface IGetStaticEntitiesRequest {
staticEntitiesList: TGetEntities[];
export interface IGetEntitiesRequest {
queries: TEntityQuery[];
toOptions: boolean;
}
export interface IGetCalculationRequest {

View File

@ -1,17 +1,8 @@
import { TEntities } from './../Entities/entityNames';
import { TElements } from './Store/elements';
import { IOption } from './Store/options';
import { TCRMEntity } from '../Entities/crmEntities';
import { TEntities } from '../Entities/crmEntityNames';
export interface IGetEntitiesOptionsResponse {
entitiesOptions: TElements<IOption[]>;
}
export interface IGetEntityOptionsResponse {
entityOptions: IOption[];
}
export interface IGetStaticEntitiesResponse {
staticEntities: TEntities<IOption[]>;
export interface IGetEntitiesResponse {
entities: TEntities<TCRMEntity[]>;
}
export interface IGetCalculationResponse {

View File

@ -1,3 +1,2 @@
import { IOption } from './options';
export type TElementFilter = (options: IOption[]) => IOption[];
import { TCRMEntity } from 'core/types/Entities/crmEntities';
export type TElementFilter = (options: TCRMEntity[]) => TCRMEntity[];

View File

@ -1,22 +1,31 @@
import { TElementFilter } from './filters';
import { IOption } from './options';
import { ITableCell, TableNames, TableProps, TCellCallback } from './tables';
import { ElementsNames, TElements } from './elements';
import { EntityNames } from '../../Entities/entityNames';
import { StaticDataNames, TStaticData } from './staticData';
import { CRMEntityNames } from '../../Entities/crmEntityNames';
import { Status } from '../../statuses';
import { StoreTables } from './tables';
import { TCRMEntity } from '../../Entities/crmEntities';
import { ElementsNames, TElements } from './elements';
import { TElementFilter } from './filters';
import { IBaseOption } from './options';
import { TStaticData } from './staticData';
import {
ITableCell,
StoreTables,
TableNames,
TableProps,
TCellCallback,
} from './tables';
import { TValue, TValues, ValuesNames } from './values';
interface ICalculationValues {
staticData: TStaticData;
getStaticData: (dataName: StaticDataNames | EntityNames) => IOption[];
getStaticData: (dataName: CRMEntityNames) => IBaseOption[];
applyStaticData: (data: TStaticData) => void;
options: TElements<IOption[]>;
getOptions: (elementName: ElementsNames) => IOption[];
setOptions: (elementName: ElementsNames, options: IOption[]) => void;
applyOptions: (options: TElements<IOption[]>) => void;
options: TElements<(IBaseOption & TCRMEntity)[]>;
getOptions: (elementName: ElementsNames) => (IBaseOption & TCRMEntity)[];
setOptions: (
elementName: ElementsNames,
options: (IBaseOption & TCRMEntity)[],
) => void;
applyOptions: (options: TElements<(IBaseOption & TCRMEntity)[]>) => void;
filters: TElements<TElementFilter>;
getFilter: (elementName: ElementsNames) => TElementFilter;
@ -75,7 +84,7 @@ interface ICalculationTables {
options,
callbacks,
}: {
options?: TableProps<IOption[]>;
options?: TableProps<(IBaseOption & TCRMEntity)[]>;
callbacks?: TableProps<TCellCallback>;
}) => void;
}

View File

@ -1,5 +1,3 @@
import { TEntity } from '../../Entities';
export type IBaseOption = {
/**
* TODO: Remove optional mark when remove fakes
@ -7,5 +5,3 @@ export type IBaseOption = {
name?: string;
value?: string | number | boolean;
};
export type IOption = IBaseOption & TEntity;

View File

@ -1,9 +1,8 @@
import { EntityNames } from '../../Entities/entityNames';
import { IOption } from '../../Calculation/Store/options';
import { CRMEntityNames } from '../../Entities/crmEntityNames';
import { TCRMEntity } from './../../Entities/crmEntities';
import { IBaseOption } from './options';
import { TValue } from './values';
export type StaticDataNames = '';
export type TStaticData = {
[dataName in StaticDataNames | EntityNames]?: IOption[] | TValue;
[dataName in CRMEntityNames]?: (IBaseOption & TCRMEntity)[] | TValue;
};

View File

@ -1,7 +1,8 @@
import { TCRMEntity } from './../../Entities/crmEntities';
import { Status } from '../../statuses';
import { ICalculationStore } from './';
import { TElementFilter } from './filters';
import { IOption } from './options';
import { Status } from '../../statuses';
import { IBaseOption } from './options';
export type TableNames = 'tableInsurance' | 'tablePayments';
export type TableValuesNames =
@ -33,7 +34,7 @@ export type TableProps<T> = {
export interface ITable {
rows: TableProps<ITableCell>[];
options?: TableProps<IOption[]>;
options?: TableProps<(IBaseOption & TCRMEntity)[]>;
callbacks?: TableProps<TCellCallback>;
}

View File

@ -1,6 +1,6 @@
import { IBaseOption } from '../Calculation/Store/options';
import { CRMEntityNames } from "./crmEntityNames";
export interface IAccount extends IBaseOption {
export interface IAccount {
name?: string;
accountid?: string;
evo_inn?: string;
@ -14,7 +14,7 @@ export interface IAccount extends IBaseOption {
evo_client_riskid?: string;
}
export interface ILead extends IBaseOption {
export interface ILead {
leadid?: string;
fullname?: string;
evo_opportunityid?: string;
@ -23,7 +23,7 @@ export interface ILead extends IBaseOption {
statecode?: number;
}
export interface IOpportunity extends IBaseOption {
export interface IOpportunity {
opportunityid?: string;
evo_accountid?: string;
evo_leadid?: string;
@ -32,7 +32,7 @@ export interface IOpportunity extends IBaseOption {
statecode?: number;
}
export interface IQuote extends IBaseOption {
export interface IQuote {
quoteid?: string;
quotenumber?: string;
evo_leadid?: string;
@ -43,25 +43,25 @@ export interface IQuote extends IBaseOption {
evo_statuscodeid?: string;
}
export interface ITransactionCurrency extends IBaseOption {
export interface ITransactionCurrency {
transactioncurrencyid?: string;
statecode?: number;
isocurrencycode?: string;
}
export interface IEvoClientType extends IBaseOption {
export interface IEvoClientType {
evo_name?: string;
evo_client_typeid?: string;
statecode?: number;
}
export interface IEvoClientRisk extends IBaseOption {
export interface IEvoClientRisk {
evo_name?: string;
evo_client_riskid?: string;
statecode?: number;
}
export interface IEvoBaseproduct extends IBaseOption {
export interface IEvoBaseproduct {
evo_name?: string;
evo_baseproductid?: string;
evo_id?: string;
@ -72,7 +72,7 @@ export interface IEvoBaseproduct extends IBaseOption {
evo_brands?: IEvoBrand[];
}
export interface IEvoLeasingObjectType extends IBaseOption {
export interface IEvoLeasingObjectType {
evo_id?: string;
evo_name?: string;
evo_leasingobject_typeid?: string;
@ -84,7 +84,7 @@ export interface IEvoLeasingObjectType extends IBaseOption {
evo_baseproduct?: any;
}
export interface IEvoBrand extends IBaseOption {
export interface IEvoBrand {
evo_name?: string;
evo_brandid?: string;
evo_importer_reward_perc?: number;
@ -92,7 +92,7 @@ export interface IEvoBrand extends IBaseOption {
statecode?: number;
}
export interface IEvoModel extends IBaseOption {
export interface IEvoModel {
evo_name?: string;
evo_brandid?: string;
evo_modelid?: string;
@ -104,7 +104,7 @@ export interface IEvoModel extends IBaseOption {
evo_baseproduct?: any;
}
export interface IEvoEquipment extends IBaseOption {
export interface IEvoEquipment {
evo_equipmentid?: string;
evo_name?: string;
evo_modelid?: string;
@ -113,7 +113,7 @@ export interface IEvoEquipment extends IBaseOption {
statecode?: number;
}
export interface IEvoRewardCondition extends IBaseOption {
export interface IEvoRewardCondition {
evo_reward_conditionid?: string;
evo_name?: string;
evo_datefrom?: Date;
@ -125,35 +125,35 @@ export interface IEvoRewardCondition extends IBaseOption {
evo_reduce_reward?: boolean;
}
export interface IEvoGPSBrand extends IBaseOption {
export interface IEvoGPSBrand {
evo_gps_brandid?: string;
evo_name?: string;
statecode?: number;
}
export interface IEvoGPSModel extends IBaseOption {
export interface IEvoGPSModel {
evo_gps_modelid?: string;
evo_name?: string;
evo_gps_brandid?: string;
statecode?: number;
}
export interface IEvoRegion extends IBaseOption {
export interface IEvoRegion {
evo_name?: string;
evo_regionid?: string;
statecode?: number;
}
export interface IEvoTown extends IBaseOption {
export interface IEvoTown {
evo_name?: string;
evo_townid?: string;
statecode?: number;
}
export interface IEvoContact extends IBaseOption {
export interface IEvoContact {
parentcustomerid?: string;
contactid?: string;
fullname?: string;
statecode?: number;
}
export interface IConnection extends IBaseOption {
export interface IConnection {
evo_name?: string;
connectionid?: string;
record1id?: string;
@ -162,19 +162,19 @@ export interface IConnection extends IBaseOption {
statecode?: number;
}
export interface IEvoConnectionRole extends IBaseOption {
export interface IEvoConnectionRole {
evo_name?: string;
evo_connection_roleid?: string;
statecode?: number;
}
export interface IEvoImpairmentGroup extends IBaseOption {
export interface IEvoImpairmentGroup {
evo_name?: string;
evo_impairment_groupid?: string;
statecode?: number;
}
export interface IEvoCurrencyChange extends IBaseOption {
export interface IEvoCurrencyChange {
evo_currencychangeid?: string;
evo_name?: string;
evo_ref_transactioncurrency?: string;
@ -183,7 +183,7 @@ export interface IEvoCurrencyChange extends IBaseOption {
statecode?: number;
}
export interface IEvoStatusCode extends IBaseOption {
export interface IEvoStatusCode {
evo_statuscodeid?: string;
evo_id?: string;
evo_name?: string;
@ -191,7 +191,7 @@ export interface IEvoStatusCode extends IBaseOption {
statecode?: number;
}
export interface IEvoCoefficient extends IBaseOption {
export interface IEvoCoefficient {
evo_coefficientid?: string;
evo_corfficient_type?: number;
statecode?: number;
@ -211,7 +211,7 @@ export interface IEvoCoefficient extends IBaseOption {
evo_job_titleid?: string;
}
export interface IEvoAddproductType extends IBaseOption {
export interface IEvoAddproductType {
evo_addproduct_typeid?: string;
evo_graph_price?: number;
evo_prime_cost?: number;
@ -235,7 +235,7 @@ export interface IEvoAddproductType extends IBaseOption {
evo_cost_equipment?: number;
}
export interface IEvoTarif extends IBaseOption {
export interface IEvoTarif {
evo_id?: string;
evo_name?: string;
evo_tarifid?: string;
@ -266,7 +266,7 @@ export interface IEvoTarif extends IBaseOption {
evo_rates?: IEvoRate[];
}
export interface IEvoRate extends IBaseOption {
export interface IEvoRate {
evo_id?: string;
evo_name?: string;
evo_rateid?: string;
@ -282,7 +282,7 @@ export interface IEvoRate extends IBaseOption {
evo_brands?: IEvoBrand[];
}
export interface IEvoPlanPayment extends IBaseOption {
export interface IEvoPlanPayment {
evo_planpaymentid?: string;
evo_name?: string;
evo_cost_telematics_withoutnds?: number;
@ -291,21 +291,26 @@ export interface IEvoPlanPayment extends IBaseOption {
evo_addproduct_typeid?: string;
}
export interface ISystemUser extends IBaseOption {
export interface ISystemUser {
domainname?: string;
systemuserid?: string;
evo_job_titleid?: string;
statecode?: number;
}
export interface IEvoSotCoefficientType extends IBaseOption {
export interface IEvoSotCoefficientType {
evo_id?: string;
statecode?: number;
evo_sot_coefficient_typeid?: string;
evo_name?: string;
}
export type TEntity = IAccount &
type BaseEntity = {
__typename?: CRMEntityNames;
};
export type TCRMEntity = BaseEntity &
IAccount &
ILead &
IOpportunity &
IQuote &

View File

@ -1,4 +1,4 @@
export type EntityNames =
export type CRMEntityNames =
| 'account'
| 'lead'
| 'opportunity'
@ -30,6 +30,7 @@ export type EntityNames =
| 'systemuser'
| 'evo_sot_coefficient_type';
//TODO: or string
export type TEntities<T> = {
[entityName in EntityNames]?: T;
[entityName in CRMEntityNames]?: T;
};

View File

@ -1,9 +1,29 @@
import { TEntity } from './index';
import { EntityNames } from './entityNames';
// import { ElementsNames } from 'core/types/Calculation/Store/elements';
import { TCRMEntity } from './crmEntities';
import { CRMEntityNames } from './crmEntityNames';
export type TGetEntities = {
entityName: EntityNames;
fields?: (keyof TEntity | TGetEntities)[];
where?: { [prop in keyof TEntity]: any };
whereIn?: { [prop in keyof TEntity]: any | any[] };
export type ComparisonOperators = {
eq?: any;
gt?: any;
lt?: any;
gte?: any;
lte?: any;
};
export type TEntitiesKeys = keyof TCRMEntity;
export type TWhere<T> = { [prop in TEntitiesKeys]?: T };
export type TBaseEntityQuery = {
//TODO: alias: ElementsNames
alias?: string;
entityName: CRMEntityNames;
fields: [TEntitiesKeys, ...TEntitiesKeys[]];
relatedEntities?: TBaseEntityQuery[];
many?: boolean;
};
export type TEntityQuery = TBaseEntityQuery & {
where: TWhere<any | any[]>;
whereCmp?: TWhere<ComparisonOperators>;
};

View File

@ -1,63 +0,0 @@
import { Request, Response } from 'express';
import {
IGetEntitiesOptionsRequest,
IGetEntityOptionsRequest,
IGetStaticEntitiesRequest,
} from './../../core/types/Calculation/Requests';
import {
IGetCalculationResponse,
IGetEntitiesOptionsResponse,
IGetEntityOptionsResponse,
IGetStaticEntitiesResponse,
} from './../../core/types/Calculation/Responses';
import {
getEntitiesOptions,
getEntityOptions,
getStaticEntities,
} from './../managers/calculationManager';
class CalculationController {
static getEntitiesOptions = async (
req: Request,
res: Response<IGetEntitiesOptionsResponse>,
): Promise<void> => {
const { elementsList }: IGetEntitiesOptionsRequest = req.body;
const { entitiesOptions } = getEntitiesOptions({ elementsList });
res.send({ entitiesOptions });
};
static getEntityOptions = async (
req: Request,
res: Response<IGetEntityOptionsResponse>,
): Promise<void> => {
const { query }: IGetEntityOptionsRequest = req.body;
const { entityOptions } = getEntityOptions({ query });
res.send({
entityOptions,
});
};
static getStaticEntities = async (
req: Request,
res: Response<IGetStaticEntitiesResponse>,
): Promise<void> => {
const { staticEntitiesList }: IGetStaticEntitiesRequest = req.body;
const { staticEntities } = getStaticEntities({ staticEntitiesList });
res.send({
staticEntities,
});
};
static calculate = async (
req: Request,
res: Response<IGetCalculationResponse>,
): Promise<void> => {
/**
* prepare Data
* send to core
* send to client
*/
};
}
export default CalculationController;

View File

@ -0,0 +1,33 @@
import { getEntities } from './crmManager';
test('getEntities', async () => {
const entities = await getEntities([
{
entityName: 'evo_baseproduct',
where: { statecode: 0, evo_account_type: [123123132] },
whereCmp: {
evo_datefrom: {
gte: new Date().toString(),
lte: 55,
},
},
fields: ['evo_id', 'evo_name'],
relatedEntities: [
{
entityName: 'evo_leasingobject_type',
fields: ['evo_id', 'evo_name'],
},
],
},
{
entityName: 'account',
where: {
accountid: 'fdf1db27-a0e3-ea11-af4b-00155d020202',
},
fields: ['accountid', 'name'],
},
]);
console.log(entities);
expect(entities).not.toBeUndefined();
});

View File

@ -0,0 +1,33 @@
import { ApolloClient, gql, HttpLink, InMemoryCache } from '@apollo/client';
import { TEntities } from 'core/types/Entities/crmEntityNames';
import fetch from 'cross-fetch';
import { CRM_SERVICE_URL } from '../../../core/constants/urls';
import { convertJSONToGQLQuery } from '../../../core/tools/query';
import { TEntityQuery } from '../../../core/types/Entities/query';
import { TCRMEntity } from '../../../core/types/Entities/crmEntities';
const client = new ApolloClient({
uri: CRM_SERVICE_URL,
cache: new InMemoryCache(),
link: new HttpLink({ uri: CRM_SERVICE_URL, fetch }),
});
export const getEntities = (
queries: TEntityQuery[],
): Promise<TEntities<TCRMEntity[] | TCRMEntity>> => {
const convertedQuery = convertJSONToGQLQuery(queries);
return client
.query({
query: gql`
${convertedQuery}
`,
})
.then(res => {
return res.data;
})
.catch(err => {
throw err;
});
// Convert
// Request to GQL
};

View File

@ -0,0 +1,64 @@
import { TCRMEntity } from './../../../core/types/Entities/crmEntities';
import { IBaseOption } from 'core/types/Calculation/Store/options';
import { NextFunction, Request, Response } from 'express';
import { convertEntityToOption } from '../../../core/tools/entities';
import {
IGetCalculationResponse,
IGetEntitiesResponse,
} from '../../../core/types/Calculation/Responses';
import {
IGetCalculationRequest,
IGetEntitiesRequest,
} from './../../../core/types/Calculation/Requests';
import {
CRMEntityNames,
TEntities,
} from '../../../core/types/Entities/crmEntityNames';
import { getEntities } from './crmManager';
class CalculationController {
static getCRMEntities = async (
req: Request,
res: Response,
next: NextFunction,
): Promise<any> => {
const { queries, toOptions } = req.body as IGetEntitiesRequest;
// console.log('CalculationController -> queries', queries);
try {
let resEntities = await getEntities(queries);
if (toOptions) {
let entitiesWithOptions: TEntities<TCRMEntity & IBaseOption> = {};
Object.keys(resEntities).forEach(name => {
const targetEntities: TCRMEntity[] = resEntities[name];
let optionatedOptions = [];
for (let entity of targetEntities) {
optionatedOptions.push(
//@ts-ignore
//TODO
convertEntityToOption(entity, entity.__typename),
);
}
entitiesWithOptions[name] = optionatedOptions;
});
res.send({ entities: entitiesWithOptions });
}
res.send({ entities: resEntities });
} catch (error) {
throw error;
}
};
static calculate = async (
req: { body: IGetCalculationRequest },
res: Response<IGetCalculationResponse>,
): Promise<void> => {
/**
* prepare Data
* send to core
* send to client
*/
};
}
export default CalculationController;

View File

@ -1,102 +1,9 @@
import { gqlRequest } from './../../core/connection/crmService';
import { convertQueryToGQL } from './../../core/tools/query';
import { IGetCalculationRequest } from 'core/types/Calculation/Requests';
import { DateTime } from 'luxon';
import valuesConstants from '../../core/constants/values';
import { IGetCalculationRequest } from '../../core/types/Calculation/Requests';
import entityFakeData from './../../core/fakeData/entityFakes';
import { objectToOption } from './../../core/tools/data';
import {
PreparedData,
PreparedValues,
TPrepareEntities,
PreparedPayments,
} from './../../core/types/Calculation/Prepare';
import {
IGetEntitiesOptionsRequest,
IGetEntityOptionsRequest,
IGetStaticEntitiesRequest,
} from './../../core/types/Calculation/Requests';
import { IOption } from './../../core/types/Calculation/Store/options';
import { TGetEntities } from './../../core/types/Entities/query';
import { calcPrice } from '../../client/stores/CalculationStore/Effects/lib/tools';
function getEntitiesFromCRM({
entityName,
fields,
where,
whereIn,
}: TGetEntities): IOption[] {
const gqlQuery = convertQueryToGQL({ entityName, fields, where, whereIn });
console.log('gqlQuery', gqlQuery);
gqlRequest({ query: gqlQuery });
let entities = entityFakeData[entityName];
let totalWhere = Object.assign({}, where, whereIn);
if (entities !== undefined) {
if (Object.keys(totalWhere).length > 0)
entities = entities.filter(entity => {
for (let w in totalWhere) {
if (entity[w] !== totalWhere[w]) {
return false;
}
}
return true;
});
return entities;
}
return [];
}
export const getEntitiesOptions = ({
elementsList,
}: IGetEntitiesOptionsRequest) => {
let entitiesOptions = {};
Object.keys(elementsList).forEach(elementName => {
const query: TGetEntities = elementsList[elementName];
let entityOptions = getEntitiesFromCRM({ ...query });
entityOptions = entityOptions.map(opt =>
objectToOption(opt, query.entityName),
);
entitiesOptions[elementName] = entityOptions;
});
return { entitiesOptions };
};
export const getEntityOptions = ({ query }: IGetEntityOptionsRequest) => {
let entityOptions = getEntitiesFromCRM(query);
entityOptions = entityOptions.map(entityOption =>
objectToOption(entityOption, query.entityName),
);
return {
entityOptions,
};
};
export const getStaticEntities = ({
staticEntitiesList,
}: IGetStaticEntitiesRequest) => {
let staticEntities = {};
staticEntitiesList.forEach(query => {
const entityOptions = getEntitiesFromCRM({ ...query });
staticEntities[query.entityName] = entityOptions;
});
return {
staticEntities,
};
};
export const getEntities = (
entitiesList: TPrepareEntities<TGetEntities>,
): TPrepareEntities<IOption[]> => {
let entitiesOptions = {};
Object.keys(entitiesList).forEach(elementName => {
const query: TGetEntities = entitiesList[elementName];
let entityOptions = getEntitiesFromCRM({ ...query });
entitiesOptions[elementName] = entityOptions;
});
return entitiesOptions;
};
import { getEntities } from './crmManager';
import { PreparedPayments } from 'core/types/Calculation/Prepare';
import { calcPrice } from 'client/stores/CalculationStore/Effects/lib/tools';
import valuesConstants from 'core/constants/values';
export const prepareCalculationData = ({
values,
@ -104,9 +11,10 @@ export const prepareCalculationData = ({
username,
}: IGetCalculationRequest): any => {
const currentDate = DateTime.local().toUTC().toJSDate();
const entities = getEntities({
evo_coefficient_season: {
const entities = getEntities([
{
entityName: 'evo_coefficient',
alias: 'evo_coefficient_season',
where: {
evo_corfficient_type: 100000000,
statecode: 0,
@ -122,7 +30,8 @@ export const prepareCalculationData = ({
'evo_season_type',
],
},
evo_coefficient_bonus: {
{
alias: 'evo_coefficient_bonus',
entityName: 'evo_coefficient',
where: {
evo_corfficient_type: 100000002,
@ -137,7 +46,7 @@ export const prepareCalculationData = ({
'evo_sot_coefficient',
],
},
evo_currencychange: {
{
entityName: 'evo_currencychange',
where: {
evo_coursedate: currentDate,
@ -145,14 +54,14 @@ export const prepareCalculationData = ({
},
fields: ['isocurrencycode', 'evo_currencychange'],
},
evo_sot_coefficient_type: {
{
entityName: 'evo_sot_coefficient_type',
where: {
statecode: 0,
},
fields: ['evo_sot_coefficient_typeid', 'evo_id'],
},
evo_addproduct_type: {
{
entityName: 'evo_addproduct_type',
where: {
statecode: 0,
@ -180,7 +89,7 @@ export const prepareCalculationData = ({
},
],
},
evo_tarif: {
{
entityName: 'evo_tarif',
where: {
evo_tarifid: values.Tarif,
@ -188,7 +97,7 @@ export const prepareCalculationData = ({
fields: ['evo_irr_plan'],
},
evo_coefficient: {
{
entityName: 'evo_coefficient',
where: {
evo_corfficient_type: 100000001,
@ -221,7 +130,7 @@ export const prepareCalculationData = ({
},
],
},
evo_leasingobject_type: {
{
entityName: 'evo_leasingobject_type',
where: {
evo_leasingobject_typeid: values.leaseObjectType,
@ -234,7 +143,7 @@ export const prepareCalculationData = ({
'evo_depreciation_rate2',
],
},
});
]);
let preparedPayments: PreparedPayments = [];
@ -899,4 +808,9 @@ export const prepareCalculationData = ({
discount -
comissionRub -
firstPaymentSum;
return {
preparedPayments,
preparedValues,
};
};

View File

@ -3,8 +3,8 @@ import { Router } from 'express';
const router = Router();
router.post('/getEntitiesOptions', CalculationController.getEntitiesOptions);
router.post('/getEntityOptions', CalculationController.getEntityOptions);
router.post('/getStaticEntities', CalculationController.getStaticEntities);
//TODO: use
router.post('/getCRMEntities', CalculationController.getCRMEntities);
router.post('/calculate', CalculationController.calculate);
export default router;