diff --git a/packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts b/packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts index 73b4c855a..c00b9f5da 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts +++ b/packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts @@ -145,7 +145,16 @@ export const mocks = [ currencyCode } createdAt - address + address { + addressStreet1 + addressStreet2 + addressCity + addressState + addressCountry + addressPostcode + addressLat + addressLng + } updatedAt name accountOwnerId @@ -262,7 +271,16 @@ export const mocks = [ currencyCode } createdAt - address + address { + addressStreet1 + addressStreet2 + addressCity + addressState + addressCountry + addressPostcode + addressLat + addressLng + } updatedAt name accountOwnerId diff --git a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapFieldMetadataToGraphQLQuery.test.tsx b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapFieldMetadataToGraphQLQuery.test.tsx index 116874b23..fc841bd27 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapFieldMetadataToGraphQLQuery.test.tsx +++ b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapFieldMetadataToGraphQLQuery.test.tsx @@ -66,6 +66,16 @@ annualRecurringRevenue } createdAt address +{ + addressStreet1 + addressStreet2 + addressCity + addressState + addressCountry + addressPostcode + addressLat + addressLng +} updatedAt name accountOwnerId @@ -86,7 +96,7 @@ idealCustomerProfile domainName: true, annualRecurringRevenue: true, createdAt: true, - address: true, + address: { addressStreet1: true }, updatedAt: true, name: true, accountOwnerId: true, @@ -129,6 +139,16 @@ annualRecurringRevenue } createdAt address +{ + addressStreet1 + addressStreet2 + addressCity + addressState + addressCountry + addressPostcode + addressLat + addressLng +} updatedAt people { diff --git a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapObjectMetadataToGraphQLQuery.test.tsx b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapObjectMetadataToGraphQLQuery.test.tsx index a5261cbfd..534428624 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapObjectMetadataToGraphQLQuery.test.tsx +++ b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapObjectMetadataToGraphQLQuery.test.tsx @@ -65,6 +65,16 @@ annualRecurringRevenue } createdAt address +{ + addressStreet1 + addressStreet2 + addressCity + addressState + addressCountry + addressPostcode + addressLat + addressLng +} updatedAt name accountOwnerId diff --git a/packages/twenty-front/src/modules/object-metadata/utils/getObjectMetadataItemsMock.ts b/packages/twenty-front/src/modules/object-metadata/utils/getObjectMetadataItemsMock.ts index 4c004f869..d20e85583 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/getObjectMetadataItemsMock.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/getObjectMetadataItemsMock.ts @@ -3039,7 +3039,7 @@ export const getObjectMetadataItemsMock = () => { { __typename: 'field', id: '20202020-ad10-4117-a039-3f04b7a5f939', - type: 'TEXT', + type: 'ADDRESS', name: 'address', label: 'Address', description: 'The company address', diff --git a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useFindManyRecords.ts b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useFindManyRecords.ts index 6de4625bf..f7251f35e 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useFindManyRecords.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useFindManyRecords.ts @@ -82,7 +82,16 @@ export const query = gql` currencyCode } createdAt - address + address { + addressStreet1 + addressStreet2 + addressCity + addressState + addressCountry + addressPostcode + addressLat + addressLng + } updatedAt name accountOwnerId diff --git a/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useToggleEditOnlyInput.test.tsx b/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useToggleEditOnlyInput.test.tsx index 3a073219f..3000ca0eb 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useToggleEditOnlyInput.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useToggleEditOnlyInput.test.tsx @@ -40,7 +40,16 @@ const mocks: MockedResponse[] = [ currencyCode } createdAt - address + address { + addressStreet1 + addressStreet2 + addressCity + addressState + addressCountry + addressPostcode + addressLat + addressLng + } updatedAt name accountOwnerId diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/mock.ts b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/mock.ts index ec60d500f..925e8c70e 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/mock.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/mock.ts @@ -800,7 +800,9 @@ export const mockPerformance = { }, employees: null, accountOwnerId: null, - address: '', + address: { + addressCity: 'San Francisco', + }, idealCustomerProfile: false, createdAt: '2024-05-01T13:16:29.046Z', id: '20202020-c21e-4ec2-873b-de4264d89025', @@ -844,7 +846,7 @@ export const mockPerformance = { }, employees: null, accountOwnerId: null, - address: '', + address: { addressCity: 'San Francisco' }, idealCustomerProfile: false, createdAt: '2024-05-01T13:16:29.046Z', id: '20202020-ed89-413a-b31a-962986e67bb4', diff --git a/packages/twenty-front/src/modules/object-record/spreadsheet-import/__tests__/useSpreadsheetRecordImport.test.tsx b/packages/twenty-front/src/modules/object-record/spreadsheet-import/__tests__/useSpreadsheetRecordImport.test.tsx index 6ee554ea0..33f43785b 100644 --- a/packages/twenty-front/src/modules/object-record/spreadsheet-import/__tests__/useSpreadsheetRecordImport.test.tsx +++ b/packages/twenty-front/src/modules/object-record/spreadsheet-import/__tests__/useSpreadsheetRecordImport.test.tsx @@ -40,7 +40,16 @@ const companyMocks = [ currencyCode } createdAt - address + address { + addressStreet1 + addressStreet2 + addressCity + addressState + addressCountry + addressPostcode + addressLat + addressLng + } updatedAt name accountOwnerId diff --git a/packages/twenty-front/src/modules/search/hooks/__mocks__/useFilteredSearchEntityQuery.ts b/packages/twenty-front/src/modules/search/hooks/__mocks__/useFilteredSearchEntityQuery.ts index 3b08ec0ce..7423e7bcb 100644 --- a/packages/twenty-front/src/modules/search/hooks/__mocks__/useFilteredSearchEntityQuery.ts +++ b/packages/twenty-front/src/modules/search/hooks/__mocks__/useFilteredSearchEntityQuery.ts @@ -78,7 +78,9 @@ export const query = gql` currencyCode } createdAt - address + address { + adressCity + } updatedAt name accountOwnerId diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockColumnDefinitions.ts b/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockColumnDefinitions.ts index 2245a1fc1..cb0634772 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockColumnDefinitions.ts +++ b/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockColumnDefinitions.ts @@ -78,7 +78,7 @@ export const SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS = ( fieldMetadataId: '20202020-ad10-4117-a039-3f04b7a5f939', label: 'Address', size: 100, - type: FieldMetadataType.Text, + type: FieldMetadataType.Address, metadata: { fieldName: 'address', placeHolder: 'Address', diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockCompanies.ts b/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockCompanies.ts index f89118b90..609536b42 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockCompanies.ts +++ b/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockCompanies.ts @@ -10,7 +10,12 @@ export const SIGN_IN_BACKGROUND_MOCK_COMPANIES = [ __typename: 'FavoriteConnection', edges: [], }, - address: 'OLINDA SAS. 18 rue de Navarin, 75009 Paris', + address: { + addressStreet1: 'OLINDA SAS', + addressStreet2: '18 rue de Navarin', + addressCity: 'Paris', + addressPostcode: '75009', + }, accountOwner: null, people: { __typename: 'PersonConnection', @@ -115,7 +120,12 @@ export const SIGN_IN_BACKGROUND_MOCK_COMPANIES = [ __typename: 'FavoriteConnection', edges: [], }, - address: '1600 Amphitheatre Pkwy, Mountain View, CA 94043', + address: { + addressStreet1: '1600 Amphitheatre Pkwy', + addressStreet2: 'Mountain View', + addressState: 'CA', + addressPostcode: '94043', + }, accountOwner: null, people: { __typename: 'PersonConnection', @@ -314,7 +324,12 @@ export const SIGN_IN_BACKGROUND_MOCK_COMPANIES = [ __typename: 'FavoriteConnection', edges: [], }, - address: '1 Hacker Way, Menlo Park, CA 94025', + address: { + addressStreet1: '1 Hacker Way', + addressStreet2: 'Menlo Park', + addressState: 'CA', + addressPostcode: '94025', + }, accountOwner: null, people: { __typename: 'PersonConnection', @@ -444,7 +459,12 @@ export const SIGN_IN_BACKGROUND_MOCK_COMPANIES = [ __typename: 'FavoriteConnection', edges: [], }, - address: '121 Albright Way, Los Gatos, CA 95032', + address: { + addressStreet1: '121 Albright Way', + addressStreet2: 'Los Gatos', + addressState: 'CA', + addressPostcode: '95032', + }, accountOwner: null, people: { __typename: 'PersonConnection', @@ -492,7 +512,12 @@ export const SIGN_IN_BACKGROUND_MOCK_COMPANIES = [ __typename: 'FavoriteConnection', edges: [], }, - address: '1 Microsoft Way, Redmond, WA 98052', + address: { + addressStreet1: '1 Microsoft Way', + addressStreet2: 'Redmond', + addressState: 'WA', + addressPostcode: '98052', + }, accountOwner: null, people: { __typename: 'PersonConnection', @@ -672,7 +697,11 @@ export const SIGN_IN_BACKGROUND_MOCK_COMPANIES = [ __typename: 'FavoriteConnection', edges: [], }, - address: '42 Rue de Paradis, 75010 Paris', + address: { + addressStreet1: '42 rue de paradis', + addressCity: 'Paris', + addressPostcode: '75010', + }, accountOwner: null, people: { __typename: 'PersonConnection', @@ -720,7 +749,12 @@ export const SIGN_IN_BACKGROUND_MOCK_COMPANIES = [ __typename: 'FavoriteConnection', edges: [], }, - address: '888 Brannan Street San Francisco, CA 94103', + address: { + addressStreet1: '888 Brannan Street', + addressCity: 'San Francisco', + addressState: 'CA', + addressPostcode: '75010', + }, accountOwner: null, people: { __typename: 'PersonConnection', @@ -768,7 +802,13 @@ export const SIGN_IN_BACKGROUND_MOCK_COMPANIES = [ __typename: 'FavoriteConnection', edges: [], }, - address: '901 Fifth Avenue; Suite 1200; Seattle, WA 98164', + address: { + addressStreet1: '901 Fifth Avenue', + addressStreet2: 'Suite 1200', + addressCity: 'Seattle', + addressState: 'WA', + addressPostcode: '98164', + }, accountOwner: null, people: { __typename: 'PersonConnection', @@ -816,7 +856,13 @@ export const SIGN_IN_BACKGROUND_MOCK_COMPANIES = [ __typename: 'FavoriteConnection', edges: [], }, - address: '3790 El Camino Real, Unit 518, Palo Alto, CA 94306', + address: { + addressStreet1: '3790 El Camino Real', + addressStreet2: 'Unit 518', + addressCity: 'Palo Alto', + addressState: 'CA', + addressPostcode: '94306', + }, accountOwner: null, people: { __typename: 'PersonConnection', @@ -895,7 +941,11 @@ export const SIGN_IN_BACKGROUND_MOCK_COMPANIES = [ __typename: 'FavoriteConnection', edges: [], }, - address: '129, Samsung-ro, Yeongtong-gu, Suwon-si, Gyeonggi-do', + address: { + addressStreet1: '129, Samsung-ro', + addressStreet2: 'Yeongtong-gu, Suwon-si', + addressCity: 'Gyeonggi-do', + }, accountOwner: null, people: { __typename: 'PersonConnection', @@ -974,7 +1024,13 @@ export const SIGN_IN_BACKGROUND_MOCK_COMPANIES = [ __typename: 'FavoriteConnection', edges: [], }, - address: '576 Folsom St., Floor 3, San Francisco, CA 94105', + address: { + addressStreet1: '576 Folsom St.', + addressStreet2: 'Floor 3', + addressCity: 'San Francisco', + addressState: 'CA', + addressPostcode: '94105', + }, accountOwner: null, people: { __typename: 'PersonConnection', @@ -1022,7 +1078,10 @@ export const SIGN_IN_BACKGROUND_MOCK_COMPANIES = [ __typename: 'FavoriteConnection', edges: [], }, - address: '575 Lexington Ave 16th Floor, New York', + address: { + addressStreet1: '575 Lexington Ave 16th Floor', + addressCity: 'New York', + }, accountOwner: null, people: { __typename: 'PersonConnection', @@ -1070,7 +1129,13 @@ export const SIGN_IN_BACKGROUND_MOCK_COMPANIES = [ __typename: 'FavoriteConnection', edges: [], }, - address: '315 Montgomery St, 13th Fl. San Francisco, CA 94104', + address: { + addressStreet1: '315 Montgomery St', + addressStreet2: '13th Fl.', + addressCity: 'San Francisco', + addressState: 'CA', + addressPostcode: '94104', + }, accountOwner: null, people: { __typename: 'PersonConnection', diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockFilterDefinitions.ts b/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockFilterDefinitions.ts index 15a87498e..f53451ad7 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockFilterDefinitions.ts +++ b/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockFilterDefinitions.ts @@ -23,7 +23,7 @@ export const SIGN_IN_BACKGROUND_MOCK_FILTER_DEFINITIONS = [ fieldMetadataId: '20202020-ad10-4117-a039-3f04b7a5f939', label: 'Address', iconName: 'IconMap', - type: 'TEXT', + type: 'ADDRESS', }, { fieldMetadataId: '20202020-0739-495d-8e70-c0807f6b2268', diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/entity-events-to-db.listener.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/entity-events-to-db.listener.ts index 04e015de1..3e00d01be 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/entity-events-to-db.listener.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/entity-events-to-db.listener.ts @@ -1,15 +1,15 @@ import { Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; -import { objectRecordChangedValues } from 'src/engine/integrations/event-emitter/utils/object-record-changed-values'; import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; import { ObjectRecordBaseEvent } from 'src/engine/integrations/event-emitter/types/object-record.base.event'; -import { UpsertTimelineActivityFromInternalEvent } from 'src/modules/timeline/jobs/upsert-timeline-activity-from-internal-event.job'; +import { objectRecordChangedValues } from 'src/engine/integrations/event-emitter/utils/object-record-changed-values'; import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; import { CreateAuditLogFromInternalEvent } from 'src/modules/timeline/jobs/create-audit-log-from-internal-event'; +import { UpsertTimelineActivityFromInternalEvent } from 'src/modules/timeline/jobs/upsert-timeline-activity-from-internal-event.job'; @Injectable() export class EntityEventsToDbListener { diff --git a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-field.decorator.ts b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-field.decorator.ts index 60a228d90..cfbb7a964 100644 --- a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-field.decorator.ts +++ b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-field.decorator.ts @@ -46,6 +46,13 @@ export function WorkspaceField( object, propertyKey.toString(), ); + const isDeprecated = + TypedReflect.getMetadata( + 'workspace:is-deprecated-field-metadata-args', + object, + propertyKey.toString(), + ) ?? false; + const defaultValue = (options.defaultValue ?? generateDefaultValue( options.type, @@ -65,6 +72,7 @@ export function WorkspaceField( isNullable, isSystem, gate, + isDeprecated, }); }; } diff --git a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-is-deprecated.decorator.ts b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-is-deprecated.decorator.ts new file mode 100644 index 000000000..a9bbb192e --- /dev/null +++ b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-is-deprecated.decorator.ts @@ -0,0 +1,12 @@ +import { TypedReflect } from 'src/utils/typed-reflect'; + +export function WorkspaceIsDeprecated(): PropertyDecorator { + return (object, propertyKey) => { + TypedReflect.defineMetadata( + 'workspace:is-deprecated-field-metadata-args', + true, + object, + propertyKey.toString(), + ); + }; +} diff --git a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface.ts b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface.ts index cad77a674..0574fb792 100644 --- a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface.ts +++ b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface.ts @@ -73,4 +73,9 @@ export interface WorkspaceFieldMetadataArgs { * Field gate. */ readonly gate?: Gate; + + /** + * Is deprecated field. + */ + readonly isDeprecated?: boolean; } diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/company.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/company.ts index 9899ffd1c..6061cef07 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/company.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/company.ts @@ -10,7 +10,12 @@ export const companyPrefillData = async ( .into(`${schemaName}.company`, [ 'name', 'domainName', - 'address', + 'addressAddressStreet1', + 'addressAddressStreet2', + 'addressAddressCity', + 'addressAddressState', + 'addressAddressPostcode', + 'addressAddressCountry', 'employees', 'position', ]) @@ -19,35 +24,60 @@ export const companyPrefillData = async ( { name: 'Airbnb', domainName: 'airbnb.com', - address: 'San Francisco', + addressAddressStreet1: '888 Brannan St', + addressAddressStreet2: null, + addressAddressCity: 'San Francisco', + addressAddressState: 'CA', + addressAddressPostcode: '94103', + addressAddressCountry: 'United States', employees: 5000, position: 1, }, { name: 'Qonto', domainName: 'qonto.com', - address: 'San Francisco', + addressAddressStreet1: '18 rue de navarrin', + addressAddressStreet2: null, + addressAddressCity: 'Paris', + addressAddressState: null, + addressAddressPostcode: '75009', + addressAddressCountry: 'France', employees: 800, position: 2, }, { name: 'Stripe', domainName: 'stripe.com', - address: 'San Francisco', + addressAddressStreet1: 'Eutaw Street', + addressAddressStreet2: null, + addressAddressCity: 'Dublin', + addressAddressState: null, + addressAddressPostcode: null, + addressAddressCountry: 'Ireland', employees: 8000, position: 3, }, { name: 'Figma', domainName: 'figma.com', - address: 'San Francisco', + addressAddressStreet1: '760 Market St', + addressAddressStreet2: 'Floor 10', + addressAddressCity: 'San Francisco', + addressAddressState: null, + addressAddressPostcode: '94102', + addressAddressCountry: 'United States', employees: 800, position: 4, }, { name: 'Notion', domainName: 'notion.com', - address: 'San Francisco', + addressAddressStreet1: '2300 Harrison St', + addressAddressStreet2: null, + addressAddressCity: 'San Francisco', + addressAddressState: 'CA', + addressAddressPostcode: '94110', + addressAddressCountry: 'United States', employees: 400, position: 5, }, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-field.comparator.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-field.comparator.ts index f1659ea6b..7e51a398f 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-field.comparator.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-field.comparator.ts @@ -8,11 +8,11 @@ import { } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/comparator.interface'; import { ComputedPartialFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface'; -import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util'; import { FieldMetadataEntity, FieldMetadataType, } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util'; const commonFieldPropertiesToIgnore = [ 'id', @@ -28,6 +28,12 @@ const commonFieldPropertiesToIgnore = [ const fieldPropertiesToStringify = ['defaultValue'] as const; +const shouldSkipFieldCreation = ( + standardFieldMetadata: ComputedPartialFieldMetadata | undefined, +) => { + return standardFieldMetadata?.isCustom; +}; + @Injectable() export class WorkspaceFieldComparator { constructor() {} @@ -108,10 +114,6 @@ export class WorkspaceFieldComparator { const findField = ( field: ComputedPartialFieldMetadata | FieldMetadataEntity, ) => { - if (field.isCustom) { - return field.name === fieldName; - } - return field.standardId === fieldName; }; // Object shouldn't have thousands of fields, so we can use find here @@ -122,6 +124,9 @@ export class WorkspaceFieldComparator { switch (difference.type) { case 'CREATE': { + if (shouldSkipFieldCreation(standardFieldMetadata)) { + break; + } if (!standardFieldMetadata) { throw new Error( `Field ${fieldName} not found in standardObjectMetadata`, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts index 8fe3c7d3c..63b64692a 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts @@ -114,7 +114,8 @@ export const COMMENT_STANDARD_FIELD_IDS = { export const COMPANY_STANDARD_FIELD_IDS = { name: '20202020-4d99-4e2e-a84c-4a27837b1ece', domainName: '20202020-0c28-43d8-8ba5-3659924d3489', - address: '20202020-a82a-4ee2-96cc-a18a3259d953', + address_deprecated: '20202020-a82a-4ee2-96cc-a18a3259d953', + address: '20202020-c5ce-4adc-b7b6-9c0979fc55e7', employees: '20202020-8965-464a-8a75-74bafc152a0b', linkedinLink: '20202020-ebeb-4beb-b9ad-6848036fb451', xLink: '20202020-6f64-4fd9-9580-9c1991c7d8c3', diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts index 20c720e1e..eff6dedbd 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts @@ -162,7 +162,7 @@ export class StandardFieldFactory { options: workspaceFieldMetadataArgs.options, workspaceId: context.workspaceId, isNullable: workspaceFieldMetadataArgs.isNullable, - isCustom: false, + isCustom: workspaceFieldMetadataArgs.isDeprecated ? true : false, isSystem: workspaceEntityMetadataArgs?.isSystem || workspaceFieldMetadataArgs.isSystem, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-metadata-updater.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-metadata-updater.service.ts index ac3f8961a..1ae597c2d 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-metadata-updater.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-metadata-updater.service.ts @@ -125,16 +125,6 @@ export class WorkspaceMetadataUpdaterService { updatedFieldMetadataCollection: FieldMetadataUpdate[]; }> { const fieldMetadataRepository = manager.getRepository(FieldMetadataEntity); - - /** - * Create field metadata - */ - const createdFieldMetadataCollection = await fieldMetadataRepository.save( - storage.fieldMetadataCreateCollection.map((field) => - this.prepareFieldMetadataForCreation(field), - ) as DeepPartial[], - ); - /** * Update field metadata */ @@ -145,6 +135,15 @@ export class WorkspaceMetadataUpdaterService { 'workspaceId', ]); + /** + * Create field metadata + */ + const createdFieldMetadataCollection = await fieldMetadataRepository.save( + storage.fieldMetadataCreateCollection.map((field) => + this.prepareFieldMetadataForCreation(field), + ) as DeepPartial[], + ); + /** * Delete field metadata */ diff --git a/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts b/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts index c721f4b14..d356969a3 100644 --- a/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts +++ b/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts @@ -1,3 +1,5 @@ +import { Address } from 'nodemailer/lib/mailer'; + import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; import { CurrencyMetadata } from 'src/engine/metadata-modules/field-metadata/composite-types/currency.composite-type'; @@ -22,6 +24,7 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { WorkspaceIsDeprecated } from 'src/engine/twenty-orm/decorators/workspace-is-deprecated.decorator'; import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ @@ -52,15 +55,6 @@ export class CompanyWorkspaceEntity extends BaseWorkspaceEntity { }) domainName?: string; - @WorkspaceField({ - standardId: COMPANY_STANDARD_FIELD_IDS.address, - type: FieldMetadataType.TEXT, - label: 'Address', - description: 'The company address', - icon: 'IconMap', - }) - address: string; - @WorkspaceField({ standardId: COMPANY_STANDARD_FIELD_IDS.employees, type: FieldMetadataType.NUMBER, @@ -102,6 +96,28 @@ export class CompanyWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceIsNullable() annualRecurringRevenue: CurrencyMetadata | null; + @WorkspaceField({ + standardId: COMPANY_STANDARD_FIELD_IDS.address_deprecated, + type: FieldMetadataType.TEXT, + label: 'Address (deprecated) ', + description: + 'Address of the company - deprecated in favor of new address field', + icon: 'IconMap', + }) + @WorkspaceIsDeprecated() + @WorkspaceIsNullable() + address_old: string; + + @WorkspaceField({ + standardId: COMPANY_STANDARD_FIELD_IDS.address, + type: FieldMetadataType.ADDRESS, + label: 'Address', + description: 'Address of the company', + icon: 'IconMap', + }) + @WorkspaceIsNullable() + address: Address; + @WorkspaceField({ standardId: COMPANY_STANDARD_FIELD_IDS.idealCustomerProfile, type: FieldMetadataType.BOOLEAN, diff --git a/packages/twenty-server/src/utils/typed-reflect.ts b/packages/twenty-server/src/utils/typed-reflect.ts index 6e9fdb819..5abec76b8 100644 --- a/packages/twenty-server/src/utils/typed-reflect.ts +++ b/packages/twenty-server/src/utils/typed-reflect.ts @@ -8,6 +8,7 @@ export interface ReflectMetadataTypeMap { ['workspace:is-system-metadata-args']: true; ['workspace:is-audit-logged-metadata-args']: false; ['workspace:is-primary-field-metadata-args']: true; + ['workspace:is-deprecated-field-metadata-args']: true; } export class TypedReflect { diff --git a/packages/twenty-server/test/company.e2e-spec.ts b/packages/twenty-server/test/company.e2e-spec.ts index 40658d931..1a5299860 100644 --- a/packages/twenty-server/test/company.e2e-spec.ts +++ b/packages/twenty-server/test/company.e2e-spec.ts @@ -31,7 +31,9 @@ describe('CompanyResolver (e2e)', () => { id name domainName - address + address { + addressCity + } } } `, @@ -39,7 +41,7 @@ describe('CompanyResolver (e2e)', () => { data: { name: 'New Company', domainName: 'new-company.com', - address: 'New Address', + address: { addressCity: 'Paris' }, }, }, }; @@ -57,7 +59,7 @@ describe('CompanyResolver (e2e)', () => { expect(data).toHaveProperty('id'); expect(data).toHaveProperty('name', 'New Company'); expect(data).toHaveProperty('domainName', 'new-company.com'); - expect(data).toHaveProperty('address', 'New Address'); + expect(data).toHaveProperty('address', { addressCity: 'Paris' }); }); }); @@ -69,7 +71,9 @@ describe('CompanyResolver (e2e)', () => { id name domainName - address + address { + addressCity + } } } `, @@ -92,7 +96,7 @@ describe('CompanyResolver (e2e)', () => { expect(company).toHaveProperty('id'); expect(company).toHaveProperty('name', 'New Company'); expect(company).toHaveProperty('domainName', 'new-company.com'); - expect(company).toHaveProperty('address', 'New Address'); + expect(company).toHaveProperty('address', { addressCity: 'Paris' }); // Check if we have access to ressources outside of our workspace const instagramCompany = data.find((c) => c.name === 'Instagram'); @@ -109,7 +113,9 @@ describe('CompanyResolver (e2e)', () => { id name domainName - address + address { + addressCity + } } } `, @@ -131,7 +137,7 @@ describe('CompanyResolver (e2e)', () => { expect(data).toHaveProperty('id'); expect(data).toHaveProperty('name', 'New Company'); expect(data).toHaveProperty('domainName', 'new-company.com'); - expect(data).toHaveProperty('address', 'New Address'); + expect(data).toHaveProperty('address', { addressCity: 'Paris' }); }); }); @@ -143,7 +149,9 @@ describe('CompanyResolver (e2e)', () => { id name domainName - address + address { + addressCity + } } } `, @@ -175,7 +183,9 @@ describe('CompanyResolver (e2e)', () => { id name domainName - address + address { + addressCity + } } } `, @@ -186,7 +196,7 @@ describe('CompanyResolver (e2e)', () => { data: { name: 'Updated Company', domainName: 'updated-company.com', - address: 'Updated Address', + address: { addressCity: 'Updated City' }, }, }, }; @@ -202,7 +212,7 @@ describe('CompanyResolver (e2e)', () => { expect(data).toHaveProperty('id'); expect(data).toHaveProperty('name', 'Updated Company'); expect(data).toHaveProperty('domainName', 'updated-company.com'); - expect(data).toHaveProperty('address', 'Updated Address'); + expect(data).toHaveProperty('address', { addressCity: 'Updated City' }); }); }); @@ -214,7 +224,9 @@ describe('CompanyResolver (e2e)', () => { id name domainName - address + address { + addressCity + } } } `, diff --git a/packages/twenty-zapier/src/test/creates/crud_record.test.ts b/packages/twenty-zapier/src/test/creates/crud_record.test.ts index f1c177233..eb763338b 100644 --- a/packages/twenty-zapier/src/test/creates/crud_record.test.ts +++ b/packages/twenty-zapier/src/test/creates/crud_record.test.ts @@ -14,7 +14,7 @@ describe('creates.create_company', () => { nameSingular: 'Company', crudZapierOperation: Operation.create, name: 'Company Name', - address: 'Company Address', + address: { addressCity: 'Paris' }, domainName: 'Company Domain Name', linkedinLink: { url: '/linkedin_url', label: 'Test linkedinUrl' }, xLink: { url: '/x_url', label: 'Test xUrl' }, diff --git a/packages/twenty-zapier/src/test/triggers/trigger_record.test.ts b/packages/twenty-zapier/src/test/triggers/trigger_record.test.ts index 962fe9111..9139629da 100644 --- a/packages/twenty-zapier/src/test/triggers/trigger_record.test.ts +++ b/packages/twenty-zapier/src/test/triggers/trigger_record.test.ts @@ -67,7 +67,7 @@ describe('triggers.trigger_record.created', () => { name: '', domainName: '', createdAt: '2023-10-19 10:10:12.490', - address: '', + address: { addressCity: null }, employees: null, linkedinUrl: null, xUrl: null, diff --git a/packages/twenty-zapier/src/test/utils/handleQueryParams.test.ts b/packages/twenty-zapier/src/test/utils/handleQueryParams.test.ts index c407c4a6c..872879900 100644 --- a/packages/twenty-zapier/src/test/utils/handleQueryParams.test.ts +++ b/packages/twenty-zapier/src/test/utils/handleQueryParams.test.ts @@ -10,7 +10,7 @@ describe('utils.handleQueryParams', () => { test('should format', () => { const inputData = { name: 'Company Name', - address: 'Company Address', + address: { addressCity: 'Paris' }, domainName: 'Company Domain Name', linkedinUrl__url: '/linkedin_url', linkedinUrl__label: 'Test linkedinUrl', @@ -23,7 +23,7 @@ describe('utils.handleQueryParams', () => { const result = handleQueryParams(inputData); const expectedResult = 'name: "Company Name", ' + - 'address: "Company Address", ' + + 'address: { addressCity: "Paris" }, ' + 'domainName: "Company Domain Name", ' + 'linkedinUrl: {url: "/linkedin_url", label: "Test linkedinUrl"}, ' + 'xUrl: {url: "/x_url", label: "Test xUrl"}, ' +