feat(contacts): reject duplicate company names per tenant #296
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/PMS-400-reject-duplicate-company-names"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Companies had no uniqueness on name within a tenant: the only indexes were the non-unique idx_companies_name and a trigram index, and ContactService::create_company / update_company performed no existence check. Two companies with the identical name could coexist in one tenant, producing ambiguous pickers and confusing list/search results.
Enforce tenant-scoped, case-insensitive, trimmed name uniqueness in two layers. ContactService::create_company runs SELECT EXISTS on lower(btrim(name)) inside its transaction before the INSERT and returns AppError::Conflict on a hit; update_company runs the same check (excluding the company's own id) only when the request sets a name, so re-saving an unchanged name still succeeds. Migration 054 adds the matching UNIQUE INDEX on (tenant_id, lower(btrim(name))) as the concurrency-safe backstop, and both mutations map a 23505 violation on that index to the same friendly 409 instead of a 500.
Contacts are intentionally out of scope: a real company routinely has multiple contacts sharing a name, so contact-name uniqueness is not a valid invariant. PMS-325 field validation is untouched.
#PMS-400
159ce14d0611fafc0dfd