Skip to content

feat(analytics): dashboards state their base; one money, quantity and date format (#2370) - #2379

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-es8o0t
Oct 29, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-es8o0t

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Irene · project thread

Fixes #2370

维护者速读

  1. 10 行里 8 行在本仓修好,第 10 行(NeedsAnalysis)已经是对的(图上是两行的 "Needs Analysis"),第 5 行只能说明何时有数(forecast_snapshot 与启动重播种的互动:每次 dev 重启后,当季出现一条无 owner 的幻影快照行与 owner 键控行并存 #702 禁止种子开当季预测)。
  2. 两个 SLA 磁贴写明基数:Open Cases Past SLA 只数未结工单,SLA Met (Closed Cases) 只算已结案;SLA 报表改名 SLA on Closed Cases。
  3. Revenue Trend 只留在 Executive Overview;Top Products 改名 List Price by Category(对公式字段 total_price 求和会被 DATASET_INVALID 拒绝,实测)。
  4. Opportunity Funnel by Owner 改成矩阵:每个负责人一行、每个阶段一列、带 Total,图按负责人画。
  5. 侧边栏条目名 = 报表标题,四种语言都一致,有测试;Sales Home 金额整数显示,数量整数(小数被拒),报价和价格表日期带年份。
  6. 平台侧 4 项未在本仓绕过:指标磁贴显示度量名不显示描述、公式 returnType: 'currency' 不显示货币、百分比字段的进度条、报表图不能按维度分系列。

What changes

Dashboards (rows 1–6)

  • service.dashboard.ts: sla_violations is Open Cases Past SLA and counts open cases only (status $nin [resolved, closed] AND (flagged OR past due)). A case closed late leaves the count when it closes. The gauge is SLA Met (Closed Cases). case.report.ts: sla_performance is SLA on Closed Cases, and its chart is SLA Violation Rate by Priority.
  • crm.dashboard.ts, sales.dashboard.ts: the two copies of the 12‑month revenue trend are removed. Executive Overview's Revenue Trend is the one home. The rows are reflowed, and Why We Lose now sits beside Lead Source.
  • crm.dashboard.ts: top_products is List Price by Category, described as "Catalog list prices summed per product category, not sales". Summing sold line items is refused on 18.2.0: a dataset sum over the formula total_price answers DATASET_INVALID.
  • opportunity.report.ts: Opportunity Funnel by Owner is type: 'matrix' with rows: ['owner'], columns: ['stage'], and a per-owner Total. Its chart is a horizontal bar of amount by owner.
  • sales.dashboard.ts: the Quota Attainment by Rep description says when it fills: after the nightly forecast snapshot opens the quarter and a manager sets each quota. The snapshot flow is unchanged.
  • Nav labels equal report labels in en and in the zh‑CN, ja‑JP and es‑ES packs (crm.app.ts, service/index.ts, translations/*/app.ts): Pipeline Coverage by Quarter, Opportunity Funnel by Owner, Lead Engagement by Month, Accounts by Industry and Type, SLA on Closed Cases, Cases Opened by Day.

Formats (rows 7–10)

  • home.page.ts: the two amount object-metrics carry format: '0,0', so Sales Home reads $1,290,000 like the dashboards instead of $1,290,000.00.
  • Opportunity and quote line items: quantity is scale: 0, so it reads 4 and a fractional quantity is refused. total_price and subtotal declare returnType: 'currency'. The quote line related list shows discount instead of a second subtotal column.
  • quote.object.ts (quote_date, expiration_date) and price_book.object.ts (valid_from, valid_to) use format: 'short', so they always show the year and are never relative: Nov 27, '26, where the list used to show Nov 27.
  • New docs/developers/number-formats.md, linked from docs/README.md: the convention, plus where the tenant currency is set (Setup → Settings → Localization → Default currency). The currency symbol comes from that setting. Measured: Executive Overview reads 1,290,000 without it and $1,290,000 with it.

Docs: dashboards, reports, quick tour, analytics index, pipeline management, cases, SLA & escalation, service and marketing index pages, in en, zh‑Hans and zh‑Hant, plus src/docs/crm_analytics_metrics(.zh).md. The dashboards page's "No tile shows a trend arrow" section was stale on main since #2296. It now lists the tiles that declare compareTo.

Tests

  • test/app-navigation-shape.test.ts: new test, "each entry is labelled with its report's own name, in every locale". Ablation: setting the zh‑CN nav_report_pipeline_coverage back to 管道覆盖率 turns it red (zh-CN nav_report_pipeline_coverage: "管道覆盖率" vs report "季度管道覆盖率").
  • test/line-item-conventions.test.ts: new test for both line kinds. A rep's quantity: 2.5 rejects with code: 'VALIDATION_FAILED' on field quantity, and 4 is stored as 4. Ablation: with scale: 2 restored, both cases go red with "promise resolved … instead of rejecting".
  • test/case-sla-breach-on-close.test.ts: the tile no longer counts late closes (0), and the tile filter is pinned against the sweep's predicate.
  • test/pipeline-by-stage-chart.test.ts: the funnel matrix and owner chart.
  • Doc pins updated: docs-service-index-analytics (labels, and SLA Performance is now refused outright), docs-quick-tour-navigation (CRM Overview has no close_date dimension now), docs-analytics-vocabulary, case-creation-date, seed-sla-share.

Acceptance notes

Row Verdict Evidence
1 SLA tiles state their base fixed titles and descriptions; tile filter is open-only (test)
2 Revenue Trend ×3, KPI caption trend fixed; caption platform one home on Executive Overview; a metric tile prints the measure label, not description (18.2.0)
3 Top Products reads as revenue fixed (renamed) sold-amount sum refused: DATASET_INVALID over formula total_price
4 Funnel not split by owner fixed within 18.2.0 matrix with a row and a Total per owner; a stacked by-stage series is platform
5 Quota attainment empty explained description says when it fills; #702 forbids seeding a current-quarter forecast
6 Nav vs report titles fixed equal in 4 locales, test + ablation
7 Currency / decimals on KPIs fixed $1,290,000 on Sales Home; currency is the tenant setting
8 Quantity / money on lines quantity fixed; formula face platform whole numbers (4), where scale 2 showed 1.00; returnType: 'currency' still renders 24,000 (18.2.0)
9 Discount bar, dates dates fixed; bar platform Nov 27, '26; Field.percent draws a progress bar, no key turns it off
10 NeedsAnalysis axis already correct the axis draws "Needs Analysis" on two lines; the run-on word is two SVG tspans read as innerText

Before/after screenshots for sales.manager, service.manager and admin, in en and zh‑CN, are attached in the project thread.

Verification

  • pnpm verify on 31bc156: validate, typecheck, lint, hygiene, token ratchet, build, and test all green. Result: Test Files 252 passed (252), Tests 4854 passed | 1 skipped (4855).
  • ffcec3d is docs and a comment only. After it, test/docs-dashboard-tiles passed (11/11), and pnpm hygiene and pnpm hygiene:tokens were clean.
  • Measured on ObjectStack 18.2.0 dev servers, comparing the main baseline with this branch, with USD set as the tenant currency on both.

🤖 Generated with Claude Code

https://claude.ai/code/session_01J8VVAoAy1McNK4cq14Q2vC

@vercel

vercel Bot commented Oct 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
hotcrm Ignored Ignored Oct 29, 2026 5:47am UTC

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation ci/cd CI plumbing and the verification pipeline metadata Declarative metadata — schema, security posture, UI surfaces labels Oct 29, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对

Verdict: ACCEPT · repo:hotcrm seat 1 · huangyiirene · session session_01J8VVAnPkgK6CWrJa6t7Fk5 · 2026-10-29T05:50Z · head ffcec3d
Implemented-by: card thread session session_01J8VVAoAy1McNK4cq14Q2vC (report 6489085271 on #2370). Reviewed-by: the seat, against the 62-file diff and hotcrm origin/main 66c63cb.

  • Shape:
    • Draft, base main, assignee huangyiirene. The body says Fixes #2370.
    • No governed path is touched, and no permission set, position or sharing rule changes. No flow changes, and no currency is hard-coded.
    • The branch is cut from 66c63cb, the current main, and git merge-tree against it is clean, so the branch's own pnpm verify stands for the merged tree.
  • Rows:
    • 1 (SLA base): the tile is now "Open Cases Past SLA" and its filter is scoped to open cases on both branches of the $or. The gauge is "SLA Met (Closed Cases)" and the report is "SLA on Closed Cases". case-sla-breach-on-close still pins the tile to the sweep's selection.
    • 2 (revenue trend): one home, Executive Overview. It is removed from CRM Overview and Sales Performance, and Why We Lose moves up beside Lead Source. The KPI caption half is platform-only.
    • 3: "Top Products" is now "List Price by Category", described as catalog prices and not sales. Summing sold amounts is refused by the dataset over a formula field (platform).
    • 4: the owner funnel is an owner × stage matrix with a per-owner Total, and its chart is one bar per owner. A stage split inside each bar is platform-only.
    • 5: explained in the Quota Attainment description. No seeding, per forecast_snapshot 与启动重播种的互动:每次 dev 重启后,当季出现一条无 owner 的幻影快照行与 owner 键控行并存 #702.
    • 6: each sidebar report label equals its report's own label in every locale, pinned by app-navigation-shape.
    • 7: the Sales Home money tiles use 0,0, the same as the dashboards.
    • 8: line quantities are scale: 0 and line totals are returnType: 'currency'. The quote line panel shows Discount in place of the duplicate Subtotal.
    • 9: quote and price-book dates use format: 'short', which keeps the year.
    • 10: already fixed on 18.2.0.
  • Tests:
    • pnpm verify exits 0 at 31bc156: 252 files, 4854 passed, 1 skipped.
    • ffcec3d is docs only. Hygiene and tokens are clean after it.
    • Ablations went red and were restored: the zh-CN nav label, and quantity scale 2.
  • Gates: CI on ffcec3d: every run is success except Build and Test, which is still running.
  • For the maintainer, not blocking: with scale: 0, a fractional line quantity (2.5) is now refused, which the new test pins. HotCRM products carry no unit of measure, so a line counts units. A product sold by the hour would need that unit first.
  • Platform gaps: the KPI tile caption, the formula currency face, the percent bar switch, the report series split and subtotals, and dataset sum over a formula. The seat files these upstream.
  • Landing: non-governed. In this stroke the seat marks the PR ready and turns on auto-merge.

Generated by Claude Code

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

Labels

ci/cd CI plumbing and the verification pipeline documentation Improvements or additions to documentation metadata Declarative metadata — schema, security posture, UI surfaces

Projects

None yet

2 participants