import { NextResponse } from "next/server"; import { prisma } from "@/lib/prisma"; import { sendPushover } from "@/lib/push-notify"; // Call daily with: // POST /api/cron/milk-expiry // Authorization: Bearer async function getCronSecret(): Promise { const row = await prisma.systemConfig.findUnique({ where: { key: "cron_secret" } }); return row?.value || process.env.CRON_SECRET || ""; } export async function POST(req: Request) { const secret = await getCronSecret(); if (secret) { const authHeader = req.headers.get("authorization") ?? ""; if (authHeader !== `Bearer ${secret}`) { return NextResponse.json({ error: "Non autorisé" }, { status: 401 }); } } const windowEnd = new Date(Date.now() + 24 * 3600 * 1000); const expiringLots = await prisma.milkStock.findMany({ where: { used: false, expiresAt: { lte: windowEnd }, }, include: { baby: { include: { family: { include: { users: { where: { pushoverUserKey: { not: null } }, select: { pushoverUserKey: true }, }, }, }, }, }, }, orderBy: { expiresAt: "asc" }, }); if (expiringLots.length === 0) { return NextResponse.json({ ok: true, sent: 0 }); } // Group by family const byFamily = new Map(); for (const lot of expiringLots) { const familyId = lot.baby.family.id; if (!byFamily.has(familyId)) { byFamily.set(familyId, { users: lot.baby.family.users, lines: [], babyName: lot.baby.name }); } const entry = byFamily.get(familyId)!; const expiresIn = lot.expiresAt.getTime() - Date.now(); const hoursLeft = Math.max(0, Math.floor(expiresIn / 3600000)); const loc = lot.location === "fridge" ? "frigo" : lot.location === "freezer" ? "congélateur" : "ambiant"; const alreadyExpired = expiresIn <= 0; entry.lines.push( alreadyExpired ? `⚠️ ${lot.volume} mL (${loc}) — expiré` : `🥛 ${lot.volume} mL (${loc}) — expire dans ${hoursLeft}h` ); } let sent = 0; for (const { users, lines, babyName } of byFamily.values()) { const message = [`🥛 Stock lait — ${babyName}`, "", ...lines].join("\n"); for (const user of users) { if (user.pushoverUserKey) { await sendPushover(user.pushoverUserKey, message, `🥛 Alerte stock lait`); sent++; } } } return NextResponse.json({ ok: true, sent, lots: expiringLots.length }); }