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.

Activity

  1. added
    enhancementNew feature or request
    pm:queueReady for the PM dispatch loop
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed on Aug 2, 2026
  2. self-assigned this
    on Aug 4, 2026
  3. os-zhuang commented on Aug 4, 2026

    @os-zhuang
    ContributorAuthor

    认领:PM 循环第 1 轮
    会话:session_01Rvtsew6XgsSjxVa59HRPRK
    分支:claude/issue-592-activity-model
    Worktree:hotcrm-issue-592
    文件面:src/objects/(新增 event 对象族 + index.ts barrel + task.hook.ts)、src/actions/、src/dashboards/、src/views/、src/translations/(越界即停,报告说明)

    范围裁定(PM):⛔ 本轮不碰 src/data/(演示种子不在验收标准内;若需要演示数据,由 PM 另立后续 issue)。attendees 的形态(junction 对象 vs user 多 lookup)按验收标准"可查询记录、非 JSON 字符串"由 dev 依平台既有模式定夺,PR 里写明理由即可。


    Generated by Claude Code

  4. os-zhuang commented on Aug 4, 2026

    @os-zhuang
    ContributorAuthor

    验收(PM 循环,会话 session_01Rvtsew6XgsSjxVa59HRPRK):ACCEPT,已经合并队列落地 —— PR #670(实现 + 第 1 轮返工,commit 486865f)。

    交付摘要:

    • crm_event + crm_event_attendee junction(参会人是带 response/is_organizer 的可查询记录,junction 选型理由在 PR 正文);
    • log_call / log_meeting / schedule_meeting 按对象 × 种类生成,覆盖 lead/contact/account/opportunity/case(15 个注册,绕开上游 Global (objectless) body actions are unreachable — runtime registers them under 'global' but the dispatcher only probes '<object>' and '*' #509);
    • 修复了「无生产者」缺陷:crm_account.last_activity_date 此前从未有有效写入者(冒泡不上行 + readonly 剥离静默丢写,#2948),现在冒泡向上走到客户且字段可写,有真实 ObjectQL 下的回归证明;
    • event_metrics 数据集 + Sales Activity 仪表盘(同时是 task_metrics 的第一个消费者);
    • 两轮 dogfood 浏览器验证:第一轮发现 schedule_meeting 的 datetime 参数在 UI 恒 400(平台缺陷,已上报 objectstack#5061),返工改为 date + time 参数并在 body 归一化为 UTC instant(带 #5061 回退信号测试 —— 平台修复落地时该用例转红即为回退提示);第二轮实测同一 POST 200、planned 事件落库、booking 不刷新 recency、三个记录头动作可达。

    后续项(均已立案,未派发 —— 循环按维护者指示暂停):#671(演示种子 + last_activity_date 分布)、#672(crm_event 用户文档 + 文档门禁建议)、#673(sys_activity.actor_name 裸 id)、objectstack#5061(上游 datetime 参数)。


    Generated by Claude Code

  5. added
    priority:p0Critical: blocker, must ship before MVP
    and removed on Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestpm:dispatchedDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch looppriority:p0Critical: blocker, must ship before MVP

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions