Initial import: shopdb-flask multi-site asset platform
Flask + Vue rewrite of the classic-ASP shopdb, built as a plugin framework so sister GE Aerospace sites can adopt it. Product version 0.7.0-pre-0.8.0, plugin contract 0.11.0, 966 backend tests. Key entry points: - docs/INSTALL-WINDOWS-IIS.md - tested Windows + IIS install runbook (own-site and subpath deployment methods) - docs/PILOT-DEPLOY.md - production pilot: stand up + import + verify - docs/IMPORT-API.md - schema-agnostic legacy data import contract - scripts/site_imports/wjf/ - West Jefferson reference import loader - docs/adr/ - twelve accepted architecture decision records
This commit is contained in:
95
shopdb/core/models/application.py
Normal file
95
shopdb/core/models/application.py
Normal file
@@ -0,0 +1,95 @@
|
||||
"""Application tracking models."""
|
||||
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from shopdb.extensions import db
|
||||
from .base import BaseModel
|
||||
|
||||
|
||||
def _utcnow():
|
||||
# naive UTC to match the other DB DateTime columns (stored without tzinfo)
|
||||
return datetime.now(timezone.utc).replace(tzinfo=None)
|
||||
# SupportTeam / SupportTeamContact live in supportteam.py; imported by the
|
||||
# models package so the Application.supportteam relationship resolves.
|
||||
|
||||
|
||||
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)
|
||||
isrequired = db.Column(
|
||||
db.Boolean, default=False,
|
||||
comment='Required on all PCs (drives the software-compliance report)'
|
||||
)
|
||||
image = db.Column(db.String(255))
|
||||
|
||||
# Relationships
|
||||
supportteam = db.relationship('SupportTeam', back_populates='applications')
|
||||
versions = db.relationship('AppVersion', back_populates='application', lazy='dynamic')
|
||||
|
||||
def to_dict(self):
|
||||
"""Serialize, flattening the support team + its active contacts.
|
||||
|
||||
Emits supportteamname, teamurl, and the team's active contacts so the
|
||||
frontend needs a single call to render the Support card.
|
||||
"""
|
||||
result = super().to_dict()
|
||||
team = self.supportteam
|
||||
result['supportteamname'] = team.teamname if team else None
|
||||
result['teamurl'] = team.teamurl if team else None
|
||||
result['contacts'] = [
|
||||
{'name': c.name, 'sso': c.sso}
|
||||
for c in team.active_contacts()
|
||||
] if team else []
|
||||
return result
|
||||
|
||||
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=_utcnow)
|
||||
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}>"
|
||||
Reference in New Issue
Block a user