Files
formbricks/docker/cube
Dhruwang 602ffd5bba feat(analytics): augment Cube measures with CSAT/CES + bug fixes (ENG-804)
Adds CSAT and CES measures, plus a couple of universal cross-type measures,
to the FeedbackRecords Cube. Also fixes correctness bugs in the existing NPS
measures and constrains the AI chart-query output to known measure / dimension
ids.

Measures added
- csatScore: % of answered CSAT responses rated 4 or 5 (top-2-box on 1-5).
- csatAverage: AVG of answered CSAT ratings.
- csatSatisfiedCount: count where field_type='csat' AND value_number >= 4.
- csatCount: count of answered CSAT responses.
- cesAverage: AVG of answered CES ratings (1-5 or 1-7 depending on the question).
- cesCount: count of answered CES responses.
- uniqueRespondents: countDistinct(user_id).
- uniqueResponses: countDistinct(submission_id).
- npsAverage: AVG of answered NPS ratings (replaces the old `averageScore`
  measure, which silently averaged every numeric value across all field types).

Bug fixes (existing NPS measures)
- promoterCount / passiveCount / detractorCount / npsScore now filter
  field_type = 'nps'. Before, any numeric value in the band was counted
  (so a CSAT 5/5 was lumped in as a detractor).
- npsScore now divides by *answered* NPS responses only (value_number IS NOT
  NULL); dismissed/abandoned NPS records no longer drag the score toward 0.
- npsScore returns NULL when no answered NPS responses exist instead of the
  literal 0, so empty-data days render as gaps rather than a misleading
  flat-zero line.
- Same NULL-safe denominator fix applied to csatScore.
- csatCount / cesCount now exclude dismissed (value_number IS NULL) responses
  so they match the score denominators.

Dimensions
- Renamed `npsValue` -> `valueNumber` (the underlying value_number column
  stores values for NPS, CSAT, CES, rating, and number field types).
- New `valueText` dimension for grouping by categorical / open-text answers.

AI chart generation
- ZGenerateAIQueryResponse now enum-constrains `measures`, `dimensions`,
  `timeDimensions.dimension`, and `filters.member` against the known ids
  derived from FEEDBACK_FIELDS. Vercel AI SDK + Gemini structured outputs
  enforce these at decoding time, so the model can no longer return invalid
  or hallucinated measure names.
- generateText now pins temperature: 0. Same prompt produces the same query.

Breaking changes
- Charts that referenced `FeedbackRecords.averageScore` need to switch to
  `FeedbackRecords.npsAverage`.
- Charts that referenced `FeedbackRecords.npsValue` need to switch to
  `FeedbackRecords.valueNumber`.

Pre-GA on epic/v5; no production charts are expected to be impacted yet.
2026-05-12 16:05:38 +05:30
..