feat: add test digest mode (?test=true) + group company sees all entries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { runDigest } from "@/core/notifications";
|
||||
import { sendTestDigest } from "@/core/notifications/notification-service";
|
||||
|
||||
/**
|
||||
* POST /api/notifications/digest
|
||||
*
|
||||
* Server-to-server endpoint called by N8N cron.
|
||||
* Auth via Authorization: Bearer <NOTIFICATION_CRON_SECRET>
|
||||
*
|
||||
* Query params:
|
||||
* ?test=true — send a test email with sample data to all subscribers
|
||||
*/
|
||||
export async function POST(request: Request) {
|
||||
const secret = process.env.NOTIFICATION_CRON_SECRET;
|
||||
@@ -24,7 +28,10 @@ export async function POST(request: Request) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
const result = await runDigest();
|
||||
const url = new URL(request.url);
|
||||
const isTest = url.searchParams.get("test") === "true";
|
||||
|
||||
const result = isTest ? await sendTestDigest() : await runDigest();
|
||||
|
||||
return NextResponse.json(result, {
|
||||
status: result.success ? 200 : 500,
|
||||
|
||||
@@ -74,7 +74,11 @@ function buildCompanyDigest(
|
||||
entries: RegistryEntry[],
|
||||
company: CompanyId,
|
||||
): DigestSection[] {
|
||||
const companyEntries = entries.filter((e) => e.company === company);
|
||||
// "group" users see ALL entries across all companies
|
||||
const companyEntries =
|
||||
company === "group"
|
||||
? entries
|
||||
: entries.filter((e) => e.company === company);
|
||||
const sections: DigestSection[] = [];
|
||||
|
||||
const now = new Date();
|
||||
@@ -385,3 +389,107 @@ export async function runDigest(): Promise<DigestResult> {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ── Test digest — sends sample email to all subscribers ──
|
||||
|
||||
export async function sendTestDigest(): Promise<DigestResult> {
|
||||
const result: DigestResult = {
|
||||
success: true,
|
||||
totalEmails: 0,
|
||||
errors: [],
|
||||
companySummary: {},
|
||||
};
|
||||
|
||||
try {
|
||||
const preferences = await getAllPreferences();
|
||||
|
||||
if (preferences.length === 0) {
|
||||
return { ...result, errors: ["Nu exista preferinte de notificare configurate"] };
|
||||
}
|
||||
|
||||
const today = new Date().toISOString().slice(0, 10);
|
||||
|
||||
// Sample data for testing
|
||||
const testSections: DigestSection[] = [
|
||||
{
|
||||
type: "deadline-urgent",
|
||||
title: "Termene urgente (5 zile sau mai putin)",
|
||||
items: [
|
||||
{
|
||||
entryNumber: "BTG-0001/2026",
|
||||
subject: "[TEST] Certificat de urbanism - str. Exemplu nr. 10",
|
||||
label: "Emitere CU (30 zile lucratoare)",
|
||||
dueDate: today,
|
||||
daysRemaining: 2,
|
||||
color: "yellow",
|
||||
},
|
||||
{
|
||||
entryNumber: "BTG-0005/2026",
|
||||
subject: "[TEST] Aviz ISU - Proiect rezidential",
|
||||
label: "Raspuns aviz ISU (15 zile)",
|
||||
dueDate: today,
|
||||
daysRemaining: 5,
|
||||
color: "yellow",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "deadline-overdue",
|
||||
title: "Termene depasite",
|
||||
items: [
|
||||
{
|
||||
entryNumber: "BTG-0003/2026",
|
||||
subject: "[TEST] Autorizatie construire - bloc P+4",
|
||||
label: "Emitere AC (30 zile lucratoare)",
|
||||
dueDate: "2026-03-01",
|
||||
daysRemaining: -10,
|
||||
color: "red",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "document-expiry",
|
||||
title: "Documente care expira",
|
||||
items: [
|
||||
{
|
||||
entryNumber: "BTG-0010/2025",
|
||||
subject: "[TEST] CU nr. 123/2025 - proiect mixt",
|
||||
label: "Expira curand",
|
||||
dueDate: "2026-03-25",
|
||||
daysRemaining: 14,
|
||||
color: "yellow",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
for (const pref of preferences) {
|
||||
if (pref.globalOptOut) continue;
|
||||
|
||||
const companyName = COMPANY_LABELS[pref.company] ?? pref.company;
|
||||
const html = renderDigestHtml(testSections, companyName, today);
|
||||
const subject = `[ArchiTools TEST] 4 alerte - ${companyName} (${formatDateRo(today)})`;
|
||||
|
||||
try {
|
||||
await sendEmail({ to: pref.email, subject, html });
|
||||
result.totalEmails++;
|
||||
} catch (err) {
|
||||
result.errors.push(
|
||||
`Eroare trimitere catre ${pref.email}: ${err instanceof Error ? err.message : String(err)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
result.companySummary["test"] = {
|
||||
emails: result.totalEmails,
|
||||
sections: testSections.length,
|
||||
};
|
||||
} catch (err) {
|
||||
result.success = false;
|
||||
result.errors.push(
|
||||
`Eroare test digest: ${err instanceof Error ? err.message : String(err)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user