wulf-pulse/app/api/mobile/tickets/route.ts
lorentz 89dbe6155b fix: mobile tickets/dashboard use classification filter instead of unpopulated MSP Service Model UDF
The hardcoded UDF filter (MSP Service Model = 'Wulf Managed') matched
only 1 company, making all mobile ticket views empty. Now reads
included_classifications from kiosk_settings (same as kiosk) which
correctly identifies all managed clients by classification ID.
2026-04-05 09:22:10 -04:00

75 lines
2.5 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import { postgresClient } from '@/lib/services/postgres-client';
async function getManagedCompanyFilter(): Promise<string> {
const result = await postgresClient.query(
`SELECT setting_value FROM kiosk_settings WHERE setting_key = 'included_classifications'`
);
const value = result.rows[0]?.setting_value || '';
const ids = value ? value.split(',').map((s: string) => parseInt(s.trim(), 10)).filter((n: number) => !isNaN(n)) : [];
return ids.length > 0 ? `c.classification::integer IN (${ids.join(',')})` : 'true';
}
export async function GET(request: NextRequest) {
const { searchParams } = request.nextUrl;
const search = searchParams.get('q') ?? '';
const queue = searchParams.get('queue') ?? '';
const priority = searchParams.get('priority') ?? '';
const page = Math.max(1, parseInt(searchParams.get('page') ?? '1'));
const limit = 30;
const offset = (page - 1) * limit;
const managedFilter = await getManagedCompanyFilter();
const conditions: string[] = [
't.status != 5',
't.is_deleted = false',
managedFilter,
];
const params: unknown[] = [];
if (search) {
params.push(`%${search}%`);
conditions.push(`(t.title ILIKE $${params.length} OR t.ticket_number ILIKE $${params.length} OR c.company_name ILIKE $${params.length})`);
}
if (queue) {
params.push(parseInt(queue));
conditions.push(`t.queue_id = $${params.length}`);
}
if (priority) {
params.push(parseInt(priority));
conditions.push(`t.priority = $${params.length}`);
}
const where = conditions.join(' AND ');
const [rows, countRow] = await Promise.all([
postgresClient.query(`
SELECT t.id, t.ticket_number, t.title, t.status, t.priority,
t.create_date, t.last_activity_date, t.due_date_time,
t.queue_id, q.label as queue_label,
c.company_name,
r.first_name || ' ' || r.last_name as assigned_to
FROM tickets t
INNER JOIN companies c ON c.id = t.company_id
LEFT JOIN queues q ON q.value = t.queue_id
LEFT JOIN resources r ON r.id = t.assigned_resource_id
WHERE ${where}
ORDER BY t.last_activity_date DESC NULLS LAST
LIMIT ${limit} OFFSET ${offset}
`, params),
postgresClient.query(`
SELECT COUNT(*) as total
FROM tickets t
INNER JOIN companies c ON c.id = t.company_id
WHERE ${where}
`, params),
]);
return NextResponse.json({
tickets: rows.rows,
total: parseInt(countRow.rows[0]?.total ?? '0'),
page,
limit,
});
}