Files
upstream-mirror 93ecc1a6f8
Some checks failed
✅ Check / 🔬 ESLint (push) Failing after 21s
✅ Check / 🏷️ Typecheck (push) Failing after 11s
✅ Check / 🔎 Test (push) Failing after 11s
✅ Check / e2e-test (push) Failing after 11s
✅ Check / 🔨 Build (push) Failing after 11s
🚀 Deploy / 🚀 Deploy (doc) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (demo) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (supabase) (push) Failing after 18s
snapshot of https://github.com/marmelab/atomic-crm.git (main, 2026-09-18; blobs > 131072B omitted)
2026-09-18 01:48:50 +05:00

7.5 KiB

Deleting companies

A spine/link resource: it owns the companies table and is a company_id link on both contacts and deals, its companies_summary view aggregates nb_contacts/nb_deals, and it adds a denormalized company_name to the Contact type. So it fans out far wider than its folder (≈50 frontend files + backend).

Confirm cascade scope first

Remove company_id fully — drop the column from the Contact/Deal types, the CSV import/export, mergeContacts, the fakerest generators, and i18n. This full removal is what makes the deletion large.

Frontend specifics

  • Activity log — a dedicated company.created branch (delete ActivityLogCompanyCreated.tsx outright + the branch in ActivityLogIterator.tsx + COMPANY_CREATED in consts.ts/types.ts) and a "company" member in the context union. Narrowing the union turns the === "company" checks in ActivityLogContactCreated/ActivityLogContactNoteCreated/ActivityLogDealCreated/ActivityLogDealNoteCreated into type errors — prune those branches (the company_id "to/at <company>" ReferenceField + the CompanyAvatar in the deal-note header). ActivityLog.tsx has a companyId prop + company_id filter; providers/commons/activity.ts has a getNewCompanies fetcher + companyId param.
  • company_id link on contacts (ContactInputs selector, ContactShow/ContactListContent avatar+name, the exporter's fetchRelatedRecords + the company CSV column, contactModel.ts's vCard ORG: line, ExportVCardButton.tsx) and on deals (DealInputs required selector, DealCard/DealShow/DealEdit avatar, DealList filter), plus the note-header CompanyAvatar in notes/Note.tsx.
  • Denormalized company_name (from companies_summary's c.name as company_name) — read in ContactOption.tsx, deals/ContactList.tsx, dashboard/HotContacts.tsx, and the position_at_company rendering. Invisible to a \bcompan(y|ies)\b grep — grep company_name separately.
  • companySectors config prop — see SKILL.md "Shapes a resource takes" for the standard config-prop locations. Companies-specific: the <Card> holds only a companySectors ArrayInput (no validateItemsInUse), and it's also read in useImportFromJson.ts to validate an imported sector.
  • Providers — supabase getList/getOne route companies -> companies_summary (drop both); the contacts FTS list adds company_name. FakeRest has processCompanyLogo (favicon), fetchAndUpdateCompanyData (stamps company_name onto contacts, called from the contacts beforeCreate/beforeUpdate), updateCompany (maintains nb_contacts/nb_deals from the contacts/deals afterCreate/afterDelete), the whole companies callback block, the companies arm of the sales beforeDelete reassignment, and the getActivityLog(dataProvider, companyId, salesId) call (drop the companyId arg + the companyId/company_id filter plumbing in providers/commons/activity.ts). Delete providers/commons/getCompanyAvatar.ts + test.
  • FakeRest generators are deeply company-coupled — dataGenerator/companies.ts deleted outright + dropped from index.ts (mind the order: sales → tags → [companies] → contacts → …) and types.ts (Db.companies). contacts.ts picks a company to derive company_id/company_name/sales_id/first_seen (+ a per-company maxContacts cap), and deals.ts picks a company then filters contacts by company_id for contact_ids — rewrite both to pick a random db.sales + randomDate() (and random contacts for deals). The faker company namespace import is unrelated — keep it.
  • JSON importer treats companies as a top-level type (importCompany, $.companies.*, CompanyImport/isCompany, mapSizeToCategory, companySectors validation, stats/idsMaps keys) + the company_id mapping on imported contacts. Mirror in ImportPage.tsx + import-sample.json. CSV importer (useContactImport.tsx) has a getCompanies cache + a company column → company_id.
  • Mislabeled i18n: deals/OnlyMineInput.tsx uses resources.companies.filters.only_mine ("Only companies I manage") even though it filters deals — re-point it to a deals key, don't delete the input.

Backend

  • Drop the companies table + companies_id_seq grant + RLS-enable line + its 4 policies + table grants. Drop company_id on both contacts and deals (FKs contacts_company_id_fkey/deals_company_id_fkey + indexes contacts_company_id_idx/deals_company_id_idx). Drop the companies_summary view (+ grant). Update contacts_summary: drop co.company_id, the c.name as company_name column, the left join public.companies, and narrow the group by to co.id.
  • activity_log view carries the company pattern (a company column on every branch and a dedicated company.created branch) — remove the company + company_id columns from all branches (the contactNote/dealNote branches only joined a table to fetch company_id, so drop those now-unused joins) and delete the branch.
  • Drop the company-only function handle_company_saved (favicon-from-website trigger) + its company_saved trigger + grant, and the set_company_sales_id_trigger. Drop the company_id line from merge_contacts. Orphan subtlety: handle_company_saved calls get_domain_favicon, but so does get_avatar_for_email (contact avatars) — so it is not orphaned; keep get_domain_favicon and the favicons_excluded_domains table.
  • Edge functions: unlike contacts (delete the whole function), keep postmark/ and surgically remove the company bits — it auto-creates a company from the sender's email domain (getOrCreateCompanyFromDomain in addNoteToContact.ts, extractCompanyName in extractMailContactData.ts) and links the new contact via company_id. Delete getOrCreateCompanyFromDomain, drop the domain/companyName/website params threaded through getOrCreateContactFromEmailInfo/addNoteToContact/index.ts, drop company_id from the contact insert, remove extractCompanyName + the companyName/website output fields + the now-unused tldts import from extractMailContactData.ts, and update the postmark tests (addNoteToContact.test.ts, extractMailContactData.test.ts). Flag that auto-company-creation on inbound email is gone but contact+note creation still works. Elsewhere: _shared/db.ts declares company_id on both ContactsTable and DealsTable (no dedicated CompaniesTable); merge_contacts/index.ts merges company_id in mergeContactData; mcp/index.ts + mcp/validateSql.test.ts mention companies/companies_summary in prompt examples/fixtures (swap for a surviving table). No config.toml block changes are needed (postmark + merge_contacts both survive).

grep — benign matches to leave

  • The faker company namespace import in dataGenerator/contacts.ts (used for bsAdjective() titles), the reference="companies"/source="company_id" JSDoc examples in the mutable admin/reference-input.tsx/admin/list.tsx, and email-domain fixtures like @company.com/original.recipient@company.com in test bodies.
  • Dead i18n keys (resources.companies.*, position_at_company, you_added_company/at_company, crm.settings.companies.*) — flag, don't force (both catalogs or neither). test-data/contacts.csv keeps company_id/company_name/company columns — the importer ignores them, so leaving them is harmless; dropping means editing the header and all ~500 rows — flag it.