* Seed sample corporate hierarchy data for testing the hierarchy UI. * Creates a holding company (Omnicom Group) with subsidiaries connected * via the brand registry's house_domain field.
(orgDb: OrganizationDatabase)
| 142 | * via the brand registry's house_domain field. |
| 143 | */ |
| 144 | async function seedDevHierarchyData(orgDb: OrganizationDatabase): Promise<void> { |
| 145 | const pool = getPool(); |
| 146 | |
| 147 | // Holding company + subsidiaries |
| 148 | const hierarchyOrgs = [ |
| 149 | { id: 'org_dev_omnicom_parent', name: 'Omnicom Group', domain: 'omc.com', company_type: 'brand' as const }, |
| 150 | { id: 'org_dev_omnicom_ddb', name: 'DDB Worldwide', domain: 'ddb.com', company_type: 'agency' as const }, |
| 151 | { id: 'org_dev_omnicom_bbdo', name: 'BBDO', domain: 'bbdo.com', company_type: 'agency' as const }, |
| 152 | { id: 'org_dev_omnicom_assembly', name: 'Assembly (Omnicom)', domain: 'assemblymarketing.com', company_type: 'agency' as const }, |
| 153 | { id: 'org_dev_omnicom_hearts', name: 'Hearts & Science', domain: 'hearts-science.com', company_type: 'agency' as const }, |
| 154 | // Standalone org for merge testing |
| 155 | { id: 'org_dev_omnicom_dupe', name: 'Omnicom', domain: 'omnicomgroup.com', company_type: 'brand' as const }, |
| 156 | // Second holding company |
| 157 | { id: 'org_dev_ipg_parent', name: 'Interpublic Group (IPG)', domain: 'interpublic.com', company_type: 'brand' as const }, |
| 158 | { id: 'org_dev_ipg_mediabrands', name: 'IPG Mediabrands', domain: 'ipgmediabrands.com', company_type: 'agency' as const }, |
| 159 | { id: 'org_dev_ipg_um', name: 'UM Worldwide', domain: 'umww.com', company_type: 'agency' as const }, |
| 160 | ]; |
| 161 | |
| 162 | for (const org of hierarchyOrgs) { |
| 163 | try { |
| 164 | const existing = await orgDb.getOrganization(org.id); |
| 165 | if (!existing) { |
| 166 | await orgDb.createOrganization({ |
| 167 | workos_organization_id: org.id, |
| 168 | name: org.name, |
| 169 | is_personal: false, |
| 170 | company_type: org.company_type, |
| 171 | }); |
| 172 | // Set email_domain so hierarchy JOINs work |
| 173 | await pool.query( |
| 174 | `UPDATE organizations SET email_domain = $1 WHERE workos_organization_id = $2`, |
| 175 | [org.domain, org.id] |
| 176 | ); |
| 177 | logger.info({ orgId: org.id, name: org.name }, 'Created hierarchy test org'); |
| 178 | } |
| 179 | } catch (error) { |
| 180 | if (error instanceof Error && error.message.includes('duplicate key')) { |
| 181 | logger.debug({ orgId: org.id }, 'Hierarchy org already exists'); |
| 182 | } else { |
| 183 | logger.error({ err: error, orgId: org.id }, 'Failed to seed hierarchy org'); |
| 184 | } |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | // Brand registry entries connecting subsidiaries to parent via house_domain |
| 189 | const brandEntries = [ |
| 190 | // Parent brands (no house_domain = top-level) |
| 191 | { domain: 'omc.com', brand_name: 'Omnicom Group', house_domain: null, keller_type: 'master' }, |
| 192 | { domain: 'interpublic.com', brand_name: 'Interpublic Group', house_domain: null, keller_type: 'master' }, |
| 193 | // Omnicom subsidiaries → omc.com |
| 194 | { domain: 'ddb.com', brand_name: 'DDB Worldwide', house_domain: 'omc.com', keller_type: 'endorsed' }, |
| 195 | { domain: 'bbdo.com', brand_name: 'BBDO', house_domain: 'omc.com', keller_type: 'endorsed' }, |
| 196 | { domain: 'assemblymarketing.com', brand_name: 'Assembly', house_domain: 'omc.com', keller_type: 'sub-brand' }, |
| 197 | { domain: 'hearts-science.com', brand_name: 'Hearts & Science', house_domain: 'omc.com', keller_type: 'sub-brand' }, |
| 198 | // Duplicate Omnicom domain → also points to omc.com |
| 199 | { domain: 'omnicomgroup.com', brand_name: 'Omnicom Group', house_domain: 'omc.com', keller_type: 'endorsed' }, |
| 200 | // IPG subsidiaries → interpublic.com |
| 201 | { domain: 'ipgmediabrands.com', brand_name: 'IPG Mediabrands', house_domain: 'interpublic.com', keller_type: 'sub-brand' }, |
no test coverage detected