Add MOC auto-generation service with sequential numbering
This commit is contained in:
90
app/services/moc_generator.py
Normal file
90
app/services/moc_generator.py
Normal file
@@ -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)
|
||||||
Reference in New Issue
Block a user