Initial commit - LEGO Instructions Manager v1.5.0
This commit is contained in:
99
app/models/set.py
Normal file
99
app/models/set.py
Normal file
@@ -0,0 +1,99 @@
|
||||
from datetime import datetime
|
||||
from app import db
|
||||
|
||||
|
||||
class Set(db.Model):
|
||||
"""Model for LEGO sets."""
|
||||
|
||||
__tablename__ = 'sets'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
set_number = db.Column(db.String(20), unique=True, nullable=False, index=True)
|
||||
set_name = db.Column(db.String(200), nullable=False)
|
||||
theme = db.Column(db.String(100), nullable=False, index=True)
|
||||
year_released = db.Column(db.Integer, nullable=False, index=True)
|
||||
piece_count = db.Column(db.Integer)
|
||||
|
||||
# MOC (My Own Creation) support
|
||||
is_moc = db.Column(db.Boolean, default=False, nullable=False, index=True)
|
||||
moc_designer = db.Column(db.String(100), nullable=True) # Designer/creator name
|
||||
moc_description = db.Column(db.Text, nullable=True) # Detailed description
|
||||
|
||||
# Brickset integration
|
||||
brickset_id = db.Column(db.Integer, unique=True, nullable=True)
|
||||
image_url = db.Column(db.String(500)) # External URL (Brickset, etc.)
|
||||
cover_image = db.Column(db.String(500)) # Uploaded cover image path
|
||||
|
||||
# Metadata
|
||||
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
||||
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
|
||||
updated_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow,
|
||||
onupdate=datetime.utcnow)
|
||||
|
||||
# Relationships
|
||||
instructions = db.relationship('Instruction', backref='set', lazy='dynamic',
|
||||
cascade='all, delete-orphan')
|
||||
extra_files = db.relationship('ExtraFile', back_populates='lego_set', lazy='dynamic',
|
||||
cascade='all, delete-orphan', order_by='ExtraFile.uploaded_at.desc()')
|
||||
|
||||
def __repr__(self):
|
||||
return f'<Set {self.set_number}: {self.set_name}>'
|
||||
|
||||
def get_image(self):
|
||||
"""Get the best available image (uploaded cover takes priority)."""
|
||||
if self.cover_image:
|
||||
# Ensure forward slashes for web URLs
|
||||
clean_path = self.cover_image.replace('\\', '/')
|
||||
return f'/static/uploads/{clean_path}'
|
||||
return self.image_url
|
||||
|
||||
@property
|
||||
def has_cover_image(self):
|
||||
"""Check if set has an uploaded cover image."""
|
||||
return bool(self.cover_image)
|
||||
|
||||
@property
|
||||
def cover_image_url(self):
|
||||
"""Get the uploaded cover image URL."""
|
||||
if self.cover_image:
|
||||
clean_path = self.cover_image.replace('\\', '/')
|
||||
return f'/static/uploads/{clean_path}'
|
||||
return None
|
||||
|
||||
def to_dict(self):
|
||||
"""Convert set to dictionary."""
|
||||
return {
|
||||
'id': self.id,
|
||||
'set_number': self.set_number,
|
||||
'set_name': self.set_name,
|
||||
'theme': self.theme,
|
||||
'year_released': self.year_released,
|
||||
'piece_count': self.piece_count,
|
||||
'image_url': self.image_url,
|
||||
'is_moc': self.is_moc,
|
||||
'moc_designer': self.moc_designer,
|
||||
'moc_description': self.moc_description,
|
||||
'instruction_count': self.instructions.count(),
|
||||
'created_at': self.created_at.isoformat(),
|
||||
'updated_at': self.updated_at.isoformat()
|
||||
}
|
||||
|
||||
@property
|
||||
def instruction_files(self):
|
||||
"""Get all instruction files for this set."""
|
||||
return self.instructions.order_by(Instruction.page_number).all()
|
||||
|
||||
@property
|
||||
def pdf_instructions(self):
|
||||
"""Get only PDF instructions."""
|
||||
return self.instructions.filter_by(file_type='PDF').all()
|
||||
|
||||
@property
|
||||
def image_instructions(self):
|
||||
"""Get only image instructions."""
|
||||
return self.instructions.filter_by(file_type='IMAGE').order_by(
|
||||
Instruction.page_number).all()
|
||||
|
||||
|
||||
# Import here to avoid circular imports
|
||||
from app.models.instruction import Instruction
|
||||
Reference in New Issue
Block a user