Added project dropdown in Time Attendance import
This commit is contained in:
@@ -6583,6 +6583,11 @@ def time_attendance_dashboard():
|
||||
@log_database_operations('time_attendance_import')
|
||||
def import_time_attendance():
|
||||
"""Enhanced import with duplicate review"""
|
||||
if request.method == 'GET':
|
||||
# Load active projects for dropdown
|
||||
projects = Project.query.filter_by(active_status=True).order_by(Project.name).all()
|
||||
return render_template('time_attendance_import.html', projects=projects)
|
||||
|
||||
if request.method == 'POST':
|
||||
try:
|
||||
# Check if this is coming from invalid review (file is already in session)
|
||||
@@ -6717,12 +6722,16 @@ def import_time_attendance():
|
||||
# Proceed with import
|
||||
print("🚀 Starting import process...")
|
||||
import_source = request.form.get('import_source', f"Manual Import - {filename}")
|
||||
project_id = request.form.get('project_id')
|
||||
project_id = int(project_id) if project_id and project_id != '' else None
|
||||
|
||||
import_result = import_service.import_from_excel(
|
||||
temp_path,
|
||||
created_by=session['user_id'],
|
||||
import_source=import_source,
|
||||
skip_duplicates=skip_duplicates,
|
||||
force_import_hashes=force_import_hashes
|
||||
force_import_hashes=force_import_hashes,
|
||||
project_id=project_id
|
||||
)
|
||||
|
||||
if import_result['success']:
|
||||
|
||||
@@ -41,11 +41,15 @@ class TimeAttendance(base.db.Model):
|
||||
import_batch_id = base.db.Column(base.db.String(36), nullable=True, index=True)
|
||||
import_date = base.db.Column(base.db.DateTime, default=datetime.utcnow)
|
||||
import_source = base.db.Column(base.db.String(100), nullable=True)
|
||||
|
||||
project_id = base.db.Column(base.db.Integer, base.db.ForeignKey('projects.id'), nullable=True, index=True)
|
||||
|
||||
# Audit fields
|
||||
created_by = base.db.Column(base.db.Integer, base.db.ForeignKey('users.id'), nullable=True)
|
||||
created_date = base.db.Column(base.db.DateTime, default=datetime.utcnow)
|
||||
updated_date = base.db.Column(base.db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
# Relationship
|
||||
project = base.db.relationship('Project', backref='time_attendance_records')
|
||||
|
||||
def __repr__(self):
|
||||
return f'<TimeAttendance {self.employee_id} - {self.employee_name} at {self.location_name} on {self.attendance_date}>'
|
||||
|
||||
@@ -4,6 +4,16 @@
|
||||
{% block extra_head %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/time_attendance.css') }}">
|
||||
<style>
|
||||
.form-select:hover {
|
||||
border-color: #8b5cf6;
|
||||
}
|
||||
|
||||
.form-select:focus {
|
||||
outline: none;
|
||||
border-color: #8b5cf6;
|
||||
box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.1);
|
||||
}
|
||||
|
||||
.validation-preview {
|
||||
background: #f8fafc;
|
||||
border: 2px solid #e2e8f0;
|
||||
@@ -410,6 +420,36 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Project Selection - REQUIRED -->
|
||||
<div class="form-group" style="margin-bottom: 1.5rem;">
|
||||
<h3 style="margin-bottom: 0.75rem;">
|
||||
<i class="fas fa-project-diagram"></i>
|
||||
Select Project <span style="color: #ef4444;">*</span>
|
||||
</h3>
|
||||
<select name="project_id" id="project_id" class="form-select" required style="
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 0.5rem;
|
||||
font-size: 0.9375rem;
|
||||
background-color: #ffffff;
|
||||
transition: all 0.2s ease;
|
||||
">
|
||||
<option value="">-- Select Project (Required) --</option>
|
||||
{% for project in projects %}
|
||||
<option value="{{ project.id }}">{{ project.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<p style="
|
||||
margin-top: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
color: #64748b;
|
||||
">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
<strong>Required:</strong> Select which project this import data belongs to for filtering and reporting
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Import Source -->
|
||||
<div class="form-grid">
|
||||
<div class="form-group">
|
||||
@@ -706,6 +746,16 @@ importForm.addEventListener('submit', (e) => {
|
||||
alert('Please select a file to import');
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate project selection
|
||||
const projectSelect = document.getElementById('project_id');
|
||||
if (!projectSelect.value || projectSelect.value === '') {
|
||||
e.preventDefault();
|
||||
alert('Please select a project. Project selection is required for attendance imports.');
|
||||
projectSelect.focus();
|
||||
projectSelect.style.borderColor = '#ef4444';
|
||||
return;
|
||||
}
|
||||
|
||||
// Show progress indicator
|
||||
progressIndicator.classList.add('active');
|
||||
@@ -713,6 +763,13 @@ importForm.addEventListener('submit', (e) => {
|
||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Processing...';
|
||||
});
|
||||
|
||||
// Reset border color when project is selected
|
||||
document.getElementById('project_id').addEventListener('change', function() {
|
||||
if (this.value) {
|
||||
this.style.borderColor = '#e2e8f0';
|
||||
}
|
||||
});
|
||||
|
||||
function resetForm() {
|
||||
importForm.reset();
|
||||
fileInfo.style.display = 'none';
|
||||
|
||||
@@ -440,7 +440,7 @@ class TimeAttendanceImportService:
|
||||
|
||||
def import_from_excel(self, file_path: str, created_by: int = None,
|
||||
import_source: str = None, skip_duplicates: bool = True,
|
||||
force_import_hashes: List[str] = None) -> Dict[str, Any]:
|
||||
force_import_hashes: List[str] = None, project_id: int = None) -> Dict[str, Any]:
|
||||
"""
|
||||
Import time attendance data from Excel file with enhanced duplicate handling
|
||||
|
||||
@@ -581,7 +581,8 @@ class TimeAttendanceImportService:
|
||||
**record_data,
|
||||
import_batch_id=batch_id,
|
||||
import_source=import_source or f"Excel Import - {file_path}",
|
||||
created_by=created_by
|
||||
created_by=created_by,
|
||||
project_id=project_id
|
||||
)
|
||||
|
||||
self.db.session.add(time_attendance_record)
|
||||
|
||||
Reference in New Issue
Block a user