# `PhoenixKit.Migrations.Postgres.V138`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v2.13.7/lib/phoenix_kit/migrations/postgres/v138.ex#L1)

V138: CRM v1 — interaction tracker (contacts, companies, interactions).

Five tables for the `phoenix_kit_crm` plugin's first real data model: a
Contact (cloned in spirit from staff `Person`, but the user link is
**optional**), a Company, the contact↔company membership (carrying free-form
role + department on the edge), and the interaction log (entries + their
resolvable "involved parties" with an as-of-then profile snapshot).

## phoenix_kit_crm_contacts
A CRM contact (client/customer). Unlike staff `Person`, `user_uuid` is
**nullable** — most contacts never log in. A partial unique index keeps it
1:1 (one contact per user) only among the rows that *are* linked.

## phoenix_kit_crm_companies
A company/organization record (its own data; not a login user).

## phoenix_kit_crm_company_memberships
Contact↔company link, many-to-many, with free-form `role_in_company` and
`department` on the edge + an `is_primary` flag (drives the headline display
and the interaction snapshot).

## phoenix_kit_crm_interactions
A logged interaction ("client called, discussed X"): type, when, body,
the subject contact, and the staff user who logged it.

## phoenix_kit_crm_interaction_parties
Flat, resolvable "who was involved" list per interaction. `raw_name` is
always kept; `contact_uuid` / `staff_person_uuid` resolve to records when
matched (exclusive-arc: at most one set). `party_snapshot` freezes the
party's profile as it was at log time. `staff_person_uuid` is a **soft ref**
(no FK) so the optional staff module stays optional.

All operations are idempotent.

# `down`

Rolls V138 back by dropping the five CRM v1 tables in reverse dependency
order.

**Lossy rollback:** all contacts, companies, memberships, interactions, and
party rows are lost. Back up before rolling back in production.

# `up`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
