115 lines
4.6 KiB
Python
115 lines
4.6 KiB
Python
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'<Asset sn={self.serial_number} type={self.asset_type}>'
|