Add 'Exclude workers with loans' checkbox to batch pay modal
Backend adds has_loan flag per worker (checks active Loans). Frontend shows checkbox only when any eligible worker has a loan. Combined with team filter in a shared applyBatchFilters() function that shows/hides rows based on both filters simultaneously. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
00f16df8b1
commit
695b7cb3f1
@ -2079,6 +2079,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
function buildWorkerRow(w, idx) {
|
function buildWorkerRow(w, idx) {
|
||||||
var tr = document.createElement('tr');
|
var tr = document.createElement('tr');
|
||||||
tr.dataset.team = w.team_name; // Used by team filter
|
tr.dataset.team = w.team_name; // Used by team filter
|
||||||
|
tr.dataset.hasLoan = w.has_loan ? 'true' : 'false'; // Used by loan filter
|
||||||
|
|
||||||
// Checkbox cell
|
// Checkbox cell
|
||||||
var tdCb = document.createElement('td');
|
var tdCb = document.createElement('td');
|
||||||
@ -2272,6 +2273,26 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
filterSelect.appendChild(opt);
|
filterSelect.appendChild(opt);
|
||||||
});
|
});
|
||||||
filterRow.appendChild(filterSelect);
|
filterRow.appendChild(filterSelect);
|
||||||
|
|
||||||
|
// Only show the "Exclude loans" checkbox if any worker has a loan
|
||||||
|
var anyHasLoan = data.eligible.some(function(w) { return w.has_loan; });
|
||||||
|
var excludeLoansCheck = null;
|
||||||
|
if (anyHasLoan) {
|
||||||
|
var loanDiv = document.createElement('div');
|
||||||
|
loanDiv.className = 'form-check ms-3 mb-0';
|
||||||
|
excludeLoansCheck = document.createElement('input');
|
||||||
|
excludeLoansCheck.type = 'checkbox';
|
||||||
|
excludeLoansCheck.className = 'form-check-input';
|
||||||
|
excludeLoansCheck.id = 'batchExcludeLoans';
|
||||||
|
loanDiv.appendChild(excludeLoansCheck);
|
||||||
|
var loanLabel = document.createElement('label');
|
||||||
|
loanLabel.className = 'form-check-label text-muted small';
|
||||||
|
loanLabel.setAttribute('for', 'batchExcludeLoans');
|
||||||
|
loanLabel.textContent = 'Exclude workers with loans';
|
||||||
|
loanDiv.appendChild(loanLabel);
|
||||||
|
filterRow.appendChild(loanDiv);
|
||||||
|
}
|
||||||
|
|
||||||
body.appendChild(filterRow);
|
body.appendChild(filterRow);
|
||||||
|
|
||||||
// --- Summary header ---
|
// --- Summary header ---
|
||||||
@ -2358,14 +2379,16 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- Team filter behavior ---
|
// --- Shared filter function (team + loan filters combined) ---
|
||||||
// Shows/hides rows, checks matching workers, unchecks hidden ones
|
function applyBatchFilters() {
|
||||||
filterSelect.addEventListener('change', function() {
|
|
||||||
var selectedTeam = filterSelect.value;
|
var selectedTeam = filterSelect.value;
|
||||||
|
var excludeLoans = excludeLoansCheck ? excludeLoansCheck.checked : false;
|
||||||
var rows = tbody.querySelectorAll('tr');
|
var rows = tbody.querySelectorAll('tr');
|
||||||
for (var i = 0; i < rows.length; i++) {
|
for (var i = 0; i < rows.length; i++) {
|
||||||
var row = rows[i];
|
var row = rows[i];
|
||||||
if (!selectedTeam || row.dataset.team === selectedTeam) {
|
var teamMatch = !selectedTeam || row.dataset.team === selectedTeam;
|
||||||
|
var loanMatch = !excludeLoans || row.dataset.hasLoan !== 'true';
|
||||||
|
if (teamMatch && loanMatch) {
|
||||||
row.style.display = '';
|
row.style.display = '';
|
||||||
row.querySelector('.batch-worker-cb').checked = true;
|
row.querySelector('.batch-worker-cb').checked = true;
|
||||||
} else {
|
} else {
|
||||||
@ -2375,7 +2398,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
}
|
}
|
||||||
selectAllCb.checked = true;
|
selectAllCb.checked = true;
|
||||||
updateBatchSummary(data, summary);
|
updateBatchSummary(data, summary);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
filterSelect.addEventListener('change', applyBatchFilters);
|
||||||
|
if (excludeLoansCheck) {
|
||||||
|
excludeLoansCheck.addEventListener('change', applyBatchFilters);
|
||||||
|
}
|
||||||
|
|
||||||
// --- Skipped workers (collapsible) ---
|
// --- Skipped workers (collapsible) ---
|
||||||
if (data.skipped.length > 0) {
|
if (data.skipped.length > 0) {
|
||||||
|
|||||||
@ -1505,6 +1505,9 @@ def batch_pay_preview(request):
|
|||||||
else:
|
else:
|
||||||
period_display = "All unpaid"
|
period_display = "All unpaid"
|
||||||
|
|
||||||
|
# Check if worker has any active loans or advances
|
||||||
|
has_loan = Loan.objects.filter(worker=worker, active=True).exists()
|
||||||
|
|
||||||
eligible.append({
|
eligible.append({
|
||||||
'worker_id': worker.id,
|
'worker_id': worker.id,
|
||||||
'worker_name': worker.name,
|
'worker_name': worker.name,
|
||||||
@ -1516,6 +1519,7 @@ def batch_pay_preview(request):
|
|||||||
'net_pay': float(net),
|
'net_pay': float(net),
|
||||||
'log_ids': unpaid_log_ids,
|
'log_ids': unpaid_log_ids,
|
||||||
'adj_ids': unpaid_adj_ids,
|
'adj_ids': unpaid_adj_ids,
|
||||||
|
'has_loan': has_loan,
|
||||||
})
|
})
|
||||||
total_amount += net
|
total_amount += net
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user