133 lines
5.0 KiB
Python
133 lines
5.0 KiB
Python
"""
|
|
routes/legacy_attendance.py
|
|
============================
|
|
"Legacy Attendance" — same look/feel as Time Attendance (dashboard,
|
|
records list, Excel export) but sourced LIVE from the old remote MySQL
|
|
server (contract / employee / locations / records tables) instead of
|
|
Excel imports. Read-only: nothing is written to the remote server, and
|
|
nothing is copied into the local database.
|
|
|
|
Routes: /legacy-attendance, /legacy-attendance/records,
|
|
/legacy-attendance/export
|
|
"""
|
|
from flask import Blueprint, render_template, request, redirect, flash, send_file, url_for
|
|
from datetime import datetime
|
|
|
|
from extensions import logger_handler
|
|
from logger_handler import log_user_activity
|
|
from utils.helpers import login_required, restrict_blueprint_to_roles, PAYROLL_AREA_ROLES
|
|
from legacy_attendance_service import (
|
|
LegacyDbUnavailable,
|
|
get_legacy_dashboard_stats,
|
|
get_legacy_unique_locations,
|
|
get_legacy_records,
|
|
get_legacy_records_for_export,
|
|
build_legacy_export_workbook,
|
|
)
|
|
|
|
bp = Blueprint('legacy_attendance', __name__)
|
|
|
|
# Legacy Attendance (sidebar: admin, payroll, accounting) — checked for every route.
|
|
restrict_blueprint_to_roles(bp, PAYROLL_AREA_ROLES)
|
|
|
|
# Fixed dropdown values — confirmed values stored in the legacy `records.type` column
|
|
LEGACY_RECORD_TYPES = ['CHECK IN', 'CHECK OUT']
|
|
|
|
|
|
def _filters_from_request():
|
|
return {
|
|
'employee_search': request.args.get('employee_search', ''),
|
|
'location': request.args.get('location', ''),
|
|
'record_type': request.args.get('record_type', ''),
|
|
'start_date': request.args.get('start_date', ''),
|
|
'end_date': request.args.get('end_date', ''),
|
|
}
|
|
|
|
|
|
@bp.route('/legacy-attendance', endpoint='legacy_attendance_dashboard')
|
|
@login_required
|
|
@log_user_activity('legacy_attendance_view')
|
|
def legacy_attendance_dashboard():
|
|
"""Display legacy attendance dashboard with summary stats."""
|
|
stats = {
|
|
'total_records': 0,
|
|
'unique_employees': 0,
|
|
'unique_locations': 0,
|
|
'earliest_record': None,
|
|
'latest_record': None,
|
|
}
|
|
try:
|
|
stats = get_legacy_dashboard_stats()
|
|
except LegacyDbUnavailable as e:
|
|
flash(str(e), 'error')
|
|
except Exception as e:
|
|
logger_handler.logger.error(f"Error loading legacy attendance dashboard: {e}")
|
|
flash('Error loading legacy attendance dashboard. The legacy database may be unreachable.', 'error')
|
|
|
|
return render_template('legacy_attendance_dashboard.html', stats=stats)
|
|
|
|
|
|
@bp.route('/legacy-attendance/records', endpoint='legacy_attendance_records')
|
|
@login_required
|
|
@log_user_activity('legacy_attendance_records_view')
|
|
def legacy_attendance_records():
|
|
"""Display legacy attendance records with filtering + pagination."""
|
|
filters = _filters_from_request()
|
|
page = request.args.get('page', 1, type=int)
|
|
per_page = 50
|
|
|
|
records = None
|
|
unique_locations = []
|
|
try:
|
|
unique_locations = get_legacy_unique_locations()
|
|
records = get_legacy_records(filters, page=page, per_page=per_page)
|
|
except LegacyDbUnavailable as e:
|
|
flash(str(e), 'error')
|
|
return redirect(url_for('legacy_attendance.legacy_attendance_dashboard'))
|
|
except Exception as e:
|
|
logger_handler.logger.error(f"Error loading legacy attendance records: {e}")
|
|
flash('Error loading legacy attendance records. The legacy database may be unreachable.', 'error')
|
|
return redirect(url_for('legacy_attendance.legacy_attendance_dashboard'))
|
|
|
|
return render_template(
|
|
'legacy_attendance_records.html',
|
|
records=records,
|
|
unique_locations=unique_locations,
|
|
record_types=LEGACY_RECORD_TYPES,
|
|
filters=filters,
|
|
)
|
|
|
|
|
|
@bp.route('/legacy-attendance/export', endpoint='export_legacy_attendance')
|
|
@login_required
|
|
@log_user_activity('legacy_attendance_export')
|
|
def export_legacy_attendance():
|
|
"""Export the currently filtered legacy attendance records to Excel."""
|
|
filters = _filters_from_request()
|
|
|
|
try:
|
|
rows = get_legacy_records_for_export(filters)
|
|
except LegacyDbUnavailable as e:
|
|
flash(str(e), 'error')
|
|
return redirect(url_for('legacy_attendance.legacy_attendance_records', **filters))
|
|
except Exception as e:
|
|
logger_handler.logger.error(f"Error exporting legacy attendance records: {e}")
|
|
flash('Error generating export file. Please try again.', 'error')
|
|
return redirect(url_for('legacy_attendance.legacy_attendance_records', **filters))
|
|
|
|
if not rows:
|
|
flash('No legacy records found to export.', 'warning')
|
|
return redirect(url_for('legacy_attendance.legacy_attendance_records', **filters))
|
|
|
|
logger_handler.logger.info(f"Exported {len(rows)} legacy attendance records")
|
|
|
|
buffer = build_legacy_export_workbook(rows)
|
|
filename = f"legacy_attendance_{datetime.now().strftime('%m%d%Y_%H%M%S')}.xlsx"
|
|
|
|
return send_file(
|
|
buffer,
|
|
as_attachment=True,
|
|
download_name=filename,
|
|
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
)
|