from datetime import datetime from app.extensions import db ASSET_TYPES = [ 'Laptop', 'Desktop', 'Monitor', 'Keyboard', 'Mouse', 'Headset', 'Docking Station', 'Printer', 'Scanner', 'Tablet', 'Phone', 'Server', 'Network Equipment', 'Other', ] ASSET_STATUSES = [ ('available', 'Available'), ('assigned', 'Assigned'), ('maintenance', 'In Maintenance'), ('retired', 'Retired'), ('lost', 'Lost / Stolen'), ] class Asset(db.Model): """Hardware asset tracked by serial number and/or service tag.""" __tablename__ = 'assets' id = db.Column(db.Integer, primary_key=True) # Primary identifiers serial_number = db.Column(db.String(200), unique=True, nullable=False, index=True) service_tag = db.Column(db.String(200), unique=True, nullable=True, index=True) asset_tag = db.Column(db.String(100), nullable=True) # internal barcode / tag # Classification asset_type = db.Column(db.String(50), nullable=False) brand = db.Column(db.String(100), nullable=True) model = db.Column(db.String(150), nullable=True) # Technical specs (optional) processor = db.Column(db.String(200), nullable=True) ram_gb = db.Column(db.Integer, nullable=True) storage_gb = db.Column(db.Integer, nullable=True) operating_system = db.Column(db.String(100), nullable=True) mac_address = db.Column(db.String(50), nullable=True) # Procurement purchase_date = db.Column(db.Date, nullable=True) warranty_expiry = db.Column(db.Date, nullable=True) purchase_price = db.Column(db.Numeric(10, 2), nullable=True) supplier = db.Column(db.String(200), nullable=True) po_number = db.Column(db.String(100), nullable=True) # Current state status = db.Column(db.String(30), default='available', nullable=False) location = db.Column(db.String(200), nullable=True) notes = db.Column(db.Text, nullable=True) # Compliance / IT checks — Desktop & Laptop only inventory_number = db.Column(db.String(100), nullable=True) ad_device_name = db.Column(db.String(150), nullable=True) location_note = db.Column(db.Text, nullable=True) # free-text location note # Current boolean state encryption_checked = db.Column(db.Boolean, default=False, nullable=False) backup_checked = db.Column(db.Boolean, default=False, nullable=False) hr_notified = db.Column(db.Boolean, default=False, nullable=False) # Who last changed each check and when encryption_checked_by_id = db.Column(db.Integer, db.ForeignKey('admin_users.id'), nullable=True) encryption_checked_at = db.Column(db.DateTime, nullable=True) backup_checked_by_id = db.Column(db.Integer, db.ForeignKey('admin_users.id'), nullable=True) backup_checked_at = db.Column(db.DateTime, nullable=True) hr_notified_by_id = db.Column(db.Integer, db.ForeignKey('admin_users.id'), nullable=True) hr_notified_at = db.Column(db.DateTime, nullable=True) created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) created_by_id = db.Column(db.Integer, db.ForeignKey('admin_users.id'), nullable=True) # Relationships assignments = db.relationship( 'Assignment', backref='asset', lazy='dynamic', cascade='all, delete-orphan' ) paperwork_docs = db.relationship( 'Paperwork', backref='asset', lazy='dynamic' ) compliance_checks = db.relationship( 'ComplianceCheck', back_populates='asset', lazy='dynamic', cascade='all, delete-orphan', order_by='ComplianceCheck.performed_at.desc()', ) created_by = db.relationship('AdminUser', foreign_keys=[created_by_id]) encryption_checked_by = db.relationship('AdminUser', foreign_keys=[encryption_checked_by_id]) backup_checked_by = db.relationship('AdminUser', foreign_keys=[backup_checked_by_id]) hr_notified_by = db.relationship('AdminUser', foreign_keys=[hr_notified_by_id]) @property def current_assignment(self): return self.assignments.filter_by(is_active=True).first() @property def current_user(self): a = self.current_assignment return a.user if a else None @property def status_badge(self): colours = { 'available': 'success', 'assigned': 'primary', 'maintenance': 'warning', 'retired': 'secondary', 'lost': 'danger', } return colours.get(self.status, 'secondary') def __repr__(self): return f''