fix(admin-v2): Restore complete admin-v2 application
The admin-v2 application was incomplete in the repository. This commit restores all missing components: - Admin pages (76 pages): dashboard, ai, compliance, dsgvo, education, infrastructure, communication, development, onboarding, rbac - SDK pages (45 pages): tom, dsfa, vvt, loeschfristen, einwilligungen, vendor-compliance, tom-generator, dsr, and more - Developer portal (25 pages): API docs, SDK guides, frameworks - All components, lib files, hooks, and types - Updated package.json with all dependencies The issue was caused by incomplete initial repository state - the full admin-v2 codebase existed in backend/admin-v2 and docs-src/admin-v2 but was never fully synced to the main admin-v2 directory. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
664
admin-v2/lib/sdk/dsr/api.ts
Normal file
664
admin-v2/lib/sdk/dsr/api.ts
Normal file
@@ -0,0 +1,664 @@
|
||||
/**
|
||||
* DSR API Client
|
||||
*
|
||||
* API client for Data Subject Request management
|
||||
* Connects to the Go Consent Service backend
|
||||
*/
|
||||
|
||||
import {
|
||||
DSRRequest,
|
||||
DSRListResponse,
|
||||
DSRFilters,
|
||||
DSRCreateRequest,
|
||||
DSRUpdateRequest,
|
||||
DSRVerifyIdentityRequest,
|
||||
DSRCompleteRequest,
|
||||
DSRRejectRequest,
|
||||
DSRExtendDeadlineRequest,
|
||||
DSRSendCommunicationRequest,
|
||||
DSRCommunication,
|
||||
DSRAuditEntry,
|
||||
DSRStatistics,
|
||||
DSRDataExport,
|
||||
DSRErasureChecklist
|
||||
} from './types'
|
||||
|
||||
// =============================================================================
|
||||
// CONFIGURATION
|
||||
// =============================================================================
|
||||
|
||||
const DSR_API_BASE = process.env.NEXT_PUBLIC_CONSENT_SERVICE_URL || 'http://localhost:8081'
|
||||
const API_TIMEOUT = 30000 // 30 seconds
|
||||
|
||||
// =============================================================================
|
||||
// HELPER FUNCTIONS
|
||||
// =============================================================================
|
||||
|
||||
function getTenantId(): string {
|
||||
// In a real app, this would come from auth context or localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
return localStorage.getItem('tenantId') || 'default-tenant'
|
||||
}
|
||||
return 'default-tenant'
|
||||
}
|
||||
|
||||
function getAuthHeaders(): HeadersInit {
|
||||
const headers: HeadersInit = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Tenant-ID': getTenantId()
|
||||
}
|
||||
|
||||
// Add auth token if available
|
||||
if (typeof window !== 'undefined') {
|
||||
const token = localStorage.getItem('authToken')
|
||||
if (token) {
|
||||
headers['Authorization'] = `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
|
||||
return headers
|
||||
}
|
||||
|
||||
async function fetchWithTimeout<T>(
|
||||
url: string,
|
||||
options: RequestInit = {},
|
||||
timeout: number = API_TIMEOUT
|
||||
): Promise<T> {
|
||||
const controller = new AbortController()
|
||||
const timeoutId = setTimeout(() => controller.abort(), timeout)
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
...options,
|
||||
signal: controller.signal,
|
||||
headers: {
|
||||
...getAuthHeaders(),
|
||||
...options.headers
|
||||
}
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorBody = await response.text()
|
||||
let errorMessage = `HTTP ${response.status}: ${response.statusText}`
|
||||
try {
|
||||
const errorJson = JSON.parse(errorBody)
|
||||
errorMessage = errorJson.error || errorJson.message || errorMessage
|
||||
} catch {
|
||||
// Keep the HTTP status message
|
||||
}
|
||||
throw new Error(errorMessage)
|
||||
}
|
||||
|
||||
// Handle empty responses
|
||||
const contentType = response.headers.get('content-type')
|
||||
if (contentType && contentType.includes('application/json')) {
|
||||
return response.json()
|
||||
}
|
||||
|
||||
return {} as T
|
||||
} finally {
|
||||
clearTimeout(timeoutId)
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// DSR LIST & CRUD
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Fetch all DSR requests with optional filters
|
||||
*/
|
||||
export async function fetchDSRList(filters?: DSRFilters): Promise<DSRListResponse> {
|
||||
const params = new URLSearchParams()
|
||||
|
||||
if (filters) {
|
||||
if (filters.status) {
|
||||
const statuses = Array.isArray(filters.status) ? filters.status : [filters.status]
|
||||
statuses.forEach(s => params.append('status', s))
|
||||
}
|
||||
if (filters.type) {
|
||||
const types = Array.isArray(filters.type) ? filters.type : [filters.type]
|
||||
types.forEach(t => params.append('type', t))
|
||||
}
|
||||
if (filters.priority) params.set('priority', filters.priority)
|
||||
if (filters.assignedTo) params.set('assignedTo', filters.assignedTo)
|
||||
if (filters.overdue !== undefined) params.set('overdue', String(filters.overdue))
|
||||
if (filters.search) params.set('search', filters.search)
|
||||
if (filters.dateFrom) params.set('dateFrom', filters.dateFrom)
|
||||
if (filters.dateTo) params.set('dateTo', filters.dateTo)
|
||||
}
|
||||
|
||||
const queryString = params.toString()
|
||||
const url = `${DSR_API_BASE}/api/v1/admin/dsr${queryString ? `?${queryString}` : ''}`
|
||||
|
||||
return fetchWithTimeout<DSRListResponse>(url)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a single DSR request by ID
|
||||
*/
|
||||
export async function fetchDSR(id: string): Promise<DSRRequest> {
|
||||
return fetchWithTimeout<DSRRequest>(`${DSR_API_BASE}/api/v1/admin/dsr/${id}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DSR request
|
||||
*/
|
||||
export async function createDSR(request: DSRCreateRequest): Promise<DSRRequest> {
|
||||
return fetchWithTimeout<DSRRequest>(`${DSR_API_BASE}/api/v1/admin/dsr`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(request)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a DSR request
|
||||
*/
|
||||
export async function updateDSR(id: string, update: DSRUpdateRequest): Promise<DSRRequest> {
|
||||
return fetchWithTimeout<DSRRequest>(`${DSR_API_BASE}/api/v1/admin/dsr/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(update)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a DSR request (soft delete - marks as cancelled)
|
||||
*/
|
||||
export async function deleteDSR(id: string): Promise<void> {
|
||||
await fetchWithTimeout<void>(`${DSR_API_BASE}/api/v1/admin/dsr/${id}`, {
|
||||
method: 'DELETE'
|
||||
})
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// DSR WORKFLOW ACTIONS
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Verify the identity of the requester
|
||||
*/
|
||||
export async function verifyIdentity(
|
||||
dsrId: string,
|
||||
verification: DSRVerifyIdentityRequest
|
||||
): Promise<DSRRequest> {
|
||||
return fetchWithTimeout<DSRRequest>(
|
||||
`${DSR_API_BASE}/api/v1/admin/dsr/${dsrId}/verify-identity`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(verification)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete a DSR request
|
||||
*/
|
||||
export async function completeDSR(
|
||||
dsrId: string,
|
||||
completion?: DSRCompleteRequest
|
||||
): Promise<DSRRequest> {
|
||||
return fetchWithTimeout<DSRRequest>(
|
||||
`${DSR_API_BASE}/api/v1/admin/dsr/${dsrId}/complete`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(completion || {})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Reject a DSR request
|
||||
*/
|
||||
export async function rejectDSR(
|
||||
dsrId: string,
|
||||
rejection: DSRRejectRequest
|
||||
): Promise<DSRRequest> {
|
||||
return fetchWithTimeout<DSRRequest>(
|
||||
`${DSR_API_BASE}/api/v1/admin/dsr/${dsrId}/reject`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(rejection)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the deadline for a DSR request
|
||||
*/
|
||||
export async function extendDeadline(
|
||||
dsrId: string,
|
||||
extension: DSRExtendDeadlineRequest
|
||||
): Promise<DSRRequest> {
|
||||
return fetchWithTimeout<DSRRequest>(
|
||||
`${DSR_API_BASE}/api/v1/admin/dsr/${dsrId}/extend`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(extension)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a DSR request to a user
|
||||
*/
|
||||
export async function assignDSR(
|
||||
dsrId: string,
|
||||
assignedTo: string
|
||||
): Promise<DSRRequest> {
|
||||
return fetchWithTimeout<DSRRequest>(
|
||||
`${DSR_API_BASE}/api/v1/admin/dsr/${dsrId}/assign`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ assignedTo })
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// COMMUNICATION
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Get all communications for a DSR request
|
||||
*/
|
||||
export async function getCommunications(dsrId: string): Promise<DSRCommunication[]> {
|
||||
return fetchWithTimeout<DSRCommunication[]>(
|
||||
`${DSR_API_BASE}/api/v1/admin/dsr/${dsrId}/communications`
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a communication (email, letter, internal note)
|
||||
*/
|
||||
export async function sendCommunication(
|
||||
dsrId: string,
|
||||
communication: DSRSendCommunicationRequest
|
||||
): Promise<DSRCommunication> {
|
||||
return fetchWithTimeout<DSRCommunication>(
|
||||
`${DSR_API_BASE}/api/v1/admin/dsr/${dsrId}/send-communication`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(communication)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// AUDIT LOG
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Get audit log entries for a DSR request
|
||||
*/
|
||||
export async function getAuditLog(dsrId: string): Promise<DSRAuditEntry[]> {
|
||||
return fetchWithTimeout<DSRAuditEntry[]>(
|
||||
`${DSR_API_BASE}/api/v1/admin/dsr/${dsrId}/audit`
|
||||
)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// STATISTICS
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Get DSR statistics
|
||||
*/
|
||||
export async function getDSRStatistics(): Promise<DSRStatistics> {
|
||||
return fetchWithTimeout<DSRStatistics>(
|
||||
`${DSR_API_BASE}/api/v1/admin/dsr/statistics`
|
||||
)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// DATA EXPORT (Art. 15, 20)
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Generate data export for Art. 15 (access) or Art. 20 (portability)
|
||||
*/
|
||||
export async function generateDataExport(
|
||||
dsrId: string,
|
||||
format: 'json' | 'csv' | 'xml' | 'pdf' = 'json'
|
||||
): Promise<DSRDataExport> {
|
||||
return fetchWithTimeout<DSRDataExport>(
|
||||
`${DSR_API_BASE}/api/v1/admin/dsr/${dsrId}/export`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ format })
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Download generated data export
|
||||
*/
|
||||
export async function downloadDataExport(dsrId: string): Promise<Blob> {
|
||||
const response = await fetch(
|
||||
`${DSR_API_BASE}/api/v1/admin/dsr/${dsrId}/export/download`,
|
||||
{
|
||||
headers: getAuthHeaders()
|
||||
}
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Download failed: ${response.statusText}`)
|
||||
}
|
||||
|
||||
return response.blob()
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// ERASURE CHECKLIST (Art. 17)
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Get the erasure checklist for an Art. 17 request
|
||||
*/
|
||||
export async function getErasureChecklist(dsrId: string): Promise<DSRErasureChecklist> {
|
||||
return fetchWithTimeout<DSRErasureChecklist>(
|
||||
`${DSR_API_BASE}/api/v1/admin/dsr/${dsrId}/erasure-checklist`
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the erasure checklist
|
||||
*/
|
||||
export async function updateErasureChecklist(
|
||||
dsrId: string,
|
||||
checklist: DSRErasureChecklist
|
||||
): Promise<DSRErasureChecklist> {
|
||||
return fetchWithTimeout<DSRErasureChecklist>(
|
||||
`${DSR_API_BASE}/api/v1/admin/dsr/${dsrId}/erasure-checklist`,
|
||||
{
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(checklist)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// EMAIL TEMPLATES
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Get available email templates
|
||||
*/
|
||||
export async function getEmailTemplates(): Promise<{ id: string; name: string; stage: string }[]> {
|
||||
return fetchWithTimeout<{ id: string; name: string; stage: string }[]>(
|
||||
`${DSR_API_BASE}/api/v1/admin/dsr/email-templates`
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Preview an email with variables filled in
|
||||
*/
|
||||
export async function previewEmail(
|
||||
templateId: string,
|
||||
dsrId: string
|
||||
): Promise<{ subject: string; body: string }> {
|
||||
return fetchWithTimeout<{ subject: string; body: string }>(
|
||||
`${DSR_API_BASE}/api/v1/admin/dsr/email-templates/${templateId}/preview`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ dsrId })
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// MOCK DATA FUNCTIONS (for development without backend)
|
||||
// =============================================================================
|
||||
|
||||
export function createMockDSRList(): DSRRequest[] {
|
||||
const now = new Date()
|
||||
|
||||
return [
|
||||
{
|
||||
id: 'dsr-001',
|
||||
referenceNumber: 'DSR-2025-000001',
|
||||
type: 'access',
|
||||
status: 'intake',
|
||||
priority: 'high',
|
||||
requester: {
|
||||
name: 'Max Mustermann',
|
||||
email: 'max.mustermann@example.de'
|
||||
},
|
||||
source: 'web_form',
|
||||
sourceDetails: 'Kontaktformular auf breakpilot.de',
|
||||
receivedAt: new Date(now.getTime() - 2 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
deadline: {
|
||||
originalDeadline: new Date(now.getTime() + 28 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
currentDeadline: new Date(now.getTime() + 28 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
extended: false
|
||||
},
|
||||
identityVerification: {
|
||||
verified: false
|
||||
},
|
||||
assignment: {
|
||||
assignedTo: null
|
||||
},
|
||||
createdAt: new Date(now.getTime() - 2 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
createdBy: 'system',
|
||||
updatedAt: new Date(now.getTime() - 2 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
tenantId: 'default-tenant'
|
||||
},
|
||||
{
|
||||
id: 'dsr-002',
|
||||
referenceNumber: 'DSR-2025-000002',
|
||||
type: 'erasure',
|
||||
status: 'identity_verification',
|
||||
priority: 'high',
|
||||
requester: {
|
||||
name: 'Anna Schmidt',
|
||||
email: 'anna.schmidt@example.de',
|
||||
phone: '+49 170 1234567'
|
||||
},
|
||||
source: 'email',
|
||||
requestText: 'Ich moechte, dass alle meine Daten geloescht werden.',
|
||||
receivedAt: new Date(now.getTime() - 5 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
deadline: {
|
||||
originalDeadline: new Date(now.getTime() + 9 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
currentDeadline: new Date(now.getTime() + 9 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
extended: false
|
||||
},
|
||||
identityVerification: {
|
||||
verified: false
|
||||
},
|
||||
assignment: {
|
||||
assignedTo: 'DSB Mueller',
|
||||
assignedAt: new Date(now.getTime() - 4 * 24 * 60 * 60 * 1000).toISOString()
|
||||
},
|
||||
createdAt: new Date(now.getTime() - 5 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
createdBy: 'system',
|
||||
updatedAt: new Date(now.getTime() - 4 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
tenantId: 'default-tenant'
|
||||
},
|
||||
{
|
||||
id: 'dsr-003',
|
||||
referenceNumber: 'DSR-2025-000003',
|
||||
type: 'rectification',
|
||||
status: 'processing',
|
||||
priority: 'normal',
|
||||
requester: {
|
||||
name: 'Peter Meier',
|
||||
email: 'peter.meier@example.de'
|
||||
},
|
||||
source: 'email',
|
||||
requestText: 'Meine Adresse ist falsch gespeichert.',
|
||||
receivedAt: new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
deadline: {
|
||||
originalDeadline: new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
currentDeadline: new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
extended: false
|
||||
},
|
||||
identityVerification: {
|
||||
verified: true,
|
||||
method: 'existing_account',
|
||||
verifiedAt: new Date(now.getTime() - 6 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
verifiedBy: 'DSB Mueller'
|
||||
},
|
||||
assignment: {
|
||||
assignedTo: 'DSB Mueller',
|
||||
assignedAt: new Date(now.getTime() - 6 * 24 * 60 * 60 * 1000).toISOString()
|
||||
},
|
||||
rectificationDetails: {
|
||||
fieldsToCorrect: [
|
||||
{
|
||||
field: 'Adresse',
|
||||
currentValue: 'Musterstr. 1, 12345 Berlin',
|
||||
requestedValue: 'Musterstr. 10, 12345 Berlin',
|
||||
corrected: false
|
||||
}
|
||||
]
|
||||
},
|
||||
createdAt: new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
createdBy: 'system',
|
||||
updatedAt: new Date(now.getTime() - 1 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
tenantId: 'default-tenant'
|
||||
},
|
||||
{
|
||||
id: 'dsr-004',
|
||||
referenceNumber: 'DSR-2025-000004',
|
||||
type: 'portability',
|
||||
status: 'processing',
|
||||
priority: 'normal',
|
||||
requester: {
|
||||
name: 'Lisa Weber',
|
||||
email: 'lisa.weber@example.de'
|
||||
},
|
||||
source: 'web_form',
|
||||
receivedAt: new Date(now.getTime() - 10 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
deadline: {
|
||||
originalDeadline: new Date(now.getTime() + 20 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
currentDeadline: new Date(now.getTime() + 20 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
extended: false
|
||||
},
|
||||
identityVerification: {
|
||||
verified: true,
|
||||
method: 'id_document',
|
||||
verifiedAt: new Date(now.getTime() - 8 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
verifiedBy: 'DSB Mueller'
|
||||
},
|
||||
assignment: {
|
||||
assignedTo: 'IT Team',
|
||||
assignedAt: new Date(now.getTime() - 8 * 24 * 60 * 60 * 1000).toISOString()
|
||||
},
|
||||
notes: 'JSON-Export wird vorbereitet',
|
||||
createdAt: new Date(now.getTime() - 10 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
createdBy: 'system',
|
||||
updatedAt: new Date(now.getTime() - 2 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
tenantId: 'default-tenant'
|
||||
},
|
||||
{
|
||||
id: 'dsr-005',
|
||||
referenceNumber: 'DSR-2025-000005',
|
||||
type: 'objection',
|
||||
status: 'rejected',
|
||||
priority: 'low',
|
||||
requester: {
|
||||
name: 'Thomas Klein',
|
||||
email: 'thomas.klein@example.de'
|
||||
},
|
||||
source: 'letter',
|
||||
requestText: 'Ich widerspreche der Verarbeitung meiner Daten fuer Marketingzwecke.',
|
||||
receivedAt: new Date(now.getTime() - 35 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
deadline: {
|
||||
originalDeadline: new Date(now.getTime() - 5 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
currentDeadline: new Date(now.getTime() - 5 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
extended: false
|
||||
},
|
||||
completedAt: new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
identityVerification: {
|
||||
verified: true,
|
||||
method: 'postal',
|
||||
verifiedAt: new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
verifiedBy: 'DSB Mueller'
|
||||
},
|
||||
assignment: {
|
||||
assignedTo: 'Rechtsabteilung',
|
||||
assignedAt: new Date(now.getTime() - 28 * 24 * 60 * 60 * 1000).toISOString()
|
||||
},
|
||||
objectionDetails: {
|
||||
processingPurpose: 'Marketing',
|
||||
legalBasis: 'Berechtigtes Interesse (Art. 6(1)(f))',
|
||||
objectionGrounds: 'Keine konkreten Gruende genannt',
|
||||
decision: 'rejected',
|
||||
decisionReason: 'Zwingende schutzwuerdige Gruende fuer die Verarbeitung ueberwiegen',
|
||||
decisionBy: 'Rechtsabteilung',
|
||||
decisionAt: new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000).toISOString()
|
||||
},
|
||||
notes: 'Widerspruch unberechtigt - zwingende schutzwuerdige Gruende',
|
||||
createdAt: new Date(now.getTime() - 35 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
createdBy: 'system',
|
||||
updatedAt: new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
tenantId: 'default-tenant'
|
||||
},
|
||||
{
|
||||
id: 'dsr-006',
|
||||
referenceNumber: 'DSR-2025-000006',
|
||||
type: 'access',
|
||||
status: 'completed',
|
||||
priority: 'normal',
|
||||
requester: {
|
||||
name: 'Sarah Braun',
|
||||
email: 'sarah.braun@example.de'
|
||||
},
|
||||
source: 'email',
|
||||
receivedAt: new Date(now.getTime() - 45 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
deadline: {
|
||||
originalDeadline: new Date(now.getTime() - 15 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
currentDeadline: new Date(now.getTime() - 15 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
extended: false
|
||||
},
|
||||
completedAt: new Date(now.getTime() - 20 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
identityVerification: {
|
||||
verified: true,
|
||||
method: 'id_document',
|
||||
verifiedAt: new Date(now.getTime() - 42 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
verifiedBy: 'DSB Mueller'
|
||||
},
|
||||
assignment: {
|
||||
assignedTo: 'DSB Mueller',
|
||||
assignedAt: new Date(now.getTime() - 42 * 24 * 60 * 60 * 1000).toISOString()
|
||||
},
|
||||
dataExport: {
|
||||
format: 'pdf',
|
||||
generatedAt: new Date(now.getTime() - 20 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
generatedBy: 'DSB Mueller',
|
||||
fileName: 'datenauskunft_sarah_braun.pdf',
|
||||
fileSize: 245000,
|
||||
includesThirdPartyData: false
|
||||
},
|
||||
createdAt: new Date(now.getTime() - 45 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
createdBy: 'system',
|
||||
updatedAt: new Date(now.getTime() - 20 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
tenantId: 'default-tenant'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export function createMockStatistics(): DSRStatistics {
|
||||
return {
|
||||
total: 6,
|
||||
byStatus: {
|
||||
intake: 1,
|
||||
identity_verification: 1,
|
||||
processing: 2,
|
||||
completed: 1,
|
||||
rejected: 1,
|
||||
cancelled: 0
|
||||
},
|
||||
byType: {
|
||||
access: 2,
|
||||
rectification: 1,
|
||||
erasure: 1,
|
||||
restriction: 0,
|
||||
portability: 1,
|
||||
objection: 1
|
||||
},
|
||||
overdue: 0,
|
||||
dueThisWeek: 2,
|
||||
averageProcessingDays: 18,
|
||||
completedThisMonth: 1
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user