package iace import ( "bytes" "fmt" "time" "github.com/jung-kurt/gofpdf" ) // ExportFormat represents a supported document export format type ExportFormat string const ( ExportFormatPDF ExportFormat = "pdf" ExportFormatXLSX ExportFormat = "xlsx" ExportFormatDOCX ExportFormat = "docx" ExportFormatMD ExportFormat = "md" ExportFormatJSON ExportFormat = "json" ) // DocumentExporter handles exporting CE technical file data into various formats type DocumentExporter struct{} // NewDocumentExporter creates a new DocumentExporter instance func NewDocumentExporter() *DocumentExporter { return &DocumentExporter{} } // ============================================================================ // PDF Export // ============================================================================ // ExportPDF generates a PDF document containing the full CE technical file func (e *DocumentExporter) ExportPDF( project *Project, sections []TechFileSection, hazards []Hazard, assessments []RiskAssessment, mitigations []Mitigation, classifications []RegulatoryClassification, ) ([]byte, error) { if project == nil { return nil, fmt.Errorf("project must not be nil") } pdf := gofpdf.New("P", "mm", "A4", "") // --- Cover Page --- pdf.AddPage() e.pdfCoverPage(pdf, project) // --- Table of Contents --- pdf.AddPage() e.pdfTableOfContents(pdf, sections) // --- Sections --- for _, section := range sections { pdf.AddPage() e.pdfSection(pdf, section) } // --- Hazard Log --- pdf.AddPage() e.pdfHazardLog(pdf, hazards, assessments) // --- Risk Matrix Summary --- e.pdfRiskMatrixSummary(pdf, assessments) // --- Mitigations Table --- pdf.AddPage() e.pdfMitigationsTable(pdf, mitigations) // --- Regulatory Classifications --- if len(classifications) > 0 { pdf.AddPage() e.pdfClassifications(pdf, classifications) } // --- Footer on every page --- pdf.SetFooterFunc(func() { pdf.SetY(-15) pdf.SetFont("Helvetica", "I", 8) pdf.SetTextColor(128, 128, 128) pdf.CellFormat(0, 5, fmt.Sprintf("CE-Akte %s | Generiert am %s | BreakPilot AI Compliance SDK", project.MachineName, time.Now().Format("02.01.2006 15:04")), "", 0, "C", false, 0, "") }) var buf bytes.Buffer if err := pdf.Output(&buf); err != nil { return nil, fmt.Errorf("failed to generate PDF: %w", err) } return buf.Bytes(), nil } // ============================================================================ // Markdown Export // ============================================================================ // ExportMarkdown generates a Markdown document of the CE technical file sections func (e *DocumentExporter) ExportMarkdown( project *Project, sections []TechFileSection, ) ([]byte, error) { if project == nil { return nil, fmt.Errorf("project must not be nil") } var buf bytes.Buffer buf.WriteString(fmt.Sprintf("# CE-Akte: %s\n\n", project.MachineName)) buf.WriteString("| Eigenschaft | Wert |\n") buf.WriteString("|-------------|------|\n") buf.WriteString(fmt.Sprintf("| Hersteller | %s |\n", project.Manufacturer)) buf.WriteString(fmt.Sprintf("| Maschinentyp | %s |\n", project.MachineType)) if project.CEMarkingTarget != "" { buf.WriteString(fmt.Sprintf("| CE-Kennzeichnungsziel | %s |\n", project.CEMarkingTarget)) } buf.WriteString(fmt.Sprintf("| Status | %s |\n", project.Status)) buf.WriteString(fmt.Sprintf("| Datum | %s |\n", time.Now().Format("02.01.2006"))) buf.WriteString("\n") if project.Description != "" { buf.WriteString(fmt.Sprintf("> %s\n\n", project.Description)) } for _, section := range sections { buf.WriteString(fmt.Sprintf("## %s\n\n", section.Title)) buf.WriteString(fmt.Sprintf("*Typ: %s | Status: %s | Version: %d*\n\n", section.SectionType, string(section.Status), section.Version)) if section.Content != "" { buf.WriteString(section.Content) buf.WriteString("\n\n") } else { buf.WriteString("*(Kein Inhalt vorhanden)*\n\n") } } buf.WriteString("---\n\n") buf.WriteString(fmt.Sprintf("*Generiert am %s mit BreakPilot AI Compliance SDK*\n", time.Now().Format("02.01.2006 15:04"))) return buf.Bytes(), nil }