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:
Thomas Trompette
2024-02-23 09:51:42 +01:00
committed by GitHub
parent 679456e819
commit 67e27a69ff
5 changed files with 62 additions and 20 deletions

View File

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

View File

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

View File

@ -55,7 +55,7 @@ export class RelationMetadataHealthService {
}
const relationDirection = deduceRelationDirection(
objectMetadata.id,
fieldMetadata,
relationMetadata,
);

View File

@ -72,7 +72,7 @@ export class RelationFieldAliasFactory {
}
const relationDirection = deduceRelationDirection(
fieldMetadata.objectMetadataId,
fieldMetadata,
relationMetadata,
);
// Retrieve the referenced object metadata based on the relation direction

View File

@ -128,7 +128,7 @@ export class ExtendObjectTypeDefinitionFactory {
}
const relationDirection = deduceRelationDirection(
fieldMetadata.objectMetadataId,
fieldMetadata,
relationMetadata,
);
const relationType = this.relationTypeFactory.create(