""" Note attachment model for storing uploaded files associated with notes. """ from datetime import datetime from . import db class NoteAttachment(db.Model): """Model for files attached to notes (images, documents, etc.)""" __tablename__ = 'note_attachment' id = db.Column(db.Integer, primary_key=True) note_id = db.Column(db.Integer, db.ForeignKey('note.id'), nullable=False) # File information filename = db.Column(db.String(255), nullable=False) # Stored filename original_filename = db.Column(db.String(255), nullable=False) # Original upload name file_path = db.Column(db.String(500), nullable=False) # Relative path from uploads dir file_size = db.Column(db.Integer) # Size in bytes mime_type = db.Column(db.String(100)) # File type for easier filtering file_type = db.Column(db.String(20)) # 'image', 'document', 'archive', etc. # Metadata uploaded_at = db.Column(db.DateTime, default=datetime.now) uploaded_by_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) # For images: dimensions image_width = db.Column(db.Integer) image_height = db.Column(db.Integer) # Soft delete is_deleted = db.Column(db.Boolean, default=False) deleted_at = db.Column(db.DateTime) # Relationships note = db.relationship('Note', backref='attachments') uploaded_by = db.relationship('User', backref='uploaded_attachments') def __repr__(self): return f'' @property def is_image(self): """Check if attachment is an image""" return self.file_type == 'image' @property def url(self): """Get the URL to access this attachment""" return f'/uploads/notes/{self.file_path}' def get_file_extension(self): """Get file extension""" return self.original_filename.rsplit('.', 1)[1].lower() if '.' in self.original_filename else '' @staticmethod def allowed_file(filename, file_type='any'): """Check if file extension is allowed""" ALLOWED_EXTENSIONS = { 'image': {'png', 'jpg', 'jpeg', 'gif', 'webp', 'svg'}, 'document': {'pdf', 'doc', 'docx', 'txt', 'md', 'csv', 'xls', 'xlsx'}, 'archive': {'zip', 'tar', 'gz', '7z'}, 'any': {'png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'pdf', 'doc', 'docx', 'txt', 'md', 'csv', 'xls', 'xlsx', 'zip', 'tar', 'gz', '7z'} } if '.' not in filename: return False ext = filename.rsplit('.', 1)[1].lower() allowed = ALLOWED_EXTENSIONS.get(file_type, ALLOWED_EXTENSIONS['any']) return ext in allowed @staticmethod def get_file_type(filename): """Determine file type from extension""" if '.' not in filename: return 'unknown' ext = filename.rsplit('.', 1)[1].lower() if ext in {'png', 'jpg', 'jpeg', 'gif', 'webp', 'svg'}: return 'image' elif ext in {'pdf', 'doc', 'docx', 'txt', 'md', 'csv', 'xls', 'xlsx'}: return 'document' elif ext in {'zip', 'tar', 'gz', '7z'}: return 'archive' else: return 'other'