feat: already_done checkbox in schedule modal; fix: capacity check skips ended slots; feat: ha_poll_interval configurable
Deploy via Portainer / deploy (push) Successful in 0s

This commit is contained in:
Jo
2026-07-07 13:15:53 +02:00
parent 1b740f9cee
commit 56d80521d7
2 changed files with 46 additions and 5 deletions
+8
View File
@@ -1799,6 +1799,14 @@ def api_new_slot():
if over:
conn.close()
return jsonify({'error': f"Capacité maximale atteinte : {peak} impression(s) déjà en cours sur ce créneau (limite : {max_printers} simultanées). Décalez l'horaire ou attendez qu'une imprimante se libère."}), 409
already_done = bool(d.get('already_done', False))
if already_done:
# Retroactive — skip capacity/overlap checks, insert as done
conn.execute(
'INSERT INTO print_slots(job_id,printer_id,planned_start,planned_end,status) VALUES(?,?,?,?,?)',
(job_id, printer_id, start_dt.isoformat(), end_dt.isoformat(), 'done'))
conn.commit(); conn.close()
return jsonify({'ok': True})
conn.execute('INSERT INTO print_slots(job_id,printer_id,planned_start,planned_end,status) VALUES(?,?,?,?,?)',
(job_id, printer_id, start_dt.isoformat(), end_dt.isoformat(), 'planned'))
conn.commit(); conn.close()
+38 -5
View File
@@ -148,6 +148,15 @@
<label class="form-label fw-semibold">Date et heure de lancement</label>
<input type="datetime-local" id="modalStart" class="form-control">
</div>
<div class="mb-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="modalAlreadyDone" onchange="onAlreadyDoneChange()">
<label class="form-check-label fw-semibold text-success" for="modalAlreadyDone">
<i class="bi bi-check-circle-fill me-1"></i>Déjà imprimé
</label>
</div>
<div class="form-text ms-4">Enregistre le plateau comme terminé sans passer par le planning actif.</div>
</div>
<div id="modalSuggestion" class="alert alert-success py-2 small d-none">
<i class="bi bi-magic me-1"></i><span id="modalSuggestionText"></span>
</div>
@@ -157,7 +166,7 @@
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Annuler</button>
<button type="button" class="btn fw-bold" style="background:#ff6b35;color:#fff" onclick="saveSlot()">
<button type="button" id="modalSaveBtn" class="btn fw-bold" style="background:#ff6b35;color:#fff" onclick="saveSlot()">
<i class="bi bi-save me-1"></i>Planifier
</button>
</div>
@@ -525,11 +534,33 @@ function formatDt(iso) {
d.toLocaleTimeString('fr-FR',{hour:'2-digit',minute:'2-digit'});
}
function onAlreadyDoneChange() {
const done = document.getElementById('modalAlreadyDone').checked;
const btn = document.getElementById('modalSaveBtn');
if (done) {
btn.innerHTML = '<i class="bi bi-check-circle me-1"></i>Enregistrer comme terminé';
btn.style.background = '#22c55e';
// Reset to "now" so user picks when it was done
const now = new Date();
now.setMinutes(0, 0, 0);
document.getElementById('modalStart').value = now.toISOString().slice(0,16);
document.getElementById('modalSuggestion').classList.add('d-none');
document.getElementById('modalError').classList.add('d-none');
} else {
btn.innerHTML = '<i class="bi bi-save me-1"></i>Planifier';
btn.style.background = '#ff6b35';
}
}
function openScheduleModal(jobId, printTime, jobName) {
document.getElementById('modalJobId').value = jobId;
document.getElementById('modalPrintTime').value = printTime;
document.getElementById('modalJobName').textContent = jobName;
document.getElementById('modalSuggestion').classList.add('d-none');
document.getElementById('modalError').classList.add('d-none');
// Reset already-done checkbox
document.getElementById('modalAlreadyDone').checked = false;
onAlreadyDoneChange();
// Default: now rounded to next hour
const now = new Date();
now.setMinutes(0, 0, 0);
@@ -559,15 +590,17 @@ async function suggestSlot(jobId, printTime, jobName) {
}
async function saveSlot() {
const jobId = parseInt(document.getElementById('modalJobId').value);
const printer = parseInt(document.getElementById('modalPrinter').value);
const start = document.getElementById('modalStart').value;
const jobId = parseInt(document.getElementById('modalJobId').value);
const printer = parseInt(document.getElementById('modalPrinter').value);
const start = document.getElementById('modalStart').value;
const alreadyDone = document.getElementById('modalAlreadyDone').checked;
// Clear previous error
document.getElementById('modalError').classList.add('d-none');
const r = await fetch('/api/slots/new', {
method: 'POST',
headers: {'Content-Type':'application/json'},
body: JSON.stringify({job_id: jobId, printer_id: printer, planned_start: start})
body: JSON.stringify({job_id: jobId, printer_id: printer, planned_start: start,
already_done: alreadyDone})
});
const res = await r.json();
if (res.ok) {