Modules
CRM module for PhoenixKit.
Thin wrapper around PhoenixKit.Activity.log/1 so callers don't need to
duplicate the Code.ensure_loaded?/1 guard and rescue clause everywhere.
Safe to call from any LiveView — never crashes the caller.
Maps CRM activity action strings (e.g. "crm.interaction_logged") to a
{heroicon, human_label} pair plus an optional secondary detail/2 line, for
the contact/company Events tab. Domain labels go through
PhoenixKitCRM.Gettext. Unknown actions fall back to a humanized form of the
action string, so a newly-added action still renders without a change here.
Folder-scoped media attachments for a CRM contact, backed by core
PhoenixKit.Modules.Storage (the same per-resource-folder convention
phoenix_kit_staff/phoenix_kit_catalogue use — no module-owned table, no
migration).
Per-scope column configuration for CRM tables and card views.
Context for CRM companies — CRUD, soft-delete, and search (for the contact form's company picker).
Context for CRM contacts — CRUD, soft-delete, the (v1 single) company membership, and the optional login-user connection.
Gettext backend for phoenix_kit_crm.
Context for CRM interactions — the History/Interactions tab.
Context for CRM contact lists (PhoenixKitCRM.Schemas.ContactList) and
their memberships (PhoenixKitCRM.Schemas.ListMember).
Pure-ish CSV/plaintext import engine for CRM contact lists (Stage 3 of the
restructuring plan — the user's stated priority: account list import).
Parses rows, applies the restructuring spec's Locked decisions, and writes
only through PhoenixKitCRM.Lists — it never duplicates that context's
insert/counter/broadcast logic.
Result of an import run (PhoenixKitCRM.Lists.Import).
Context for CRM party roles — marks an existing company or contact as a
supplier, client, or partner (see PhoenixKitCRM.Schemas.PartyRole).
Centralized path helpers for the CRM module. All paths go through
PhoenixKit.Utils.Routes.path/1 for prefix/locale handling.
Real-time updates for CRM interactions, backed by PhoenixKit.PubSub.Manager.
Schema for CRM role settings.
Context for managing which roles have CRM access enabled.
Route definitions for the CRM module.
A CRM company / organization record. A first-class record (its own data),
NOT a login user. Contacts link to it via CompanyMembership.
The contact ↔ company link (many-to-many), carrying free-form
role_in_company and department on the edge, plus an is_primary flag.
A CRM contact (client / customer / prospect).
A named, sluggable CRM contact list (PhoenixKitCRM.Lists).
A logged interaction ("client called, we discussed X") — the core of the
CRM v1 interaction tracker. A structured log entry (type + when + body),
anchored to a subject Contact, with N resolvable involved parties.
An "involved party" on an interaction — a flat, resolvable mention.
The list ↔ contact join (PhoenixKitCRM.Lists), carrying a denormalized
email snapshot taken at add-time and its own status/source.
A commercial party role — marks an existing CRM company or contact as a
supplier, client, or partner (Odoo's supplier_rank/customer_rank,
SAP's Business-Partner roles, expressed as rows). One party can hold
several roles at once (a company that's both supplier and client has two
rows).
Shared LIKE/ILIKE search-term escaping for contexts that filter by a
free-text search box (Contacts, Companies, PartyRoles, Lists).
Registers CRM role subtabs into PhoenixKit.Dashboard.Registry under the
namespace :phoenix_kit_crm_roles.
Status-column soft-delete shared by Contacts and Companies.
Optional, soft integration with phoenix_kit_staff. Everything here is
guarded — the CRM module works whether or not the staff module is present
or enabled. Used by the interaction "involved parties" picker (a staff
person can be selected) and by the party snapshot.
Context for managing per-user CRM view configuration.
Schema for per-user, per-scope CRM view configuration.
Main admin LiveView for the CRM module — empty placeholder page.
Shared formatters for CRM table/card cells.
use macro that injects column-management handle_event/3 callbacks into
a CRM LiveView. The host LV must
Function component that renders the "Customize columns" modal used by both
RoleView and OrganizationsView. UX mirrors PhoenixKit.Users table column
picker: drag-to-reorder selected columns on the left, click-to-add available
columns on the right.
Admin list of CRM companies.
New / edit form for a CRM company.
The Interactions tab of a CRM company — a read-only, aggregated feed of every interaction logged on the company's member contacts. Each entry links to the contact it's about (and shows the interaction's parties + attachments), so you can jump to that person. Interactions are still logged on a contact's page; this is a company-wide rollup.
Show page for a CRM company. Tabs: Overview (details + contacts), Interactions (a read-only rollup of interactions logged on the company's contacts), and Events always; Files + Images when core Storage is enabled; Comments when the comments module is enabled. The header shows a circular logo (icon fallback).
CRM comparison ("сличение") screen — two independent, read-only reports, no auto-actions
New / edit form for a CRM contact: the profile fields, a single company block (company + free-form role + department), and the optional "allow login" checkbox (staff-style find-or-create user link).
Show page for a CRM contact. Tabs: Overview, Interactions, Events always; Files + Images when core Storage is enabled; Comments when the comments module is enabled. The header shows a circular avatar (initials fallback).
Admin list of CRM contacts.
The Events tab for a CRM record — a read-only, paginated feed of the
PhoenixKit.Activity entries scoped to it (resource_type + resource_uuid).
Parameterized by :resource_type ("crm_contact" / "crm_company") and
:resource_uuid, so it serves both the contact and company profiles.
Shared render helpers for interaction timelines (contact + company feeds): the involved-party badge and its frozen-snapshot detail/title. A party that resolved to a CRM contact or a staff person links to that page; free-text parties render as a plain badge.
The Interactions / History tab for a contact: a reverse-chronological feed of interactions involving the contact, plus a composer to log a new one with a free-form-but-resolvable "involved parties" picker (CRM contacts + staff).
New / edit form for a CRM contact list.
Import page for a single CRM contact list — paste-text or file (CSV/TXT)
upload, a dry-run preview (no writes), then a chunked real run with
progress so a large file doesn't block the LiveView process for minutes,
finishing with the full ImportReport broken out by skip reason.
Admin page for a single CRM contact list's memberships — paginated member table (status/source/email, remove action) plus a manual add-by-email form.
Admin list of CRM contact lists (card/table toggle view).
The Files and Images tabs for a CRM record (a contact or a company),
parameterized by :resource_type (:contact | :company), the :resource
struct, and :kind (:files | :images). Media is folder-scoped via core
PhoenixKit.Modules.Storage (see PhoenixKitCRM.Attachments): a
crm-<resource>-<uuid> root folder for :files, a nested Images subfolder
for :images.
Admin LiveView for the CRM Organizations subtab — lists users whose
account_type = "organization" with per-user persisted column
configuration. Supports a card/table view toggle (provided by
PhoenixKitWeb.Components.Core.TableDefault).
Shared helpers for the commercial party-role UI (badges on the list pages, the Roles checkbox section on the company/contact forms).
Admin LiveView for a single CRM role page — lists users assigned to the role
with per-user persisted column configuration. Supports a card/table view
toggle (provided by PhoenixKitWeb.Components.Core.TableDefault).
CRM settings page — exposes the enable/disable toggle and role opt-in.
Mix Tasks
Imports catalogue suppliers into CRM companies and grants them the supplier
role. This is a one-time backfill task following the SAP-CVI pattern.