package training import ( "time" "github.com/google/uuid" ) // ============================================================================ // Constants / Enums // ============================================================================ // RegulationArea represents a compliance regulation area type RegulationArea string const ( RegulationDSGVO RegulationArea = "dsgvo" RegulationNIS2 RegulationArea = "nis2" RegulationISO27001 RegulationArea = "iso27001" RegulationAIAct RegulationArea = "ai_act" RegulationGeschGehG RegulationArea = "geschgehg" RegulationHinSchG RegulationArea = "hinschg" ) // FrequencyType represents the training frequency type FrequencyType string const ( FrequencyOnboarding FrequencyType = "onboarding" FrequencyAnnual FrequencyType = "annual" FrequencyEventTrigger FrequencyType = "event_trigger" FrequencyMicro FrequencyType = "micro" ) // AssignmentStatus represents the status of a training assignment type AssignmentStatus string const ( AssignmentStatusPending AssignmentStatus = "pending" AssignmentStatusInProgress AssignmentStatus = "in_progress" AssignmentStatusCompleted AssignmentStatus = "completed" AssignmentStatusOverdue AssignmentStatus = "overdue" AssignmentStatusExpired AssignmentStatus = "expired" ) // TriggerType represents how a training was assigned type TriggerType string const ( TriggerOnboarding TriggerType = "onboarding" TriggerAnnual TriggerType = "annual" TriggerEvent TriggerType = "event" TriggerManual TriggerType = "manual" ) // ContentFormat represents the format of module content type ContentFormat string const ( ContentFormatMarkdown ContentFormat = "markdown" ContentFormatHTML ContentFormat = "html" ) // Difficulty represents the difficulty level of a quiz question type Difficulty string const ( DifficultyEasy Difficulty = "easy" DifficultyMedium Difficulty = "medium" DifficultyHard Difficulty = "hard" ) // AuditAction represents an action in the audit trail type AuditAction string const ( AuditActionAssigned AuditAction = "assigned" AuditActionStarted AuditAction = "started" AuditActionCompleted AuditAction = "completed" AuditActionQuizSubmitted AuditAction = "quiz_submitted" AuditActionEscalated AuditAction = "escalated" AuditActionCertificateIssued AuditAction = "certificate_issued" AuditActionContentGenerated AuditAction = "content_generated" ) // AuditEntityType represents the type of entity in audit log type AuditEntityType string const ( AuditEntityAssignment AuditEntityType = "assignment" AuditEntityModule AuditEntityType = "module" AuditEntityQuiz AuditEntityType = "quiz" AuditEntityCertificate AuditEntityType = "certificate" ) // ============================================================================ // Role Constants // ============================================================================ const ( RoleR1 = "R1" // Geschaeftsfuehrung RoleR2 = "R2" // IT-Leitung RoleR3 = "R3" // DSB RoleR4 = "R4" // ISB RoleR5 = "R5" // HR RoleR6 = "R6" // Einkauf RoleR7 = "R7" // Fachabteilung RoleR8 = "R8" // IT-Admin RoleR9 = "R9" // Alle Mitarbeiter ) // RoleLabels maps role codes to human-readable labels var RoleLabels = map[string]string{ RoleR1: "Geschaeftsfuehrung", RoleR2: "IT-Leitung", RoleR3: "Datenschutzbeauftragter", RoleR4: "Informationssicherheitsbeauftragter", RoleR5: "HR / Personal", RoleR6: "Einkauf / Beschaffung", RoleR7: "Fachabteilung", RoleR8: "IT-Administration", RoleR9: "Alle Mitarbeiter", } // NIS2RoleMapping maps internal roles to NIS2 levels var NIS2RoleMapping = map[string]string{ RoleR1: "N1", // Geschaeftsfuehrung RoleR2: "N2", // IT-Leitung RoleR3: "N3", // DSB RoleR4: "N3", // ISB RoleR5: "N4", // HR RoleR6: "N4", // Einkauf RoleR7: "N5", // Fachabteilung RoleR8: "N2", // IT-Admin RoleR9: "N5", // Alle Mitarbeiter } // ============================================================================ // Main Entities // ============================================================================ // TrainingModule represents a compliance training module type TrainingModule struct { ID uuid.UUID `json:"id"` TenantID uuid.UUID `json:"tenant_id"` AcademyCourseID *uuid.UUID `json:"academy_course_id,omitempty"` ModuleCode string `json:"module_code"` Title string `json:"title"` Description string `json:"description,omitempty"` RegulationArea RegulationArea `json:"regulation_area"` NIS2Relevant bool `json:"nis2_relevant"` ISOControls []string `json:"iso_controls"` // JSONB FrequencyType FrequencyType `json:"frequency_type"` ValidityDays int `json:"validity_days"` RiskWeight float64 `json:"risk_weight"` ContentType string `json:"content_type"` DurationMinutes int `json:"duration_minutes"` PassThreshold int `json:"pass_threshold"` IsActive bool `json:"is_active"` SortOrder int `json:"sort_order"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // TrainingMatrixEntry represents a role-to-module mapping in the CTM type TrainingMatrixEntry struct { ID uuid.UUID `json:"id"` TenantID uuid.UUID `json:"tenant_id"` RoleCode string `json:"role_code"` ModuleID uuid.UUID `json:"module_id"` IsMandatory bool `json:"is_mandatory"` Priority int `json:"priority"` CreatedAt time.Time `json:"created_at"` // Joined fields (optional, populated in queries) ModuleCode string `json:"module_code,omitempty"` ModuleTitle string `json:"module_title,omitempty"` } // TrainingAssignment represents a user's training assignment type TrainingAssignment struct { ID uuid.UUID `json:"id"` TenantID uuid.UUID `json:"tenant_id"` ModuleID uuid.UUID `json:"module_id"` UserID uuid.UUID `json:"user_id"` UserName string `json:"user_name"` UserEmail string `json:"user_email"` RoleCode string `json:"role_code,omitempty"` TriggerType TriggerType `json:"trigger_type"` TriggerEvent string `json:"trigger_event,omitempty"` Status AssignmentStatus `json:"status"` ProgressPercent int `json:"progress_percent"` QuizScore *float64 `json:"quiz_score,omitempty"` QuizPassed *bool `json:"quiz_passed,omitempty"` QuizAttempts int `json:"quiz_attempts"` StartedAt *time.Time `json:"started_at,omitempty"` CompletedAt *time.Time `json:"completed_at,omitempty"` Deadline time.Time `json:"deadline"` CertificateID *uuid.UUID `json:"certificate_id,omitempty"` EscalationLevel int `json:"escalation_level"` LastEscalationAt *time.Time `json:"last_escalation_at,omitempty"` EnrollmentID *uuid.UUID `json:"enrollment_id,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` // Joined fields ModuleCode string `json:"module_code,omitempty"` ModuleTitle string `json:"module_title,omitempty"` } // QuizQuestion represents a persistent quiz question for a module type QuizQuestion struct { ID uuid.UUID `json:"id"` ModuleID uuid.UUID `json:"module_id"` Question string `json:"question"` Options []string `json:"options"` // JSONB CorrectIndex int `json:"correct_index"` Explanation string `json:"explanation,omitempty"` Difficulty Difficulty `json:"difficulty"` IsActive bool `json:"is_active"` SortOrder int `json:"sort_order"` CreatedAt time.Time `json:"created_at"` } // QuizAttempt represents a single quiz attempt by a user type QuizAttempt struct { ID uuid.UUID `json:"id"` AssignmentID uuid.UUID `json:"assignment_id"` UserID uuid.UUID `json:"user_id"` Answers []QuizAnswer `json:"answers"` // JSONB Score float64 `json:"score"` Passed bool `json:"passed"` CorrectCount int `json:"correct_count"` TotalCount int `json:"total_count"` DurationSeconds *int `json:"duration_seconds,omitempty"` AttemptedAt time.Time `json:"attempted_at"` } // QuizAnswer represents a single answer within a quiz attempt type QuizAnswer struct { QuestionID uuid.UUID `json:"question_id"` SelectedIndex int `json:"selected_index"` Correct bool `json:"correct"` } // AuditLogEntry represents an entry in the training audit trail type AuditLogEntry struct { ID uuid.UUID `json:"id"` TenantID uuid.UUID `json:"tenant_id"` UserID *uuid.UUID `json:"user_id,omitempty"` Action AuditAction `json:"action"` EntityType AuditEntityType `json:"entity_type"` EntityID *uuid.UUID `json:"entity_id,omitempty"` Details map[string]interface{} `json:"details"` // JSONB IPAddress string `json:"ip_address,omitempty"` CreatedAt time.Time `json:"created_at"` } // ModuleContent represents LLM-generated or manual content for a module type ModuleContent struct { ID uuid.UUID `json:"id"` ModuleID uuid.UUID `json:"module_id"` Version int `json:"version"` ContentFormat ContentFormat `json:"content_format"` ContentBody string `json:"content_body"` Summary string `json:"summary,omitempty"` GeneratedBy string `json:"generated_by,omitempty"` LLMModel string `json:"llm_model,omitempty"` IsPublished bool `json:"is_published"` ReviewedBy *uuid.UUID `json:"reviewed_by,omitempty"` ReviewedAt *time.Time `json:"reviewed_at,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // TrainingStats contains aggregated training metrics type TrainingStats struct { TotalModules int `json:"total_modules"` TotalAssignments int `json:"total_assignments"` CompletionRate float64 `json:"completion_rate"` OverdueCount int `json:"overdue_count"` PendingCount int `json:"pending_count"` InProgressCount int `json:"in_progress_count"` CompletedCount int `json:"completed_count"` AvgQuizScore float64 `json:"avg_quiz_score"` AvgCompletionDays float64 `json:"avg_completion_days"` UpcomingDeadlines int `json:"upcoming_deadlines"` // within 7 days } // ComplianceGap represents a missing or overdue training requirement type ComplianceGap struct { ModuleID uuid.UUID `json:"module_id"` ModuleCode string `json:"module_code"` ModuleTitle string `json:"module_title"` RegulationArea RegulationArea `json:"regulation_area"` RoleCode string `json:"role_code"` IsMandatory bool `json:"is_mandatory"` AssignmentID *uuid.UUID `json:"assignment_id,omitempty"` Status string `json:"status"` // "missing", "overdue", "expired" Deadline *time.Time `json:"deadline,omitempty"` } // EscalationResult represents the result of an escalation check type EscalationResult struct { AssignmentID uuid.UUID `json:"assignment_id"` UserID uuid.UUID `json:"user_id"` UserName string `json:"user_name"` UserEmail string `json:"user_email"` ModuleTitle string `json:"module_title"` PreviousLevel int `json:"previous_level"` NewLevel int `json:"new_level"` DaysOverdue int `json:"days_overdue"` EscalationLabel string `json:"escalation_label"` } // DeadlineInfo represents upcoming deadline information type DeadlineInfo struct { AssignmentID uuid.UUID `json:"assignment_id"` ModuleCode string `json:"module_code"` ModuleTitle string `json:"module_title"` UserID uuid.UUID `json:"user_id"` UserName string `json:"user_name"` Deadline time.Time `json:"deadline"` DaysLeft int `json:"days_left"` Status AssignmentStatus `json:"status"` } // ============================================================================ // Filter Types // ============================================================================ // ModuleFilters defines filters for listing modules type ModuleFilters struct { RegulationArea RegulationArea FrequencyType FrequencyType IsActive *bool NIS2Relevant *bool Search string Limit int Offset int } // AssignmentFilters defines filters for listing assignments type AssignmentFilters struct { ModuleID *uuid.UUID UserID *uuid.UUID RoleCode string Status AssignmentStatus Overdue *bool Limit int Offset int } // AuditLogFilters defines filters for listing audit log entries type AuditLogFilters struct { UserID *uuid.UUID Action AuditAction EntityType AuditEntityType Limit int Offset int } // ============================================================================ // API Request/Response Types // ============================================================================ // CreateModuleRequest is the API request for creating a training module type CreateModuleRequest struct { ModuleCode string `json:"module_code" binding:"required"` Title string `json:"title" binding:"required"` Description string `json:"description,omitempty"` RegulationArea RegulationArea `json:"regulation_area" binding:"required"` NIS2Relevant bool `json:"nis2_relevant"` ISOControls []string `json:"iso_controls,omitempty"` FrequencyType FrequencyType `json:"frequency_type" binding:"required"` ValidityDays int `json:"validity_days"` RiskWeight float64 `json:"risk_weight"` ContentType string `json:"content_type"` DurationMinutes int `json:"duration_minutes"` PassThreshold int `json:"pass_threshold"` } // UpdateModuleRequest is the API request for updating a training module type UpdateModuleRequest struct { Title *string `json:"title,omitempty"` Description *string `json:"description,omitempty"` NIS2Relevant *bool `json:"nis2_relevant,omitempty"` ISOControls []string `json:"iso_controls,omitempty"` ValidityDays *int `json:"validity_days,omitempty"` RiskWeight *float64 `json:"risk_weight,omitempty"` DurationMinutes *int `json:"duration_minutes,omitempty"` PassThreshold *int `json:"pass_threshold,omitempty"` IsActive *bool `json:"is_active,omitempty"` } // SetMatrixEntryRequest is the API request for setting a CTM entry type SetMatrixEntryRequest struct { RoleCode string `json:"role_code" binding:"required"` ModuleID uuid.UUID `json:"module_id" binding:"required"` IsMandatory bool `json:"is_mandatory"` Priority int `json:"priority"` } // ComputeAssignmentsRequest is the API request for computing assignments type ComputeAssignmentsRequest struct { UserID uuid.UUID `json:"user_id" binding:"required"` UserName string `json:"user_name" binding:"required"` UserEmail string `json:"user_email" binding:"required"` Roles []string `json:"roles" binding:"required"` Trigger string `json:"trigger"` } // UpdateAssignmentProgressRequest updates progress on an assignment type UpdateAssignmentProgressRequest struct { Progress int `json:"progress" binding:"required"` } // SubmitTrainingQuizRequest is the API request for submitting a quiz type SubmitTrainingQuizRequest struct { AssignmentID uuid.UUID `json:"assignment_id" binding:"required"` Answers []QuizAnswer `json:"answers" binding:"required"` DurationSeconds *int `json:"duration_seconds,omitempty"` } // SubmitTrainingQuizResponse is the API response for quiz submission type SubmitTrainingQuizResponse struct { AttemptID uuid.UUID `json:"attempt_id"` Score float64 `json:"score"` Passed bool `json:"passed"` CorrectCount int `json:"correct_count"` TotalCount int `json:"total_count"` Threshold int `json:"threshold"` } // GenerateContentRequest is the API request for LLM content generation type GenerateContentRequest struct { ModuleID uuid.UUID `json:"module_id" binding:"required"` Language string `json:"language"` } // GenerateQuizRequest is the API request for LLM quiz generation type GenerateQuizRequest struct { ModuleID uuid.UUID `json:"module_id" binding:"required"` Count int `json:"count"` } // PublishContentRequest is the API request for publishing content type PublishContentRequest struct { ReviewedBy uuid.UUID `json:"reviewed_by"` } // BulkAssignRequest is the API request for bulk assigning a module type BulkAssignRequest struct { ModuleID uuid.UUID `json:"module_id" binding:"required"` RoleCodes []string `json:"role_codes" binding:"required"` Trigger string `json:"trigger"` Deadline time.Time `json:"deadline" binding:"required"` } // ModuleListResponse is the API response for listing modules type ModuleListResponse struct { Modules []TrainingModule `json:"modules"` Total int `json:"total"` } // AssignmentListResponse is the API response for listing assignments type AssignmentListResponse struct { Assignments []TrainingAssignment `json:"assignments"` Total int `json:"total"` } // MatrixResponse is the API response for the full training matrix type MatrixResponse struct { Entries map[string][]TrainingMatrixEntry `json:"entries"` // role_code -> entries Roles map[string]string `json:"roles"` // role_code -> label } // AuditLogResponse is the API response for listing audit log entries type AuditLogResponse struct { Entries []AuditLogEntry `json:"entries"` Total int `json:"total"` } // EscalationResponse is the API response for escalation check type EscalationResponse struct { Results []EscalationResult `json:"results"` TotalChecked int `json:"total_checked"` Escalated int `json:"escalated"` } // DeadlineListResponse is the API response for listing deadlines type DeadlineListResponse struct { Deadlines []DeadlineInfo `json:"deadlines"` Total int `json:"total"` } // BulkResult holds the result of a bulk generation operation type BulkResult struct { Generated int `json:"generated"` Skipped int `json:"skipped"` Errors []string `json:"errors"` }