V1.0
This commit is contained in:
@@ -530,18 +530,56 @@ function generatePDFToBuffer(timesheetId, req) {
|
||||
}
|
||||
|
||||
// Check-in/Check-out URL-Basis (wie im Dashboard-Frontend)
|
||||
function getCheckinBaseUrl(req) {
|
||||
const baseUrl = `${req.protocol}://${req.get('host')}`;
|
||||
return baseUrl.replace(/:\d+$/, ':3334');
|
||||
function getCheckinBaseUrl(req, callback) {
|
||||
// Versuche Root URL aus Datenbank zu laden
|
||||
db.get('SELECT checkin_root_url FROM system_options WHERE id = 1', (err, options) => {
|
||||
if (err) {
|
||||
console.warn('Fehler beim Laden der Root URL, verwende Fallback:', err);
|
||||
}
|
||||
|
||||
let checkinBaseUrl = null;
|
||||
if (options && options.checkin_root_url && options.checkin_root_url.trim() !== '') {
|
||||
checkinBaseUrl = options.checkin_root_url.trim();
|
||||
// Stelle sicher, dass kein trailing slash vorhanden ist
|
||||
checkinBaseUrl = checkinBaseUrl.replace(/\/+$/, '');
|
||||
}
|
||||
|
||||
// Fallback: Konstruiere URL aus Request (Port 3334 für Check-in)
|
||||
if (!checkinBaseUrl) {
|
||||
const baseUrl = `${req.protocol}://${req.get('host')}`;
|
||||
checkinBaseUrl = baseUrl.replace(/:\d+$/, ':3334');
|
||||
}
|
||||
|
||||
callback(checkinBaseUrl);
|
||||
});
|
||||
}
|
||||
|
||||
// PDF mit Check-in- und Check-out-QR-Codes (A4)
|
||||
async function generateCheckinCheckoutQRPDF(req, res) {
|
||||
// urlType: 'internal' oder 'external'
|
||||
async function generateCheckinCheckoutQRPDF(req, res, urlType = 'internal') {
|
||||
const userId = req.session.userId;
|
||||
if (!userId) {
|
||||
return res.status(401).send('Nicht angemeldet');
|
||||
}
|
||||
const checkinBaseUrl = getCheckinBaseUrl(req);
|
||||
|
||||
let checkinBaseUrl;
|
||||
|
||||
if (urlType === 'external') {
|
||||
// Externe URL: Lade aus Datenbank
|
||||
checkinBaseUrl = await new Promise((resolve) => {
|
||||
getCheckinBaseUrl(req, resolve);
|
||||
});
|
||||
} else {
|
||||
// Interne URL: Konstruiere aus Request (Port 3334)
|
||||
const baseUrl = `${req.protocol}://${req.get('host')}`;
|
||||
if (baseUrl.match(/:\d+$/)) {
|
||||
checkinBaseUrl = baseUrl.replace(/:\d+$/, ':3334');
|
||||
} else {
|
||||
const url = new URL(baseUrl);
|
||||
checkinBaseUrl = `${url.protocol}//${url.hostname}:3334`;
|
||||
}
|
||||
}
|
||||
|
||||
const checkinUrl = `${checkinBaseUrl}/api/checkin/${userId}`;
|
||||
const checkoutUrl = `${checkinBaseUrl}/api/checkout/${userId}`;
|
||||
|
||||
@@ -554,11 +592,12 @@ async function generateCheckinCheckoutQRPDF(req, res) {
|
||||
const firstname = (req.session.firstname || '').replace(/\s+/g, '');
|
||||
const lastname = (req.session.lastname || '').replace(/\s+/g, '');
|
||||
const namePart = [firstname, lastname].filter(Boolean).join('_') || 'User';
|
||||
const urlTypeLabel = urlType === 'external' ? 'Extern' : 'Intern';
|
||||
const today = new Date();
|
||||
const dateStr = today.getFullYear() + '-' +
|
||||
String(today.getMonth() + 1).padStart(2, '0') + '-' +
|
||||
String(today.getDate()).padStart(2, '0');
|
||||
const filename = `Check-in_Check-out_QR_${namePart}_${dateStr}.pdf`;
|
||||
const filename = `Check-in_Check-out_QR_${urlTypeLabel}_${namePart}_${dateStr}.pdf`;
|
||||
|
||||
res.setHeader('Content-Type', 'application/pdf');
|
||||
res.setHeader('X-Content-Type-Options', 'nosniff');
|
||||
@@ -573,7 +612,10 @@ async function generateCheckinCheckoutQRPDF(req, res) {
|
||||
const left1 = 50 + (pageWidth / 2 - qrSize - gap / 2);
|
||||
const left2 = 50 + (pageWidth / 2 + gap / 2);
|
||||
|
||||
doc.fontSize(18).text('Check-in / Check-out – Zeiterfassung', { align: 'center' });
|
||||
const title = urlType === 'external'
|
||||
? 'Check-in / Check-out – Zeiterfassung (Externe URLs)'
|
||||
: 'Check-in / Check-out – Zeiterfassung (Interne URLs)';
|
||||
doc.fontSize(18).text(title, { align: 'center' });
|
||||
doc.moveDown(1.5);
|
||||
|
||||
const topY = doc.y;
|
||||
|
||||
Reference in New Issue
Block a user