Dashboard cards: rebuild deployable dists

This commit is contained in:
2026-08-11 14:31:24 -04:00
parent 0ed8be75d9
commit 3b37603691
14 changed files with 507 additions and 62 deletions

View File

@@ -1005,12 +1005,17 @@ def _get_low_supplies_data():
model_number = model.modelnumber if model else None
modelnumberid = model.modelnumberid if model else None
# ONLY the supplies that need attention. A printer reporting one empty
# black cartridge alongside three full colour ones was listing all four,
# so the reader had to find the problem inside the row rather than being
# shown it. The whole report exists to answer "what needs replacing".
annotated = []
has_low = False
for s in supplies:
item = _annotate_supply(s, vendor_name, modelnumberid)
if item['status'] != 'ok':
has_low = True
if item['status'] == 'ok':
continue
has_low = True
annotated.append(item)
if has_low:
@@ -1388,3 +1393,45 @@ def delete_model_supply(modelsupplyid: int):
db.session.delete(supply)
db.session.commit()
return success_response(message='Supply deleted')
@printers_asset_bp.route('/dashboard/supplies', methods=['GET'])
@jwt_required()
@require_permission('printers.view')
def dashboard_supplies():
"""Printers needing a cartridge, flattened to one row per printer.
Reuses the existing low-supplies query and its five-minute cache, so the
card costs nothing extra: a Zabbix round-trip per printer on every dashboard
load would make this the slowest page in the app.
Critical first, then low. A printer with several depleted cartridges appears
once, listing them - a row per cartridge would report one printer three
times and read as three problems.
"""
data = _get_low_supplies_data()
rows = []
for printer in data.get('printers', []):
criticals = [s for s in printer['supplies'] if s['status'] == 'critical']
lows = [s for s in printer['supplies'] if s['status'] == 'low']
if not criticals and not lows:
continue
# Every depleted supply, criticals first. Listing only the worst class
# would hide a low cartridge behind a critical one on the same printer,
# and whoever walks out there wants to carry both.
worst = criticals + lows
rows.append({
'printerid': printer['printerid'],
'printername': printer['printername'] or printer['assetnumber'],
'location': printer['location'],
'status': 'critical' if criticals else 'low',
'supplies': ', '.join(
'{} {}%'.format(s.get('name') or s.get('type') or 'supply',
s.get('percent'))
for s in worst),
'iscritical': bool(criticals),
})
rows.sort(key=lambda r: (not r['iscritical'], r['printername']))
return success_response(rows)