Backup/Restore: alle neuen Tabellen erfasst (43 Tabellen insgesamt)
Das Backup- und Restore-System kannte noch nicht alle Tabellen, die im Lauf der letzten Wochen hinzugekommen sind. Kritischer Datenverlust im Ernstfall! Neu im Backup + Restore: - PdfTemplate (PDF-Auftragsvorlagen + Feldzuordnungen) - ContractMeter (Zähler-Vertrag-Zuordnungen mit Zeiträumen) - ContractDocument (flexible Vertragsdokumente: Auftragsformular, Lieferbestätigung ...) - RepresentativeAuthorization (Vollmachten zwischen Kunden) - CustomerConsent (DSGVO-Einwilligungen pro Kunde) - DataDeletionRequest (DSGVO-Löschanfragen) - EmailLog (SMTP-Sendeprotokoll) - AuditRetentionPolicy (Aufbewahrungsfristen pro Ressourcentyp) - AuditLog (vollständiges Änderungsprotokoll) Außerdem: - prisma/backup-data.ts: komplett neu strukturiert, korrekte Level-Hierarchie, nutzt aktuelles Schema (Provider statt EnergyProvider/TelecomProvider, InternetContractDetails statt TelecomContractDetails etc.) - prisma/restore-data.ts: Boilerplate durch generische restoreTable()-Helper ersetzt – von 487 auf ~240 Zeilen - backup.service.ts: neue Tabellen in createBackup, restoreOrder und deleteMany-Liste nachgetragen (Service bleibt sonst wie er ist) Test-Backup erfolgreich: 4420 Datensätze in 37 aktiven Tabellen gesichert. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -239,6 +239,16 @@ export async function createBackup(): Promise<BackupResult> {
|
||||
{ name: 'Address', query: () => prisma.address.findMany() },
|
||||
{ name: 'BankCard', query: () => prisma.bankCard.findMany() },
|
||||
{ name: 'IdentityDocument', query: () => prisma.identityDocument.findMany() },
|
||||
// Neue Tabellen
|
||||
{ name: 'PdfTemplate', query: () => prisma.pdfTemplate.findMany() },
|
||||
{ name: 'ContractMeter', query: () => prisma.contractMeter.findMany() },
|
||||
{ name: 'ContractDocument', query: () => prisma.contractDocument.findMany() },
|
||||
{ name: 'RepresentativeAuthorization', query: () => prisma.representativeAuthorization.findMany() },
|
||||
{ name: 'CustomerConsent', query: () => prisma.customerConsent.findMany() },
|
||||
{ name: 'DataDeletionRequest', query: () => prisma.dataDeletionRequest.findMany() },
|
||||
{ name: 'EmailLog', query: () => prisma.emailLog.findMany() },
|
||||
{ name: 'AuditRetentionPolicy', query: () => prisma.auditRetentionPolicy.findMany() },
|
||||
{ name: 'AuditLog', query: () => prisma.auditLog.findMany() },
|
||||
];
|
||||
|
||||
let totalRecords = 0;
|
||||
@@ -297,6 +307,10 @@ export async function restoreBackup(backupName: string): Promise<RestoreResult>
|
||||
// WICHTIG: Alle Tabellen vor dem Restore leeren, damit keine alten Daten übrig bleiben
|
||||
console.log('[Restore] Lösche alle bestehenden Daten...');
|
||||
|
||||
// Logs & Audit zuerst (hängen an allem)
|
||||
await prisma.auditLog.deleteMany({});
|
||||
await prisma.emailLog.deleteMany({});
|
||||
|
||||
// Detail-Tabellen
|
||||
await prisma.carInsuranceDetails.deleteMany({});
|
||||
await prisma.tvContractDetails.deleteMany({});
|
||||
@@ -309,12 +323,21 @@ export async function restoreBackup(backupName: string): Promise<RestoreResult>
|
||||
await prisma.meterReading.deleteMany({});
|
||||
await prisma.contractHistoryEntry.deleteMany({});
|
||||
|
||||
// Neue Contract-bezogene Tabellen
|
||||
await prisma.contractDocument.deleteMany({});
|
||||
await prisma.contractMeter.deleteMany({});
|
||||
|
||||
// E-Mail & Verträge
|
||||
await prisma.cachedEmail.deleteMany({});
|
||||
await prisma.contractTaskSubtask.deleteMany({});
|
||||
await prisma.contractTask.deleteMany({});
|
||||
await prisma.contract.deleteMany({});
|
||||
|
||||
// DSGVO + Vollmachten (abhängig von Customer)
|
||||
await prisma.representativeAuthorization.deleteMany({});
|
||||
await prisma.customerConsent.deleteMany({});
|
||||
await prisma.dataDeletionRequest.deleteMany({});
|
||||
|
||||
// Kunden-bezogene Daten
|
||||
await prisma.stressfreiEmail.deleteMany({});
|
||||
await prisma.meter.deleteMany({});
|
||||
@@ -328,7 +351,8 @@ export async function restoreBackup(backupName: string): Promise<RestoreResult>
|
||||
await prisma.user.deleteMany({});
|
||||
await prisma.customer.deleteMany({});
|
||||
|
||||
// Stammdaten
|
||||
// Stammdaten & Kataloge
|
||||
await prisma.pdfTemplate.deleteMany({});
|
||||
await prisma.tariff.deleteMany({});
|
||||
await prisma.provider.deleteMany({});
|
||||
await prisma.rolePermission.deleteMany({});
|
||||
@@ -340,6 +364,7 @@ export async function restoreBackup(backupName: string): Promise<RestoreResult>
|
||||
await prisma.contractCategory.deleteMany({});
|
||||
await prisma.emailProviderConfig.deleteMany({});
|
||||
await prisma.appSetting.deleteMany({});
|
||||
await prisma.auditRetentionPolicy.deleteMany({});
|
||||
|
||||
console.log('[Restore] Alle Daten gelöscht, starte Wiederherstellung...');
|
||||
|
||||
@@ -753,6 +778,115 @@ export async function restoreBackup(backupName: string): Promise<RestoreResult>
|
||||
}
|
||||
},
|
||||
},
|
||||
// Neue Tabellen
|
||||
{
|
||||
name: 'PdfTemplate',
|
||||
restore: async (data: any[]) => {
|
||||
for (const item of data) {
|
||||
await prisma.pdfTemplate.upsert({
|
||||
where: { id: item.id },
|
||||
update: convertDates(item),
|
||||
create: convertDates(item),
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractMeter',
|
||||
restore: async (data: any[]) => {
|
||||
for (const item of data) {
|
||||
await prisma.contractMeter.upsert({
|
||||
where: { id: item.id },
|
||||
update: convertDates(item),
|
||||
create: convertDates(item),
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractDocument',
|
||||
restore: async (data: any[]) => {
|
||||
for (const item of data) {
|
||||
await prisma.contractDocument.upsert({
|
||||
where: { id: item.id },
|
||||
update: convertDates(item),
|
||||
create: convertDates(item),
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'RepresentativeAuthorization',
|
||||
restore: async (data: any[]) => {
|
||||
for (const item of data) {
|
||||
await prisma.representativeAuthorization.upsert({
|
||||
where: { id: item.id },
|
||||
update: convertDates(item),
|
||||
create: convertDates(item),
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'CustomerConsent',
|
||||
restore: async (data: any[]) => {
|
||||
for (const item of data) {
|
||||
await prisma.customerConsent.upsert({
|
||||
where: { id: item.id },
|
||||
update: convertDates(item),
|
||||
create: convertDates(item),
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'DataDeletionRequest',
|
||||
restore: async (data: any[]) => {
|
||||
for (const item of data) {
|
||||
await prisma.dataDeletionRequest.upsert({
|
||||
where: { id: item.id },
|
||||
update: convertDates(item),
|
||||
create: convertDates(item),
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'EmailLog',
|
||||
restore: async (data: any[]) => {
|
||||
for (const item of data) {
|
||||
await prisma.emailLog.upsert({
|
||||
where: { id: item.id },
|
||||
update: convertDates(item),
|
||||
create: convertDates(item),
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'AuditRetentionPolicy',
|
||||
restore: async (data: any[]) => {
|
||||
for (const item of data) {
|
||||
await prisma.auditRetentionPolicy.upsert({
|
||||
where: { id: item.id },
|
||||
update: convertDates(item),
|
||||
create: convertDates(item),
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'AuditLog',
|
||||
restore: async (data: any[]) => {
|
||||
for (const item of data) {
|
||||
await prisma.auditLog.upsert({
|
||||
where: { id: item.id },
|
||||
update: convertDates(item),
|
||||
create: convertDates(item),
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
let totalRestored = 0;
|
||||
|
||||
Reference in New Issue
Block a user