Skip to content

Commit

Permalink
xStream-512 Attribute inherited override
Browse files Browse the repository at this point in the history
Feat/xstream 512 attribute inherited override
  • Loading branch information
fatb38 authored May 2, 2024
2 parents 5c1d392 + cbc27a5 commit 16f852d
Show file tree
Hide file tree
Showing 22 changed files with 653 additions and 159 deletions.
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
/libs/ui/src/_gqlTypes
**/_gqlTypes/*
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License text available at https://www.gnu.org/licenses/lgpl-3.0.txt
import {IAttributeDomain} from 'domain/attribute/attributeDomain';
import {IVariableValue} from 'domain/helpers/calculationVariable';
import {ActionsListValueType, IActionsListContext} from '_types/actionsList';
import {IActionsListContext} from '_types/actionsList';
import {IRecord} from '_types/record';
import {AttributeTypes} from '../../_types/attribute';
import inheritanceCalculationAction from './inheritanceCalculationAction';
Expand All @@ -12,6 +12,7 @@ const mockCalculationsVariable = {
processVariableString: async (ctx: IActionsListContext, variable: string): Promise<IVariableValue[]> => [
{
value: `${variable}Value`,
raw_value: 'testRawValue',
recordId: '1',
library: 'meh'
}
Expand All @@ -27,22 +28,25 @@ const action = inheritanceCalculationAction({
'core.domain.attribute': mockAttributeDomain as IAttributeDomain
}).action;

describe('heritageCalculationAction', () => {
describe('inheritanceCalculationAction', () => {
test('Simply call processVariableString', async () => {
const ctx: IActionsListContext = {
attribute: {
id: 'meh',
type: AttributeTypes.SIMPLE
}
};

const res = await action(
null,
{
Formula: '42'
},
ctx
);

expect(res.values[0].value).toBe('42Value');
expect((res.values[0] as any).raw_value).toBe('testRawValue');
});

test('No formula', async () => {
Expand Down
19 changes: 8 additions & 11 deletions apps/core/src/domain/actions/inheritanceCalculationAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,18 @@
// License text available at https://www.gnu.org/licenses/lgpl-3.0.txt
import {IAttributeDomain} from 'domain/attribute/attributeDomain';
import {ICalculationVariable} from 'domain/helpers/calculationVariable';
import {ActionsListIOTypes, IActionsListContext} from '../../_types/actionsList';
import {ActionsListIOTypes, IActionsListFunction} from '../../_types/actionsList';
import {AttributeTypes} from '../../_types/attribute';
import {IValue} from '_types/value';

interface IDeps {
'core.domain.helpers.calculationVariable'?: ICalculationVariable;
'core.domain.attribute'?: IAttributeDomain;
}

type ActionsListInheritanceValueType = string | number | boolean | {};

export interface IActionListInheritanceContext extends IActionsListContext {
value?: ActionsListInheritanceValueType;
}

export default function ({
'core.domain.helpers.calculationVariable': calculationVariable = null,
'core.domain.attribute': attributeDomain = null
}: IDeps = {}) {
}: IDeps = {}): IActionsListFunction {
return {
id: 'inheritanceCalculation',
name: 'Inheritance calculation',
Expand Down Expand Up @@ -54,7 +47,7 @@ export default function ({
default_value: ''
}
],
action: async (values: IValue[], params, ctx) => {
action: async (values, params, ctx) => {
const {Formula: formula} = params;
const attrProps = await attributeDomain.getAttributeProperties({id: ctx.attribute.id, ctx});
let inheritedValues = [];
Expand All @@ -71,7 +64,11 @@ export default function ({
isInherited: true
}));
} else {
inheritedValues = result.map(v => ({value: v.value, isInherited: true, raw_value: v.value}));
inheritedValues = result.map(v => ({
value: v.value,
isInherited: true,
raw_value: v.raw_value
}));
}

return {values: [...(values ?? []), ...inheritedValues], errors: []};
Expand Down
6 changes: 4 additions & 2 deletions apps/core/src/domain/helpers/calculationVariable/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import {IVariableFunctions} from '../calculationsVariableFunctions';
interface IDeps {
'core.domain.helpers.calculationsVariableFunctions'?: IVariableFunctions;
}

export interface IVariableValue {
recordId: string;
library: string;
value: IValue | string | number | boolean;
value: string | number | boolean | Record<string, any>;
raw_value?: string | number | boolean | Record<string, any>;
}

export interface ICalculationVariable {
Expand All @@ -25,7 +27,7 @@ export interface ICalculationVariable {
) => Promise<IVariableValue[]>;
}

export default function({'core.domain.helpers.calculationsVariableFunctions': variableFunctions = null}: IDeps = {}) {
export default function ({'core.domain.helpers.calculationsVariableFunctions': variableFunctions = null}: IDeps = {}) {
const processVariableString: ICalculationVariable['processVariableString'] = async (
context,
variableString,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,56 @@
// Copyright LEAV Solutions 2017
// This file is released under LGPL V3
// License text available at https://www.gnu.org/licenses/lgpl-3.0.txt

import {IAttributeDomain} from 'domain/attribute/attributeDomain';
import {IRecordDomain} from 'domain/record/recordDomain';
import {IValueDomain} from 'domain/value/valueDomain';
import {IActionsListContext} from '_types/actionsList';
import calculationsVariableFunctions from '.';
import {TypeGuards} from '../../../utils';

const mockRecordDomain: Mockify<IRecordDomain> = {
getRecordFieldValue: global.__mockPromise([{value: 'test'}])
getRecordFieldValue: jest.fn()
};
const mockAttributeDomainDomain: Mockify<IAttributeDomain> = {
getAttributeProperties: global.__mockPromise({linked_library_id: 'meh'})

const mockAttributeDomain: Mockify<IAttributeDomain> = {
getAttributeProperties: jest.fn()
};
describe('calculationVariable', () => {

describe('calculationsVariableFunctions', () => {
const calculationFunctions = calculationsVariableFunctions({
'core.domain.record': mockRecordDomain as IRecordDomain,
'core.domain.attribute': mockAttributeDomainDomain as IAttributeDomain
'core.domain.attribute': mockAttributeDomain as IAttributeDomain
});
const ctx: IActionsListContext = {};
test('test getValue', async () => {
const res = await calculationFunctions.getValue.run(ctx, [{value: 'meh'}], ['toto']);
expect(res).toHaveLength(1);
expect(res[0]).toHaveProperty('value');
expect(res[0].value).toBe('test');

beforeEach(() => {
mockRecordDomain.getRecordFieldValue.mockResolvedValue([{value: 'test'}]);
mockAttributeDomain.getAttributeProperties.mockResolvedValue({linked_library_id: 'meh'});
});

describe('test getValue', () => {
test('Should map without "raw_value"', async () => {
const res = await calculationFunctions.getValue.run(ctx, [{value: 'meh'}], ['toto']);

expect(res).toHaveLength(1);
expect(res[0]).toHaveProperty('value');
expect(res[0].value).toBe('test');
expect(res[0]).toHaveProperty('raw_value');
expect(res[0].raw_value).toBe(null);
});

test('Should map "raw_value" field', async () => {
mockRecordDomain.getRecordFieldValue.mockResolvedValue([{value: 'meh', raw_value: 42}]);
mockAttributeDomain.getAttributeProperties.mockResolvedValue({});
jest.spyOn(TypeGuards, 'isIStandardValue').mockReturnValue(true);

const res = await calculationFunctions.getValue.run(ctx, [{value: 'meh'}], ['toto']);

expect(res).toHaveLength(1);
expect(res[0]).toHaveProperty('value');
expect(res[0].value).toBe('meh');
expect(res[0]).toHaveProperty('raw_value');
expect(res[0].raw_value).toBe(42);
});
});

test('test input', async () => {
Expand All @@ -33,12 +59,14 @@ describe('calculationVariable', () => {
expect(res[0]).toHaveProperty('value');
expect(res[0].value).toBe('meh');
});

test('test first', async () => {
const res = await calculationFunctions.first.run(ctx, [{value: 'meh'}, {value: 'meh2'}], ['toto']);
expect(res).toHaveLength(1);
expect(res[0]).toHaveProperty('value');
expect(res[0].value).toBe('meh');
});

test('test last', async () => {
const res = await calculationFunctions.last.run(
ctx,
Expand All @@ -49,24 +77,28 @@ describe('calculationVariable', () => {
expect(res[0]).toHaveProperty('value');
expect(res[0].value).toBe('meh3');
});

test('test sum', async () => {
const res = await calculationFunctions.sum.run(ctx, [{value: 1}, {value: 2}, {value: 3}], ['toto']);
expect(res).toHaveLength(1);
expect(res[0]).toHaveProperty('value');
expect(res[0].value).toBe(6);
});

test('test avg', async () => {
const res = await calculationFunctions.avg.run(ctx, [{value: 1}, {value: 2}, {value: 3}], ['toto']);
expect(res).toHaveLength(1);
expect(res[0]).toHaveProperty('value');
expect(res[0].value).toBe(2);
});

test('test concat', async () => {
const res = await calculationFunctions.concat.run(ctx, [{value: 1}, {value: 2}, {value: 3}], ['toto']);
expect(res).toHaveLength(1);
expect(res[0]).toHaveProperty('value');
expect(res[0].value).toBe('1toto2toto3');
});

test('test dedup', async () => {
const res = await calculationFunctions.dedup.run(
ctx,
Expand Down
104 changes: 47 additions & 57 deletions apps/core/src/domain/helpers/calculationsVariableFunctions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ import {IAttributeDomain} from 'domain/attribute/attributeDomain';
import {IVariableValue} from 'domain/helpers/calculationVariable';
import {IRecordDomain} from 'domain/record/recordDomain';
import {IActionsListContext} from '_types/actionsList';
import {TypeGuards} from '../../../utils';

interface IDeps {
'core.domain.record'?: IRecordDomain;
'core.domain.attribute'?: IAttributeDomain;
}

interface IVariableFunction {
run: (context: IActionsListContext, initialValue: any, ...params: any[]) => Promise<IVariableValue[]>;
run: (context: IActionsListContext, inputValue: any, ...params: any[]) => Promise<IVariableValue[]>;
after: string[];
}

export interface IVariableFunctions {
[key: string]: IVariableFunction;
}
Expand Down Expand Up @@ -76,70 +78,58 @@ export default function ({
context: IActionsListContext,
inputValue: IVariableValue[],
attributeKey: string
): Promise<IVariableValue[]> => {
const properties = await attributeDomain.getAttributeProperties({id: attributeKey, ctx: context});
let returnValue = {...inputValue};

const tmpPromises = inputValue.map(async inputV => {
const recordId = inputV.recordId;
const library = inputV.library;
): Promise<IVariableValue[]> =>
Promise.all(
inputValue.map(async ({library, recordId}) => {
let values = await recordDomain.getRecordFieldValue({
library,
record: {
id: recordId,
library
},
attributeId: attributeKey,
ctx: context
});

let values = await recordDomain.getRecordFieldValue({
library,
record: {
id: recordId,
library
},
attributeId: attributeKey,
ctx: context
});

let currReturnValue = [{...inputV}];
if (!Array.isArray(values)) {
values = [values];
}

if (!Array.isArray(values)) {
values = [values];
}
let currReturnValue: IVariableValue[] = [];

if (values.length) {
currReturnValue = [];
if (values.length) {
const properties = await attributeDomain.getAttributeProperties({id: attributeKey, ctx: context});

if (properties?.linked_library) {
currReturnValue = values
.map(v =>
!!v?.value
? {
library: properties?.linked_library,
recordId: v.value.id,
value: v.value.id
}
: null
)
.filter(v => !!v);
} else {
currReturnValue = values.map(v => ({
library,
recordId,
value: v?.value ?? null
}));
if (properties?.linked_library) {
currReturnValue = values
.map(v =>
!!v?.value
? {
library: properties?.linked_library,
recordId: v.value.id,
value: v.value.id
}
: null
)
.filter(v => !!v);
} else {
currReturnValue = values.map(v => ({
library,
recordId,
value: v?.value ?? null,
raw_value: TypeGuards.isIStandardValue(v) ? v?.raw_value : null
}));
}
}
} else {
currReturnValue = [];
}

return currReturnValue;
});
const tmp = await Promise.all(tmpPromises);
if (tmp.length) {
returnValue = tmp.reduce((acc, v) => {
return currReturnValue;
})
).then(tmp =>
tmp.reduce((acc, v) => {
acc = [...acc, ...v];
return acc;
}, []);
} else {
returnValue = [];
}

return returnValue;
};
}, [])
);

return {
input: {
Expand Down
1 change: 1 addition & 0 deletions apps/core/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
// License text available at https://www.gnu.org/licenses/lgpl-3.0.txt
export {default as logger} from './logger/logger';
export {default} from './utils';
export {TypeGuards} from './typeGuards';
10 changes: 10 additions & 0 deletions apps/core/src/utils/typeGuards/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright LEAV Solutions 2017
// This file is released under LGPL V3
// License text available at https://www.gnu.org/licenses/lgpl-3.0.txt
import {IVariableValue} from '../../domain/helpers/calculationVariable';
import {IStandardValue, IValue} from '../../_types/value';

export const TypeGuards = {
isVariableIValue: (value: IVariableValue['value']): value is IValue => typeof value === 'object',
isIStandardValue: (value: IValue): value is IStandardValue => 'raw_value' in value
};
Loading

0 comments on commit 16f852d

Please sign in to comment.