feat(config): hard-delete employees instead of soft-deactivating
Some checks failed
CI / lint-and-test (3.11) (push) Has been cancelled
CI / lint-and-test (3.13) (push) Has been cancelled

Updates DELETE /employees/<id> to nullify FK references, remove dependent rows (permissions/sessions), and delete the employee record. Owners remain protected.
This commit is contained in:
2026-06-30 17:33:41 +00:00
parent 8b378c3476
commit bd5f733d6f

View File

@@ -315,8 +315,9 @@ def update_employee(emp_id):
@config_bp.route('/employees/<int:emp_id>', methods=['DELETE'])
@require_auth('config.edit')
def delete_employee(emp_id):
"""Soft-delete (deactivate) an employee. Owners cannot be deleted via UI
to prevent locking out the tenant; use direct DB access if really needed."""
"""Hard-delete an employee. Foreign-key references are nulled and
dependent rows (permissions/sessions) are removed. Owners cannot be
deleted via UI to prevent locking out the tenant."""
conn = get_tenant_conn(g.tenant_id)
cur = conn.cursor()
@@ -330,15 +331,32 @@ def delete_employee(emp_id):
cur.close(); conn.close()
return jsonify({'error': 'No se puede eliminar una cuenta de dueno'}), 403
cur.execute("UPDATE employees SET is_active = false WHERE id = %s", (emp_id,))
# Resolve every foreign-key column that points back to employees.
cur.execute("""
SELECT c.relname::text AS tbl, a.attname::text AS col
FROM pg_constraint con
JOIN pg_class c ON c.oid = con.conrelid
JOIN pg_attribute a ON a.attrelid = con.conrelid AND a.attnum = ANY(con.conkey)
WHERE con.confrelid = 'public.employees'::regclass
AND con.contype = 'f'
""")
refs = cur.fetchall()
for tbl, col in refs:
if tbl in ('employee_permissions', 'employee_sessions', 'notification_preferences'):
cur.execute(f"DELETE FROM \"{tbl}\" WHERE \"{col}\" = %s", (emp_id,))
else:
cur.execute(f"UPDATE \"{tbl}\" SET \"{col}\" = NULL WHERE \"{col}\" = %s", (emp_id,))
cur.execute("DELETE FROM employees WHERE id = %s", (emp_id,))
from services.audit import log_action
log_action(conn, 'EMPLOYEE_DEACTIVATE', 'employee', emp_id)
log_action(conn, 'EMPLOYEE_DELETE', 'employee', emp_id)
conn.commit()
cur.close()
conn.close()
return jsonify({'ok': True, 'message': 'Employee deactivated'})
return jsonify({'ok': True, 'message': 'Empleado eliminado'})
@config_bp.route('/currency', methods=['GET'])