forked from wangziqi/gongxue-base
165 lines
5.7 KiB
TypeScript
165 lines
5.7 KiB
TypeScript
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) };
|
|
}
|