feat: track ignored objects from HA (pieces_ignored on print_slots)
Deploy via Portainer / deploy (push) Successful in 0s
Deploy via Portainer / deploy (push) Successful in 0s
This commit is contained in:
@@ -267,6 +267,7 @@ def init_db():
|
|||||||
'ALTER TABLE jobs ADD COLUMN client_token TEXT DEFAULT NULL',
|
'ALTER TABLE jobs ADD COLUMN client_token TEXT DEFAULT NULL',
|
||||||
'ALTER TABLE jobs ADD COLUMN plate_name TEXT DEFAULT ""',
|
'ALTER TABLE jobs ADD COLUMN plate_name TEXT DEFAULT ""',
|
||||||
'ALTER TABLE printers ADD COLUMN ha_entity_prefix TEXT DEFAULT ""',
|
'ALTER TABLE printers ADD COLUMN ha_entity_prefix TEXT DEFAULT ""',
|
||||||
|
'ALTER TABLE print_slots ADD COLUMN pieces_ignored INTEGER DEFAULT 0',
|
||||||
]
|
]
|
||||||
for sql in migrations:
|
for sql in migrations:
|
||||||
try:
|
try:
|
||||||
@@ -1629,6 +1630,7 @@ def api_slots():
|
|||||||
slots = conn.execute('''
|
slots = conn.execute('''
|
||||||
SELECT ps.id, ps.job_id, ps.printer_id, ps.planned_start, ps.planned_end,
|
SELECT ps.id, ps.job_id, ps.printer_id, ps.planned_start, ps.planned_end,
|
||||||
ps.status, ps.failure_note,
|
ps.status, ps.failure_note,
|
||||||
|
COALESCE(ps.pieces_ignored, 0) as pieces_ignored,
|
||||||
j.name as job_name, j.print_time_s, j.final_price,
|
j.name as job_name, j.print_time_s, j.final_price,
|
||||||
j.pieces_per_plate, j.order_qty, j.weight_g,
|
j.pieces_per_plate, j.order_qty, j.weight_g,
|
||||||
j.plate_name,
|
j.plate_name,
|
||||||
@@ -1971,6 +1973,9 @@ def _ha_sync_once():
|
|||||||
if new_status:
|
if new_status:
|
||||||
conn.execute('UPDATE print_slots SET status=? WHERE id=?',
|
conn.execute('UPDATE print_slots SET status=? WHERE id=?',
|
||||||
(new_status, slot['id']))
|
(new_status, slot['id']))
|
||||||
|
if ha_ignored > 0:
|
||||||
|
conn.execute('UPDATE print_slots SET pieces_ignored=? WHERE id=?',
|
||||||
|
(ha_ignored, slot['id']))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -2025,6 +2030,10 @@ def api_ha_status():
|
|||||||
except: layer = 0
|
except: layer = 0
|
||||||
try: layers_total = int(float(gs('nombre_total_de_couches', '0')))
|
try: layers_total = int(float(gs('nombre_total_de_couches', '0')))
|
||||||
except: layers_total = 0
|
except: layers_total = 0
|
||||||
|
try: pieces_ignored = int(float(gs('objets_ignores', '0')))
|
||||||
|
except: pieces_ignored = 0
|
||||||
|
try: pieces_total = int(float(gs('objets_imprimables', '0')))
|
||||||
|
except: pieces_total = 0
|
||||||
result[str(p['id'])] = {
|
result[str(p['id'])] = {
|
||||||
'printer_name': p['name'],
|
'printer_name': p['name'],
|
||||||
'status': gs('etat_de_l_impression'),
|
'status': gs('etat_de_l_impression'),
|
||||||
@@ -2034,6 +2043,8 @@ def api_ha_status():
|
|||||||
'layer': layer,
|
'layer': layer,
|
||||||
'layers_total': layers_total,
|
'layers_total': layers_total,
|
||||||
'error': gb('erreur_d_impression') == 'on',
|
'error': gb('erreur_d_impression') == 'on',
|
||||||
|
'pieces_ignored': pieces_ignored,
|
||||||
|
'pieces_total': pieces_total,
|
||||||
}
|
}
|
||||||
return jsonify({'printers': result})
|
return jsonify({'printers': result})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
+11
-2
@@ -402,9 +402,12 @@ function renderSlotsList(slots) {
|
|||||||
const clientPart = s.client_name
|
const clientPart = s.client_name
|
||||||
? `<br><span class="text-muted fw-normal" style="font-size:.75rem">${s.client_name}</span>`
|
? `<br><span class="text-muted fw-normal" style="font-size:.75rem">${s.client_name}</span>`
|
||||||
: '';
|
: '';
|
||||||
|
const ignoredPart = (s.pieces_ignored > 0)
|
||||||
|
? `<br><span style="font-size:.7rem;background:#fef3c7;color:#92400e;padding:1px 5px;border-radius:3px"><i class="bi bi-exclamation-triangle-fill me-1"></i>${s.pieces_per_plate - s.pieces_ignored}/${s.pieces_per_plate} pièces</span>`
|
||||||
|
: '';
|
||||||
return `<tr style="cursor:pointer" onclick="openSlotModal(${JSON.stringify(s).replace(/"/g,'"')})">
|
return `<tr style="cursor:pointer" onclick="openSlotModal(${JSON.stringify(s).replace(/"/g,'"')})">
|
||||||
<td class="small" style="white-space:nowrap">${formatDt(s.planned_start)}</td>
|
<td class="small" style="white-space:nowrap">${formatDt(s.planned_start)}</td>
|
||||||
<td class="small fw-semibold">${s.job_name}${platePart}${filPart}${clientPart}</td>
|
<td class="small fw-semibold">${s.job_name}${platePart}${ignoredPart}${filPart}${clientPart}</td>
|
||||||
<td class="small text-muted" style="white-space:nowrap">${dur}</td>
|
<td class="small text-muted" style="white-space:nowrap">${dur}</td>
|
||||||
<td class="small" style="white-space:nowrap">${s.printer_name}</td>
|
<td class="small" style="white-space:nowrap">${s.printer_name}</td>
|
||||||
<td><span class="badge" style="background:${STATUS_COLORS[s.status]}">${STATUS_LABELS[s.status]||s.status}</span></td>
|
<td><span class="badge" style="background:${STATUS_COLORS[s.status]}">${STATUS_LABELS[s.status]||s.status}</span></td>
|
||||||
@@ -588,12 +591,18 @@ async function refreshHaStatus() {
|
|||||||
const taskInfo = (p.task_name && p.task_name !== 'unknown')
|
const taskInfo = (p.task_name && p.task_name !== 'unknown')
|
||||||
? `<div class="text-truncate" style="font-size:.72rem;color:#6b7280;max-width:220px" title="${p.task_name}">${p.task_name}</div>`
|
? `<div class="text-truncate" style="font-size:.72rem;color:#6b7280;max-width:220px" title="${p.task_name}">${p.task_name}</div>`
|
||||||
: '';
|
: '';
|
||||||
return `<div class="p-2 mb-1 rounded" style="background:#f8f9fa;border:1px solid #e5e7eb">
|
const ignoredWarn = (p.pieces_ignored > 0)
|
||||||
|
? `<div class="mt-1"><span class="badge" style="background:#fef3c7;color:#92400e;font-size:.7rem">
|
||||||
|
<i class="bi bi-exclamation-triangle-fill me-1"></i>${p.pieces_total - p.pieces_ignored}/${p.pieces_total} pièces — ${p.pieces_ignored} ignorée(s)
|
||||||
|
</span></div>`
|
||||||
|
: '';
|
||||||
|
return `<div class="p-2 mb-1 rounded" style="background:#f8f9fa;border:1px solid ${p.pieces_ignored>0?'#fbbf24':'#e5e7eb'}">
|
||||||
<div class="d-flex justify-content-between align-items-center mb-1">
|
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||||
<span class="fw-semibold small">${p.printer_name}</span>
|
<span class="fw-semibold small">${p.printer_name}</span>
|
||||||
<span class="badge bg-${sc} text-${sc==='light'?'dark':'white'}">${sl}</span>
|
<span class="badge bg-${sc} text-${sc==='light'?'dark':'white'}">${sl}</span>
|
||||||
</div>
|
</div>
|
||||||
${taskInfo}
|
${taskInfo}
|
||||||
|
${ignoredWarn}
|
||||||
<div class="d-flex justify-content-between align-items-center mt-1">
|
<div class="d-flex justify-content-between align-items-center mt-1">
|
||||||
<div class="flex-fill me-2">
|
<div class="flex-fill me-2">
|
||||||
<div style="height:6px;background:#e5e7eb;border-radius:3px;overflow:hidden">
|
<div style="height:6px;background:#e5e7eb;border-radius:3px;overflow:hidden">
|
||||||
|
|||||||
Reference in New Issue
Block a user