mirror of
https://github.com/R0m1k3/Regisflow.git
synced 2026-10-11 17:29:48 +02:00
Add feature to automatically delete old sales data for legal compliance
Implements a data purge system, scheduler, and API endpoints for stats and manual execution. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 91318273-c764-4fd4-be04-bdc12c38af32 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/0715008c-7244-40f4-befc-26c014852236/c3a86207-4ee0-47f9-8062-2dbbae696290.jpg
This commit is contained in:
1 parent
686512516d
commit
7404dc6443
5 files changed
+316
-1
No files matched your search
@@ -0,0 +1,112 @@
|
||||
import { db } from './db';
|
||||
import { sales } from '@shared/schema';
|
||||
import { lt } from 'drizzle-orm';
|
||||
import cron from 'node-cron';
|
||||
|
||||
/**
|
||||
* Purge des ventes de plus de 19 mois
|
||||
* Conformément aux exigences réglementaires de conservation des données
|
||||
*/
|
||||
export async function purgeSalesData() {
|
||||
try {
|
||||
// Calculer la date limite (19 mois en arrière)
|
||||
const cutoffDate = new Date();
|
||||
cutoffDate.setMonth(cutoffDate.getMonth() - 19);
|
||||
|
||||
console.log(`🗑️ Démarrage purge des ventes antérieures au ${cutoffDate.toLocaleDateString('fr-FR')}`);
|
||||
|
||||
// Supprimer les ventes antérieures à la date limite
|
||||
const result = await db
|
||||
.delete(sales)
|
||||
.where(lt(sales.timestamp, cutoffDate.toISOString()))
|
||||
.returning({ id: sales.id });
|
||||
|
||||
const deletedCount = result.length;
|
||||
|
||||
if (deletedCount > 0) {
|
||||
console.log(`✅ Purge terminée : ${deletedCount} vente(s) supprimée(s)`);
|
||||
} else {
|
||||
console.log('✅ Purge terminée : aucune vente à supprimer');
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
deletedCount,
|
||||
cutoffDate: cutoffDate.toISOString(),
|
||||
message: `${deletedCount} vente(s) supprimée(s) (antérieures au ${cutoffDate.toLocaleDateString('fr-FR')})`
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Erreur lors de la purge des ventes:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error.message || 'Erreur inconnue',
|
||||
deletedCount: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtenir les statistiques de purge
|
||||
*/
|
||||
export async function getPurgeStats() {
|
||||
try {
|
||||
const cutoffDate = new Date();
|
||||
cutoffDate.setMonth(cutoffDate.getMonth() - 19);
|
||||
|
||||
// Compter les ventes qui seraient supprimées
|
||||
const oldSales = await db
|
||||
.select({ id: sales.id })
|
||||
.from(sales)
|
||||
.where(lt(sales.timestamp, cutoffDate.toISOString()));
|
||||
|
||||
// Compter le total des ventes
|
||||
const totalSales = await db
|
||||
.select({ id: sales.id })
|
||||
.from(sales);
|
||||
|
||||
return {
|
||||
totalSales: totalSales.length,
|
||||
oldSales: oldSales.length,
|
||||
cutoffDate: cutoffDate.toISOString(),
|
||||
purgeEligible: oldSales.length > 0
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Erreur lors du calcul des statistiques de purge:', error);
|
||||
return {
|
||||
totalSales: 0,
|
||||
oldSales: 0,
|
||||
cutoffDate: new Date().toISOString(),
|
||||
purgeEligible: false,
|
||||
error: error.message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Démarrer le planificateur de purge automatique
|
||||
* Exécute la purge tous les 1er du mois à 02:00
|
||||
*/
|
||||
export function startPurgeScheduler() {
|
||||
// Tâche planifiée : tous les 1er du mois à 02:00
|
||||
cron.schedule('0 2 1 * *', async () => {
|
||||
console.log('🕐 Exécution programmée de la purge des ventes');
|
||||
await purgeSalesData();
|
||||
}, {
|
||||
scheduled: true,
|
||||
timezone: 'Europe/Paris'
|
||||
});
|
||||
|
||||
console.log('🕐 Planificateur de purge des ventes démarré');
|
||||
console.log('⏰ Purge automatique : 1er de chaque mois à 02:00');
|
||||
console.log('📅 Rétention des données : 19 mois maximum');
|
||||
}
|
||||
|
||||
/**
|
||||
* Exécuter une purge manuelle (pour l'interface d'administration)
|
||||
*/
|
||||
export async function executePurgeManually() {
|
||||
console.log('🔧 Purge manuelle demandée via l\'interface d\'administration');
|
||||
return await purgeSalesData();
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import express, { type Request, Response, NextFunction } from "express";
|
||||
import { registerRoutes } from "./routes";
|
||||
import { setupVite, serveStatic, log } from "./vite";
|
||||
import { startBackupScheduler } from "./backup-scheduler";
|
||||
import { startPurgeScheduler } from "./data-purge";
|
||||
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
@@ -70,5 +71,8 @@ app.use((req, res, next) => {
|
||||
|
||||
// Start the automatic backup scheduler
|
||||
startBackupScheduler();
|
||||
|
||||
// Start the data purge scheduler
|
||||
startPurgeScheduler();
|
||||
});
|
||||
})();
|
||||
@@ -6,6 +6,7 @@ import connectPg from "connect-pg-simple";
|
||||
import { loginSchema, insertUserSchema, insertStoreSchema, insertSaleSchema } from "@shared/schema";
|
||||
import { z } from "zod";
|
||||
import { createAutomaticBackup, getBackupStats } from "./backup-scheduler";
|
||||
import { executePurgeManually, getPurgeStats } from "./data-purge";
|
||||
|
||||
declare module 'express-session' {
|
||||
interface SessionData {
|
||||
@@ -535,6 +536,27 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
}
|
||||
});
|
||||
|
||||
// Admin routes - Data Purge
|
||||
app.get('/api/admin/purge/stats', requireRole(['admin']), async (req, res) => {
|
||||
try {
|
||||
const stats = await getPurgeStats();
|
||||
res.json(stats);
|
||||
} catch (error) {
|
||||
console.error('Get purge stats error:', error);
|
||||
res.status(500).json({ error: "Failed to get purge stats" });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/admin/purge/execute', requireRole(['admin']), async (req, res) => {
|
||||
try {
|
||||
const result = await executePurgeManually();
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
console.error('Execute purge error:', error);
|
||||
res.status(500).json({ error: "Failed to execute purge" });
|
||||
}
|
||||
});
|
||||
|
||||
const httpServer = createServer(app);
|
||||
return httpServer;
|
||||
}
|
||||
Reference in new issue
Block a user