From 944a679372f0c412528f30f71f4dff661e5f7a6b Mon Sep 17 00:00:00 2001 From: jessikitty Date: Mon, 15 Dec 2025 00:34:34 +1100 Subject: [PATCH] Add MOC auto-generation service with sequential numbering --- app/services/moc_generator.py | 90 +++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 app/services/moc_generator.py diff --git a/app/services/moc_generator.py b/app/services/moc_generator.py new file mode 100644 index 0000000..e7a7381 --- /dev/null +++ b/app/services/moc_generator.py @@ -0,0 +1,90 @@ +"""MOC Number Generation Service for LEGO Instructions Manager""" + +from app.models.set import Set +from app import db + + +class MOCNumberGenerator: + """Service for auto-generating MOC (My Own Creation) set numbers""" + + DEFAULT_PREFIX = 'MOC' + DEFAULT_START = 10000 + + @staticmethod + def generate_next_number(prefix=None, user_id=None): + """ + Generate the next available MOC number + + Args: + prefix: MOC prefix (default: 'MOC') + user_id: Optional user ID to scope MOC numbers per user + + Returns: + str: Next MOC number (e.g., 'MOC-10001') + """ + if prefix is None: + prefix = MOCNumberGenerator.DEFAULT_PREFIX + + # Build query for highest MOC number + query = Set.query.filter( + Set.is_moc == True, + Set.set_number.like(f'{prefix}%') + ) + + # Optionally scope to user + if user_id: + query = query.filter_by(user_id=user_id) + + # Get highest MOC number + highest_moc = query.order_by(Set.set_number.desc()).first() + + if highest_moc: + try: + # Extract number from format like "MOC-12345" or "MOC12345" + number_part = highest_moc.set_number.replace(prefix, '').replace('-', '').strip() + current_num = int(number_part) + next_num = current_num + 1 + except (ValueError, AttributeError): + # If parsing fails, start from default + next_num = MOCNumberGenerator.DEFAULT_START + else: + next_num = MOCNumberGenerator.DEFAULT_START + + return f'{prefix}-{next_num}' + + @staticmethod + def validate_moc_number(set_number, user_id=None): + """ + Check if a MOC number is available + + Args: + set_number: MOC number to validate + user_id: Optional user ID to check user-specific availability + + Returns: + bool: True if available, False if already in use + """ + query = Set.query.filter_by(set_number=set_number) + + if user_id: + query = query.filter_by(user_id=user_id) + + existing = query.first() + return existing is None + + @staticmethod + def is_moc_number(set_number, prefix=None): + """ + Check if a set number follows MOC format + + Args: + set_number: Set number to check + prefix: MOC prefix to match (default: 'MOC') + + Returns: + bool: True if it's a MOC number + """ + if prefix is None: + prefix = MOCNumberGenerator.DEFAULT_PREFIX + + return set_number.upper().startswith(prefix)