Part markers become their own assets under the operation they serve

This commit is contained in:
2026-08-10 15:55:36 -04:00
parent 28b1dfb89e
commit 2924a53346
5 changed files with 371 additions and 1 deletions

View File

@@ -52,6 +52,52 @@ def byteshash(raw):
return hashlib.sha256(raw).hexdigest()
def markerforsource(sourcehostname):
"""Asset id of the part marker the reporting PC drives, or None.
A part-marker PC's config describes ITS marker, not the operation the
marker serves. Several markers can serve one operation - 0613, 0615 and
WJPRT each do - so filing by machine number put several devices' configs in
one history where they overwrote each other. The computers collector gives
each marker PC a marker asset (`collector:partmarker`), and that is what a
backup from that PC belongs to.
Falls through to None, and so to the machine number, whenever anything is
missing: no hostname, no computers or machines plugin on a lean build
(ADR-014), or a marker PC that has not reported to the computers collector
yet. Filing under the operation is the old behaviour and still better than
rejecting the backup.
"""
from shopdb.api import db, AssetRelationship, RelationshipType
hostname = (sourcehostname or '').strip()
if not hostname:
return None
try:
from plugins.computers.models import Computer
from plugins.computers.plugin import PARTMARKER_LINK_ORIGIN
except ImportError:
return None
computer = Computer.query.filter(Computer.hostname.ilike(hostname)).first()
if computer is None or not computer.assetid:
return None
controls = RelationshipType.query.filter_by(
relationshiptype='controls').first()
if controls is None:
return None
link = (db.session.query(AssetRelationship)
.filter(AssetRelationship.sourceassetid == computer.assetid,
AssetRelationship.relationshiptypeid ==
controls.relationshiptypeid,
AssetRelationship.label == PARTMARKER_LINK_ORIGIN,
AssetRelationship.isactive.is_(True))
.first())
return link.targetassetid if link else None
class BackupKind:
"""Base class. Subclasses override what applies to them."""
@@ -198,6 +244,10 @@ class NtlarsKind(BackupKind):
def resolveassetid(self, payload):
from shopdb.api import db, Asset
marker = markerforsource(payload.get('sourcehostname'))
if marker is not None:
return marker, None
machinenumber = (payload.get('machinenumber') or '').strip()
if not machinenumber:
return None, 'no machinenumber in payload'
@@ -229,6 +279,10 @@ class PartMarkerKind(BackupKind):
def resolveassetid(self, payload):
from shopdb.api import db, Asset
marker = markerforsource(payload.get('sourcehostname'))
if marker is not None:
return marker, None
identifier = (payload.get('machinenumber')
or payload.get('assetnumber') or '').strip()
if not identifier: