Migrate view filter group to v2 (#16876)

## Introduction
On the side hanlded PR with a // agents on another repo
Made several iterations to fix behavior and direction
Find below auto-generated PR description

closes https://github.com/twentyhq/core-team-issues/issues/2037

Created generic tooling for entity circular dep checking, will be useful
for permissions validation too @Weiko


## Migrate `viewFilterGroup` entity to v2 flat architecture

### Summary
Migrates the `viewFilterGroup` entity from v1 to the v2 flat entity
architecture, following the established patterns for other v2 entities
like `viewFilter`, `view`, and `viewField`.

### Changes

**Types & Constants**
- Added `FlatViewFilterGroup` and `FlatViewFilterGroupMaps` types
- Added editable properties constant for `viewFilterGroup`
- Registered `viewFilterGroup` in `ALL_METADATA_NAME`,
`ALL_METADATA_RELATION_PROPERTIES`,
`ALL_METADATA_MANY_TO_ONE_RELATIONS`, and related constants

**Cache Service**
- Created `WorkspaceFlatViewFilterGroupMapCacheService` with proper
relation loading for `viewFilters` and `childViewFilterGroups`
- Updated `WorkspaceFlatViewMapCacheService` to load `viewFilterGroups`
relation

**Builder & Validator**
- Created `WorkspaceMigrationV2ViewFilterGroupActionsBuilderService`
- Created `FlatViewFilterGroupValidatorService` with creation, update,
and deletion validation
- Integrated validation into the orchestrator service (runs before
`viewFilter` validation)

**Action Handlers**
- Created create, update, and delete action handlers for
`viewFilterGroup`

**Service Migration**
- Rewrote `ViewFilterGroupService` to use v2 migration pattern with
`WorkspaceMigrationValidateBuildAndRunService`
- Created utility functions for transforming DTOs to flat entities

**Database Migration**
- Added migration to make `parentViewFilterGroupId` foreign key
deferrable (handles self-referential parent/child insertions)

**ViewFilter Integration**
- Added `viewFilterGroupId` validation in
`FlatViewFilterValidatorService`
- Updated `viewFilter` many-to-one relations to include
`viewFilterGroup`

**Tests**
- Added integration tests for successful creation, update, deletion, and
destruction
- Added failing test cases for non-existent entities and invalid
references
- Added failing test for `viewFilter` creation with non-existent
`viewFilterGroupId`

### Breaking Changes
None - existing API contracts are preserved.
This commit is contained in:
Paul Rastoin
2026-01-02 14:16:01 +01:00
committed by GitHub
parent 0adbe439d5
commit 98a9ae2a0e
106 changed files with 4648 additions and 439 deletions
@@ -14,6 +14,7 @@ import { FLAT_ROLE_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-
import { FLAT_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/constants/flat-row-level-permission-predicate-group-editable-properties.constant';
import { FLAT_ROW_LEVEL_PERMISSION_PREDICATE_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/constants/flat-row-level-permission-predicate-editable-properties.constant';
import { FLAT_VIEW_FIELD_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-field/constants/flat-view-field-editable-properties.constant';
import { FLAT_VIEW_FILTER_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-filter-group/constants/flat-view-filter-group-editable-properties.constant';
import { FLAT_VIEW_FILTER_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-editable-properties.constant';
import { FLAT_VIEW_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-group/constants/flat-view-group-editable-properties.constant';
import { FLAT_VIEW_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view/constants/flat-view-editable-properties.constant';
@@ -148,6 +149,14 @@ export const ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY = {
],
propertiesToStringify: [],
},
viewFilterGroup: {
propertiesToCompare: [
'viewId',
'deletedAt',
...FLAT_VIEW_FILTER_GROUP_EDITABLE_PROPERTIES,
],
propertiesToStringify: [],
},
} as const satisfies {
[P in AllMetadataName]: OneFlatEntityConfiguration<P>;
};
@@ -100,6 +100,10 @@ export const ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY = {
metadataName: 'fieldMetadata',
flatEntityForeignKeyAggregator: 'viewFilterIds',
},
viewFilterGroupId: {
metadataName: 'viewFilterGroup',
flatEntityForeignKeyAggregator: 'viewFilterIds',
},
},
role: {},
roleTarget: {
@@ -124,4 +128,14 @@ export const ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY = {
},
rowLevelPermissionPredicate: {},
rowLevelPermissionPredicateGroup: {},
viewFilterGroup: {
viewId: {
metadataName: 'view',
flatEntityForeignKeyAggregator: 'viewFilterGroupIds',
},
parentViewFilterGroupId: {
metadataName: 'viewFilterGroup',
flatEntityForeignKeyAggregator: 'childViewFilterGroupIds',
},
},
} as const satisfies MetadataNameAndRelations;
@@ -143,6 +143,14 @@ export const ALL_METADATA_RELATION_PROPERTIES = {
rowLevelPermissionPredicates: true,
application: true,
},
viewFilterGroup: {
view: true,
viewFilters: true,
parentViewFilterGroup: true,
childViewFilterGroups: true,
workspace: true,
application: true,
},
} as const satisfies {
[TName in AllMetadataName]: {
[P in ExtractEntityRelatedEntityProperties<MetadataEntity<TName>>]: true;
@@ -44,11 +44,16 @@ export const ALL_METADATA_REQUIRED_METADATA_FOR_VALIDATION = {
viewFilter: {
view: true,
fieldMetadata: true,
viewFilterGroup: true,
},
viewGroup: {
fieldMetadata: true,
view: true,
},
viewFilterGroup: {
view: true,
viewFilterGroup: true,
},
role: {},
roleTarget: {
role: true,