41d5d80a65
# Migrate Company and Person standard fields in preparation for the
enrichment app
## Why
Our standard `Person`/`Company` objects accumulated fields that aren't
generic to every
business, while missing a more universal revenue field that essentially
every CRM ships.
This PR makes the **Standard application** hold a tighter, more
universal set of fields,
and sets the stage for a follow-up PR that introduces a **People Data
Labs enrichment app**
to populate them.
## What changes
### Standard fields
**Demoted (Standard → Workspace Custom application)** — not generic
enough to ship as standard:
| Object | Field | Type |
| ------- | ------------------------------ | -------- |
| Company | annualRecurringRevenue (ARR) | CURRENCY |
| Company | employees | NUMBER |
| Company | idealCustomerProfile (ICP) | BOOLEAN |
| Company | xLink (X/Twitter) | LINKS |
| Person | xLink (X/Twitter) | LINKS |
| Person | city | TEXT |
**Added (new generic Standard field)** — present in
Salesforce/HubSpot/Zoho, PDL-populatable:
| Object | Field | Type |
| ------- | ------------- |
-------------------------------------------------------- |
| Company | annualRevenue | CURRENCY (generic total revenue; replaces
the niche ARR) |
### Behavior by workspace
* **New workspaces:** demoted fields are gone; `annualRevenue` is
**active**.
* **Existing workspaces:** demoted fields are **preserved as active
custom fields, data intact**;
`annualRevenue` is created **inactive (opt-in)** with its column ready,
so a later activation
is a metadata-only toggle.
### Upgrade commands (v2.9)
Three idempotent, per-workspace commands, run in timestamp order:
1. **`upgrade:2-9:move-demoted-standard-fields-to-custom-application`**
(1799000040000) —
re-owns the 6 demoted fields to the workspace custom application
(`isCustom = true`,
new `applicationId` + fresh `universalIdentifier`), keeping their data
and active state.
2. **`upgrade:2-9:rename-conflicting-custom-fields`** (1799000045000) —
if a workspace already
has a *custom* field named `annualRevenue`, renames it to
`annualRevenueCustom`
(data preserved via column rename) so the standard field can be added.
Skips non-custom matches.
3. **`upgrade:2-9:add-inactive-generic-standard-fields`**
(1799000050000) — creates
`Company.annualRevenue` on existing workspaces as inactive, guarded to
skip workspaces
missing the target object or where the name is still taken.
**Failure model:** the workspace iterator isolates failures per
workspace (one workspace failing
never affects others); within a workspace the runner records per-command
status and resumes on the
next run, and every command is idempotent, so partial runs self-heal.
### Supporting changes
* **Field-option color palette:** widened the `TagColor` union
(`twenty-shared` `FieldMetadataOptions`
+ the field-metadata `options.input` DTO) from 10 colors to the full
theme palette, benefiting any
future SELECT/MULTI_SELECT field.
* **Dev seeder:**
* The default "Annual Recurring Revenue" dashboard widget now points at
the generic
`annualRevenue` field (renamed to "Annual Revenue").
* Removed the "Companies by Size (Stacked by City)" widget (relied on
the demoted `employees`).
* `employees` is dropped from company data seeds and re-added as a
**custom** field seed, so dev
workspaces still get an `employees` column matching the demoted
behavior.
### Cleanup
Front-end record types (`Company.ts`/`Person.ts`), the
`getDisplayNameFromParticipant` test mock,
metadata integration specs, the Zapier `crud_record` test, and the
regenerated
`get-standard-object-metadata-related-entity-ids` snapshot.
## ⚠️ Breaking change (intentional)
Removes standard fields `Company.annualRecurringRevenue`,
`Company.employees`,
`Company.idealCustomerProfile`, `Company.xLink`, `Person.xLink`, and
`Person.city` from the core
GraphQL schema (replaced by `Company.annualRevenue`).
This is why the breaking-changes check reports a large number of
removals — `graphql-inspector`
flags any removed object field plus its derived
aggregate/order-by/filter/update types.
**Mitigation:** the
`upgrade:2-9:move-demoted-standard-fields-to-custom-application` command
re-owns these fields as custom fields per workspace, preserving their
name and data, so existing
tenants keep working. New workspaces won't have them.
91 lines
1.3 KiB
TypeScript
91 lines
1.3 KiB
TypeScript
export const TOO_MANY_RELATION_QUERY_GQL_FIELDS = `
|
|
id
|
|
jobTitle
|
|
avatarUrl
|
|
intro
|
|
searchVector
|
|
pointOfContactForOpportunities {
|
|
edges {
|
|
node {
|
|
id
|
|
company {
|
|
id
|
|
}
|
|
}
|
|
}
|
|
}
|
|
noteTargets {
|
|
edges {
|
|
node {
|
|
id
|
|
targetCompany {
|
|
id
|
|
}
|
|
note {
|
|
id
|
|
}
|
|
targetPerson {
|
|
id
|
|
company {
|
|
id
|
|
}
|
|
}
|
|
targetCompany {
|
|
id
|
|
}
|
|
targetOpportunity {
|
|
id
|
|
}
|
|
}
|
|
}
|
|
}
|
|
taskTargets {
|
|
edges {
|
|
node {
|
|
id
|
|
targetCompany {
|
|
id
|
|
}
|
|
targetPerson {
|
|
id
|
|
company {
|
|
id
|
|
}
|
|
}
|
|
targetCompany {
|
|
id
|
|
}
|
|
targetOpportunity {
|
|
id
|
|
}
|
|
}
|
|
}
|
|
}
|
|
company {
|
|
id
|
|
people {
|
|
edges {
|
|
node {
|
|
id
|
|
company {
|
|
id
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
attachments {
|
|
edges {
|
|
node {
|
|
id
|
|
person {
|
|
id
|
|
company {
|
|
id
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`;
|