Files
ArchiTools/src/app/api/eterra/db-summary/route.ts
T

146 lines
4.0 KiB
TypeScript

import { NextResponse } from "next/server";
import { prisma } from "@/core/storage/prisma";
export const runtime = "nodejs";
export const dynamic = "force-dynamic";
/**
* GET /api/eterra/db-summary
*
* Returns a summary of ALL data in the GIS database, grouped by UAT.
* No siruta required — shows everything across all UATs.
*
* Response shape:
* {
* uats: [{
* siruta, uatName,
* layers: [{ layerId, count, enrichedCount, lastSynced }],
* totalFeatures, totalEnriched
* }],
* totalFeatures, totalUats
* }
*/
export async function GET() {
try {
// Feature counts per siruta + layerId
const featureCounts = await prisma.gisFeature.groupBy({
by: ["siruta", "layerId"],
_count: { id: true },
});
// Enriched counts per siruta + layerId
const enrichedCounts = await prisma.gisFeature.groupBy({
by: ["siruta", "layerId"],
where: { enrichedAt: { not: null } },
_count: { id: true },
});
const enrichedMap = new Map<string, number>();
for (const e of enrichedCounts) {
enrichedMap.set(`${e.siruta}:${e.layerId}`, e._count.id);
}
// Latest sync run per siruta + layerId
const latestRuns = await prisma.gisSyncRun.findMany({
where: { status: "done" },
orderBy: { completedAt: "desc" },
select: {
siruta: true,
uatName: true,
layerId: true,
completedAt: true,
},
});
const latestRunMap = new Map<
string,
{ completedAt: Date | null; uatName: string | null }
>();
for (const r of latestRuns) {
const key = `${r.siruta}:${r.layerId}`;
if (!latestRunMap.has(key)) {
latestRunMap.set(key, {
completedAt: r.completedAt,
uatName: r.uatName,
});
}
}
// UAT names from GisUat table
const uatNames = await prisma.gisUat.findMany({
select: { siruta: true, name: true, county: true },
});
const uatNameMap = new Map<
string,
{ name: string; county: string | null }
>();
for (const u of uatNames) {
uatNameMap.set(u.siruta, { name: u.name, county: u.county });
}
// Group by siruta
const uatMap = new Map<
string,
{
siruta: string;
uatName: string;
county: string | null;
layers: {
layerId: string;
count: number;
enrichedCount: number;
lastSynced: string | null;
}[];
totalFeatures: number;
totalEnriched: number;
}
>();
for (const fc of featureCounts) {
if (!uatMap.has(fc.siruta)) {
const uatInfo = uatNameMap.get(fc.siruta);
const runInfo = latestRunMap.get(`${fc.siruta}:${fc.layerId}`);
uatMap.set(fc.siruta, {
siruta: fc.siruta,
uatName: uatInfo?.name ?? runInfo?.uatName ?? `UAT ${fc.siruta}`,
county: uatInfo?.county ?? null,
layers: [],
totalFeatures: 0,
totalEnriched: 0,
});
}
const uat = uatMap.get(fc.siruta)!;
const enriched = enrichedMap.get(`${fc.siruta}:${fc.layerId}`) ?? 0;
const runInfo = latestRunMap.get(`${fc.siruta}:${fc.layerId}`);
uat.layers.push({
layerId: fc.layerId,
count: fc._count.id,
enrichedCount: enriched,
lastSynced: runInfo?.completedAt?.toISOString() ?? null,
});
uat.totalFeatures += fc._count.id;
uat.totalEnriched += enriched;
// Update UAT name if we got one from sync runs
if (uat.uatName.startsWith("UAT ") && runInfo?.uatName) {
uat.uatName = runInfo.uatName;
}
}
const uats = Array.from(uatMap.values()).sort(
(a, b) => b.totalFeatures - a.totalFeatures,
);
const totalFeatures = uats.reduce((s, u) => s + u.totalFeatures, 0);
return NextResponse.json({
uats,
totalFeatures,
totalUats: uats.length,
});
} catch (error) {
const message = error instanceof Error ? error.message : "Eroare server";
return NextResponse.json({ error: message }, { status: 500 });
}
}