import type { RequestContext } from '../../core/http.js'; import { intParam, stringParam, tenantIdFrom } from '../../core/request.js'; import { query, queryOne } from '../../core/db.js'; export async function scorelineFieldsRoute(ctx: RequestContext) { const tenantId = tenantIdFrom(ctx); const regionId = stringParam(ctx, 'regionId'); const items = await query( ` select id, legacy_id as "legacyId", region_id as "regionId", field_key as "fieldKey", field_name as "fieldName", field_type as "fieldType", unit, is_filter as "isFilter", is_required as "isRequired", is_visible as "isVisible", is_trend as "isTrend", options, placeholder, description, sort_order as "sortOrder", created_at as "createdAt", updated_at as "updatedAt" from public.scoreline_fields where tenant_id = $1 and ($2::uuid is null or region_id = $2::uuid) order by sort_order asc, field_name asc `, [tenantId, regionId || null], ); return { items }; } export async function scorelineSchoolsRoute(ctx: RequestContext) { const tenantId = tenantIdFrom(ctx); const regionId = stringParam(ctx, 'regionId'); const q = stringParam(ctx, 'q'); const limit = intParam(ctx, 'limit', 200, 1000); const items = await query( ` select id, legacy_id as "legacyId", region_id as "regionId", name, short_name as "shortName", type, is_hot as "isHot", sort_order as "order", created_at as "createdAt", updated_at as "updatedAt" from public.scoreline_schools where tenant_id = $1 and ($2::uuid is null or region_id = $2::uuid) and ($3::text = '' or name ilike '%' || $3 || '%' or short_name ilike '%' || $3 || '%') order by is_hot desc, sort_order asc, name asc, type asc nulls last limit $4 `, [tenantId, regionId || null, q, limit], ); return { items }; } export async function scorelineMajorsRoute(ctx: RequestContext) { const tenantId = tenantIdFrom(ctx); const regionId = stringParam(ctx, 'regionId'); const schoolId = stringParam(ctx, 'schoolId'); const limit = intParam(ctx, 'limit', 500, 2000); const items = await query( ` select id, legacy_id as "legacyId", region_id as "regionId", school_id as "schoolId", name, sort_order as "order", has_restriction as "hasRestriction", restriction_desc as "restrictionDesc", created_at as "createdAt", updated_at as "updatedAt" from public.scoreline_majors where tenant_id = $1 and ($2::uuid is null or region_id = $2::uuid) and ($3::uuid is null or school_id = $3::uuid) order by sort_order asc, name asc limit $4 `, [tenantId, regionId || null, schoolId || null, limit], ); return { items }; } export async function scorelineRecordsRoute(ctx: RequestContext) { const tenantId = tenantIdFrom(ctx); const regionId = stringParam(ctx, 'regionId'); const schoolId = stringParam(ctx, 'schoolId'); const majorId = stringParam(ctx, 'majorId'); const year = Number(ctx.url.searchParams.get('year') || 0); const page = intParam(ctx, 'page', 1, 10_000); const pageSize = intParam(ctx, 'pageSize', intParam(ctx, 'perPage', 20, 100), 100); const offset = (page - 1) * pageSize; const where = ` tenant_id = $1 and ($2::uuid is null or region_id = $2::uuid) and ($3::uuid is null or school_id = $3::uuid) and ($4::uuid is null or major_id = $4::uuid) and ($5::integer = 0 or year = $5::integer) `; const params = [tenantId, regionId || null, schoolId || null, majorId || null, Number.isFinite(year) ? Math.trunc(year) : 0]; const [countRow, items] = await Promise.all([ queryOne<{ total: string }>(`select count(*)::text as total from public.scoreline_records where ${where}`, params), query( ` select id, legacy_id as "legacyId", region_id as "regionId", school_id as "schoolId", major_id as "majorId", year, school_name as "schoolName", major_name as "majorName", field_values as "fieldValues", created_at as "createdAt", updated_at as "updatedAt" from public.scoreline_records where ${where} order by year desc, school_name asc nulls last, major_name asc nulls last limit $6 offset $7 `, [...params, pageSize, offset], ), ]); return { page, pageSize, total: Number(countRow?.total || 0), items, }; } export async function scorelineTrendRoute(ctx: RequestContext) { const tenantId = tenantIdFrom(ctx); const regionId = stringParam(ctx, 'regionId'); const schoolId = stringParam(ctx, 'schoolId'); const majorId = stringParam(ctx, 'majorId'); const limit = intParam(ctx, 'limit', 20, 100); const items = await query( ` select id, region_id as "regionId", school_id as "schoolId", major_id as "majorId", year, school_name as "schoolName", major_name as "majorName", field_values as "fieldValues" from public.scoreline_records where tenant_id = $1 and ($2::uuid is null or region_id = $2::uuid) and ($3::uuid is null or school_id = $3::uuid) and ($4::uuid is null or major_id = $4::uuid) order by year asc, major_name asc nulls last limit $5 `, [tenantId, regionId || null, schoolId || null, majorId || null, limit], ); return { items }; } export async function scorelineYearsRoute(ctx: RequestContext) { const tenantId = tenantIdFrom(ctx); const regionId = stringParam(ctx, 'regionId'); const items = await query<{ year: number }>( ` select distinct year from public.scoreline_records where tenant_id = $1 and ($2::uuid is null or region_id = $2::uuid) order by year desc `, [tenantId, regionId || null], ); return { items: items.map(item => item.year) }; }