fix: Fix booking count discrepancy between KPI cards and trends chart (#23619)

* fix: correct booking count in EventTrendsChart by restructuring SQL query

- Replace JOIN-based query with CTE approach to count distinct bookings
- Separate booking stats from guest stats to prevent duplicate counting
- Preserve no-show guest functionality with LEFT JOIN
- Ensure EventTrendsChart 'Created' sum matches BookingKPICards 'events_created'

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: use positional GROUP BY references to resolve PostgreSQL error

- Replace column expressions in GROUP BY with positional references (1, 2, 3)
- Fixes PostgreSQL error 42803 caused by parameter resolution in CTE queries
- Maintains the same query logic while avoiding column reference conflicts

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* address feedback

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Eunjae Lee
2025-09-10 11:13:29 +01:00
committed by GitHub
co-authored by Devin AI
parent d30d2792cd
commit 6066ed206b
@@ -650,31 +650,42 @@ export class InsightsBookingBaseService {
noShowGuests: number;
}[]
>`
SELECT
"date",
CAST(COUNT(*) AS INTEGER) AS "bookingsCount",
CAST(COUNT(CASE WHEN "isNoShowGuest" = true THEN 1 END) AS INTEGER) AS "noShowGuests",
"timeStatus",
"noShowHost"
FROM (
WITH booking_stats AS (
SELECT
DATE("createdAt" AT TIME ZONE ${timeZone}) as "date",
"a"."noShow" AS "isNoShowGuest",
"timeStatus",
"noShowHost"
FROM
"BookingTimeStatusDenormalized"
JOIN
"Attendee" "a" ON "a"."bookingId" = "BookingTimeStatusDenormalized"."id"
WHERE
${baseConditions}
) AS bookings
GROUP BY
"date",
"timeStatus",
"noShowHost"
ORDER BY
"date"
COALESCE("noShowHost", false) AS "noShowHost",
COUNT(*) as "bookingsCount"
FROM "BookingTimeStatusDenormalized"
WHERE ${baseConditions}
GROUP BY
1, 2, 3
),
guest_stats AS (
SELECT
DATE(b."createdAt" AT TIME ZONE ${timeZone}) as "date",
b."timeStatus",
COALESCE(b."noShowHost", false) AS "noShowHost",
COUNT(CASE WHEN a."noShow" = true THEN 1 END) as "noShowGuests"
FROM "BookingTimeStatusDenormalized" b
INNER JOIN "Attendee" a ON a."bookingId" = b.id
WHERE ${baseConditions}
GROUP BY
1, 2, 3
)
SELECT
bs."date",
CAST(bs."bookingsCount" AS INTEGER) AS "bookingsCount",
bs."timeStatus",
bs."noShowHost",
CAST(COALESCE(gs."noShowGuests", 0) AS INTEGER) AS "noShowGuests"
FROM booking_stats bs
LEFT JOIN guest_stats gs ON (
bs."date" = gs."date" AND
bs."timeStatus" = gs."timeStatus" AND
bs."noShowHost" = gs."noShowHost"
)
ORDER BY bs."date"
`;
// Initialize aggregate object with zero counts for all date ranges