import { Response } from 'express'; import { AuthRequest } from '../types/index.js'; import * as pdfTemplateService from '../services/pdfTemplate.service.js'; import { logChange } from '../services/audit.service.js'; export async function getTemplates(req: AuthRequest, res: Response) { try { const templates = await pdfTemplateService.getAllTemplates(); res.json({ success: true, data: templates }); } catch (error) { res.status(500).json({ success: false, error: 'Fehler beim Laden' }); } } export async function getTemplate(req: AuthRequest, res: Response) { try { const template = await pdfTemplateService.getTemplateById(parseInt(req.params.id)); if (!template) return res.status(404).json({ success: false, error: 'Vorlage nicht gefunden' }); res.json({ success: true, data: template }); } catch (error) { res.status(500).json({ success: false, error: 'Fehler beim Laden' }); } } export async function createTemplate(req: AuthRequest, res: Response) { try { if (!req.file) return res.status(400).json({ success: false, error: 'PDF-Datei erforderlich' }); const { name, description, providerName, phoneFieldPrefix, maxPhoneFields } = req.body; const templatePath = `/uploads/pdf-templates/${req.file.filename}`; // PDF-Felder auslesen let pdfFields: { name: string; type: string; page: number; y: number }[] = []; try { const extracted = await pdfTemplateService.extractPdfFields(templatePath); pdfFields = extracted.fields; } catch { // PDF hat keine Formularfelder - OK, kann trotzdem gespeichert werden } const template = await pdfTemplateService.createTemplate({ name, description, providerName, templatePath, originalName: req.file.originalname, phoneFieldPrefix, maxPhoneFields: maxPhoneFields ? parseInt(maxPhoneFields) : undefined, }); await logChange({ req, action: 'CREATE', resourceType: 'PdfTemplate', resourceId: template.id.toString(), label: `Auftragsvorlage "${name}" angelegt`, }); res.status(201).json({ success: true, data: { ...template, pdfFields } }); } catch (error) { res.status(400).json({ success: false, error: error instanceof Error ? error.message : 'Fehler beim Erstellen', }); } } export async function updateTemplate(req: AuthRequest, res: Response) { try { const id = parseInt(req.params.id); const { name, description, providerName, fieldMapping, phoneFieldPrefix, maxPhoneFields, isActive } = req.body; const template = await pdfTemplateService.updateTemplate(id, { name, description, providerName, fieldMapping: fieldMapping ? JSON.stringify(fieldMapping) : undefined, phoneFieldPrefix, maxPhoneFields: maxPhoneFields !== undefined ? parseInt(maxPhoneFields) : undefined, isActive, }); await logChange({ req, action: 'UPDATE', resourceType: 'PdfTemplate', resourceId: id.toString(), label: `Auftragsvorlage "${template.name}" aktualisiert`, }); res.json({ success: true, data: template }); } catch (error) { res.status(400).json({ success: false, error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren', }); } } export async function deleteTemplate(req: AuthRequest, res: Response) { try { const id = parseInt(req.params.id); const template = await pdfTemplateService.getTemplateById(id); await pdfTemplateService.deleteTemplate(id); await logChange({ req, action: 'DELETE', resourceType: 'PdfTemplate', resourceId: id.toString(), label: `Auftragsvorlage "${template?.name}" gelöscht`, }); res.json({ success: true, message: 'Vorlage gelöscht' }); } catch (error) { res.status(400).json({ success: false, error: 'Fehler beim Löschen' }); } } export async function extractFields(req: AuthRequest, res: Response) { try { const id = parseInt(req.params.id); const template = await pdfTemplateService.getTemplateById(id); if (!template) return res.status(404).json({ success: false, error: 'Vorlage nicht gefunden' }); const result = await pdfTemplateService.extractPdfFields(template.templatePath); res.json({ success: true, data: result.fields, totalPages: result.totalPages }); } catch (error) { res.status(400).json({ success: false, error: error instanceof Error ? error.message : 'Fehler beim Auslesen der PDF-Felder', }); } } export async function getAnnotatedPreview(req: AuthRequest, res: Response) { try { const id = parseInt(req.params.id); const template = await pdfTemplateService.getTemplateById(id); if (!template) return res.status(404).json({ success: false, error: 'Vorlage nicht gefunden' }); const pdfBuffer = await pdfTemplateService.generateAnnotatedPreview(template.templatePath); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', 'inline; filename="preview.pdf"'); res.send(pdfBuffer); } catch (error) { res.status(400).json({ success: false, error: error instanceof Error ? error.message : 'Fehler' }); } } export async function getCrmFields(req: AuthRequest, res: Response) { const maxPhoneFields = req.query.maxPhoneFields ? parseInt(req.query.maxPhoneFields as string) : 8; res.json({ success: true, data: pdfTemplateService.getCrmFieldsForTemplate(maxPhoneFields) }); } export async function getRequiredInputs(req: AuthRequest, res: Response) { try { const templateId = parseInt(req.params.id); const contractId = parseInt(req.params.contractId); const inputs = await pdfTemplateService.getRequiredInputs(templateId, contractId); res.json({ success: true, data: inputs }); } catch (error) { res.status(400).json({ success: false, error: error instanceof Error ? error.message : 'Fehler' }); } } export async function generatePdf(req: AuthRequest, res: Response) { try { const templateId = parseInt(req.params.id); const contractId = parseInt(req.params.contractId); // Extras aus Body (POST) oder Query-Parametern (GET) const stressfreiEmailId = req.body?.stressfreiEmailId || req.query.stressfreiEmailId; const manualValues: Record = req.body?.manualValues || {}; // Manual-Werte aus Query-Parametern extrahieren (manual_manual:1=Wert) if (req.query) { for (const [key, value] of Object.entries(req.query)) { if (key.startsWith('manual_') && typeof value === 'string') { manualValues[key.replace('manual_', '')] = value; } } } const pdfBuffer = await pdfTemplateService.generateFilledPdf(templateId, contractId, { stressfreiEmailId: stressfreiEmailId ? parseInt(stressfreiEmailId as string) : undefined, manualValues: Object.keys(manualValues).length > 0 ? manualValues : undefined, }); const template = await pdfTemplateService.getTemplateById(templateId); const filename = `${template?.name || 'Auftrag'}_${new Date().toISOString().split('T')[0]}.pdf`; await logChange({ req, action: 'CREATE', resourceType: 'GeneratedPdf', label: `PDF "${template?.name}" generiert für Vertrag #${contractId}`, }); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `inline; filename="${encodeURIComponent(filename)}"`); res.send(pdfBuffer); } catch (error) { console.error('PDF generate error:', error); res.status(400).json({ success: false, error: error instanceof Error ? error.message : 'Fehler beim Generieren', }); } }