9051ff73d0
Replace ~440 lines of hand-written structural DB client types across 7 lib files with `Pick<PrismaClient, ...>` from @capakraken/db. This eliminates all `as any` casts at Prisma boundaries (cron routes, allocation effects, vacation procedures) and surfaces two pre-existing bugs: - weekly-digest.ts: `db.allocation.count()` called non-existent model (fixed → demandRequirement) - estimate-reminders.ts: `submittedAt` field doesn't exist on EstimateVersion (fixed → updatedAt) Also adds root eslint.config.mjs so lint-staged can lint package files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
41 lines
1.2 KiB
TypeScript
41 lines
1.2 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { prisma } from "@capakraken/db";
|
|
import { checkChargeabilityAlerts } from "@capakraken/api";
|
|
import { logger } from "@capakraken/api/lib/logger";
|
|
import { verifyCronSecret } from "~/lib/cron-auth.js";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
export const runtime = "nodejs";
|
|
|
|
/**
|
|
* GET /api/cron/chargeability-alerts
|
|
*
|
|
* Finds resources whose current-month chargeability is >15 percentage points
|
|
* below their target and creates in-app notifications for managers.
|
|
*
|
|
* Duplicate-safe: only one alert per resource per month.
|
|
*
|
|
* Optionally protect with CRON_SECRET environment variable.
|
|
* When set, requests must include `Authorization: Bearer <secret>`.
|
|
*/
|
|
export async function GET(request: Request) {
|
|
const deny = verifyCronSecret(request);
|
|
if (deny) return deny;
|
|
|
|
try {
|
|
const alertsSent = await checkChargeabilityAlerts(prisma);
|
|
|
|
return NextResponse.json({
|
|
ok: true,
|
|
alertsSent,
|
|
checkedAt: new Date().toISOString(),
|
|
});
|
|
} catch (error) {
|
|
logger.error(
|
|
{ error, route: "/api/cron/chargeability-alerts" },
|
|
"Chargeability alert cron failed",
|
|
);
|
|
return NextResponse.json({ ok: false, error: "Internal error" }, { status: 500 });
|
|
}
|
|
}
|