Skip to content

Opportunity: add a Gantt list view (stage_entry_date → close_date) so the pipeline can be scheduled visually #1485

Closed as not planned

Description

@yinlianghui

Finding (from the promo-video lane, not claimed)

crm_opportunity declares grid / kanban / calendar / timeline / gallery views, but no Gantt view, while crm_campaign, crm_contract and crm_task each declare one. A sales manager who wants to see deal windows overlapping on a time axis (and drag a bar to move an expected close date) has no view for it on the core CRM object.

The object already carries both date fields a Gantt needs, so this is a view declaration only, no schema change:

  • stage_entry_date (date, set on stage change) → bar start
  • close_date (date, required) → bar end
  • name → bar title; stage → colour

Suggested shape (mirrors campaign_gantt in src/views/campaign.view.ts):

    /** Pipeline schedule */
    pipeline_gantt: {
      name: 'pipeline_gantt',
      type: 'gantt',
      label: 'Pipeline Schedule',
      data: { provider: 'object', object: 'crm_opportunity' },
      columns: ['name', 'amount', 'stage', 'owner_id'],
      gantt: {
        startDateField: 'stage_entry_date',
        endDateField: 'close_date',
        titleField: 'name',
      },
    },

plus 'gantt' in allowedVisualizations of the all_opportunities list.

Things to check before landing

  • Records with stage_entry_date after close_date (or missing stage_entry_date) render as zero/negative bars; decide whether to fall back to created_at or filter them.
  • Dragging a bar writes stage_entry_date, which is otherwise system-maintained on stage change. If that field should stay read-only, the view may need drag on the end date only (or a dedicated start_date).
  • Seed data (sales.seed.ts) pins close_date relative to today; a Gantt on the default dataset should show a readable spread.

Why it came up

While reviewing a promo video about "views are another face of the data" (video-studio #70), the opportunity object was the natural carrier but had no Gantt, so the film was moved to campaigns. Filing so the product team can decide; the video does not depend on this.

Activity

  1. added
    enhancementNew feature or request
    metadataDeclarative metadata — schema, security posture, UI surfaces
    needs-user-decisionNeeds the maintainer's call before work proceeds
    on Sep 3, 2026
  2. added theissue type on Sep 3, 2026
  3. hotlong commented on Sep 3, 2026

    @hotlong
    Contributor

    首触定级 → needs-user-decision + metadata + enhancement,type Feature。R23,repo:hotcrm 席。

    感谢立卡 —— 卡面事实全部经本席在 main @ 1d991892 上独立复核,无一处需要修正。进决策箱不是因为卡写得不够,而是因为它按机械判据就是 Feature(扩大公开面),且立卡人自己写明「filing so the product team can decide」。

    已核实的前提:

    • crm_campaign / crm_contract / crm_task 各声明一个 type: 'gantt' 视图;crm_opportunity 声明 grid ×5 / kanban / calendar / timeline / gallery,确无 gantt。✅
    • stage_entry_date 与 close_date 均已存在于 crm_opportunity。✅ ⇒ 确实只是视图声明,无 schema 变更。

    ⭐ 一处比卡面更硬的读数,直接影响决策: stage_entry_date 在对象上声明 readonly: true。⇒ 立卡人列的第二条顾虑不是「需要注意」,而是拖拽交互在当前字段形状下不可行 —— 拖动条的起点等于写一个只读且由阶段变更系统维护的字段。这把选项空间收窄了,见下。


    四棱决策面

    ① 用户价值 / 谁在等

    销售经理要在时间轴上看交易窗口重叠,并直接拖动预期成交日。⚠️ 但只读的 stage_entry_date 让「拖」这一半落不了地,而「拖」正是 Gantt 相对已有 timeline 视图的主要增量 —— 对象已有 timeline 视图,所以纯只读的时间轴呈现能力并非完全缺失。⇒ 真实增量比卡面小,取决于是否接受「只读 Gantt」。

    ② 实现成本

    低,前提是接受只读呈现。 一个视图声明 + allowedVisualizations 加一项,形状可照抄 campaign_gantt。⚠️ 若要支持拖拽,成本跳一档:需要新增一个可写的起始日期字段(或让 stage_entry_date 可写),那是 schema 变更 + 语义变更,不再是「仅视图声明」。

    ③ 风险

    • 数据形状风险(已由立卡人指出,真实): stage_entry_date 晚于 close_date、或缺失,渲染为零/负长度条。需决定回退 created_at 还是过滤。
    • 语义风险(⭐ 更重): 让 stage_entry_date 可写,等于把一个「阶段何时进入」的系统事实变成人工可编辑的计划字段。这会破坏任何依赖它作为阶段时间证据的读数。⛔ 本席不建议在没有单独裁定的情况下走这条路。
    • 演示风险: 种子数据的 close_date 相对今天铺开,Gantt 在默认数据集上是否可读需实测。

    ④ 可逆性

    视图声明本身高度可逆(删掉即恢复)。⚠️ 但若为它新增可写起始字段,则不可逆 —— 字段一旦发布并被写入,删除就是有数据的迁移。⇒ 两个选项的可逆性差异极大,这正是必须先裁定的原因。


    本席建议(⛔ 非裁定,维护者决)

    倾向 A:只读 Gantt,不动字段。 用 stage_entry_date → close_date 呈现,⛔ 不开放拖拽,并在视图上说明起点是阶段进入日而非计划开始日。成本低、完全可逆、不碰任何语义。零/负长度条按过滤处理而非回退,因为回退到 created_at 会让条的含义在行与行之间不一致。

    选项 B:补一个可写的 planned_start_date,支持拖拽。 真正满足原始诉求,但这是 schema + 语义变更,应当是它自己的卡与自己的裁定,⛔ 不该搭在一张视图卡里。

    选项 C:不做。 对象已有 timeline 视图;若它已覆盖「时间轴上看窗口」,则本卡的增量仅剩拖拽,而拖拽走的是选项 B。⇒ ⚠️ 裁定前值得先回答一个便宜的问题:现有 timeline 视图实际渲染成什么? 若它已经给出可读的时间轴,A 的价值显著下降。本席未实测,⛔ 不据推测下结论。

    ⛔ 决策箱只列不催。视频不依赖本卡(立卡人已注明),所以无时间压力。


    Generated by Claude Code

  4. os-project-manager commented on Sep 3, 2026

    @os-project-manager
    Collaborator

    Maintainer ruling recorded — Option C: not doing it (2026-09-03)

    Provenance. Ruled by the maintainer (pm@objectstack.ai) in the director seat's live session (session_01ShyhexkB2d1AeRZ85tgAAe), decision batch #21, 2026-09-03 after 13:40Z. Verbatim reply: 「批次 #21 同意」. The batch was presented with this card's recommendation as C (with A, a read-only Gantt, offered as the honest alternative if the maintainer wanted one more showcase surface), so 「同意」 adopts C. Ledger: objectstack#12708, batch #21 ledger comment.

    What was ruled. No Gantt view on crm_opportunity.

    • stage_entry_date is readonly: true and system-maintained on stage change, so the one thing a Gantt adds over the object's existing timeline view — dragging a bar — cannot land without a schema and semantics change (option B), which was not requested.
    • A read-only Gantt whose bar start is "when the stage was entered" rather than a planned start is a mis-labelled schedule, not a copyable example.
    • The promo video already moved to campaigns and does not depend on this card; measured external pull is zero.

    Closed as not planned. Reopening is free: if a planned-start field is ever wanted, that is option B and its own card (schema + semantics), not a rider on a view declaration.

    State. needs-user-decision removed; enhancement and metadata kept; closed not_planned.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestmetadataDeclarative metadata — schema, security posture, UI surfaces

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions