Update attendance report functions: edit & delete record for admin & payroll users

This commit is contained in:
2025-08-13 22:40:57 -04:00
parent 1d762a2641
commit 03c75d5d30
5 changed files with 637 additions and 37 deletions
+115 -35
View File
@@ -266,11 +266,22 @@
</td>
<td>
<div class="record-actions">
{% if session.role in ['admin', 'payroll'] %}
<button onclick="editRecord('{{ record.id }}')"
class="action-btn btn-edit"
title="Edit Record">
<i class="fas fa-edit"></i>
</button>
<button onclick="deleteRecord('{{ record.id }}', '{{ record.employee_id }}')"
class="action-btn btn-delete"
title="Delete Record">
<i class="fas fa-trash"></i>
</button>
{% else %}
<span class="text-muted" title="Admin or Payroll access required">
<i class="fas fa-lock"></i>
</span>
{% endif %}
</div>
</td>
</tr>
@@ -353,6 +364,14 @@
{% block extra_scripts %}
<script src="{{ url_for('static', filename='js/attendance_report.js') }}"></script>
<script>
// Template variables (processed by Flask)
const userRole = '{{ session.role }}';
const hasEditPermission = ['admin', 'payroll'].includes(userRole);
// Debug logging
console.log('User Role:', userRole);
console.log('Has Edit Permission:', hasEditPermission);
// Enhanced JavaScript for new functionality
const hasLocationAccuracy = {{ 'true' if has_location_accuracy_feature else 'false' }};
@@ -443,44 +462,12 @@ function viewRecordDetails(recordId) {
${record.accuracy_level.toUpperCase()}
</span>
</div>
<div class="detail-item">
<strong>QR Address:</strong>
<span>${record.qr_address}</span>
</div>
<div class="detail-item">
<strong>Check-in Address:</strong>
<span>${record.checked_in_address}</span>
</div>
</div>
`;
} else if (record.gps_accuracy) {
accuracySection = `
<div class="detail-section">
<h4><i class="fas fa-crosshairs"></i> GPS Information</h4>
<div class="detail-item">
<strong>GPS Accuracy:</strong>
<span>${record.gps_accuracy}m</span>
</div>
<div class="detail-item">
<strong>Coordinates:</strong>
<span>${record.coordinates}</span>
</div>
</div>
`;
} else {
accuracySection = `
<div class="detail-section">
<h4><i class="fas fa-question-circle"></i> Location Information</h4>
<div class="detail-item">
<strong>Status:</strong>
<span>No location data available</span>
</div>
</div>
`;
}
modalBody.innerHTML = `
<div class="record-details-grid">
<div class="record-details">
<div class="detail-section">
<h4><i class="fas fa-user"></i> Employee Information</h4>
<div class="detail-item">
@@ -520,9 +507,67 @@ function viewRecordDetails(recordId) {
modal.style.display = 'block';
}
// OVERRIDE EDIT/DELETE FUNCTIONS WITH PROPER PERMISSION CHECKING
function editRecord(recordId) {
console.log(`Edit record: ${recordId}`);
alert('Edit functionality to be implemented');
console.log('Edit function called for record:', recordId);
console.log('User role:', userRole);
console.log('Has permission:', hasEditPermission);
// Check permissions before allowing edit
if (!hasEditPermission) {
alert('Access denied. Only administrators and payroll staff can edit attendance records.');
return;
}
console.log(`[LOG] User attempting to edit attendance record: ${recordId}`);
// Redirect to edit page
window.location.href = `/attendance/${recordId}/edit`;
}
function deleteRecord(recordId, employeeId) {
console.log('Delete function called for record:', recordId);
console.log('User role:', userRole);
console.log('Has permission:', hasEditPermission);
// Check permissions before allowing delete
if (!hasEditPermission) {
alert('Access denied. Only administrators and payroll staff can delete attendance records.');
return;
}
console.log(`Delete record: ${recordId}`);
// Confirmation dialog
const confirmMessage = `Are you sure you want to delete the attendance record for employee "${employeeId}"?\n\nThis action cannot be undone.`;
if (confirm(confirmMessage)) {
console.log(`[LOG] User confirmed deletion of attendance record: ${recordId}`);
// Send delete request
fetch(`/attendance/${recordId}/delete`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
console.log(`[LOG] Successfully deleted attendance record: ${recordId}`);
alert('Attendance record deleted successfully!');
window.location.reload();
} else {
console.error(`[LOG] Failed to delete attendance record: ${recordId} - ${data.message}`);
alert(data.message || 'Error deleting record. Please try again.');
}
})
.catch(error => {
console.error(`[LOG] Error during attendance record deletion: ${recordId}`, error);
alert('Error deleting record. Please try again.');
});
}
}
// Close modals when clicking outside
@@ -545,5 +590,40 @@ document.addEventListener('keydown', function(event) {
closeMapModal();
}
});
// Force update buttons on page load for admin/payroll users
document.addEventListener('DOMContentLoaded', function() {
console.log('Page loaded. User role:', userRole, 'Has edit permission:', hasEditPermission);
if (hasEditPermission) {
// Find all record action containers and update them
const recordActions = document.querySelectorAll('.record-actions');
recordActions.forEach(function(actionDiv) {
// Check if it contains a lock icon (meaning user is locked out)
const lockIcon = actionDiv.querySelector('.fa-lock');
if (lockIcon) {
const recordRow = actionDiv.closest('tr');
const recordId = recordRow.dataset.recordId;
const employeeCell = recordRow.querySelector('.employee-id');
const employeeId = employeeCell ? employeeCell.textContent.trim() : 'Unknown';
// Replace lock icon with edit/delete buttons
actionDiv.innerHTML = `
<button onclick="editRecord('${recordId}')"
class="action-btn btn-edit"
title="Edit Record">
<i class="fas fa-edit"></i>
</button>
<button onclick="deleteRecord('${recordId}', '${employeeId}')"
class="action-btn btn-delete"
title="Delete Record">
<i class="fas fa-trash"></i>
</button>
`;
}
});
console.log('✅ Admin/Payroll edit/delete buttons have been activated');
}
});
</script>
{% endblock %}
+215
View File
@@ -0,0 +1,215 @@
{% extends "base_authenticated.html" %} {% block title %}Edit Attendance Record
- QR Code Management{% endblock %} {% block extra_head %}
<link
rel="stylesheet"
href="{{ url_for('static', filename='css/forms.css') }}"
/>
<style>
.edit-attendance-container {
max-width: 800px;
margin: 2rem auto;
padding: 2rem;
background: white;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.form-header {
text-align: center;
margin-bottom: 2rem;
padding-bottom: 1rem;
border-bottom: 2px solid #e5e7eb;
}
.form-header h1 {
color: #1f2937;
margin-bottom: 0.5rem;
}
.form-header p {
color: #6b7280;
margin: 0;
}
.form-section {
margin-bottom: 2rem;
}
.form-section h3 {
color: #374151;
margin-bottom: 1rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid #e5e7eb;
}
.form-actions {
display: flex;
gap: 1rem;
justify-content: center;
margin-top: 2rem;
padding-top: 1rem;
border-top: 1px solid #e5e7eb;
}
.record-info {
background: #f9fafb;
padding: 1rem;
border-radius: 8px;
margin-bottom: 1.5rem;
}
.record-info h4 {
color: #374151;
margin-bottom: 0.5rem;
}
.record-info p {
color: #6b7280;
margin: 0.25rem 0;
}
</style>
{% endblock %} {% block content %}
<div class="edit-attendance-container">
<div class="form-header">
<h1>
<i class="fas fa-edit"></i>
Edit Attendance Record
</h1>
<p>Modify attendance record details (Admin & Payroll Access)</p>
</div>
<!-- Current Record Info -->
<div class="record-info">
<h4><i class="fas fa-info-circle"></i> Current Record Information</h4>
<p><strong>Record ID:</strong> {{ attendance_record.id }}</p>
<p>
<strong>Current Employee:</strong> {{ attendance_record.employee_id }}
</p>
<p>
<strong>Current Date:</strong> {{
attendance_record.check_in_date.strftime('%Y-%m-%d') }}
</p>
<p>
<strong>Current Time:</strong> {{
attendance_record.check_in_time.strftime('%H:%M') }}
</p>
<p>
<strong>Current Location:</strong> {{ attendance_record.location_name }}
</p>
</div>
<form
method="POST"
action="{{ url_for('edit_attendance', record_id=attendance_record.id) }}"
>
<!-- Employee Information -->
<div class="form-section">
<h3><i class="fas fa-user"></i> Employee Information</h3>
<div class="form-group">
<label for="employee_id">Employee ID *</label>
<input
type="text"
id="employee_id"
name="employee_id"
value="{{ attendance_record.employee_id }}"
required
class="form-control"
placeholder="Enter employee ID"
/>
</div>
</div>
<!-- Date & Time Information -->
<div class="form-section">
<h3><i class="fas fa-clock"></i> Check-in Details</h3>
<div class="form-row">
<div class="form-group">
<label for="check_in_date">Check-in Date *</label>
<input
type="date"
id="check_in_date"
name="check_in_date"
value="{{ attendance_record.check_in_date.strftime('%Y-%m-%d') }}"
required
class="form-control"
/>
</div>
<div class="form-group">
<label for="check_in_time">Check-in Time *</label>
<input
type="time"
id="check_in_time"
name="check_in_time"
value="{{ attendance_record.check_in_time.strftime('%H:%M') }}"
required
class="form-control"
/>
</div>
</div>
</div>
<!-- Location Information -->
<div class="form-section">
<h3><i class="fas fa-map-marker-alt"></i> Location Information</h3>
<div class="form-group">
<label for="location_name">Location Name *</label>
<input
type="text"
id="location_name"
name="location_name"
value="{{ attendance_record.location_name }}"
required
class="form-control"
placeholder="Enter location name"
/>
</div>
</div>
<!-- Form Actions -->
<div class="form-actions">
<button type="submit" class="btn btn-primary">
<i class="fas fa-save"></i>
Update Record
</button>
<a href="{{ url_for('attendance_report') }}" class="btn btn-secondary">
<i class="fas fa-times"></i>
Cancel
</a>
</div>
</form>
</div>
{% endblock %} {% block extra_scripts %}
<script>
document.addEventListener("DOMContentLoaded", function () {
// Form validation
const form = document.querySelector("form");
form.addEventListener("submit", function (e) {
const employeeId = document.getElementById("employee_id").value.trim();
const locationName = document
.getElementById("location_name")
.value.trim();
if (!employeeId || !locationName) {
e.preventDefault();
alert("Please fill in all required fields.");
return;
}
// Confirm update
const confirmUpdate = confirm(
"Are you sure you want to update this attendance record?"
);
if (!confirmUpdate) {
e.preventDefault();
}
});
// Auto-uppercase employee ID
document
.getElementById("employee_id")
.addEventListener("input", function () {
this.value = this.value.toUpperCase();
});
});
</script>
{% endblock %}