This commit is contained in:
Flatlogic Bot 2026-02-03 21:39:20 +00:00
parent 6cb2211e8f
commit c6cc41cce3
3 changed files with 124 additions and 16 deletions

View File

@ -15,7 +15,7 @@
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="card p-4 shadow-sm">
<form method="post">
<form method="post" id="workLogForm">
{% csrf_token %}
<div class="row mb-4">
@ -79,6 +79,40 @@
</div>
</div>
{% if is_conflict %}
<!-- Conflict Resolution Modal -->
<div class="modal fade" id="conflictModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="conflictModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-warning text-dark">
<h5 class="modal-title fw-bold" id="conflictModalLabel">
Duplicate Logs Detected
</h5>
</div>
<div class="modal-body">
<p class="fw-bold">The following workers have already been logged for {{ conflict_date }}:</p>
<div class="card bg-light mb-3">
<ul class="list-group list-group-flush">
{% for worker in conflicting_workers %}
<li class="list-group-item bg-transparent">{{ worker.name }}</li>
{% endfor %}
</ul>
</div>
<p>How would you like to proceed?</p>
<div class="alert alert-info small mb-0">
<strong>Skip:</strong> Log only the new workers. Keep existing logs as they are.<br>
<strong>Overwrite:</strong> Remove these workers from previous logs for this date and add them here.
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="submitConflict('skip')">Skip Duplicate Workers</button>
<button type="button" class="btn btn-primary" onclick="submitConflict('overwrite')">Overwrite Existing</button>
</div>
</div>
</div>
</div>
{% endif %}
<style>
.hover-shadow:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.05);
@ -105,7 +139,6 @@
// Select workers belonging to the team
workerIds.forEach(function(id) {
// Find the checkbox for this worker ID
// Django form checkboxes usually have name 'workers' and value equal to ID
const checkbox = document.querySelector(`input[name="workers"][value="${id}"]`);
if (checkbox) {
checkbox.checked = true;
@ -114,6 +147,27 @@
}
});
}
// Show conflict modal if it exists
const conflictModalEl = document.getElementById('conflictModal');
if (conflictModalEl) {
var myModal = new bootstrap.Modal(conflictModalEl);
myModal.show();
}
});
function submitConflict(action) {
const form = document.getElementById('workLogForm');
// Check if input already exists
let input = form.querySelector('input[name="conflict_action"]');
if (!input) {
input = document.createElement('input');
input.type = 'hidden';
input.name = 'conflict_action';
form.appendChild(input);
}
input.value = action;
form.submit();
}
</script>
{% endblock %}

View File

@ -62,19 +62,7 @@ def home(request):
return render(request, "core/index.html", context)
def log_attendance(request):
if request.method == 'POST':
form = WorkLogForm(request.POST, user=request.user)
if form.is_valid():
work_log = form.save(commit=False)
if request.user.is_authenticated:
work_log.supervisor = request.user
work_log.save()
form.save_m2m()
return redirect('home')
else:
form = WorkLogForm(user=request.user if request.user.is_authenticated else None)
# Build team workers map for frontend JS
# Build team workers map for frontend JS (needed for both GET and POST if re-rendering)
teams_qs = Team.objects.filter(is_active=True)
if request.user.is_authenticated and not request.user.is_superuser:
teams_qs = teams_qs.filter(supervisor=request.user)
@ -84,6 +72,72 @@ def log_attendance(request):
# Get active workers for the team
active_workers = team.workers.filter(is_active=True).values_list('id', flat=True)
team_workers_map[team.id] = list(active_workers)
if request.method == 'POST':
form = WorkLogForm(request.POST, user=request.user)
if form.is_valid():
date = form.cleaned_data['date']
selected_workers = form.cleaned_data['workers']
conflict_action = request.POST.get('conflict_action')
# Check for existing logs for these workers on this date
# We want to find workers who ARE in selected_workers AND have a WorkLog on 'date'
conflicting_workers = Worker.objects.filter(
work_logs__date=date,
id__in=selected_workers.values_list('id', flat=True)
).distinct()
if conflicting_workers.exists() and not conflict_action:
context = {
'form': form,
'team_workers_json': json.dumps(team_workers_map),
'conflicting_workers': conflicting_workers,
'is_conflict': True,
'conflict_date': date,
}
return render(request, 'core/log_attendance.html', context)
# If we are here, either no conflicts or action is chosen
workers_to_save = list(selected_workers)
if conflict_action == 'skip':
# Exclude conflicting workers
conflicting_ids = conflicting_workers.values_list('id', flat=True)
workers_to_save = [w for w in selected_workers if w.id not in conflicting_ids]
if not workers_to_save:
messages.warning(request, "No new workers to log (all skipped).")
return redirect('home')
messages.success(request, f"Logged {len(workers_to_save)} workers (skipped {conflicting_workers.count()} duplicates).")
elif conflict_action == 'overwrite':
# Remove conflicting workers from their OLD logs
for worker in conflicting_workers:
old_logs = WorkLog.objects.filter(date=date, workers=worker)
for log in old_logs:
log.workers.remove(worker)
# Cleanup empty logs
if log.workers.count() == 0:
log.delete()
messages.success(request, f"Logged {len(workers_to_save)} workers (overwrote {conflicting_workers.count()} previous entries).")
else:
# No conflicts initially
messages.success(request, "Work log saved successfully.")
# Save the new log
work_log = form.save(commit=False)
if request.user.is_authenticated:
work_log.supervisor = request.user
work_log.save()
# Manually set workers
work_log.workers.set(workers_to_save)
return redirect('home')
else:
form = WorkLogForm(user=request.user if request.user.is_authenticated else None)
context = {
'form': form,
@ -240,4 +294,4 @@ def payslip_detail(request, pk):
'record': record,
'logs': logs,
}
return render(request, 'core/payslip.html', context)
return render(request, 'core/payslip.html', context)