Files
app/src/services/leave-notification.ts
BOHA baceb88347 feat: NAS storage for invoices/offers, code cleanup, date/time fixes
- NAS storage for created invoices (PDF via puppeteer), received invoices,
  and offers with auto-save on create/edit
- Deterministic file paths derived from DB fields (no file_path column needed)
- Separate NAS mount points: NAS_FINANCIALS_PATH, NAS_OFFERS_PATH
- Invoice language field (cs/en) stored per invoice, replaces lang modal
- Invoices list filtered by month/year matching KPI card selection
- Centralized date helpers (src/utils/date.ts) replacing all .toISOString()
  calls that returned UTC instead of local time
- Attendance project switching uses exact time (not rounded)
- Comment cleanup: removed ~100 unnecessary/Czech comments
- Removed as-any casts in orders and attendance
- Prisma migrations: add invoice language, drop received_invoices BLOB columns

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 10:36:39 +01:00

111 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { sendMail } from "./mailer";
import { config } from "../config/env";
import { localDateCzStr, localDateTimeCzStr } from "../utils/date";
const LEAVE_TYPE_LABELS: Record<string, string> = {
vacation: "Dovolená",
sick: "Nemocenská",
unpaid: "Neplacené volno",
};
function formatDate(dateStr: string): string {
try {
const d = new Date(dateStr);
return localDateCzStr(d);
} catch {
return dateStr;
}
}
function escapeHtml(str: string): string {
return str
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}
interface LeaveRequestData {
leave_type: string;
date_from: string;
date_to: string;
total_days: number;
total_hours: number;
notes?: string | null;
}
export async function notifyNewLeaveRequest(
request: LeaveRequestData,
employeeName: string,
): Promise<void> {
const notifyEmail = config.email.leaveNotify;
if (!notifyEmail) return;
const leaveType = LEAVE_TYPE_LABELS[request.leave_type] || request.leave_type;
const dateFrom = formatDate(request.date_from);
const dateTo = formatDate(request.date_to);
const notes = request.notes || "";
const subject = `Nová žádost o nepřítomnost - ${employeeName} (${leaveType})`;
const appUrl = config.appUrl || "";
const approvalLink = appUrl
? `<p style="margin-top: 20px;">
<a href="${escapeHtml(appUrl)}/leave-approval"
style="background: #de3a3a; color: #fff; padding: 10px 20px;
text-decoration: none; border-radius: 5px;">
Přejít ke schvalování
</a>
</p>`
: "";
const now = new Date();
const timestamp = localDateTimeCzStr(now);
const html = `
<html>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
<h2 style="color: #de3a3a;">Nová žádost o nepřítomnost</h2>
<table style="width: 100%; border-collapse: collapse; margin: 20px 0;">
<tr>
<td style="padding: 10px; background: #f5f5f5; font-weight: bold; width: 180px;">Zaměstnanec:</td>
<td style="padding: 10px; border-bottom: 1px solid #ddd;">${escapeHtml(employeeName)}</td>
</tr>
<tr>
<td style="padding: 10px; background: #f5f5f5; font-weight: bold;">Typ:</td>
<td style="padding: 10px; border-bottom: 1px solid #ddd;">${escapeHtml(leaveType)}</td>
</tr>
<tr>
<td style="padding: 10px; background: #f5f5f5; font-weight: bold;">Období:</td>
<td style="padding: 10px; border-bottom: 1px solid #ddd;">${dateFrom} ${dateTo}</td>
</tr>
<tr>
<td style="padding: 10px; background: #f5f5f5; font-weight: bold;">Pracovní dny:</td>
<td style="padding: 10px; border-bottom: 1px solid #ddd;">${request.total_days} dní (${request.total_hours} hodin)</td>
</tr>
${
notes
? `<tr>
<td style="padding: 10px; background: #f5f5f5; font-weight: bold;">Poznámka:</td>
<td style="padding: 10px; border-bottom: 1px solid #ddd;">${escapeHtml(notes)}</td>
</tr>`
: ""
}
</table>
${approvalLink}
<hr style="margin: 30px 0; border: none; border-top: 1px solid #ddd;">
<p style="font-size: 12px; color: #999;">
Tato zpráva byla automaticky vygenerována systémem.<br>
Datum: ${timestamp}
</p>
</body>
</html>`;
const sent = await sendMail(notifyEmail, subject, html);
if (!sent) {
console.error(
`LeaveNotification: Failed to send notification to ${notifyEmail}`,
);
}
}