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

@@ -994,3 +994,73 @@ def dashboard_quiet():
# down the list, not the order the rows came out of the table.
rows.sort(key=lambda r: (r['quietdays'] is not None, -(r['quietdays'] or 0)))
return success_response(rows[:50])
@computers_bp.route('/dashboard/sharedmachines', methods=['GET'])
@jwt_required()
@require_permission('computers.view')
def dashboard_sharedmachines():
"""Machine numbers claimed by more than one PC, with nothing filed under
them.
Several devices genuinely sharing a number is legitimate - part markers do
it - and those are modelled: each device is its own asset filed `partof` the
operation, so the operation has CHILD ASSETS. Two PCs carrying the same
machine number by mistake looks identical from a count and has none. That
distinction is the whole card; without it this would list correct data
alongside faults and get ignored.
Promoted from `flask relationships check-shared-machines`, which answers the
same question and which nobody will remember to run. This one found seven
mis-numbered bays that had been that way for weeks.
"""
from shopdb.api import AssetRelationship, RelationshipType
from sqlalchemy.orm import aliased
controls = RelationshipType.query.filter_by(
relationshiptype='controls').first()
partof = RelationshipType.query.filter_by(relationshiptype='partof').first()
if not controls:
return success_response([])
pcasset = aliased(Asset)
machineasset = aliased(Asset)
rows = (db.session.query(machineasset.assetid, machineasset.assetnumber,
pcasset.assetnumber)
.select_from(AssetRelationship)
.join(pcasset, AssetRelationship.sourceassetid == pcasset.assetid)
.join(machineasset,
AssetRelationship.targetassetid == machineasset.assetid)
.filter(AssetRelationship.relationshiptypeid ==
controls.relationshiptypeid,
AssetRelationship.label == 'collector:machine',
AssetRelationship.isactive.is_(True))
.all())
bymachine = {}
for assetid, machinenumber, pcnumber in rows:
bymachine.setdefault((assetid, machinenumber), []).append(pcnumber)
out = []
for (assetid, machinenumber), pcs in bymachine.items():
if len(pcs) < 2:
continue
children = 0
if partof:
children = (AssetRelationship.query
.filter_by(targetassetid=assetid,
relationshiptypeid=partof.relationshiptypeid,
isactive=True)
.count())
if children:
continue # modelled: the devices are assets in their own right
out.append({
'assetid': assetid,
'machinenumber': machinenumber,
'pccount': len(pcs),
'pcs': ', '.join(sorted(p for p in pcs if p)),
})
out.sort(key=lambda r: -r['pccount'])
return success_response(out)