Skip to content

Activity model: first-class meetings/events + call logging on every sales object #592

Description

@os-zhuang

Batch-2 (business completeness) item from the 2026-08-02 review. This is the batch's most important item — it decides whether the CRM can answer "what happened with this customer, and when?"

Problems

  • No crm_event/meeting object: crm_task.type offers meeting (_picklists.ts:99) but there is no start/end time, no attendees, no location. log_meeting stuffs attendees into a sys_activity JSON metadata string — unqueryable, unreportable (src/actions/global.actions.ts:392).
  • log_call/log_meeting are scoped to crm_case only (workaround for upstream Global (objectless) body actions are unreachable — runtime registers them under 'global' but the dispatcher only probes '<object>' and '*' #509 — see the comment at global.actions.ts:255-262). A sales rep cannot log a call on a lead, contact, account, or opportunity.
  • crm_account.last_activity_date / crm_lead.last_contacted_date are written almost exclusively by task completion (task.hook.ts:211) — the at_risk_accounts view and customer_churn_signals report are built on a signal nothing real writes.
  • No activity metrics exist anywhere (calls per rep, meetings booked, activity per deal); task_metrics dataset exists but no widget uses it.

Scope

  1. New crm_event object: subject, start/end datetime, location, related-to lookups (same pattern as crm_task), owner; attendees as a crm_event_attendee junction (or platform user lookups — design open). Calendar view (platform view type exists).
  2. Per-object log_call / log_meeting actions on lead/contact/account/opportunity, replicating the case-scoped pattern (this sidesteps Global (objectless) body actions are unreachable — runtime registers them under 'global' but the dispatcher only probes '<object>' and '*' #509 without waiting for the platform).
  3. Every activity writer (call, meeting, email send, task completion, event) bumps last_activity_date on the related account and last_contacted_date on the related lead/contact.
  4. Activity widgets: activities this week by rep, activity-per-open-deal, accounts with no activity 30/60/90d — the churn story becomes real.

Acceptance

  • A rep can log a call on a lead and schedule a meeting on an opportunity from the UI.
  • at_risk_accounts and customer_churn_signals reflect genuine interaction recency.
  • Attendees are queryable records, not JSON strings.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestpm:dispatchedDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch loopprio:p0Blocking the current release goal — do first

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions