import pool from "../../db"; import { logger } from "./logger"; export type AuditArea = 'member' | 'calendar' | 'roles' | 'auth' | 'leave_of_absence' | 'application' | 'course'; export interface AuditContext { actorId: number; // The person doing the action (created_by) targetId?: number; // The ID of the thing being changed (target_id) } class AuditLogger { async record( area: AuditArea, action: string, context: AuditContext, data: Record = {} // Already optional with default {} ) { const actionType = `${area}.${action}`; try { await pool.query( `INSERT INTO audit_log (action_type, payload, target_id, created_by) VALUES (?, ?, ?, ?)`, // Fixed: removed extra comma/placeholder [ actionType, JSON.stringify(data), context.targetId || null, context.actorId, ] ); } catch (err) { logger.error('audit', `AUDIT_FAILURE: Failed to log ${actionType}`, { error: err }); } } member(action: 'update_rank'| 'update_unit' | 'suspension_added' | 'suspension_removed' | 'discharged', context: AuditContext, data: any = {}) { return this.record('member', action, context, data); } roles(action: 'add_member' | 'remove_member' | 'create' | 'delete', context: AuditContext, data: any = {}) { return this.record('roles', action, context, data); } leaveOfAbsence(action: 'created' | 'admin_created' | 'ended' | 'admin_ended' | 'extended', context: AuditContext, data: any = {}) { return this.record('leave_of_absence', action, context, data); } calendar(action: 'event_created' | 'event_updated' | 'attendance_set' | 'cancelled' | 'un-cancelled', context: AuditContext, data: any = {}) { return this.record('calendar', action, context, data); } application(action: 'created' | 'approved' | 'denied' | 'restarted', context: AuditContext, data: any = {}) { return this.record('application', action, context, data); } course(action: 'report_created' | 'report_edited', context: AuditContext, data: any = {}) { return this.record('course', action, context, data); } } export const audit = new AuditLogger();