The asset/computer model is now the single source of truth. Remove the Machine instance layer end to end: - Delete models Machine, MachineStatus, PCType, MachineRelationship, InstalledApp, PrinterData; keep MachineType (models.machinetypeid still references it). - Delete the /api/machines, /api/statuses, /api/pctypes blueprints and the legacy /api/printers/legacy (PrinterData) blueprint. - Drop the deprecated communications.machineid column and its FK. - Migration 7c01 drops tables machines, machinestatuses, pctypes, machinerelationships, installedapps, printerdata (idempotent). - Fix remaining readers (applications install counts) to ComputerInstalledApp. - Frontend: remove dead machinesApi/statusesApi/pctypesApi wrappers; repoint the PC Types settings page at computer types. 143 tests pass; all asset/computer/dashboard/report/collector endpoints 200. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
100 lines
3.5 KiB
Python
100 lines
3.5 KiB
Python
"""Application tracking models."""
|
|
|
|
from shopdb.extensions import db
|
|
from .base import BaseModel
|
|
|
|
|
|
class AppOwner(BaseModel):
|
|
"""Application owner/contact."""
|
|
__tablename__ = 'appowners'
|
|
|
|
appownerid = db.Column(db.Integer, primary_key=True)
|
|
appowner = db.Column(db.String(100), nullable=False)
|
|
sso = db.Column(db.String(50))
|
|
email = db.Column(db.String(100))
|
|
|
|
# Relationships
|
|
supportteams = db.relationship('SupportTeam', back_populates='owner', lazy='dynamic')
|
|
|
|
def __repr__(self):
|
|
return f"<AppOwner {self.appowner}>"
|
|
|
|
|
|
class SupportTeam(BaseModel):
|
|
"""Application support team."""
|
|
__tablename__ = 'supportteams'
|
|
|
|
supportteamid = db.Column(db.Integer, primary_key=True)
|
|
teamname = db.Column(db.String(100), nullable=False)
|
|
teamurl = db.Column(db.String(255))
|
|
appownerid = db.Column(db.Integer, db.ForeignKey('appowners.appownerid'))
|
|
|
|
# Relationships
|
|
owner = db.relationship('AppOwner', back_populates='supportteams')
|
|
applications = db.relationship('Application', back_populates='supportteam', lazy='dynamic')
|
|
|
|
def __repr__(self):
|
|
return f"<SupportTeam {self.teamname}>"
|
|
|
|
|
|
class Application(BaseModel):
|
|
"""Application catalog."""
|
|
__tablename__ = 'applications'
|
|
|
|
appid = db.Column(db.Integer, primary_key=True)
|
|
appname = db.Column(db.String(100), unique=True, nullable=False)
|
|
appdescription = db.Column(db.String(255))
|
|
supportteamid = db.Column(db.Integer, db.ForeignKey('supportteams.supportteamid'))
|
|
isinstallable = db.Column(db.Boolean, default=False)
|
|
applicationnotes = db.Column(db.Text)
|
|
installpath = db.Column(db.String(255))
|
|
applicationlink = db.Column(db.String(512))
|
|
documentationpath = db.Column(db.String(512))
|
|
ishidden = db.Column(db.Boolean, default=False)
|
|
isprinter = db.Column(db.Boolean, default=False)
|
|
islicenced = db.Column(db.Boolean, default=False)
|
|
image = db.Column(db.String(255))
|
|
|
|
# Relationships
|
|
supportteam = db.relationship('SupportTeam', back_populates='applications')
|
|
versions = db.relationship('AppVersion', back_populates='application', lazy='dynamic')
|
|
|
|
def __repr__(self):
|
|
return f"<Application {self.appname}>"
|
|
|
|
|
|
class AppVersion(db.Model):
|
|
"""Application version tracking."""
|
|
__tablename__ = 'appversions'
|
|
|
|
appversionid = db.Column(db.Integer, primary_key=True)
|
|
appid = db.Column(db.Integer, db.ForeignKey('applications.appid'), nullable=False)
|
|
version = db.Column(db.String(50), nullable=False)
|
|
releasedate = db.Column(db.Date)
|
|
notes = db.Column(db.String(255))
|
|
dateadded = db.Column(db.DateTime, default=db.func.now())
|
|
isactive = db.Column(db.Boolean, default=True)
|
|
|
|
# Relationships
|
|
application = db.relationship('Application', back_populates='versions')
|
|
|
|
# Unique constraint on app + version
|
|
__table_args__ = (
|
|
db.UniqueConstraint('appid', 'version', name='uq_app_version'),
|
|
)
|
|
|
|
def to_dict(self):
|
|
"""Convert to dictionary."""
|
|
return {
|
|
'appversionid': self.appversionid,
|
|
'appid': self.appid,
|
|
'version': self.version,
|
|
'releasedate': self.releasedate.isoformat() if self.releasedate else None,
|
|
'notes': self.notes,
|
|
'dateadded': self.dateadded.isoformat() + 'Z' if self.dateadded else None,
|
|
'isactive': self.isactive
|
|
}
|
|
|
|
def __repr__(self):
|
|
return f"<AppVersion {self.application.appname if self.application else self.appid} v{self.version}>"
|