Handle relations between same objects (#4137)
* Handle relations between same objects * Simplify conditions --------- Co-authored-by: Thomas Trompette <thomast@twenty.com>
This commit is contained in:
@ -1,5 +1,7 @@
|
||||
import { FieldMetadataInterface } from 'src/metadata/field-metadata/interfaces/field-metadata.interface';
|
||||
import { RelationMetadataInterface } from 'src/metadata/field-metadata/interfaces/relation-metadata.interface';
|
||||
|
||||
import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity';
|
||||
import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-metadata.entity';
|
||||
import {
|
||||
deduceRelationDirection,
|
||||
@ -7,39 +9,61 @@ import {
|
||||
} from 'src/workspace/utils/deduce-relation-direction.util';
|
||||
|
||||
describe('deduceRelationDirection', () => {
|
||||
it('should return FROM when the current object Metadata ID matches fromObjectMetadataId', () => {
|
||||
const currentObjectId = 'from_object_id';
|
||||
it('should return FROM when the current object Metadata ID matches fromObjectMetadataId and id matches fromFieldMetadataId', () => {
|
||||
const fieldMetadata: FieldMetadataInterface = {
|
||||
id: 'field_id',
|
||||
objectMetadataId: 'from_object_id',
|
||||
type: FieldMetadataType.RELATION,
|
||||
name: 'field_name',
|
||||
label: 'Field Name',
|
||||
description: 'Field Description',
|
||||
targetColumnMap: {
|
||||
default: 'default_column',
|
||||
},
|
||||
};
|
||||
|
||||
const relationMetadata = {
|
||||
id: 'relation_id',
|
||||
fromObjectMetadataId: currentObjectId,
|
||||
fromObjectMetadataId: fieldMetadata.objectMetadataId,
|
||||
toObjectMetadataId: 'to_object_id',
|
||||
fromFieldMetadataId: 'from_field_id',
|
||||
fromFieldMetadataId: fieldMetadata.id,
|
||||
toFieldMetadataId: 'to_field_id',
|
||||
relationType: RelationMetadataType.ONE_TO_ONE,
|
||||
};
|
||||
|
||||
const result = deduceRelationDirection(
|
||||
currentObjectId,
|
||||
fieldMetadata,
|
||||
relationMetadata as RelationMetadataInterface,
|
||||
);
|
||||
|
||||
expect(result).toBe(RelationDirection.FROM);
|
||||
});
|
||||
|
||||
it('should return TO when the current object Metadata ID matches toObjectMetadataId', () => {
|
||||
it('should return TO when the current object Metadata ID matches toObjectMetadataId and id matches toFieldMetadataId', () => {
|
||||
// Arrange
|
||||
const currentObjectId = 'to_object_id';
|
||||
const fieldMetadata: FieldMetadataInterface = {
|
||||
id: 'field_id',
|
||||
objectMetadataId: 'to_object_id',
|
||||
type: FieldMetadataType.RELATION,
|
||||
name: 'field_name',
|
||||
label: 'Field Name',
|
||||
description: 'Field Description',
|
||||
targetColumnMap: {
|
||||
default: 'default_column',
|
||||
},
|
||||
};
|
||||
|
||||
const relationMetadata = {
|
||||
id: 'relation_id',
|
||||
fromObjectMetadataId: 'from_object_id',
|
||||
toObjectMetadataId: currentObjectId,
|
||||
toObjectMetadataId: fieldMetadata.objectMetadataId,
|
||||
fromFieldMetadataId: 'from_field_id',
|
||||
toFieldMetadataId: 'to_field_id',
|
||||
toFieldMetadataId: fieldMetadata.id,
|
||||
relationType: RelationMetadataType.ONE_TO_ONE,
|
||||
};
|
||||
|
||||
const result = deduceRelationDirection(
|
||||
currentObjectId,
|
||||
fieldMetadata,
|
||||
relationMetadata as RelationMetadataInterface,
|
||||
);
|
||||
|
||||
@ -47,7 +71,18 @@ describe('deduceRelationDirection', () => {
|
||||
});
|
||||
|
||||
it('should throw an error when the current object Metadata ID does not match any object metadata ID', () => {
|
||||
const currentObjectId = 'unrelated_object_id';
|
||||
const fieldMetadata: FieldMetadataInterface = {
|
||||
id: 'field_id',
|
||||
objectMetadataId: 'unrelated_object_id',
|
||||
type: FieldMetadataType.RELATION,
|
||||
name: 'field_name',
|
||||
label: 'Field Name',
|
||||
description: 'Field Description',
|
||||
targetColumnMap: {
|
||||
default: 'default_column',
|
||||
},
|
||||
};
|
||||
|
||||
const relationMetadata = {
|
||||
id: 'relation_id',
|
||||
fromObjectMetadataId: 'from_object_id',
|
||||
@ -59,11 +94,11 @@ describe('deduceRelationDirection', () => {
|
||||
|
||||
expect(() =>
|
||||
deduceRelationDirection(
|
||||
currentObjectId,
|
||||
fieldMetadata,
|
||||
relationMetadata as RelationMetadataInterface,
|
||||
),
|
||||
).toThrow(
|
||||
`Relation metadata ${relationMetadata.id} is not related to object ${currentObjectId}`,
|
||||
`Relation metadata ${relationMetadata.id} is not related to object ${fieldMetadata.objectMetadataId}`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { FieldMetadataInterface } from 'src/metadata/field-metadata/interfaces/field-metadata.interface';
|
||||
import { RelationMetadataInterface } from 'src/metadata/field-metadata/interfaces/relation-metadata.interface';
|
||||
|
||||
export enum RelationDirection {
|
||||
@ -6,18 +7,24 @@ export enum RelationDirection {
|
||||
}
|
||||
|
||||
export const deduceRelationDirection = (
|
||||
currentObjectId: string,
|
||||
fieldMetadata: FieldMetadataInterface,
|
||||
relationMetadata: RelationMetadataInterface,
|
||||
): RelationDirection => {
|
||||
if (relationMetadata.fromObjectMetadataId === currentObjectId) {
|
||||
if (
|
||||
relationMetadata.fromObjectMetadataId === fieldMetadata.objectMetadataId &&
|
||||
relationMetadata.fromFieldMetadataId === fieldMetadata.id
|
||||
) {
|
||||
return RelationDirection.FROM;
|
||||
}
|
||||
|
||||
if (relationMetadata.toObjectMetadataId === currentObjectId) {
|
||||
if (
|
||||
relationMetadata.toObjectMetadataId === fieldMetadata.objectMetadataId &&
|
||||
relationMetadata.toFieldMetadataId === fieldMetadata.id
|
||||
) {
|
||||
return RelationDirection.TO;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Relation metadata ${relationMetadata.id} is not related to object ${currentObjectId}`,
|
||||
`Relation metadata ${relationMetadata.id} is not related to object ${fieldMetadata.objectMetadataId}`,
|
||||
);
|
||||
};
|
||||
|
||||
@ -55,7 +55,7 @@ export class RelationMetadataHealthService {
|
||||
}
|
||||
|
||||
const relationDirection = deduceRelationDirection(
|
||||
objectMetadata.id,
|
||||
fieldMetadata,
|
||||
relationMetadata,
|
||||
);
|
||||
|
||||
|
||||
@ -72,7 +72,7 @@ export class RelationFieldAliasFactory {
|
||||
}
|
||||
|
||||
const relationDirection = deduceRelationDirection(
|
||||
fieldMetadata.objectMetadataId,
|
||||
fieldMetadata,
|
||||
relationMetadata,
|
||||
);
|
||||
// Retrieve the referenced object metadata based on the relation direction
|
||||
|
||||
@ -128,7 +128,7 @@ export class ExtendObjectTypeDefinitionFactory {
|
||||
}
|
||||
|
||||
const relationDirection = deduceRelationDirection(
|
||||
fieldMetadata.objectMetadataId,
|
||||
fieldMetadata,
|
||||
relationMetadata,
|
||||
);
|
||||
const relationType = this.relationTypeFactory.create(
|
||||
|
||||
Reference in New Issue
Block a user