Fixed import issues
This commit is contained in:
@@ -6547,9 +6547,35 @@ def import_time_attendance():
|
||||
"""Enhanced import with duplicate review"""
|
||||
if request.method == 'POST':
|
||||
try:
|
||||
# Check if file is uploaded
|
||||
# Check if this is coming from invalid review (file is already in session)
|
||||
coming_from_invalid_review = request.form.get('from_invalid_review', 'false').lower() == 'true'
|
||||
|
||||
print(f"\n🔍 IMPORT FLOW DEBUG:")
|
||||
print(f" Coming from invalid review: {coming_from_invalid_review}")
|
||||
|
||||
if coming_from_invalid_review:
|
||||
# Retrieve file from session
|
||||
if 'pending_import_file' not in session or 'pending_import_filename' not in session:
|
||||
flash('Session expired. Please upload the file again.', 'error')
|
||||
return redirect(url_for('import_time_attendance'))
|
||||
|
||||
temp_path = session['pending_import_file']
|
||||
filename = session['pending_import_filename']
|
||||
|
||||
# Verify file still exists
|
||||
if not os.path.exists(temp_path):
|
||||
flash('Temporary file not found. Please upload the file again.', 'error')
|
||||
session.pop('pending_import_file', None)
|
||||
session.pop('pending_import_filename', None)
|
||||
return redirect(url_for('import_time_attendance'))
|
||||
|
||||
print(f"✅ Retrieved file from session: {filename}")
|
||||
print(f"✅ Temp path exists: {os.path.exists(temp_path)}")
|
||||
|
||||
else:
|
||||
# Normal file upload flow
|
||||
if 'file' not in request.files:
|
||||
flash('No file selected.', 'error')
|
||||
flash('No file uploaded.', 'error')
|
||||
return redirect(request.url)
|
||||
|
||||
file = request.files['file']
|
||||
@@ -6570,10 +6596,13 @@ def import_time_attendance():
|
||||
os.makedirs(os.path.dirname(temp_path), exist_ok=True)
|
||||
file.save(temp_path)
|
||||
|
||||
# Store file path in session for duplicate review
|
||||
# Store file path in session for duplicate/invalid review
|
||||
session['pending_import_file'] = temp_path
|
||||
session['pending_import_filename'] = filename
|
||||
|
||||
print(f"✅ Uploaded new file: {filename}")
|
||||
print(f"✅ Saved to: {temp_path}")
|
||||
|
||||
try:
|
||||
import_service = TimeAttendanceImportService(db, logger_handler)
|
||||
|
||||
@@ -6581,40 +6610,56 @@ def import_time_attendance():
|
||||
skip_duplicates = request.form.get('skip_duplicates', 'true').lower() == 'true'
|
||||
validate_only = request.form.get('validate_only', 'false').lower() == 'true'
|
||||
analyze_duplicates = request.form.get('analyze_duplicates', 'false').lower() == 'true'
|
||||
analyze_invalid = request.form.get('analyze_invalid', 'false').lower() == 'true'
|
||||
|
||||
print(f"📋 Import Options:")
|
||||
print(f" Skip duplicates: {skip_duplicates}")
|
||||
print(f" Validate only: {validate_only}")
|
||||
print(f" Analyze duplicates: {analyze_duplicates}")
|
||||
print(f" Analyze invalid: {analyze_invalid}")
|
||||
print(f" Coming from invalid review: {coming_from_invalid_review}")
|
||||
|
||||
# Check if this is coming from duplicate review
|
||||
force_import_hashes = request.form.getlist('force_import_hashes[]')
|
||||
|
||||
# If analyzing for duplicates, show review page
|
||||
if analyze_duplicates and not force_import_hashes:
|
||||
# If analyzing for duplicates, show review page (but not if coming from invalid review)
|
||||
if analyze_duplicates and not force_import_hashes and not coming_from_invalid_review:
|
||||
print("🔍 Analyzing for duplicates...")
|
||||
duplicate_analysis = import_service.analyze_for_duplicates(temp_path)
|
||||
|
||||
if duplicate_analysis['duplicate_records'] > 0:
|
||||
print(f"⚠️ Found {duplicate_analysis['duplicate_records']} duplicates")
|
||||
# Show duplicate review page
|
||||
return render_template('time_attendance_duplicate_review.html',
|
||||
analysis=duplicate_analysis,
|
||||
filename=filename)
|
||||
else:
|
||||
print("✅ No duplicates found")
|
||||
flash('No duplicates found. Proceeding with import.', 'info')
|
||||
|
||||
# Check for invalid rows and show review if any
|
||||
analyze_invalid = request.form.get('analyze_invalid', 'false').lower() == 'true'
|
||||
|
||||
if analyze_invalid:
|
||||
# Check for invalid rows and show review if any (but not if coming from invalid review)
|
||||
if analyze_invalid and not coming_from_invalid_review:
|
||||
print("🔍 Analyzing for invalid rows...")
|
||||
invalid_analysis = import_service.analyze_for_invalid_rows(temp_path)
|
||||
|
||||
if invalid_analysis['invalid_rows'] > 0:
|
||||
print(f"⚠️ Found {invalid_analysis['invalid_rows']} invalid rows")
|
||||
# Show invalid row review page
|
||||
return render_template('time_attendance_invalid_review.html',
|
||||
analysis=invalid_analysis,
|
||||
filename=filename)
|
||||
else:
|
||||
print("✅ All rows are valid")
|
||||
flash('All rows are valid. Proceeding with import.', 'info')
|
||||
|
||||
# If coming from invalid review, skip validation (already done)
|
||||
if not coming_from_invalid_review:
|
||||
print("🔍 Validating file...")
|
||||
# Validate file
|
||||
validation_result = import_service.validate_excel_file(temp_path)
|
||||
|
||||
if not validation_result['valid']:
|
||||
print(f"❌ Validation failed: {validation_result['errors']}")
|
||||
flash(f"File validation failed: {'; '.join(validation_result['errors'])}", 'error')
|
||||
return render_template('time_attendance_import.html',
|
||||
validation_result=validation_result)
|
||||
@@ -6624,11 +6669,15 @@ def import_time_attendance():
|
||||
flash(warning, 'warning')
|
||||
|
||||
if validate_only:
|
||||
print(f"✅ Validation successful: {validation_result['valid_rows']} valid records")
|
||||
flash(f"File validation successful! Found {validation_result['valid_rows']} valid records.", 'success')
|
||||
return render_template('time_attendance_import.html',
|
||||
validation_result=validation_result)
|
||||
else:
|
||||
print("⏭️ Skipping validation (already validated)")
|
||||
|
||||
# Proceed with import
|
||||
print("🚀 Starting import process...")
|
||||
import_source = request.form.get('import_source', f"Manual Import - {filename}")
|
||||
import_result = import_service.import_from_excel(
|
||||
temp_path,
|
||||
@@ -6639,6 +6688,12 @@ def import_time_attendance():
|
||||
)
|
||||
|
||||
if import_result['success']:
|
||||
print(f"✅ Import successful!")
|
||||
print(f" Batch ID: {import_result['batch_id']}")
|
||||
print(f" Imported: {import_result['imported_records']}/{import_result['total_records']}")
|
||||
print(f" Duplicates: {import_result['duplicate_records']}")
|
||||
print(f" Failed: {import_result['failed_records']}")
|
||||
|
||||
logger_handler.logger.info(
|
||||
f"User {session['username']} successfully imported time attendance data - "
|
||||
f"Batch: {import_result['batch_id']}, "
|
||||
@@ -6661,33 +6716,41 @@ def import_time_attendance():
|
||||
flash(f"Note: {import_result['failed_records']} records failed to import. "
|
||||
f"Check the error details below.", 'warning')
|
||||
|
||||
# Clean up temp file after successful import
|
||||
if os.path.exists(temp_path):
|
||||
try:
|
||||
os.remove(temp_path)
|
||||
session.pop('pending_import_file', None)
|
||||
session.pop('pending_import_filename', None)
|
||||
print("🗑️ Cleaned up temp file")
|
||||
except Exception as cleanup_error:
|
||||
print(f"⚠️ Failed to cleanup temp file: {cleanup_error}")
|
||||
|
||||
return render_template('time_attendance_import_result.html',
|
||||
import_result=import_result)
|
||||
else:
|
||||
print(f"❌ Import failed: {import_result['errors']}")
|
||||
flash(f"Import failed: {'; '.join(import_result['errors'][:3])}", 'error')
|
||||
if len(import_result['errors']) > 3:
|
||||
flash(f"...and {len(import_result['errors']) - 3} more errors", 'warning')
|
||||
return render_template('time_attendance_import.html',
|
||||
import_result=import_result)
|
||||
|
||||
finally:
|
||||
# Clean up if import completed or failed (not if showing duplicate review)
|
||||
if not analyze_duplicates or force_import_hashes:
|
||||
if os.path.exists(temp_path):
|
||||
try:
|
||||
os.remove(temp_path)
|
||||
if 'pending_import_file' in session:
|
||||
session.pop('pending_import_file')
|
||||
if 'pending_import_filename' in session:
|
||||
session.pop('pending_import_filename')
|
||||
except Exception as cleanup_error:
|
||||
logger_handler.logger.warning(f"Failed to cleanup temp file: {cleanup_error}")
|
||||
except Exception as import_error:
|
||||
print(f"❌ Import exception: {import_error}")
|
||||
import traceback
|
||||
print(f"❌ Traceback: {traceback.format_exc()}")
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
logger_handler.log_database_error('time_attendance_import', e)
|
||||
print(f"❌ Top-level exception: {e}")
|
||||
import traceback
|
||||
print(f"❌ Traceback: {traceback.format_exc()}")
|
||||
flash('Import failed due to an unexpected error.', 'error')
|
||||
return render_template('time_attendance_import.html')
|
||||
|
||||
# GET request
|
||||
return render_template('time_attendance_import.html')
|
||||
|
||||
|
||||
|
||||
@@ -321,7 +321,10 @@
|
||||
<!-- Invalid Rows List -->
|
||||
{% if analysis.invalid_rows > 0 %}
|
||||
<form id="invalidReviewForm" method="POST" action="{{ url_for('import_time_attendance') }}">
|
||||
<input type="hidden" name="from_invalid_review" value="true">
|
||||
<input type="hidden" name="analyze_invalid" value="false">
|
||||
<input type="hidden" name="analyze_duplicates" value="false">
|
||||
<input type="hidden" name="validate_only" value="false">
|
||||
<input type="hidden" name="skip_duplicates" value="true">
|
||||
<input type="hidden" name="import_source" value="Import (Skipped Invalid Rows) - {{ filename }}">
|
||||
|
||||
@@ -457,29 +460,57 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const form = document.getElementById('invalidReviewForm');
|
||||
const proceedBtn = document.getElementById('proceedBtn');
|
||||
|
||||
console.log('🔍 Invalid Review Page - Debug Info:');
|
||||
console.log(' Form element:', form);
|
||||
console.log(' Button element:', proceedBtn);
|
||||
console.log(' Form action:', form ? form.action : 'N/A');
|
||||
console.log(' Form method:', form ? form.method : 'N/A');
|
||||
|
||||
if (form && proceedBtn) {
|
||||
proceedBtn.addEventListener('click', function(e) {
|
||||
form.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const validCount = {{ analysis.valid_rows }};
|
||||
const invalidCount = {{ analysis.invalid_rows }};
|
||||
|
||||
console.log(`📊 Attempting to import ${validCount} valid records`);
|
||||
console.log(`📊 Skipping ${invalidCount} invalid records`);
|
||||
|
||||
const message = `You are about to import ${validCount} valid record(s).\n\n` +
|
||||
`${invalidCount} invalid row(s) will be skipped.\n\n` +
|
||||
`Continue with import?`;
|
||||
|
||||
if (!confirm(message)) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
if (confirm(message)) {
|
||||
console.log('✅ User confirmed import');
|
||||
|
||||
// Log all form data for debugging
|
||||
const formData = new FormData(form);
|
||||
console.log('📋 Form Data Being Submitted:');
|
||||
for (let [key, value] of formData.entries()) {
|
||||
console.log(` ${key}: ${value}`);
|
||||
}
|
||||
|
||||
// Show loading state
|
||||
proceedBtn.disabled = true;
|
||||
proceedBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Processing Import...';
|
||||
|
||||
// Use HTMLFormElement.submit() which bypasses event listeners
|
||||
console.log('🚀 Submitting form to:', form.action);
|
||||
HTMLFormElement.prototype.submit.call(form);
|
||||
} else {
|
||||
console.log('❌ User cancelled import');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
else {
|
||||
console.error('❌ Form or button not found!');
|
||||
if (!form) console.error(' Missing form element with id="invalidReviewForm"');
|
||||
if (!proceedBtn) console.error(' Missing button element with id="proceedBtn"');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user