/**
* GET /reports/facility-performance — 施設別パフォーマンス一覧(稼働率ワースト順)
*
* 形は `app/api/ds-alerts/route.ts` に合わせている。
* 仕様の正は `d-watch-api.yaml` の /reports/facility-performance。
*/
import { NextResponse } from "next/server";
import { loadFacilityPerformance } from "@/lib/reports/facility-performance-load";
import { parseReportQuery } from "@/lib/reports/query";
import { withRequestId } from "@/lib/logger";
import { logApiError } from "@/lib/logger/api";
import type { ApiError, FacilityPerformance, ListResponse } from "@/lib/types";
const ROUTE = "/api/reports/facility-performance";
function errorResponse(error: ApiError, status: number) {
return NextResponse.json(error, { status });
}
export async function GET(request: Request) {
return withRequestId(request, async () => {
const { searchParams } = new URL(request.url);
const parsed = parseReportQuery(searchParams);
if (!parsed.ok) {
return errorResponse(parsed.error, parsed.status);
}
// ★★取得 → 絞り込み → 並べ替え → 連続日数の上限処理 は CSV(`/export`)と同じ1本★★(D-163)—
// ★ここで独自に絞り込みを足さないこと★(画面の表と CSV が食い違う)。
// 中身の注記(施設名の解決・分類との積集合・表示上限)は `lib/reports/facility-performance-load.ts`。
let sorted: FacilityPerformance[];
try {
sorted = await loadFacilityPerformance(parsed.query);
} catch (e) {
const body: ApiError = {
error: {
code: "internal_error",
message: "データの取得に失敗しました",
details: null,
},
};
logApiError({ route: ROUTE, method: "GET", body, status: 500, err: e });
return errorResponse(body, 500);
}
// ★meta.total は「絞り込み後・limit 適用前」の件数★(YAML の meta の説明)
// 画面の「全N施設を表示」の N がこれ。limit で切った後の件数ではない。
const total = sorted.length;
const { limit } = parsed.query;
const items = sorted.slice(0, limit);
// page / per_page パラメータを持たない一覧なので meta.page は常に1、
// meta.per_page は実際に適用された limit を返す(YAML の meta の説明)。
const body: ListResponse<FacilityPerformance> = {
items,
meta: { total, page: 1, per_page: limit },
};
return NextResponse.json(body);
});
}