diff --git a/.changeset/afraid-ends-mate.md b/.changeset/afraid-ends-mate.md new file mode 100644 index 0000000000..6dcf0b4089 --- /dev/null +++ b/.changeset/afraid-ends-mate.md @@ -0,0 +1,4 @@ +--- +--- + +Fix missing column references in admin stats queries (engagement_reasons, next_step, subscription_status) diff --git a/server/src/addie/home/builders/admin.ts b/server/src/addie/home/builders/admin.ts index e6e1102ea6..53a7dfc714 100644 --- a/server/src/addie/home/builders/admin.ts +++ b/server/src/addie/home/builders/admin.ts @@ -53,7 +53,13 @@ export async function buildAdminPanel(adminUserId?: string): Promise COUNT(*) as total, COUNT(CASE WHEN o.engagement_score >= 30 THEN 1 END) as hot, COUNT(CASE - WHEN (o.next_step_due_date IS NOT NULL AND o.next_step_due_date < CURRENT_DATE) + WHEN EXISTS ( + SELECT 1 FROM org_activities + WHERE organization_id = o.workos_organization_id + AND is_next_step = TRUE + AND next_step_completed_at IS NULL + AND next_step_due_date < CURRENT_DATE + ) OR EXTRACT(DAY FROM NOW() - COALESCE( (SELECT MAX(activity_date) FROM org_activities WHERE organization_id = o.workos_organization_id), o.created_at @@ -65,7 +71,7 @@ export async function buildAdminPanel(adminUserId?: string): Promise WHERE os.user_id = $1 AND os.role = 'owner' AND o.is_personal IS NOT TRUE - AND (o.stripe_subscription_status IS NULL OR o.stripe_subscription_status != 'active') + AND (o.subscription_status IS NULL OR o.subscription_status != 'active') `, [adminUserId]); const row = result.rows[0]; diff --git a/server/src/addie/mcp/admin-tools.ts b/server/src/addie/mcp/admin-tools.ts index 8e718e117c..cb9d17cdbd 100644 --- a/server/src/addie/mcp/admin-tools.ts +++ b/server/src/addie/mcp/admin-tools.ts @@ -5051,14 +5051,13 @@ Use add_committee_leader to assign a leader.`; o.prospect_status, o.interest_level, o.company_type, - (SELECT array_agg(r) FROM (SELECT unnest(engagement_reasons) ORDER BY 1) AS dt(r)) as engagement_reasons, (SELECT MAX(activity_date) FROM org_activities WHERE organization_id = o.workos_organization_id) as last_activity FROM organizations o JOIN org_stakeholders os ON os.organization_id = o.workos_organization_id WHERE os.user_id = $1 AND os.role = 'owner' AND o.is_personal IS NOT TRUE - AND (o.stripe_subscription_status IS NULL OR o.stripe_subscription_status != 'active') + AND (o.subscription_status IS NULL OR o.subscription_status != 'active') `; if (hotOnly) { @@ -5090,9 +5089,6 @@ Use add_committee_leader to assign a leader.`; if (row.prospect_status) response += ` | Status: ${row.prospect_status}`; if (row.interest_level) response += ` | Interest: ${row.interest_level}`; response += `\n`; - if (row.engagement_reasons?.length > 0) { - response += ` Signals: ${row.engagement_reasons.join(', ')}\n`; - } if (row.last_activity) { response += ` Last activity: ${new Date(row.last_activity).toLocaleDateString()}\n`; } @@ -5149,7 +5145,7 @@ Use add_committee_leader to assign a leader.`; WHERE os.user_id = $1 AND os.role = 'owner' AND o.is_personal IS NOT TRUE - AND (o.stripe_subscription_status IS NULL OR o.stripe_subscription_status != 'active') + AND (o.subscription_status IS NULL OR o.subscription_status != 'active') ) SELECT *, CASE @@ -5221,11 +5217,10 @@ Use add_committee_leader to assign a leader.`; o.email_domain, o.engagement_score, o.prospect_status, - o.company_type, - (SELECT array_agg(r) FROM (SELECT unnest(engagement_reasons) ORDER BY 1) AS dt(r)) as engagement_reasons + o.company_type FROM organizations o WHERE o.is_personal IS NOT TRUE - AND (o.stripe_subscription_status IS NULL OR o.stripe_subscription_status != 'active') + AND (o.subscription_status IS NULL OR o.subscription_status != 'active') AND o.engagement_score >= $1 AND NOT EXISTS ( SELECT 1 FROM org_stakeholders os @@ -5253,9 +5248,6 @@ Use add_committee_leader to assign a leader.`; response += ` Score: ${row.engagement_score || 0}`; if (row.company_type) response += ` | Type: ${row.company_type}`; response += `\n`; - if (row.engagement_reasons?.length > 0) { - response += ` Signals: ${row.engagement_reasons.join(', ')}\n`; - } response += ` ID: ${row.org_id}\n`; response += `\n`; } diff --git a/server/src/routes/admin/stats.ts b/server/src/routes/admin/stats.ts index 17cbb066a6..bf57b4eb7d 100644 --- a/server/src/routes/admin/stats.ts +++ b/server/src/routes/admin/stats.ts @@ -393,14 +393,13 @@ export function setupStatsRoutes(apiRouter: Router): void { o.email_domain, o.engagement_score, o.prospect_status, - o.interest_level, - (SELECT array_agg(r) FROM (SELECT unnest(engagement_reasons) ORDER BY 1) AS dt(r)) as engagement_reasons + o.interest_level FROM organizations o JOIN org_stakeholders os ON os.organization_id = o.workos_organization_id WHERE os.user_id = $1 AND os.role = 'owner' AND o.is_personal IS NOT TRUE - AND (o.stripe_subscription_status IS NULL OR o.stripe_subscription_status != 'active') + AND (o.subscription_status IS NULL OR o.subscription_status != 'active') AND o.engagement_score >= 30 ORDER BY o.engagement_score DESC LIMIT 5 @@ -414,8 +413,8 @@ export function setupStatsRoutes(apiRouter: Router): void { o.name, o.email_domain, o.engagement_score, - o.next_step, - o.next_step_due_date, + ns.description as next_step, + ns.next_step_due_date, (SELECT MAX(activity_date) FROM org_activities WHERE organization_id = o.workos_organization_id) as last_activity, EXTRACT(DAY FROM NOW() - COALESCE( (SELECT MAX(activity_date) FROM org_activities WHERE organization_id = o.workos_organization_id), @@ -423,10 +422,19 @@ export function setupStatsRoutes(apiRouter: Router): void { )) as days_since_activity FROM organizations o JOIN org_stakeholders os ON os.organization_id = o.workos_organization_id + LEFT JOIN LATERAL ( + SELECT description, next_step_due_date + FROM org_activities + WHERE organization_id = o.workos_organization_id + AND is_next_step = TRUE + AND next_step_completed_at IS NULL + ORDER BY next_step_due_date ASC NULLS LAST + LIMIT 1 + ) ns ON true WHERE os.user_id = $1 AND os.role = 'owner' AND o.is_personal IS NOT TRUE - AND (o.stripe_subscription_status IS NULL OR o.stripe_subscription_status != 'active') + AND (o.subscription_status IS NULL OR o.subscription_status != 'active') ) SELECT *, CASE @@ -467,7 +475,13 @@ export function setupStatsRoutes(apiRouter: Router): void { COUNT(*) as total, COUNT(CASE WHEN o.engagement_score >= 30 THEN 1 END) as hot, COUNT(CASE - WHEN (o.next_step_due_date IS NOT NULL AND o.next_step_due_date < CURRENT_DATE) + WHEN EXISTS ( + SELECT 1 FROM org_activities + WHERE organization_id = o.workos_organization_id + AND is_next_step = TRUE + AND next_step_completed_at IS NULL + AND next_step_due_date < CURRENT_DATE + ) OR EXTRACT(DAY FROM NOW() - COALESCE( (SELECT MAX(activity_date) FROM org_activities WHERE organization_id = o.workos_organization_id), o.created_at @@ -479,7 +493,7 @@ export function setupStatsRoutes(apiRouter: Router): void { WHERE os.user_id = $1 AND os.role = 'owner' AND o.is_personal IS NOT TRUE - AND (o.stripe_subscription_status IS NULL OR o.stripe_subscription_status != 'active') + AND (o.subscription_status IS NULL OR o.subscription_status != 'active') `, [userId]), ]);