diff --git a/app.py b/app.py index 24a6d6c..8ca02a5 100644 --- a/app.py +++ b/app.py @@ -4243,6 +4243,14 @@ def edit_attendance(record_id): attendance_record = AttendanceData.query.get_or_404(record_id) if request.method == 'POST': + # Get the audit note from form - REQUIRED + edit_note = request.form.get('edit_note', '').strip() + if not edit_note: + flash('Edit reason is required for audit purposes.', 'error') + return render_template('edit_attendance.html', + attendance_record=attendance_record, + qr_codes=QRCode.query.filter_by(active_status=True).all()) + # Track changes for logging changes = {} old_values = { @@ -4274,20 +4282,56 @@ def edit_attendance(record_id): attendance_record.check_in_time = new_check_in_time attendance_record.location_name = new_location_name attendance_record.updated_timestamp = datetime.utcnow() + + # Store the audit note with timestamp and user info + timestamp = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S UTC') + username = session.get('username', 'Unknown') + role = session.get('role', 'unknown') + + new_note_entry = f"[{timestamp}] {role.title()} '{username}': {edit_note}" + + if attendance_record.edit_note: + # Append to existing notes + attendance_record.edit_note = f"{attendance_record.edit_note}\n\n{new_note_entry}" + else: + # First edit note + attendance_record.edit_note = new_note_entry db.session.commit() - # Log the successful update + # Enhanced logging with audit note if changes: logger_handler.log_security_event( event_type="attendance_record_update", description=f"{session.get('role', 'unknown').title()} {session.get('username')} updated attendance record {record_id}", severity="MEDIUM", - additional_data={'record_id': record_id, 'changes': changes, 'user_role': session.get('role')} + additional_data={ + 'record_id': record_id, + 'changes': changes, + 'user_role': session.get('role'), + 'edit_reason': edit_note, + 'editor_username': session.get('username') + } ) print(f"[LOG] {session.get('role', 'unknown').title()} {session.get('username')} updated attendance record {record_id}: {changes}") + print(f"[LOG] Edit reason: {edit_note}") + else: + # Log even if no changes were made (for audit purposes) + logger_handler.log_security_event( + event_type="attendance_record_edit_no_changes", + description=f"{session.get('role', 'unknown').title()} {session.get('username')} accessed edit form for record {record_id} but made no changes", + severity="LOW", + additional_data={ + 'record_id': record_id, + 'user_role': session.get('role'), + 'edit_reason': edit_note, + 'editor_username': session.get('username') + } + ) + print(f"[LOG] {session.get('role', 'unknown').title()} {session.get('username')} edited record {record_id} with no changes") + print(f"[LOG] Edit reason: {edit_note}") - flash(f'Attendance record for {new_employee_id} updated successfully!', 'success') + flash(f'Attendance record for {new_employee_id} updated successfully! Edit reason logged for audit.', 'success') return redirect(url_for('attendance_report')) # GET request - show edit form diff --git a/models/attendance.py b/models/attendance.py index 2350ecb..443af71 100644 --- a/models/attendance.py +++ b/models/attendance.py @@ -33,7 +33,7 @@ class AttendanceData(base.db.Model): altitude = base.db.Column(base.db.Float, nullable=True) location_source = base.db.Column(base.db.String(50), default='manual') address = base.db.Column(base.db.String(500), nullable=True) - + edit_note = base.db.Column(base.db.Text, nullable=True) # Relationships qr_code = base.db.relationship('QRCode', backref=base.db.backref('attendance_records', lazy='dynamic')) diff --git a/templates/edit_attendance.html b/templates/edit_attendance.html index d484c5b..66bfba6 100644 --- a/templates/edit_attendance.html +++ b/templates/edit_attendance.html @@ -1,9 +1,7 @@ -{% extends "base_authenticated.html" %} {% block title %}Edit Attendance Record -- QR Code Management{% endblock %} {% block extra_head %} - +{% extends "base_authenticated.html" %} +{% block title %}Edit Attendance Record - QR Code Management{% endblock %} +{% block extra_head %} + -{% endblock %} {% block content %} +{% endblock %} + +{% block content %}

@@ -82,26 +133,47 @@

Current Record Information

Record ID: {{ attendance_record.id }}

-

- Current Employee: {{ attendance_record.employee_id }} -

-

- Current Date: {{ - attendance_record.check_in_date.strftime('%Y-%m-%d') }} -

-

- Current Time: {{ - attendance_record.check_in_time.strftime('%H:%M') }} -

-

- Current Location: {{ attendance_record.location_name }} -

+

Current Employee: {{ attendance_record.employee_id }}

+

Current Date: {{ attendance_record.check_in_date.strftime('%Y-%m-%d') }}

+

Current Time: {{ attendance_record.check_in_time.strftime('%H:%M') }}

+

Current Location: {{ attendance_record.location_name }}

-
+ + + +
+

Audit Information

+ + {% if attendance_record.edit_note %} +
+

Previous Edit History

+
+ +
+
+ {% endif %} + +
+ + + + {% if attendance_record.edit_note %} + Note: Your new reason will be appended to the existing audit trail. + {% else %} + This note will be logged for audit purposes and added to the record's audit trail. + {% endif %} + +
+
+

Employee Information

@@ -178,26 +250,27 @@

-{% endblock %} {% block extra_scripts %} +{% endblock %} + +{% block extra_scripts %} -{% endblock %} +{% endblock %} \ No newline at end of file